/**
 *  @brief This function enable host sleep
 *
 *  @param priv    A pointer to bt_private structure
 *  @return 	   BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
int
bt_enable_hs(bt_private * priv)
{
    struct sk_buff *skb = NULL;
    u8 ret = BT_STATUS_SUCCESS;
    BT_CMD *pCmd;
    ENTER();
    skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
    if (skb == NULL) {
        PRINTM(WARN, "No free skb\n");
        ret = BT_STATUS_FAILURE;
        goto exit;
    }
    pCmd = (BT_CMD *) skb->tail;
    pCmd->ocf_ogf = (OGF << 10) | BT_CMD_HOST_SLEEP_ENABLE;
    pCmd->length = 0;
    bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
    skb_put(skb, sizeof(BT_CMD));
    skb->dev = (void *) priv->bt_dev.hcidev;
    skb_queue_head(&priv->adapter->tx_queue, skb);
    PRINTM(CMD, "Queue hs enable Command\n");
    wake_up_interruptible(&priv->MainThread.waitQ);
    if (!os_wait_interruptible_timeout
        (priv->adapter->cmd_wait_q, priv->adapter->hs_state,
         WAIT_UNTIL_HS_STATE_CHANGED)) {
        ret = BT_STATUS_FAILURE;
        PRINTM(MSG, "bt_enable_hs: timeout: %d, %d,%d\n",
               priv->adapter->hs_state, priv->adapter->ps_state,
               priv->adapter->WakeupTries);
    }
  exit:
    LEAVE();
    return ret;
}
Beispiel #2
0
/** 
 *  @brief Exit deep sleep with timeout
 *   
 *  @param priv		A pointer to wlan_private structure
 *  @return    		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
 */
int
wlan_exit_deep_sleep_timeout(wlan_private * priv)
{
    wlan_adapter *Adapter = priv->adapter;
    int ret = WLAN_STATUS_SUCCESS;

    ENTER();

    Adapter->IsAutoDeepSleepEnabled = FALSE;
    if (Adapter->IsDeepSleep == TRUE) {
        PRINTM(CMND, "Exit deep sleep... @ %lu\n", os_time_get());
        sbi_exit_deep_sleep(priv);
        if (Adapter->IsDeepSleep == TRUE) {
            if (os_wait_interruptible_timeout(Adapter->ds_awake_q,
                                              !Adapter->IsDeepSleep,
                                              MRVDRV_DEEP_SLEEP_EXIT_TIMEOUT) ==
                0) {
                PRINTM(MSG, "ds_awake_q: timer expired\n");
                ret = WLAN_STATUS_FAILURE;
            }
        }
    }

    LEAVE();
    return ret;
}
/**
 *  @brief This function send module cfg cmd to firmware
 *
 *  Command format:
 *  +--------+--------+--------+--------+--------+--------+--------+
 *  |     OCF OGF     | Length |                Data               |
 *  +--------+--------+--------+--------+--------+--------+--------+
 *  |     2-byte      | 1-byte |               4-byte              |
 *  +--------+--------+--------+--------+--------+--------+--------+
 *
 *  @param priv    A pointer to bt_private structure
 *  @param subcmd  sub command
 *  @return 	   BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
int
bt_send_module_cfg_cmd(bt_private * priv, int subcmd)
{
    struct sk_buff *skb = NULL;
    u8 ret = BT_STATUS_SUCCESS;
    BT_CMD *pCmd;
    ENTER();
    skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
    if (skb == NULL) {
        PRINTM(WARN, "No free skb\n");
        ret = BT_STATUS_FAILURE;
        goto exit;
    }
    pCmd = (BT_CMD *) skb->tail;
    pCmd->ocf_ogf = (OGF << 10) | BT_CMD_MODULE_CFG_REQ;
    pCmd->length = 1;
    pCmd->data[0] = subcmd;
    bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
    skb_put(skb, sizeof(BT_CMD));
    skb->dev = (void *) priv->bt_dev.hcidev;
    skb_queue_head(&priv->adapter->tx_queue, skb);
    priv->bt_dev.sendcmdflag = TRUE;
    priv->adapter->cmd_complete = FALSE;
    PRINTM(CMD, "Queue module cfg Command\n");
    wake_up_interruptible(&priv->MainThread.waitQ);
    /*
       On some Adroind platforms certain delay is needed for HCI daemon to
       remove this module and close itself gracefully. Otherwise it hangs. This
       10ms delay is a workaround for such platforms as the root cause has not
       been found yet. */
    mdelay(10);
    if (!os_wait_interruptible_timeout
        (priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
         WAIT_UNTIL_CMD_RESP)) {
        ret = BT_STATUS_FAILURE;
        PRINTM(MSG, "module_cfg_cmd (0x%x): timeout sendcmdflag=%d\n", subcmd,
               priv->bt_dev.sendcmdflag);
    }
    PRINTM(CMD, "module cfg Command done\n");
  exit:
    LEAVE();
    return ret;
}
/** 
 *  @brief This function enables Host Sleep.
 *  
 *  @param priv    A pointer to wlan_private
 *  @return        WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
 */
int
wlan_enable_hs(wlan_private * priv)
{
    wlan_adapter *Adapter = priv->adapter;
    int ret = WLAN_STATUS_SUCCESS;

    ENTER();

    /* suspend not supported in PPS/UAPSD mode */
    if ((Adapter->PSMode != Wlan802_11PowerModeCAM)
        && Adapter->sleep_period.period) {
        ret = WLAN_STATUS_FAILURE;
        PRINTM(MSG,
               "wlan_enable_hs: suspend not supported. PSMode=%d SleepPeriod=%d\n",
               Adapter->PSMode, Adapter->sleep_period.period);
    } else if (!Adapter->HS_Activated) {
        ret = wlan_prepare_cmd(priv,
                               HostCmd_CMD_802_11_HOST_SLEEP_CFG,
                               0, HostCmd_OPTION_WAITFORRSP, 0,
                               &Adapter->HSCfg);
        if (!os_wait_interruptible_timeout
            (Adapter->HS_wait_q, Adapter->HS_Activated,
             WAIT_UNTIL_HS_STATE_CHANGED)) {
            ret = WLAN_STATUS_FAILURE;
            PRINTM(MSG, "wlan_enable_hs: timeout:%d, %d, %d, %d, %d\n",
                   Adapter->MediaConnectStatus, Adapter->PSState,
                   Adapter->bWakeupDevRequired, Adapter->WakeupTries,
                   Adapter->HS_Activated);
        }
    } else {
        PRINTM(MSG, "wlan_enable_hs: already activated:%d, %d, %d, %d, %d\n",
               Adapter->MediaConnectStatus, Adapter->PSState,
               Adapter->bWakeupDevRequired, Adapter->WakeupTries,
               Adapter->HS_Activated);
    }

    LEAVE();
    return ret;
}