Exemplo n.º 1
0
/**
 *  @brief Handle suspend 
 *
 *  @param intf		  Pointer to usb_interface
 *  @param message	  Pointer to pm_message_t structure 			
 *
 *  @return 	   	  MLAN_STATUS_SUCCESS
 */
static int
woal_usb_suspend(struct usb_interface *intf, pm_message_t message)
{
    struct usb_card_rec *cardp = usb_get_intfdata(intf);
    moal_handle *handle = NULL;
    int i;

    ENTER();

    if (!cardp || !cardp->phandle) {
        PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
        LEAVE();
        return MLAN_STATUS_SUCCESS;
    }
    handle = cardp->phandle;

    /* Enable Host Sleep */
    woal_enable_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY));

    /* Indicate device suspended */
    /* The flag must be set here before the usb_kill_urb() calls. Reason: In
       the complete handlers, urb->status(= -ENOENT) and 'is_suspended' flag is 
       used in combination to distinguish between a suspended state and a
       'disconnect' one. */
    handle->is_suspended = MTRUE;
    for (i = 0; i < handle->priv_num; i++)
        netif_carrier_off(handle->priv[i]->netdev);

    /* Unlink Rx cmd URB */
    if (atomic_read(&cardp->rx_cmd_urb_pending) && cardp->rx_cmd.urb) {
        usb_kill_urb(cardp->rx_cmd.urb);
    }
    /* Unlink Rx data URBs */
    if (atomic_read(&cardp->rx_data_urb_pending)) {
        for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
            if (cardp->rx_data_list[i].urb)
                usb_kill_urb(cardp->rx_data_list[i].urb);
        }
    }

    /* Unlink Tx data URBs */
    for (i = 0; i < MVUSB_TX_HIGH_WMARK; i++) {
        if (cardp->tx_data_list[i].urb) {
            usb_kill_urb(cardp->tx_data_list[i].urb);
        }
    }
    /* Unlink Tx cmd URB */
    if (cardp->tx_cmd.urb) {
        usb_kill_urb(cardp->tx_cmd.urb);
    }

    handle->suspend_wait_q_woken = MTRUE;
    wake_up_interruptible(&handle->suspend_wait_q);

    LEAVE();
    return MLAN_STATUS_SUCCESS;
}
/**  @brief This function handles client driver suspend
 *  
 *  @param dev	   A pointer to device structure
 *  @return 	   MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
int
woal_sdio_suspend(struct device *dev)
{
    struct sdio_func *func = dev_to_sdio_func(dev);
    mmc_pm_flag_t pm_flags = 0;
    moal_handle *handle = NULL;
    struct sdio_mmc_card *cardp;
    int i;
    int ret = MLAN_STATUS_SUCCESS;
    int hs_actived = 0;

    ENTER();

    if (func) {
        pm_flags = sdio_get_host_pm_caps(func);
        PRINTM(MCMND, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
               pm_flags);
        if (!(pm_flags & MMC_PM_KEEP_POWER)) {
            PRINTM(MERROR, "%s: cannot remain alive while host is suspended\n",
                   sdio_func_id(func));
            LEAVE();
            return -ENOSYS;
        }
        cardp = sdio_get_drvdata(func);
        if (!cardp || !cardp->handle) {
            PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
            LEAVE();
            return MLAN_STATUS_SUCCESS;
        }
    } else {
        PRINTM(MERROR, "sdio_func is not specified\n");
        LEAVE();
        return MLAN_STATUS_SUCCESS;
    }
    handle = cardp->handle;

    if (pm_keep_power) {
        /* Enable the Host Sleep */
        hs_actived = woal_enable_hs(woal_get_priv(handle, MLAN_BSS_TYPE_ANY));
        if (hs_actived) {
            PRINTM(MCMND, "suspend with MMC_PM_KEEP_POWER\n");
            ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
        }
    }

    /* Indicate device suspended */
    handle->is_suspended = MTRUE;
    for (i = 0; i < handle->priv_num; i++)
        netif_carrier_off(handle->priv[i]->netdev);

    LEAVE();
    return ret;
}
Exemplo n.º 3
0
/**  @brief This function handles client driver suspend
 *
 *  @param dev      A pointer to device structure
 *  @return         MLAN_STATUS_SUCCESS or error code
 */
int
woal_sdio_suspend(struct device *dev)
{
	struct sdio_func *func = dev_to_sdio_func(dev);
	mmc_pm_flag_t pm_flags = 0;
	moal_handle *handle = NULL;
	struct sdio_mmc_card *cardp;
	int i, retry_num = 8;
	int ret = MLAN_STATUS_SUCCESS;
	int hs_actived = 0;
	mlan_ds_ps_info pm_info;

	ENTER();
	PRINTM(MCMND, "<--- Enter woal_sdio_suspend --->\n");
	pm_flags = sdio_get_host_pm_caps(func);
	PRINTM(MCMND, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
	       pm_flags);
	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
		PRINTM(MERROR,
		       "%s: cannot remain alive while host is suspended\n",
		       sdio_func_id(func));
		LEAVE();
		return -ENOSYS;
	}
	cardp = sdio_get_drvdata(func);
	if (!cardp || !cardp->handle) {
		PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
		LEAVE();
		return MLAN_STATUS_SUCCESS;
	}

	handle = cardp->handle;
	if (handle->is_suspended == MTRUE) {
		PRINTM(MWARN, "Device already suspended\n");
		LEAVE();
		return MLAN_STATUS_SUCCESS;
	}
	if (handle->fw_dump) {
		PRINTM(MMSG, "suspend not allowed while FW dump!");
		ret = -EBUSY;
		goto done;
	}
	handle->suspend_fail = MFALSE;
	memset(&pm_info, 0, sizeof(pm_info));
	for (i = 0; i < retry_num; i++) {
		if (MLAN_STATUS_SUCCESS ==
		    woal_get_pm_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
				     &pm_info)) {
			if (pm_info.is_suspend_allowed == MTRUE)
				break;
			else
				PRINTM(MMSG,
				       "Suspend not allowed and retry again\n");
		}
		woal_sched_timeout(100);
	}
	if (pm_info.is_suspend_allowed == MFALSE) {
		PRINTM(MMSG, "Suspend not allowed\n");
		ret = -EBUSY;
		goto done;
	}

	for (i = 0; i < handle->priv_num; i++)
		netif_device_detach(handle->priv[i]->netdev);

	if (pm_keep_power) {
		/* Enable the Host Sleep */
#ifdef MMC_PM_FUNC_SUSPENDED
		handle->suspend_notify_req = MTRUE;
#endif
		hs_actived =
			woal_enable_hs(woal_get_priv
				       (handle, MLAN_BSS_ROLE_ANY));
#ifdef MMC_PM_FUNC_SUSPENDED
		handle->suspend_notify_req = MFALSE;
#endif
		if (hs_actived) {
#ifdef MMC_PM_SKIP_RESUME_PROBE
			PRINTM(MCMND,
			       "suspend with MMC_PM_KEEP_POWER and MMC_PM_SKIP_RESUME_PROBE\n");
			ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER |
						     MMC_PM_SKIP_RESUME_PROBE);
#else
			PRINTM(MCMND, "suspend with MMC_PM_KEEP_POWER\n");
			ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
#endif
		} else {
			PRINTM(MMSG, "HS not actived, suspend fail!");
			handle->suspend_fail = MTRUE;
			for (i = 0; i < handle->priv_num; i++)
				netif_device_attach(handle->priv[i]->netdev);
			ret = -EBUSY;
			goto done;
		}
	}

	/* Indicate device suspended */
	handle->is_suspended = MTRUE;
done:
	PRINTM(MCMND, "<--- Leave woal_sdio_suspend --->\n");
	LEAVE();
	return ret;
}