diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-04-12 16:18:44 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-12 16:18:44 -0400 |
commit | 252f4bf400df1712408fe83ba199a66a1b57ab1d (patch) | |
tree | e07fa00abdd55b31e22567786c78635f32c6a66c /net/bluetooth/hci_core.c | |
parent | 6ba1037c3d871ab70e342631516dbf841c35b086 (diff) | |
parent | b37e3b6d64358604960b35e8ecbb7aed22e0926e (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/ath/ar9170/main.c
drivers/net/wireless/ath/ar9170/phy.c
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
Diffstat (limited to 'net/bluetooth/hci_core.c')
-rw-r--r-- | net/bluetooth/hci_core.c | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index c83f618282f..1ad4907766c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -56,7 +56,6 @@ | |||
56 | static void hci_cmd_task(unsigned long arg); | 56 | static void hci_cmd_task(unsigned long arg); |
57 | static void hci_rx_task(unsigned long arg); | 57 | static void hci_rx_task(unsigned long arg); |
58 | static void hci_tx_task(unsigned long arg); | 58 | static void hci_tx_task(unsigned long arg); |
59 | static void hci_notify(struct hci_dev *hdev, int event); | ||
60 | 59 | ||
61 | static DEFINE_RWLOCK(hci_task_lock); | 60 | static DEFINE_RWLOCK(hci_task_lock); |
62 | 61 | ||
@@ -1083,6 +1082,70 @@ static void hci_cmd_timer(unsigned long arg) | |||
1083 | tasklet_schedule(&hdev->cmd_task); | 1082 | tasklet_schedule(&hdev->cmd_task); |
1084 | } | 1083 | } |
1085 | 1084 | ||
1085 | struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, | ||
1086 | bdaddr_t *bdaddr) | ||
1087 | { | ||
1088 | struct oob_data *data; | ||
1089 | |||
1090 | list_for_each_entry(data, &hdev->remote_oob_data, list) | ||
1091 | if (bacmp(bdaddr, &data->bdaddr) == 0) | ||
1092 | return data; | ||
1093 | |||
1094 | return NULL; | ||
1095 | } | ||
1096 | |||
1097 | int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr) | ||
1098 | { | ||
1099 | struct oob_data *data; | ||
1100 | |||
1101 | data = hci_find_remote_oob_data(hdev, bdaddr); | ||
1102 | if (!data) | ||
1103 | return -ENOENT; | ||
1104 | |||
1105 | BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); | ||
1106 | |||
1107 | list_del(&data->list); | ||
1108 | kfree(data); | ||
1109 | |||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | int hci_remote_oob_data_clear(struct hci_dev *hdev) | ||
1114 | { | ||
1115 | struct oob_data *data, *n; | ||
1116 | |||
1117 | list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) { | ||
1118 | list_del(&data->list); | ||
1119 | kfree(data); | ||
1120 | } | ||
1121 | |||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1125 | int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, | ||
1126 | u8 *randomizer) | ||
1127 | { | ||
1128 | struct oob_data *data; | ||
1129 | |||
1130 | data = hci_find_remote_oob_data(hdev, bdaddr); | ||
1131 | |||
1132 | if (!data) { | ||
1133 | data = kmalloc(sizeof(*data), GFP_ATOMIC); | ||
1134 | if (!data) | ||
1135 | return -ENOMEM; | ||
1136 | |||
1137 | bacpy(&data->bdaddr, bdaddr); | ||
1138 | list_add(&data->list, &hdev->remote_oob_data); | ||
1139 | } | ||
1140 | |||
1141 | memcpy(data->hash, hash, sizeof(data->hash)); | ||
1142 | memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); | ||
1143 | |||
1144 | BT_DBG("%s for %s", hdev->name, batostr(bdaddr)); | ||
1145 | |||
1146 | return 0; | ||
1147 | } | ||
1148 | |||
1086 | /* Register HCI device */ | 1149 | /* Register HCI device */ |
1087 | int hci_register_dev(struct hci_dev *hdev) | 1150 | int hci_register_dev(struct hci_dev *hdev) |
1088 | { | 1151 | { |
@@ -1147,6 +1210,8 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1147 | 1210 | ||
1148 | INIT_LIST_HEAD(&hdev->link_keys); | 1211 | INIT_LIST_HEAD(&hdev->link_keys); |
1149 | 1212 | ||
1213 | INIT_LIST_HEAD(&hdev->remote_oob_data); | ||
1214 | |||
1150 | INIT_WORK(&hdev->power_on, hci_power_on); | 1215 | INIT_WORK(&hdev->power_on, hci_power_on); |
1151 | INIT_WORK(&hdev->power_off, hci_power_off); | 1216 | INIT_WORK(&hdev->power_off, hci_power_off); |
1152 | setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev); | 1217 | setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev); |
@@ -1226,6 +1291,7 @@ int hci_unregister_dev(struct hci_dev *hdev) | |||
1226 | hci_blacklist_clear(hdev); | 1291 | hci_blacklist_clear(hdev); |
1227 | hci_uuids_clear(hdev); | 1292 | hci_uuids_clear(hdev); |
1228 | hci_link_keys_clear(hdev); | 1293 | hci_link_keys_clear(hdev); |
1294 | hci_remote_oob_data_clear(hdev); | ||
1229 | hci_dev_unlock_bh(hdev); | 1295 | hci_dev_unlock_bh(hdev); |
1230 | 1296 | ||
1231 | __hci_dev_put(hdev); | 1297 | __hci_dev_put(hdev); |
@@ -1275,7 +1341,7 @@ int hci_recv_frame(struct sk_buff *skb) | |||
1275 | EXPORT_SYMBOL(hci_recv_frame); | 1341 | EXPORT_SYMBOL(hci_recv_frame); |
1276 | 1342 | ||
1277 | static int hci_reassembly(struct hci_dev *hdev, int type, void *data, | 1343 | static int hci_reassembly(struct hci_dev *hdev, int type, void *data, |
1278 | int count, __u8 index, gfp_t gfp_mask) | 1344 | int count, __u8 index) |
1279 | { | 1345 | { |
1280 | int len = 0; | 1346 | int len = 0; |
1281 | int hlen = 0; | 1347 | int hlen = 0; |
@@ -1305,7 +1371,7 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data, | |||
1305 | break; | 1371 | break; |
1306 | } | 1372 | } |
1307 | 1373 | ||
1308 | skb = bt_skb_alloc(len, gfp_mask); | 1374 | skb = bt_skb_alloc(len, GFP_ATOMIC); |
1309 | if (!skb) | 1375 | if (!skb) |
1310 | return -ENOMEM; | 1376 | return -ENOMEM; |
1311 | 1377 | ||
@@ -1391,8 +1457,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) | |||
1391 | return -EILSEQ; | 1457 | return -EILSEQ; |
1392 | 1458 | ||
1393 | while (count) { | 1459 | while (count) { |
1394 | rem = hci_reassembly(hdev, type, data, count, | 1460 | rem = hci_reassembly(hdev, type, data, count, type - 1); |
1395 | type - 1, GFP_ATOMIC); | ||
1396 | if (rem < 0) | 1461 | if (rem < 0) |
1397 | return rem; | 1462 | return rem; |
1398 | 1463 | ||
@@ -1426,8 +1491,8 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count) | |||
1426 | } else | 1491 | } else |
1427 | type = bt_cb(skb)->pkt_type; | 1492 | type = bt_cb(skb)->pkt_type; |
1428 | 1493 | ||
1429 | rem = hci_reassembly(hdev, type, data, | 1494 | rem = hci_reassembly(hdev, type, data, count, |
1430 | count, STREAM_REASSEMBLY, GFP_ATOMIC); | 1495 | STREAM_REASSEMBLY); |
1431 | if (rem < 0) | 1496 | if (rem < 0) |
1432 | return rem; | 1497 | return rem; |
1433 | 1498 | ||