aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-02-28 02:33:44 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-02-28 02:41:07 -0500
commita3172b7eb4a2719711187cfca12097d2326e85a7 (patch)
treefc5191af513e40eac0ba1af3728fe7a0afe120be /net/bluetooth/mgmt.c
parentc9910d0fb4fc2ede468b26d45a1d50c309897770 (diff)
Bluetooth: Add timer to force power off
If some of the cleanup commands caused by mgmt_set_powered(off) never complete we should still force the adapter to be powered down. This is rather easy to do since hdev->power_off is already a delayed work struct. This patch schedules this delayed work if at least one HCI command was sent by the cleanup procedure. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 73b6ff817796..e7c87231b9ea 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1031,8 +1031,10 @@ static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1031{ 1031{
1032 BT_DBG("%s status 0x%02x", hdev->name, status); 1032 BT_DBG("%s status 0x%02x", hdev->name, status);
1033 1033
1034 if (hci_conn_count(hdev) == 0) 1034 if (hci_conn_count(hdev) == 0) {
1035 cancel_delayed_work(&hdev->power_off);
1035 queue_work(hdev->req_workqueue, &hdev->power_off.work); 1036 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1037 }
1036} 1038}
1037 1039
1038static int clean_up_hci_state(struct hci_dev *hdev) 1040static int clean_up_hci_state(struct hci_dev *hdev)
@@ -1139,9 +1141,13 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
1139 } else { 1141 } else {
1140 /* Disconnect connections, stop scans, etc */ 1142 /* Disconnect connections, stop scans, etc */
1141 err = clean_up_hci_state(hdev); 1143 err = clean_up_hci_state(hdev);
1144 if (!err)
1145 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1146 HCI_POWER_OFF_TIMEOUT);
1142 1147
1143 /* ENODATA means there were no HCI commands queued */ 1148 /* ENODATA means there were no HCI commands queued */
1144 if (err == -ENODATA) { 1149 if (err == -ENODATA) {
1150 cancel_delayed_work(&hdev->power_off);
1145 queue_work(hdev->req_workqueue, &hdev->power_off.work); 1151 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1146 err = 0; 1152 err = 0;
1147 } 1153 }
@@ -5147,8 +5153,10 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
5147 /* The connection is still in hci_conn_hash so test for 1 5153 /* The connection is still in hci_conn_hash so test for 1
5148 * instead of 0 to know if this is the last one. 5154 * instead of 0 to know if this is the last one.
5149 */ 5155 */
5150 if (!cp->val && hci_conn_count(hdev) == 1) 5156 if (!cp->val && hci_conn_count(hdev) == 1) {
5157 cancel_delayed_work(&hdev->power_off);
5151 queue_work(hdev->req_workqueue, &hdev->power_off.work); 5158 queue_work(hdev->req_workqueue, &hdev->power_off.work);
5159 }
5152 } 5160 }
5153 5161
5154 if (!mgmt_connected) 5162 if (!mgmt_connected)
@@ -5217,8 +5225,10 @@ void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5217 /* The connection is still in hci_conn_hash so test for 1 5225 /* The connection is still in hci_conn_hash so test for 1
5218 * instead of 0 to know if this is the last one. 5226 * instead of 0 to know if this is the last one.
5219 */ 5227 */
5220 if (!cp->val && hci_conn_count(hdev) == 1) 5228 if (!cp->val && hci_conn_count(hdev) == 1) {
5229 cancel_delayed_work(&hdev->power_off);
5221 queue_work(hdev->req_workqueue, &hdev->power_off.work); 5230 queue_work(hdev->req_workqueue, &hdev->power_off.work);
5231 }
5222 } 5232 }
5223 5233
5224 bacpy(&ev.addr.bdaddr, bdaddr); 5234 bacpy(&ev.addr.bdaddr, bdaddr);