diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2011-11-08 13:40:16 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-11-09 09:33:46 -0500 |
commit | 56e5cb86eb377970825486a5861f5926d65e64c1 (patch) | |
tree | 87e57ea9c98f2663a359717b658c05d0ee2fecac /net/bluetooth | |
parent | 2e58ef3e11d0775795345a20185b5a7c4bdae194 (diff) |
Bluetooth: Add missing hci_dev locking when calling mgmt functions
Now that the pending commands are within struct hci_dev we can properly
control access to them throught the hci_dev locking mechanism.
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')
-rw-r--r-- | net/bluetooth/hci_core.c | 12 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 45 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 13 |
3 files changed, 57 insertions, 13 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index e5cf01396773..f87bf242539e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -549,8 +549,11 @@ int hci_dev_open(__u16 dev) | |||
549 | hci_dev_hold(hdev); | 549 | hci_dev_hold(hdev); |
550 | set_bit(HCI_UP, &hdev->flags); | 550 | set_bit(HCI_UP, &hdev->flags); |
551 | hci_notify(hdev, HCI_DEV_UP); | 551 | hci_notify(hdev, HCI_DEV_UP); |
552 | if (!test_bit(HCI_SETUP, &hdev->flags)) | 552 | if (!test_bit(HCI_SETUP, &hdev->flags)) { |
553 | hci_dev_lock_bh(hdev); | ||
553 | mgmt_powered(hdev, 1); | 554 | mgmt_powered(hdev, 1); |
555 | hci_dev_unlock_bh(hdev); | ||
556 | } | ||
554 | } else { | 557 | } else { |
555 | /* Init failed, cleanup */ | 558 | /* Init failed, cleanup */ |
556 | tasklet_kill(&hdev->rx_task); | 559 | tasklet_kill(&hdev->rx_task); |
@@ -642,7 +645,9 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
642 | * and no tasks are scheduled. */ | 645 | * and no tasks are scheduled. */ |
643 | hdev->close(hdev); | 646 | hdev->close(hdev); |
644 | 647 | ||
648 | hci_dev_lock_bh(hdev); | ||
645 | mgmt_powered(hdev, 0); | 649 | mgmt_powered(hdev, 0); |
650 | hci_dev_unlock_bh(hdev); | ||
646 | 651 | ||
647 | /* Clear flags */ | 652 | /* Clear flags */ |
648 | hdev->flags = 0; | 653 | hdev->flags = 0; |
@@ -1561,8 +1566,11 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
1561 | kfree_skb(hdev->reassembly[i]); | 1566 | kfree_skb(hdev->reassembly[i]); |
1562 | 1567 | ||
1563 | if (!test_bit(HCI_INIT, &hdev->flags) && | 1568 | if (!test_bit(HCI_INIT, &hdev->flags) && |
1564 | !test_bit(HCI_SETUP, &hdev->flags)) | 1569 | !test_bit(HCI_SETUP, &hdev->flags)) { |
1570 | hci_dev_lock_bh(hdev); | ||
1565 | mgmt_index_removed(hdev); | 1571 | mgmt_index_removed(hdev); |
1572 | hci_dev_unlock_bh(hdev); | ||
1573 | } | ||
1566 | 1574 | ||
1567 | /* mgmt_index_removed should take care of emptying the | 1575 | /* mgmt_index_removed should take care of emptying the |
1568 | * pending list */ | 1576 | * pending list */ |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8303f8fa1821..a89cf1f24e47 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -60,7 +60,9 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) | |||
60 | 60 | ||
61 | clear_bit(HCI_INQUIRY, &hdev->flags); | 61 | clear_bit(HCI_INQUIRY, &hdev->flags); |
62 | 62 | ||
63 | hci_dev_lock(hdev); | ||
63 | mgmt_discovering(hdev, 0); | 64 | mgmt_discovering(hdev, 0); |
65 | hci_dev_unlock(hdev); | ||
64 | 66 | ||
65 | hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); | 67 | hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); |
66 | 68 | ||
@@ -201,13 +203,15 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | |||
201 | if (!sent) | 203 | if (!sent) |
202 | return; | 204 | return; |
203 | 205 | ||
206 | hci_dev_lock(hdev); | ||
207 | |||
204 | if (test_bit(HCI_MGMT, &hdev->flags)) | 208 | if (test_bit(HCI_MGMT, &hdev->flags)) |
205 | mgmt_set_local_name_complete(hdev, sent, status); | 209 | mgmt_set_local_name_complete(hdev, sent, status); |
206 | 210 | ||
207 | if (status) | 211 | if (status == 0) |
208 | return; | 212 | memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); |
209 | 213 | ||
210 | memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); | 214 | hci_dev_unlock(hdev); |
211 | } | 215 | } |
212 | 216 | ||
213 | static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) | 217 | static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -282,6 +286,8 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
282 | 286 | ||
283 | param = *((__u8 *) sent); | 287 | param = *((__u8 *) sent); |
284 | 288 | ||
289 | hci_dev_lock(hdev); | ||
290 | |||
285 | if (status != 0) { | 291 | if (status != 0) { |
286 | mgmt_write_scan_failed(hdev, param, status); | 292 | mgmt_write_scan_failed(hdev, param, status); |
287 | hdev->discov_timeout = 0; | 293 | hdev->discov_timeout = 0; |
@@ -311,6 +317,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
311 | mgmt_connectable(hdev, 0); | 317 | mgmt_connectable(hdev, 0); |
312 | 318 | ||
313 | done: | 319 | done: |
320 | hci_dev_unlock(hdev); | ||
314 | hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); | 321 | hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); |
315 | } | 322 | } |
316 | 323 | ||
@@ -834,19 +841,24 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) | |||
834 | 841 | ||
835 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | 842 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
836 | 843 | ||
844 | hci_dev_lock(hdev); | ||
845 | |||
837 | if (test_bit(HCI_MGMT, &hdev->flags)) | 846 | if (test_bit(HCI_MGMT, &hdev->flags)) |
838 | mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); | 847 | mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); |
839 | 848 | ||
840 | if (rp->status != 0) | 849 | if (rp->status != 0) |
841 | return; | 850 | goto unlock; |
842 | 851 | ||
843 | cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); | 852 | cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); |
844 | if (!cp) | 853 | if (!cp) |
845 | return; | 854 | goto unlock; |
846 | 855 | ||
847 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | 856 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); |
848 | if (conn) | 857 | if (conn) |
849 | conn->pin_length = cp->pin_len; | 858 | conn->pin_length = cp->pin_len; |
859 | |||
860 | unlock: | ||
861 | hci_dev_unlock(hdev); | ||
850 | } | 862 | } |
851 | 863 | ||
852 | static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) | 864 | static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -855,10 +867,15 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) | |||
855 | 867 | ||
856 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | 868 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
857 | 869 | ||
870 | hci_dev_lock(hdev); | ||
871 | |||
858 | if (test_bit(HCI_MGMT, &hdev->flags)) | 872 | if (test_bit(HCI_MGMT, &hdev->flags)) |
859 | mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, | 873 | mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, |
860 | rp->status); | 874 | rp->status); |
875 | |||
876 | hci_dev_unlock(hdev); | ||
861 | } | 877 | } |
878 | |||
862 | static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, | 879 | static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, |
863 | struct sk_buff *skb) | 880 | struct sk_buff *skb) |
864 | { | 881 | { |
@@ -885,9 +902,13 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) | |||
885 | 902 | ||
886 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | 903 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
887 | 904 | ||
905 | hci_dev_lock(hdev); | ||
906 | |||
888 | if (test_bit(HCI_MGMT, &hdev->flags)) | 907 | if (test_bit(HCI_MGMT, &hdev->flags)) |
889 | mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, | 908 | mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, |
890 | rp->status); | 909 | rp->status); |
910 | |||
911 | hci_dev_unlock(hdev); | ||
891 | } | 912 | } |
892 | 913 | ||
893 | static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, | 914 | static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, |
@@ -897,9 +918,13 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, | |||
897 | 918 | ||
898 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | 919 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
899 | 920 | ||
921 | hci_dev_lock(hdev); | ||
922 | |||
900 | if (test_bit(HCI_MGMT, &hdev->flags)) | 923 | if (test_bit(HCI_MGMT, &hdev->flags)) |
901 | mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, | 924 | mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, |
902 | rp->status); | 925 | rp->status); |
926 | |||
927 | hci_dev_unlock(hdev); | ||
903 | } | 928 | } |
904 | 929 | ||
905 | static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, | 930 | static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, |
@@ -909,8 +934,10 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, | |||
909 | 934 | ||
910 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | 935 | BT_DBG("%s status 0x%x", hdev->name, rp->status); |
911 | 936 | ||
937 | hci_dev_lock(hdev); | ||
912 | mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, | 938 | mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, |
913 | rp->randomizer, rp->status); | 939 | rp->randomizer, rp->status); |
940 | hci_dev_unlock(hdev); | ||
914 | } | 941 | } |
915 | 942 | ||
916 | static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | 943 | static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, |
@@ -985,14 +1012,18 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | |||
985 | if (status) { | 1012 | if (status) { |
986 | hci_req_complete(hdev, HCI_OP_INQUIRY, status); | 1013 | hci_req_complete(hdev, HCI_OP_INQUIRY, status); |
987 | hci_conn_check_pending(hdev); | 1014 | hci_conn_check_pending(hdev); |
1015 | hci_dev_lock(hdev); | ||
988 | if (test_bit(HCI_MGMT, &hdev->flags)) | 1016 | if (test_bit(HCI_MGMT, &hdev->flags)) |
989 | mgmt_inquiry_failed(hdev, status); | 1017 | mgmt_inquiry_failed(hdev, status); |
1018 | hci_dev_unlock(hdev); | ||
990 | return; | 1019 | return; |
991 | } | 1020 | } |
992 | 1021 | ||
993 | set_bit(HCI_INQUIRY, &hdev->flags); | 1022 | set_bit(HCI_INQUIRY, &hdev->flags); |
994 | 1023 | ||
1024 | hci_dev_lock(hdev); | ||
995 | mgmt_discovering(hdev, 1); | 1025 | mgmt_discovering(hdev, 1); |
1026 | hci_dev_unlock(hdev); | ||
996 | } | 1027 | } |
997 | 1028 | ||
998 | static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) | 1029 | static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) |
@@ -1378,7 +1409,9 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
1378 | if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) | 1409 | if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) |
1379 | return; | 1410 | return; |
1380 | 1411 | ||
1412 | hci_dev_lock(hdev); | ||
1381 | mgmt_discovering(hdev, 0); | 1413 | mgmt_discovering(hdev, 0); |
1414 | hci_dev_unlock(hdev); | ||
1382 | } | 1415 | } |
1383 | 1416 | ||
1384 | static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1417 | static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1572,7 +1605,9 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
1572 | BT_DBG("%s status %d", hdev->name, ev->status); | 1605 | BT_DBG("%s status %d", hdev->name, ev->status); |
1573 | 1606 | ||
1574 | if (ev->status) { | 1607 | if (ev->status) { |
1608 | hci_dev_lock(hdev); | ||
1575 | mgmt_disconnect_failed(hdev); | 1609 | mgmt_disconnect_failed(hdev); |
1610 | hci_dev_unlock(hdev); | ||
1576 | return; | 1611 | return; |
1577 | } | 1612 | } |
1578 | 1613 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index be198f382ed8..be4c3d03d808 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1335,16 +1335,19 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status) | |||
1335 | static void pairing_complete_cb(struct hci_conn *conn, u8 status) | 1335 | static void pairing_complete_cb(struct hci_conn *conn, u8 status) |
1336 | { | 1336 | { |
1337 | struct pending_cmd *cmd; | 1337 | struct pending_cmd *cmd; |
1338 | struct hci_dev *hdev = conn->hdev; | ||
1338 | 1339 | ||
1339 | BT_DBG("status %u", status); | 1340 | BT_DBG("status %u", status); |
1340 | 1341 | ||
1342 | hci_dev_lock_bh(hdev); | ||
1343 | |||
1341 | cmd = find_pairing(conn); | 1344 | cmd = find_pairing(conn); |
1342 | if (!cmd) { | 1345 | if (!cmd) |
1343 | BT_DBG("Unable to find a pending command"); | 1346 | BT_DBG("Unable to find a pending command"); |
1344 | return; | 1347 | else |
1345 | } | 1348 | pairing_complete(cmd, status); |
1346 | 1349 | ||
1347 | pairing_complete(cmd, status); | 1350 | hci_dev_unlock_bh(hdev); |
1348 | } | 1351 | } |
1349 | 1352 | ||
1350 | static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | 1353 | static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) |
@@ -2302,9 +2305,7 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) | |||
2302 | goto failed; | 2305 | goto failed; |
2303 | } | 2306 | } |
2304 | 2307 | ||
2305 | hci_dev_lock_bh(hdev); | ||
2306 | update_eir(hdev); | 2308 | update_eir(hdev); |
2307 | hci_dev_unlock_bh(hdev); | ||
2308 | 2309 | ||
2309 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, &ev, | 2310 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, &ev, |
2310 | sizeof(ev)); | 2311 | sizeof(ev)); |