aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/mgmt.c62
1 files changed, 40 insertions, 22 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index f5ef7a3374c7..52e5f88b753a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -219,14 +219,14 @@ static void mgmt_pending_free(struct pending_cmd *cmd)
219 kfree(cmd); 219 kfree(cmd);
220} 220}
221 221
222static int mgmt_pending_add(struct sock *sk, u16 opcode, int index, 222static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
223 void *data, u16 len) 223 u16 index, void *data, u16 len)
224{ 224{
225 struct pending_cmd *cmd; 225 struct pending_cmd *cmd;
226 226
227 cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); 227 cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
228 if (!cmd) 228 if (!cmd)
229 return -ENOMEM; 229 return NULL;
230 230
231 cmd->opcode = opcode; 231 cmd->opcode = opcode;
232 cmd->index = index; 232 cmd->index = index;
@@ -234,7 +234,7 @@ static int mgmt_pending_add(struct sock *sk, u16 opcode, int index,
234 cmd->cmd = kmalloc(len, GFP_ATOMIC); 234 cmd->cmd = kmalloc(len, GFP_ATOMIC);
235 if (!cmd->cmd) { 235 if (!cmd->cmd) {
236 kfree(cmd); 236 kfree(cmd);
237 return -ENOMEM; 237 return NULL;
238 } 238 }
239 239
240 memcpy(cmd->cmd, data, len); 240 memcpy(cmd->cmd, data, len);
@@ -244,7 +244,7 @@ static int mgmt_pending_add(struct sock *sk, u16 opcode, int index,
244 244
245 list_add(&cmd->list, &cmd_list); 245 list_add(&cmd->list, &cmd_list);
246 246
247 return 0; 247 return cmd;
248} 248}
249 249
250static void mgmt_pending_foreach(u16 opcode, int index, 250static void mgmt_pending_foreach(u16 opcode, int index,
@@ -305,8 +305,9 @@ static int set_powered(struct sock *sk, unsigned char *data, u16 len)
305{ 305{
306 struct mgmt_mode *cp; 306 struct mgmt_mode *cp;
307 struct hci_dev *hdev; 307 struct hci_dev *hdev;
308 struct pending_cmd *cmd;
308 u16 dev_id; 309 u16 dev_id;
309 int ret, up; 310 int err, up;
310 311
311 cp = (void *) data; 312 cp = (void *) data;
312 dev_id = get_unaligned_le16(&cp->index); 313 dev_id = get_unaligned_le16(&cp->index);
@@ -321,36 +322,39 @@ static int set_powered(struct sock *sk, unsigned char *data, u16 len)
321 322
322 up = test_bit(HCI_UP, &hdev->flags); 323 up = test_bit(HCI_UP, &hdev->flags);
323 if ((cp->val && up) || (!cp->val && !up)) { 324 if ((cp->val && up) || (!cp->val && !up)) {
324 ret = cmd_status(sk, MGMT_OP_SET_POWERED, EALREADY); 325 err = cmd_status(sk, MGMT_OP_SET_POWERED, EALREADY);
325 goto failed; 326 goto failed;
326 } 327 }
327 328
328 if (mgmt_pending_find(MGMT_OP_SET_POWERED, dev_id)) { 329 if (mgmt_pending_find(MGMT_OP_SET_POWERED, dev_id)) {
329 ret = cmd_status(sk, MGMT_OP_SET_POWERED, EBUSY); 330 err = cmd_status(sk, MGMT_OP_SET_POWERED, EBUSY);
330 goto failed; 331 goto failed;
331 } 332 }
332 333
333 ret = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, dev_id, data, len); 334 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, dev_id, data, len);
334 if (ret < 0) 335 if (!cmd) {
336 err = -ENOMEM;
335 goto failed; 337 goto failed;
338 }
336 339
337 if (cp->val) 340 if (cp->val)
338 queue_work(hdev->workqueue, &hdev->power_on); 341 queue_work(hdev->workqueue, &hdev->power_on);
339 else 342 else
340 queue_work(hdev->workqueue, &hdev->power_off); 343 queue_work(hdev->workqueue, &hdev->power_off);
341 344
342 ret = 0; 345 err = 0;
343 346
344failed: 347failed:
345 hci_dev_unlock_bh(hdev); 348 hci_dev_unlock_bh(hdev);
346 hci_dev_put(hdev); 349 hci_dev_put(hdev);
347 return ret; 350 return err;
348} 351}
349 352
350static int set_discoverable(struct sock *sk, unsigned char *data, u16 len) 353static int set_discoverable(struct sock *sk, unsigned char *data, u16 len)
351{ 354{
352 struct mgmt_mode *cp; 355 struct mgmt_mode *cp;
353 struct hci_dev *hdev; 356 struct hci_dev *hdev;
357 struct pending_cmd *cmd;
354 u16 dev_id; 358 u16 dev_id;
355 u8 scan; 359 u8 scan;
356 int err; 360 int err;
@@ -383,9 +387,11 @@ static int set_discoverable(struct sock *sk, unsigned char *data, u16 len)
383 goto failed; 387 goto failed;
384 } 388 }
385 389
386 err = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, dev_id, data, len); 390 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, dev_id, data, len);
387 if (err < 0) 391 if (!cmd) {
392 err = -ENOMEM;
388 goto failed; 393 goto failed;
394 }
389 395
390 scan = SCAN_PAGE; 396 scan = SCAN_PAGE;
391 397
@@ -407,6 +413,7 @@ static int set_connectable(struct sock *sk, unsigned char *data, u16 len)
407{ 413{
408 struct mgmt_mode *cp; 414 struct mgmt_mode *cp;
409 struct hci_dev *hdev; 415 struct hci_dev *hdev;
416 struct pending_cmd *cmd;
410 u16 dev_id; 417 u16 dev_id;
411 u8 scan; 418 u8 scan;
412 int err; 419 int err;
@@ -438,9 +445,11 @@ static int set_connectable(struct sock *sk, unsigned char *data, u16 len)
438 goto failed; 445 goto failed;
439 } 446 }
440 447
441 err = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, dev_id, data, len); 448 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, dev_id, data, len);
442 if (err < 0) 449 if (!cmd) {
450 err = -ENOMEM;
443 goto failed; 451 goto failed;
452 }
444 453
445 if (cp->val) 454 if (cp->val)
446 scan = SCAN_PAGE; 455 scan = SCAN_PAGE;
@@ -828,6 +837,7 @@ static int disconnect(struct sock *sk, unsigned char *data, u16 len)
828 struct hci_dev *hdev; 837 struct hci_dev *hdev;
829 struct mgmt_cp_disconnect *cp; 838 struct mgmt_cp_disconnect *cp;
830 struct hci_cp_disconnect dc; 839 struct hci_cp_disconnect dc;
840 struct pending_cmd *cmd;
831 struct hci_conn *conn; 841 struct hci_conn *conn;
832 u16 dev_id; 842 u16 dev_id;
833 int err; 843 int err;
@@ -859,9 +869,11 @@ static int disconnect(struct sock *sk, unsigned char *data, u16 len)
859 goto failed; 869 goto failed;
860 } 870 }
861 871
862 err = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, dev_id, data, len); 872 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, dev_id, data, len);
863 if (err < 0) 873 if (!cmd) {
874 err = -ENOMEM;
864 goto failed; 875 goto failed;
876 }
865 877
866 put_unaligned_le16(conn->handle, &dc.handle); 878 put_unaligned_le16(conn->handle, &dc.handle);
867 dc.reason = 0x13; /* Remote User Terminated Connection */ 879 dc.reason = 0x13; /* Remote User Terminated Connection */
@@ -938,6 +950,7 @@ static int pin_code_reply(struct sock *sk, unsigned char *data, u16 len)
938 struct hci_dev *hdev; 950 struct hci_dev *hdev;
939 struct mgmt_cp_pin_code_reply *cp; 951 struct mgmt_cp_pin_code_reply *cp;
940 struct hci_cp_pin_code_reply reply; 952 struct hci_cp_pin_code_reply reply;
953 struct pending_cmd *cmd;
941 u16 dev_id; 954 u16 dev_id;
942 int err; 955 int err;
943 956
@@ -957,9 +970,11 @@ static int pin_code_reply(struct sock *sk, unsigned char *data, u16 len)
957 goto failed; 970 goto failed;
958 } 971 }
959 972
960 err = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, dev_id, data, len); 973 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, dev_id, data, len);
961 if (err < 0) 974 if (!cmd) {
975 err = -ENOMEM;
962 goto failed; 976 goto failed;
977 }
963 978
964 bacpy(&reply.bdaddr, &cp->bdaddr); 979 bacpy(&reply.bdaddr, &cp->bdaddr);
965 reply.pin_len = cp->pin_len; 980 reply.pin_len = cp->pin_len;
@@ -980,6 +995,7 @@ static int pin_code_neg_reply(struct sock *sk, unsigned char *data, u16 len)
980{ 995{
981 struct hci_dev *hdev; 996 struct hci_dev *hdev;
982 struct mgmt_cp_pin_code_neg_reply *cp; 997 struct mgmt_cp_pin_code_neg_reply *cp;
998 struct pending_cmd *cmd;
983 u16 dev_id; 999 u16 dev_id;
984 int err; 1000 int err;
985 1001
@@ -999,10 +1015,12 @@ static int pin_code_neg_reply(struct sock *sk, unsigned char *data, u16 len)
999 goto failed; 1015 goto failed;
1000 } 1016 }
1001 1017
1002 err = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, dev_id, 1018 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, dev_id,
1003 data, len); 1019 data, len);
1004 if (err < 0) 1020 if (!cmd) {
1021 err = -ENOMEM;
1005 goto failed; 1022 goto failed;
1023 }
1006 1024
1007 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(bdaddr_t), 1025 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(bdaddr_t),
1008 &cp->bdaddr); 1026 &cp->bdaddr);