aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2011-11-08 13:40:15 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-11-09 09:33:39 -0500
commit2e58ef3e11d0775795345a20185b5a7c4bdae194 (patch)
tree3187787dd2693ad0c43fb3e3c7f5ec959c7713e7 /net/bluetooth/mgmt.c
parent744cf19eadcf4de914394e0eb227f94f4318f5e4 (diff)
Bluetooth: Move pending management command list into struct hci_dev
This patch moves the pending management command list (previously global to mgmt.c) into struct hci_dev. This makes it possible to do proper locking when accessing it (through the existing hci_dev locks) and thereby avoid race conditions. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c79
1 files changed, 39 insertions, 40 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 2ca7b4427e3..be198f382ed 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -43,8 +43,6 @@ struct pending_cmd {
43 void *user_data; 43 void *user_data;
44}; 44};
45 45
46static LIST_HEAD(cmd_list);
47
48static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) 46static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
49{ 47{
50 struct sk_buff *skb; 48 struct sk_buff *skb;
@@ -227,7 +225,8 @@ static void mgmt_pending_free(struct pending_cmd *cmd)
227} 225}
228 226
229static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, 227static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
230 u16 index, void *data, u16 len) 228 struct hci_dev *hdev,
229 void *data, u16 len)
231{ 230{
232 struct pending_cmd *cmd; 231 struct pending_cmd *cmd;
233 232
@@ -236,7 +235,7 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
236 return NULL; 235 return NULL;
237 236
238 cmd->opcode = opcode; 237 cmd->opcode = opcode;
239 cmd->index = index; 238 cmd->index = hdev->id;
240 239
241 cmd->param = kmalloc(len, GFP_ATOMIC); 240 cmd->param = kmalloc(len, GFP_ATOMIC);
242 if (!cmd->param) { 241 if (!cmd->param) {
@@ -250,7 +249,7 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
250 cmd->sk = sk; 249 cmd->sk = sk;
251 sock_hold(sk); 250 sock_hold(sk);
252 251
253 list_add(&cmd->list, &cmd_list); 252 list_add(&cmd->list, &hdev->mgmt_pending);
254 253
255 return cmd; 254 return cmd;
256} 255}
@@ -261,7 +260,7 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
261{ 260{
262 struct list_head *p, *n; 261 struct list_head *p, *n;
263 262
264 list_for_each_safe(p, n, &cmd_list) { 263 list_for_each_safe(p, n, &hdev->mgmt_pending) {
265 struct pending_cmd *cmd; 264 struct pending_cmd *cmd;
266 265
267 cmd = list_entry(p, struct pending_cmd, list); 266 cmd = list_entry(p, struct pending_cmd, list);
@@ -276,15 +275,15 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
276 } 275 }
277} 276}
278 277
279static struct pending_cmd *mgmt_pending_find(u16 opcode, int index) 278static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
280{ 279{
281 struct pending_cmd *cmd; 280 struct pending_cmd *cmd;
282 281
283 list_for_each_entry(cmd, &cmd_list, list) { 282 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
284 if (cmd->opcode != opcode) 283 if (cmd->opcode != opcode)
285 continue; 284 continue;
286 285
287 if (index >= 0 && cmd->index != index) 286 if (hdev && cmd->index != hdev->id)
288 continue; 287 continue;
289 288
290 return cmd; 289 return cmd;
@@ -325,12 +324,12 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
325 goto failed; 324 goto failed;
326 } 325 }
327 326
328 if (mgmt_pending_find(MGMT_OP_SET_POWERED, index)) { 327 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
329 err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY); 328 err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY);
330 goto failed; 329 goto failed;
331 } 330 }
332 331
333 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, index, data, len); 332 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
334 if (!cmd) { 333 if (!cmd) {
335 err = -ENOMEM; 334 err = -ENOMEM;
336 goto failed; 335 goto failed;
@@ -376,8 +375,8 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
376 goto failed; 375 goto failed;
377 } 376 }
378 377
379 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) || 378 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
380 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) { 379 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
381 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY); 380 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY);
382 goto failed; 381 goto failed;
383 } 382 }
@@ -388,7 +387,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
388 goto failed; 387 goto failed;
389 } 388 }
390 389
391 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, index, data, len); 390 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
392 if (!cmd) { 391 if (!cmd) {
393 err = -ENOMEM; 392 err = -ENOMEM;
394 goto failed; 393 goto failed;
@@ -442,8 +441,8 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
442 goto failed; 441 goto failed;
443 } 442 }
444 443
445 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) || 444 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
446 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) { 445 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
447 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY); 446 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY);
448 goto failed; 447 goto failed;
449 } 448 }
@@ -453,7 +452,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
453 goto failed; 452 goto failed;
454 } 453 }
455 454
456 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, index, data, len); 455 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
457 if (!cmd) { 456 if (!cmd) {
458 err = -ENOMEM; 457 err = -ENOMEM;
459 goto failed; 458 goto failed;
@@ -1038,7 +1037,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
1038 goto failed; 1037 goto failed;
1039 } 1038 }
1040 1039
1041 if (mgmt_pending_find(MGMT_OP_DISCONNECT, index)) { 1040 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
1042 err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY); 1041 err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY);
1043 goto failed; 1042 goto failed;
1044 } 1043 }
@@ -1052,7 +1051,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
1052 goto failed; 1051 goto failed;
1053 } 1052 }
1054 1053
1055 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, index, data, len); 1054 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
1056 if (!cmd) { 1055 if (!cmd) {
1057 err = -ENOMEM; 1056 err = -ENOMEM;
1058 goto failed; 1057 goto failed;
@@ -1143,7 +1142,7 @@ static int send_pin_code_neg_reply(struct sock *sk, u16 index,
1143 struct pending_cmd *cmd; 1142 struct pending_cmd *cmd;
1144 int err; 1143 int err;
1145 1144
1146 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index, cp, 1145 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
1147 sizeof(*cp)); 1146 sizeof(*cp));
1148 if (!cmd) 1147 if (!cmd)
1149 return -ENOMEM; 1148 return -ENOMEM;
@@ -1204,7 +1203,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
1204 goto failed; 1203 goto failed;
1205 } 1204 }
1206 1205
1207 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len); 1206 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
1208 if (!cmd) { 1207 if (!cmd) {
1209 err = -ENOMEM; 1208 err = -ENOMEM;
1210 goto failed; 1209 goto failed;
@@ -1297,7 +1296,7 @@ static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
1297 struct hci_dev *hdev = conn->hdev; 1296 struct hci_dev *hdev = conn->hdev;
1298 struct pending_cmd *cmd; 1297 struct pending_cmd *cmd;
1299 1298
1300 list_for_each_entry(cmd, &cmd_list, list) { 1299 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
1301 if (cmd->opcode != MGMT_OP_PAIR_DEVICE) 1300 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
1302 continue; 1301 continue;
1303 1302
@@ -1396,7 +1395,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
1396 goto unlock; 1395 goto unlock;
1397 } 1396 }
1398 1397
1399 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, index, data, len); 1398 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
1400 if (!cmd) { 1399 if (!cmd) {
1401 err = -ENOMEM; 1400 err = -ENOMEM;
1402 hci_conn_put(conn); 1401 hci_conn_put(conn);
@@ -1458,7 +1457,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
1458 goto failed; 1457 goto failed;
1459 } 1458 }
1460 1459
1461 cmd = mgmt_pending_add(sk, mgmt_op, index, data, len); 1460 cmd = mgmt_pending_add(sk, mgmt_op, hdev, data, len);
1462 if (!cmd) { 1461 if (!cmd) {
1463 err = -ENOMEM; 1462 err = -ENOMEM;
1464 goto failed; 1463 goto failed;
@@ -1495,7 +1494,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
1495 1494
1496 hci_dev_lock_bh(hdev); 1495 hci_dev_lock_bh(hdev);
1497 1496
1498 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len); 1497 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
1499 if (!cmd) { 1498 if (!cmd) {
1500 err = -ENOMEM; 1499 err = -ENOMEM;
1501 goto failed; 1500 goto failed;
@@ -1541,12 +1540,12 @@ static int read_local_oob_data(struct sock *sk, u16 index)
1541 goto unlock; 1540 goto unlock;
1542 } 1541 }
1543 1542
1544 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) { 1543 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
1545 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY); 1544 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY);
1546 goto unlock; 1545 goto unlock;
1547 } 1546 }
1548 1547
1549 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0); 1548 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
1550 if (!cmd) { 1549 if (!cmd) {
1551 err = -ENOMEM; 1550 err = -ENOMEM;
1552 goto unlock; 1551 goto unlock;
@@ -1650,7 +1649,7 @@ static int start_discovery(struct sock *sk, u16 index)
1650 goto failed; 1649 goto failed;
1651 } 1650 }
1652 1651
1653 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0); 1652 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
1654 if (!cmd) { 1653 if (!cmd) {
1655 err = -ENOMEM; 1654 err = -ENOMEM;
1656 goto failed; 1655 goto failed;
@@ -1681,7 +1680,7 @@ static int stop_discovery(struct sock *sk, u16 index)
1681 1680
1682 hci_dev_lock_bh(hdev); 1681 hci_dev_lock_bh(hdev);
1683 1682
1684 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index, NULL, 0); 1683 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
1685 if (!cmd) { 1684 if (!cmd) {
1686 err = -ENOMEM; 1685 err = -ENOMEM;
1687 goto failed; 1686 goto failed;
@@ -2147,7 +2146,7 @@ int mgmt_disconnect_failed(struct hci_dev *hdev)
2147 struct pending_cmd *cmd; 2146 struct pending_cmd *cmd;
2148 int err; 2147 int err;
2149 2148
2150 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev->id); 2149 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
2151 if (!cmd) 2150 if (!cmd)
2152 return -ENOENT; 2151 return -ENOENT;
2153 2152
@@ -2188,7 +2187,7 @@ int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2188 struct mgmt_rp_pin_code_reply rp; 2187 struct mgmt_rp_pin_code_reply rp;
2189 int err; 2188 int err;
2190 2189
2191 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev->id); 2190 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
2192 if (!cmd) 2191 if (!cmd)
2193 return -ENOENT; 2192 return -ENOENT;
2194 2193
@@ -2210,7 +2209,7 @@ int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2210 struct mgmt_rp_pin_code_reply rp; 2209 struct mgmt_rp_pin_code_reply rp;
2211 int err; 2210 int err;
2212 2211
2213 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev->id); 2212 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
2214 if (!cmd) 2213 if (!cmd)
2215 return -ENOENT; 2214 return -ENOENT;
2216 2215
@@ -2247,7 +2246,7 @@ static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2247 struct mgmt_rp_user_confirm_reply rp; 2246 struct mgmt_rp_user_confirm_reply rp;
2248 int err; 2247 int err;
2249 2248
2250 cmd = mgmt_pending_find(opcode, hdev->id); 2249 cmd = mgmt_pending_find(opcode, hdev);
2251 if (!cmd) 2250 if (!cmd)
2252 return -ENOENT; 2251 return -ENOENT;
2253 2252
@@ -2293,7 +2292,7 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
2293 memset(&ev, 0, sizeof(ev)); 2292 memset(&ev, 0, sizeof(ev));
2294 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); 2293 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2295 2294
2296 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev->id); 2295 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
2297 if (!cmd) 2296 if (!cmd)
2298 goto send_event; 2297 goto send_event;
2299 2298
@@ -2330,7 +2329,7 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
2330 2329
2331 BT_DBG("%s status %u", hdev->name, status); 2330 BT_DBG("%s status %u", hdev->name, status);
2332 2331
2333 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev->id); 2332 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
2334 if (!cmd) 2333 if (!cmd)
2335 return -ENOENT; 2334 return -ENOENT;
2336 2335
@@ -2390,7 +2389,7 @@ int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status)
2390 struct pending_cmd *cmd; 2389 struct pending_cmd *cmd;
2391 int err; 2390 int err;
2392 2391
2393 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev->id); 2392 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
2394 if (!cmd) 2393 if (!cmd)
2395 return -ENOENT; 2394 return -ENOENT;
2396 2395
@@ -2405,9 +2404,9 @@ int mgmt_discovering(struct hci_dev *hdev, u8 discovering)
2405 struct pending_cmd *cmd; 2404 struct pending_cmd *cmd;
2406 2405
2407 if (discovering) 2406 if (discovering)
2408 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev->id); 2407 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
2409 else 2408 else
2410 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev->id); 2409 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
2411 2410
2412 if (cmd != NULL) { 2411 if (cmd != NULL) {
2413 cmd_complete(cmd->sk, hdev->id, cmd->opcode, NULL, 0); 2412 cmd_complete(cmd->sk, hdev->id, cmd->opcode, NULL, 0);
@@ -2423,7 +2422,7 @@ int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr)
2423 struct pending_cmd *cmd; 2422 struct pending_cmd *cmd;
2424 struct mgmt_ev_device_blocked ev; 2423 struct mgmt_ev_device_blocked ev;
2425 2424
2426 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev->id); 2425 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
2427 2426
2428 bacpy(&ev.bdaddr, bdaddr); 2427 bacpy(&ev.bdaddr, bdaddr);
2429 2428
@@ -2436,7 +2435,7 @@ int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr)
2436 struct pending_cmd *cmd; 2435 struct pending_cmd *cmd;
2437 struct mgmt_ev_device_unblocked ev; 2436 struct mgmt_ev_device_unblocked ev;
2438 2437
2439 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev->id); 2438 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
2440 2439
2441 bacpy(&ev.bdaddr, bdaddr); 2440 bacpy(&ev.bdaddr, bdaddr);
2442 2441