Skip to content

Commit

Permalink
Bluetooth: btmrvl: add support for SDIO suspend/resume callbacks
Browse files Browse the repository at this point in the history
Host sleep is activated using already configured host sleep
parameters in suspend handler and it is cancelled in resume
handler.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo@padovan.org>
  • Loading branch information
Amitkumar Karwar authored and Gustavo Padovan committed May 9, 2012
1 parent 6ff9b5e commit ba54a16
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 1 deletion.
2 changes: 2 additions & 0 deletions drivers/bluetooth/btmrvl_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct btmrvl_adapter {
u8 wakeup_tries;
wait_queue_head_t cmd_wait_q;
u8 cmd_complete;
bool is_suspended;
};

struct btmrvl_private {
Expand Down Expand Up @@ -142,6 +143,7 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd);
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);
int btmrvl_enable_ps(struct btmrvl_private *priv);
int btmrvl_prepare_command(struct btmrvl_private *priv);
int btmrvl_enable_hs(struct btmrvl_private *priv);

#ifdef CONFIG_DEBUG_FS
void btmrvl_debugfs_init(struct hci_dev *hdev);
Expand Down
3 changes: 2 additions & 1 deletion drivers/bluetooth/btmrvl_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ int btmrvl_enable_ps(struct btmrvl_private *priv)
}
EXPORT_SYMBOL_GPL(btmrvl_enable_ps);

static int btmrvl_enable_hs(struct btmrvl_private *priv)
int btmrvl_enable_hs(struct btmrvl_private *priv)
{
struct sk_buff *skb;
struct btmrvl_cmd *cmd;
Expand Down Expand Up @@ -298,6 +298,7 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv)

return ret;
}
EXPORT_SYMBOL_GPL(btmrvl_enable_hs);

int btmrvl_prepare_command(struct btmrvl_private *priv)
{
Expand Down
100 changes: 100 additions & 0 deletions drivers/bluetooth/btmrvl_sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1046,11 +1046,111 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
}
}

static int btmrvl_sdio_suspend(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);
struct btmrvl_sdio_card *card;
struct btmrvl_private *priv;
mmc_pm_flag_t pm_flags;
struct hci_dev *hcidev;

if (func) {
pm_flags = sdio_get_host_pm_caps(func);
BT_DBG("%s: suspend: PM flags = 0x%x", sdio_func_id(func),
pm_flags);
if (!(pm_flags & MMC_PM_KEEP_POWER)) {
BT_ERR("%s: cannot remain alive while suspended",
sdio_func_id(func));
return -ENOSYS;
}
card = sdio_get_drvdata(func);
if (!card || !card->priv) {
BT_ERR("card or priv structure is not valid");
return 0;
}
} else {
BT_ERR("sdio_func is not specified");
return 0;
}

priv = card->priv;

if (priv->adapter->hs_state != HS_ACTIVATED) {
if (btmrvl_enable_hs(priv)) {
BT_ERR("HS not actived, suspend failed!");
return -EBUSY;
}
}
hcidev = priv->btmrvl_dev.hcidev;
BT_DBG("%s: SDIO suspend", hcidev->name);
hci_suspend_dev(hcidev);
skb_queue_purge(&priv->adapter->tx_queue);

priv->adapter->is_suspended = true;

/* We will keep the power when hs enabled successfully */
if (priv->adapter->hs_state == HS_ACTIVATED) {
BT_DBG("suspend with MMC_PM_KEEP_POWER");
return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
} else {
BT_DBG("suspend without MMC_PM_KEEP_POWER");
return 0;
}
}

static int btmrvl_sdio_resume(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);
struct btmrvl_sdio_card *card;
struct btmrvl_private *priv;
mmc_pm_flag_t pm_flags;
struct hci_dev *hcidev;

if (func) {
pm_flags = sdio_get_host_pm_caps(func);
BT_DBG("%s: resume: PM flags = 0x%x", sdio_func_id(func),
pm_flags);
card = sdio_get_drvdata(func);
if (!card || !card->priv) {
BT_ERR("card or priv structure is not valid");
return 0;
}
} else {
BT_ERR("sdio_func is not specified");
return 0;
}
priv = card->priv;

if (!priv->adapter->is_suspended) {
BT_DBG("device already resumed");
return 0;
}

priv->adapter->is_suspended = false;
hcidev = priv->btmrvl_dev.hcidev;
BT_DBG("%s: SDIO resume", hcidev->name);
hci_resume_dev(hcidev);
priv->hw_wakeup_firmware(priv);
priv->adapter->hs_state = HS_DEACTIVATED;
BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name);

return 0;
}

static const struct dev_pm_ops btmrvl_sdio_pm_ops = {
.suspend = btmrvl_sdio_suspend,
.resume = btmrvl_sdio_resume,
};

static struct sdio_driver bt_mrvl_sdio = {
.name = "btmrvl_sdio",
.id_table = btmrvl_sdio_ids,
.probe = btmrvl_sdio_probe,
.remove = btmrvl_sdio_remove,
.drv = {
.owner = THIS_MODULE,
.pm = &btmrvl_sdio_pm_ops,
}
};

static int __init btmrvl_sdio_init_module(void)
Expand Down

0 comments on commit ba54a16

Please sign in to comment.