aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorChan-yeol Park <chanyeol.park@samsung.com>2014-10-31 01:23:06 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2014-11-01 17:20:21 -0400
commit039fada5cd1963c32ed13d18d0dd467fdf966b66 (patch)
tree8f6c1f136152b3b40816f6bc99369c31daa29111 /net
parent6bc6c49f1e2f3ab1bec05d1c08aad219ab4eb5d0 (diff)
Bluetooth: Fix hci_sync missing wakeup interrupt
__hci_cmd_sync_ev(), __hci_req_sync() could miss wake_up_interrupt from hci_req_sync_complete() because hci_cmd_work() workqueue and its response could be completed before they are ready to get the signal through add_wait_queue(), set_current_state(TASK_INTERRUPTIBLE). Signed-off-by: Chan-yeol Park <chanyeol.park@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_core.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 91995f8ab0a0..41b147c36d11 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1147,13 +1147,15 @@ struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
1147 1147
1148 hdev->req_status = HCI_REQ_PEND; 1148 hdev->req_status = HCI_REQ_PEND;
1149 1149
1150 err = hci_req_run(&req, hci_req_sync_complete);
1151 if (err < 0)
1152 return ERR_PTR(err);
1153
1154 add_wait_queue(&hdev->req_wait_q, &wait); 1150 add_wait_queue(&hdev->req_wait_q, &wait);
1155 set_current_state(TASK_INTERRUPTIBLE); 1151 set_current_state(TASK_INTERRUPTIBLE);
1156 1152
1153 err = hci_req_run(&req, hci_req_sync_complete);
1154 if (err < 0) {
1155 remove_wait_queue(&hdev->req_wait_q, &wait);
1156 return ERR_PTR(err);
1157 }
1158
1157 schedule_timeout(timeout); 1159 schedule_timeout(timeout);
1158 1160
1159 remove_wait_queue(&hdev->req_wait_q, &wait); 1161 remove_wait_queue(&hdev->req_wait_q, &wait);
@@ -1211,10 +1213,15 @@ static int __hci_req_sync(struct hci_dev *hdev,
1211 1213
1212 func(&req, opt); 1214 func(&req, opt);
1213 1215
1216 add_wait_queue(&hdev->req_wait_q, &wait);
1217 set_current_state(TASK_INTERRUPTIBLE);
1218
1214 err = hci_req_run(&req, hci_req_sync_complete); 1219 err = hci_req_run(&req, hci_req_sync_complete);
1215 if (err < 0) { 1220 if (err < 0) {
1216 hdev->req_status = 0; 1221 hdev->req_status = 0;
1217 1222
1223 remove_wait_queue(&hdev->req_wait_q, &wait);
1224
1218 /* ENODATA means the HCI request command queue is empty. 1225 /* ENODATA means the HCI request command queue is empty.
1219 * This can happen when a request with conditionals doesn't 1226 * This can happen when a request with conditionals doesn't
1220 * trigger any commands to be sent. This is normal behavior 1227 * trigger any commands to be sent. This is normal behavior
@@ -1226,9 +1233,6 @@ static int __hci_req_sync(struct hci_dev *hdev,
1226 return err; 1233 return err;
1227 } 1234 }
1228 1235
1229 add_wait_queue(&hdev->req_wait_q, &wait);
1230 set_current_state(TASK_INTERRUPTIBLE);
1231
1232 schedule_timeout(timeout); 1236 schedule_timeout(timeout);
1233 1237
1234 remove_wait_queue(&hdev->req_wait_q, &wait); 1238 remove_wait_queue(&hdev->req_wait_q, &wait);