/** @brief This function handles client driver suspend * * @param dev A pointer to device structure * @return BT_STATUS_SUCCESS or BT_STATUS_FAILURE */ int bt_sdio_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); mmc_pm_flag_t pm_flags = 0; bt_private *priv = NULL; struct sdio_mmc_card *cardp; struct hci_dev *hcidev; ENTER(); if (func) { pm_flags = sdio_get_host_pm_caps(func); PRINTM(CMD, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func), pm_flags); if (!(pm_flags & MMC_PM_KEEP_POWER)) { PRINTM(ERROR, "%s: cannot remain alive while host is suspended\n", sdio_func_id(func)); return -ENOSYS; } cardp = sdio_get_drvdata(func); if (!cardp || !cardp->priv) { PRINTM(ERROR, "Card or priv structure is not valid\n"); LEAVE(); return BT_STATUS_SUCCESS; } } else { PRINTM(ERROR, "sdio_func is not specified\n"); LEAVE(); return BT_STATUS_SUCCESS; } PRINTM(CMD, "SDIO suspend\n"); priv = cardp->priv; if ((pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) bt_enable_hs(priv); hcidev = priv->bt_dev.hcidev; hci_suspend_dev(hcidev); skb_queue_purge(&priv->adapter->tx_queue); LEAVE(); /* We will keep the power when hs enabled successfully */ if ((pm_keep_power) && (priv->adapter->hs_state == HS_ACTIVATED)) #ifdef MMC_PM_SKIP_RESUME_PROBE return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER | MMC_PM_SKIP_RESUME_PROBE); #else return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); #endif else return BT_STATUS_SUCCESS;
/** @brief This function handles client driver suspend * * @param dev A pointer to device structure * @return BT_STATUS_SUCCESS or other error no. */ int bt_sdio_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); mmc_pm_flag_t pm_flags = 0; bt_private *priv = NULL; struct sdio_mmc_card *cardp; struct m_dev *m_dev = NULL; ENTER(); pm_flags = sdio_get_host_pm_caps(func); PRINTM(CMD, "BT: %s: suspend: PM flags = 0x%x\n", sdio_func_id(func), pm_flags); if (!(pm_flags & MMC_PM_KEEP_POWER)) { PRINTM(ERROR, "BT: %s: cannot remain alive while host is suspended\n", sdio_func_id(func)); return -ENOSYS; } cardp = sdio_get_drvdata(func); if (!cardp || !cardp->priv) { PRINTM(ERROR, "BT: Card or priv structure is not valid\n"); LEAVE(); return BT_STATUS_SUCCESS; } priv = cardp->priv; if ((mbt_pm_keep_power) && (priv->adapter->hs_state != HS_ACTIVATED)) { /* disable FM event mask */ if ((priv->bt_dev.m_dev[FM_SEQ].dev_type == FM_TYPE) && test_bit(HCI_RUNNING, &(priv->bt_dev.m_dev[FM_SEQ].flags))) fm_set_intr_mask(priv, FM_DISABLE_INTR_MASK); if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) { PRINTM(CMD, "BT: HS not actived, suspend fail!\n"); if (BT_STATUS_SUCCESS != bt_enable_hs(priv)) { PRINTM(CMD, "BT: HS not actived the second time, force to suspend!\n"); } } } m_dev = &(priv->bt_dev.m_dev[BT_SEQ]); PRINTM(CMD, "BT %s: SDIO suspend\n", m_dev->name); mbt_hci_suspend_dev(m_dev); skb_queue_purge(&priv->adapter->tx_queue); priv->adapter->is_suspended = TRUE; LEAVE(); /* We will keep the power when hs enabled successfully */ if ((mbt_pm_keep_power) && (priv->adapter->hs_state == HS_ACTIVATED)) { #ifdef MMC_PM_SKIP_RESUME_PROBE PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER and " "MMC_PM_SKIP_RESUME_PROBE\n"); return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER | MMC_PM_SKIP_RESUME_PROBE); #else PRINTM(CMD, "BT: suspend with MMC_PM_KEEP_POWER\n"); return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); #endif } else { PRINTM(CMD, "BT: suspend without MMC_PM_KEEP_POWER\n"); return BT_STATUS_SUCCESS; } }