aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChin-Ran Lo <crlo@marvell.com>2014-07-15 00:05:37 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-07-15 02:01:19 -0400
commit5bf8a7481d21a669dd9dd874c00f7815a878111a (patch)
tree7ed1828deea12066a24ed7516bf9509351c5a182
parent4d042654afb342386cb5c33e29843b76d598ab61 (diff)
Bluetooth: btmrvl: avoid sending data to firmware after hs_activated
We should suspend hci device and purge remaining data in tx queue before enabling host sleep in firmware. If any data is sent to firmware after host sleep is activated, firmware may end up sending a TX_DONE interrupt to driver. If this interrupt gets delivered to host while the SDIO host controller is suspending, it may crash the system. Conversely, in resume handler, we should resume hci device after host sleep is de-activated. Signed-off-by: Chin-Ran Lo <crlo@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index efff06438b02..3e683b153259 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -1169,6 +1169,10 @@ static int btmrvl_sdio_suspend(struct device *dev)
1169 } 1169 }
1170 1170
1171 priv = card->priv; 1171 priv = card->priv;
1172 hcidev = priv->btmrvl_dev.hcidev;
1173 BT_DBG("%s: SDIO suspend", hcidev->name);
1174 hci_suspend_dev(hcidev);
1175 skb_queue_purge(&priv->adapter->tx_queue);
1172 1176
1173 if (priv->adapter->hs_state != HS_ACTIVATED) { 1177 if (priv->adapter->hs_state != HS_ACTIVATED) {
1174 if (btmrvl_enable_hs(priv)) { 1178 if (btmrvl_enable_hs(priv)) {
@@ -1176,10 +1180,6 @@ static int btmrvl_sdio_suspend(struct device *dev)
1176 return -EBUSY; 1180 return -EBUSY;
1177 } 1181 }
1178 } 1182 }
1179 hcidev = priv->btmrvl_dev.hcidev;
1180 BT_DBG("%s: SDIO suspend", hcidev->name);
1181 hci_suspend_dev(hcidev);
1182 skb_queue_purge(&priv->adapter->tx_queue);
1183 1183
1184 priv->adapter->is_suspended = true; 1184 priv->adapter->is_suspended = true;
1185 1185
@@ -1221,13 +1221,13 @@ static int btmrvl_sdio_resume(struct device *dev)
1221 return 0; 1221 return 0;
1222 } 1222 }
1223 1223
1224 priv->adapter->is_suspended = false;
1225 hcidev = priv->btmrvl_dev.hcidev;
1226 BT_DBG("%s: SDIO resume", hcidev->name);
1227 hci_resume_dev(hcidev);
1228 priv->hw_wakeup_firmware(priv); 1224 priv->hw_wakeup_firmware(priv);
1229 priv->adapter->hs_state = HS_DEACTIVATED; 1225 priv->adapter->hs_state = HS_DEACTIVATED;
1226 hcidev = priv->btmrvl_dev.hcidev;
1230 BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name); 1227 BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name);
1228 priv->adapter->is_suspended = false;
1229 BT_DBG("%s: SDIO resume", hcidev->name);
1230 hci_resume_dev(hcidev);
1231 1231
1232 return 0; 1232 return 0;
1233} 1233}