All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RESEND 1/2] Bluetooth: btmrvl: configure default host sleep parameters
@ 2012-04-24 23:31 Bing Zhao
  2012-04-24 23:31 ` [PATCH RESEND 2/2] Bluetooth: btmrvl: add support for SDIO suspend/resume callbacks Bing Zhao
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Bing Zhao @ 2012-04-24 23:31 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: linux-wireless, Marcel Holtmann, Gustavo Padovan, Johan Hedberg,
	Bing Zhao, Amitkumar Karwar

From: Amitkumar Karwar <akarwar@marvell.com>

Currently debugfs commands "hscfgcmd" and "gpiogap" are provided
for host sleep configuration. But if user doesn't configure host
sleep parameters using these commands, host sleep activation is
failed during suspend (support for suspend and resume handlers is
added in next patch).

Default host sleep configuration is done during driver initialisation
in this patch.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
Last 2 patches were sent to Gustavo's old e-mail address.
Resending...

 drivers/bluetooth/btmrvl_drv.h  |    1 +
 drivers/bluetooth/btmrvl_main.c |   53 ++++++++++++++++++++++----------------
 drivers/bluetooth/btmrvl_sdio.c |    3 ++
 3 files changed, 35 insertions(+), 22 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 90bda50..2c79e76 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -139,6 +139,7 @@ void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
 int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
 
 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);
 
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index d1209ad..a880537 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -200,6 +200,36 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
 }
 EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
 
+int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)
+{
+	struct sk_buff *skb;
+	struct btmrvl_cmd *cmd;
+
+	skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
+	if (!skb) {
+		BT_ERR("No free skb");
+		return -ENOMEM;
+	}
+
+	cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
+	cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF,
+						   BT_CMD_HOST_SLEEP_CONFIG));
+	cmd->length = 2;
+	cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
+	cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff);
+
+	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+
+	skb->dev = (void *) priv->btmrvl_dev.hcidev;
+	skb_queue_head(&priv->adapter->tx_queue, skb);
+
+	BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0],
+	       cmd->data[1]);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd);
+
 int btmrvl_enable_ps(struct btmrvl_private *priv)
 {
 	struct sk_buff *skb;
@@ -271,32 +301,11 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv)
 
 int btmrvl_prepare_command(struct btmrvl_private *priv)
 {
-	struct sk_buff *skb = NULL;
-	struct btmrvl_cmd *cmd;
 	int ret = 0;
 
 	if (priv->btmrvl_dev.hscfgcmd) {
 		priv->btmrvl_dev.hscfgcmd = 0;
-
-		skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
-		if (skb == NULL) {
-			BT_ERR("No free skb");
-			return -ENOMEM;
-		}
-
-		cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
-		cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG));
-		cmd->length = 2;
-		cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
-		cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff);
-
-		bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
-
-		skb->dev = (void *) priv->btmrvl_dev.hcidev;
-		skb_queue_head(&priv->adapter->tx_queue, skb);
-
-		BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x",
-						cmd->data[0], cmd->data[1]);
+		btmrvl_send_hscfg_cmd(priv);
 	}
 
 	if (priv->btmrvl_dev.pscmd) {
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 27b74b0..f93a7a2 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -1013,6 +1013,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
 	priv->btmrvl_dev.psmode = 1;
 	btmrvl_enable_ps(priv);
 
+	priv->btmrvl_dev.gpio_gap = 0xffff;
+	btmrvl_send_hscfg_cmd(priv);
+
 	return 0;
 
 disable_host_int:
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH RESEND 2/2] Bluetooth: btmrvl: add support for SDIO suspend/resume callbacks
  2012-04-24 23:31 [PATCH RESEND 1/2] Bluetooth: btmrvl: configure default host sleep parameters Bing Zhao
@ 2012-04-24 23:31 ` Bing Zhao
  2012-04-25  6:39   ` Marcel Holtmann
  2012-04-25  6:41 ` [PATCH RESEND 1/2] Bluetooth: btmrvl: configure default host sleep parameters Marcel Holtmann
  2012-04-25 18:50 ` Gustavo Padovan
  2 siblings, 1 reply; 6+ messages in thread
From: Bing Zhao @ 2012-04-24 23:31 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: linux-wireless, Marcel Holtmann, Gustavo Padovan, Johan Hedberg,
	Bing Zhao, Amitkumar Karwar

From: Amitkumar Karwar <akarwar@marvell.com>

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>
---
Last 2 patches were sent to Gustavo's old e-mail address.
Resending...

 drivers/bluetooth/btmrvl_drv.h  |    2 +
 drivers/bluetooth/btmrvl_main.c |    3 +-
 drivers/bluetooth/btmrvl_sdio.c |  100 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 1 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 2c79e76..94f2d65 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -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 {
@@ -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);
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index a880537..681ca9d 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -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;
@@ -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)
 {
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index f93a7a2..35a3e7c 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -1051,11 +1051,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\n", sdio_func_id(func),
+		       pm_flags);
+		if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+			BT_ERR("%s: cannot remain alive while host is "
+			       "suspended\n", sdio_func_id(func));
+			return -ENOSYS;
+		}
+		card = sdio_get_drvdata(func);
+		if (!card || !card->priv) {
+			BT_ERR("Card or priv structure is not valid\n");
+			return 0;
+		}
+	} else {
+		BT_ERR("sdio_func is not specified\n");
+		return 0;
+	}
+
+	priv = card->priv;
+
+	if (priv->adapter->hs_state != HS_ACTIVATED) {
+		if (btmrvl_enable_hs(priv)) {
+			BT_ERR("HS not actived, suspend fail!\n");
+			return -EBUSY;
+		}
+	}
+	hcidev = priv->btmrvl_dev.hcidev;
+	BT_DBG("%s: SDIO suspend\n", 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\n");
+		return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+	} else {
+		BT_DBG("suspend without MMC_PM_KEEP_POWER\n");
+		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\n", sdio_func_id(func),
+		       pm_flags);
+		card = sdio_get_drvdata(func);
+		if (!card || !card->priv) {
+			BT_ERR("Card or priv structure is not valid\n");
+			return 0;
+		}
+	} else {
+		BT_ERR("sdio_func is not specified\n");
+		return 0;
+	}
+	priv = card->priv;
+
+	if (!priv->adapter->is_suspended) {
+		BT_DBG("device already resumed\n");
+		return 0;
+	}
+
+	priv->adapter->is_suspended = false;
+	hcidev = priv->btmrvl_dev.hcidev;
+	BT_DBG("%s: SDIO resume\n", hcidev->name);
+	hci_resume_dev(hcidev);
+	priv->hw_wakeup_firmware(priv);
+	priv->adapter->hs_state = HS_DEACTIVATED;
+	BT_DBG("%s: HS DEACTIVATED in resume!\n", 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)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH RESEND 2/2] Bluetooth: btmrvl: add support for SDIO suspend/resume callbacks
  2012-04-24 23:31 ` [PATCH RESEND 2/2] Bluetooth: btmrvl: add support for SDIO suspend/resume callbacks Bing Zhao
@ 2012-04-25  6:39   ` Marcel Holtmann
  0 siblings, 0 replies; 6+ messages in thread
From: Marcel Holtmann @ 2012-04-25  6:39 UTC (permalink / raw)
  To: Bing Zhao
  Cc: linux-bluetooth, linux-wireless, Gustavo Padovan, Johan Hedberg,
	Amitkumar Karwar

Hi Bing,

> 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>
> ---
> Last 2 patches were sent to Gustavo's old e-mail address.
> Resending...
> 
>  drivers/bluetooth/btmrvl_drv.h  |    2 +
>  drivers/bluetooth/btmrvl_main.c |    3 +-
>  drivers/bluetooth/btmrvl_sdio.c |  100 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 104 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
> index 2c79e76..94f2d65 100644
> --- a/drivers/bluetooth/btmrvl_drv.h
> +++ b/drivers/bluetooth/btmrvl_drv.h
> @@ -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 {
> @@ -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);
> diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
> index a880537..681ca9d 100644
> --- a/drivers/bluetooth/btmrvl_main.c
> +++ b/drivers/bluetooth/btmrvl_main.c
> @@ -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;
> @@ -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)
>  {
> diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
> index f93a7a2..35a3e7c 100644
> --- a/drivers/bluetooth/btmrvl_sdio.c
> +++ b/drivers/bluetooth/btmrvl_sdio.c
> @@ -1051,11 +1051,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\n", sdio_func_id(func),
> +		       pm_flags);
> +		if (!(pm_flags & MMC_PM_KEEP_POWER)) {
> +			BT_ERR("%s: cannot remain alive while host is "
> +			       "suspended\n", sdio_func_id(func));
> +			return -ENOSYS;
> +		}
> +		card = sdio_get_drvdata(func);
> +		if (!card || !card->priv) {
> +			BT_ERR("Card or priv structure is not valid\n");

you do not need the \n at the end of BT_DBG, BT_ERR etc. Please fix
this.

Regards

Marcel



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH RESEND 1/2] Bluetooth: btmrvl: configure default host sleep parameters
  2012-04-24 23:31 [PATCH RESEND 1/2] Bluetooth: btmrvl: configure default host sleep parameters Bing Zhao
  2012-04-24 23:31 ` [PATCH RESEND 2/2] Bluetooth: btmrvl: add support for SDIO suspend/resume callbacks Bing Zhao
@ 2012-04-25  6:41 ` Marcel Holtmann
  2012-04-25 18:50 ` Gustavo Padovan
  2 siblings, 0 replies; 6+ messages in thread
From: Marcel Holtmann @ 2012-04-25  6:41 UTC (permalink / raw)
  To: Bing Zhao
  Cc: linux-bluetooth, linux-wireless, Gustavo Padovan, Johan Hedberg,
	Amitkumar Karwar

Hi Bing,

> Currently debugfs commands "hscfgcmd" and "gpiogap" are provided
> for host sleep configuration. But if user doesn't configure host
> sleep parameters using these commands, host sleep activation is
> failed during suspend (support for suspend and resume handlers is
> added in next patch).
> 
> Default host sleep configuration is done during driver initialisation
> in this patch.
> 
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> Signed-off-by: Bing Zhao <bzhao@marvell.com>

Acked-by: Marcel Holtmann <marcel@holtmann.org>

> ---
> Last 2 patches were sent to Gustavo's old e-mail address.
> Resending...
> 
>  drivers/bluetooth/btmrvl_drv.h  |    1 +
>  drivers/bluetooth/btmrvl_main.c |   53 ++++++++++++++++++++++----------------
>  drivers/bluetooth/btmrvl_sdio.c |    3 ++
>  3 files changed, 35 insertions(+), 22 deletions(-)

Regards

Marcel



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH RESEND 1/2] Bluetooth: btmrvl: configure default host sleep parameters
  2012-04-24 23:31 [PATCH RESEND 1/2] Bluetooth: btmrvl: configure default host sleep parameters Bing Zhao
  2012-04-24 23:31 ` [PATCH RESEND 2/2] Bluetooth: btmrvl: add support for SDIO suspend/resume callbacks Bing Zhao
  2012-04-25  6:41 ` [PATCH RESEND 1/2] Bluetooth: btmrvl: configure default host sleep parameters Marcel Holtmann
@ 2012-04-25 18:50 ` Gustavo Padovan
  2 siblings, 0 replies; 6+ messages in thread
From: Gustavo Padovan @ 2012-04-25 18:50 UTC (permalink / raw)
  To: Bing Zhao
  Cc: linux-bluetooth, linux-wireless, Marcel Holtmann, Johan Hedberg,
	Amitkumar Karwar

Hi Bing,

* Bing Zhao <bzhao@marvell.com> [2012-04-24 16:31:40 -0700]:

> From: Amitkumar Karwar <akarwar@marvell.com>
> 
> Currently debugfs commands "hscfgcmd" and "gpiogap" are provided
> for host sleep configuration. But if user doesn't configure host
> sleep parameters using these commands, host sleep activation is
> failed during suspend (support for suspend and resume handlers is
> added in next patch).
> 
> Default host sleep configuration is done during driver initialisation
> in this patch.
> 
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> Signed-off-by: Bing Zhao <bzhao@marvell.com>
> ---
> Last 2 patches were sent to Gustavo's old e-mail address.
> Resending...
> 
>  drivers/bluetooth/btmrvl_drv.h  |    1 +
>  drivers/bluetooth/btmrvl_main.c |   53 ++++++++++++++++++++++----------------
>  drivers/bluetooth/btmrvl_sdio.c |    3 ++
>  3 files changed, 35 insertions(+), 22 deletions(-)

Patch has been applied to bluetooth-next. Thanks.

	Gustavo

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH RESEND 2/2] Bluetooth: btmrvl: add support for SDIO suspend/resume callbacks
  2012-04-24 23:18 Bing Zhao
@ 2012-04-24 23:18 ` Bing Zhao
  0 siblings, 0 replies; 6+ messages in thread
From: Bing Zhao @ 2012-04-24 23:18 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: linux-wireless, Marcel Holtmann, Gustavo Padovan, Johan Hedberg,
	Bing Zhao, Amitkumar Karwar

From: Amitkumar Karwar <akarwar@marvell.com>

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>
---
 drivers/bluetooth/btmrvl_drv.h  |    2 +
 drivers/bluetooth/btmrvl_main.c |    3 +-
 drivers/bluetooth/btmrvl_sdio.c |  100 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 1 deletions(-)

diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 2c79e76..94f2d65 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -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 {
@@ -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);
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index a880537..681ca9d 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -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;
@@ -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)
 {
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index f93a7a2..35a3e7c 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -1051,11 +1051,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\n", sdio_func_id(func),
+		       pm_flags);
+		if (!(pm_flags & MMC_PM_KEEP_POWER)) {
+			BT_ERR("%s: cannot remain alive while host is "
+			       "suspended\n", sdio_func_id(func));
+			return -ENOSYS;
+		}
+		card = sdio_get_drvdata(func);
+		if (!card || !card->priv) {
+			BT_ERR("Card or priv structure is not valid\n");
+			return 0;
+		}
+	} else {
+		BT_ERR("sdio_func is not specified\n");
+		return 0;
+	}
+
+	priv = card->priv;
+
+	if (priv->adapter->hs_state != HS_ACTIVATED) {
+		if (btmrvl_enable_hs(priv)) {
+			BT_ERR("HS not actived, suspend fail!\n");
+			return -EBUSY;
+		}
+	}
+	hcidev = priv->btmrvl_dev.hcidev;
+	BT_DBG("%s: SDIO suspend\n", 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\n");
+		return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+	} else {
+		BT_DBG("suspend without MMC_PM_KEEP_POWER\n");
+		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\n", sdio_func_id(func),
+		       pm_flags);
+		card = sdio_get_drvdata(func);
+		if (!card || !card->priv) {
+			BT_ERR("Card or priv structure is not valid\n");
+			return 0;
+		}
+	} else {
+		BT_ERR("sdio_func is not specified\n");
+		return 0;
+	}
+	priv = card->priv;
+
+	if (!priv->adapter->is_suspended) {
+		BT_DBG("device already resumed\n");
+		return 0;
+	}
+
+	priv->adapter->is_suspended = false;
+	hcidev = priv->btmrvl_dev.hcidev;
+	BT_DBG("%s: SDIO resume\n", hcidev->name);
+	hci_resume_dev(hcidev);
+	priv->hw_wakeup_firmware(priv);
+	priv->adapter->hs_state = HS_DEACTIVATED;
+	BT_DBG("%s: HS DEACTIVATED in resume!\n", 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)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-04-25 18:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-24 23:31 [PATCH RESEND 1/2] Bluetooth: btmrvl: configure default host sleep parameters Bing Zhao
2012-04-24 23:31 ` [PATCH RESEND 2/2] Bluetooth: btmrvl: add support for SDIO suspend/resume callbacks Bing Zhao
2012-04-25  6:39   ` Marcel Holtmann
2012-04-25  6:41 ` [PATCH RESEND 1/2] Bluetooth: btmrvl: configure default host sleep parameters Marcel Holtmann
2012-04-25 18:50 ` Gustavo Padovan
  -- strict thread matches above, loose matches on Subject: below --
2012-04-24 23:18 Bing Zhao
2012-04-24 23:18 ` [PATCH RESEND 2/2] Bluetooth: btmrvl: add support for SDIO suspend/resume callbacks Bing Zhao

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.