aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2013-03-15 18:07:00 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-03-18 13:02:03 -0400
commit13928971396fb5ad022ec65f694cea367ca48504 (patch)
tree1e17017716aa44cd435ef28cc095b85dd451c218 /net/bluetooth/mgmt.c
parent35b973c9dd6d518491b251ac777d767d7820aa37 (diff)
Bluetooth: Fix waiting for EIR update when setting local name
We shouldn't respond to the mgmt_set_local_name command until all related HCI commands have completed. This patch fixes the issue by running the local name HCI command and the EIR update in the same asynchronous request, and returning the mgmt command complete through the complete callback of the request. The downside of this is that we must set hdev->dev_name before the local name HCI command has completed since otherwise the generated EIR command doesn't contain the new name. This means that we can no-longer reliably detect when the name has really changed and when not. Luckily this only affects scenarios where the mgmt interface is *not* used (e.g. hciconfig) so redundant mgmt_ev_local_name_changed events in these cases are an acceptable drawback. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c96
1 files changed, 49 insertions, 47 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 3e3cb0102b13..1d50841fa707 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2358,15 +2358,44 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
2358 HCI_OP_USER_PASSKEY_NEG_REPLY, 0); 2358 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
2359} 2359}
2360 2360
2361static void update_name(struct hci_request *req, const char *name) 2361static void update_name(struct hci_request *req)
2362{ 2362{
2363 struct hci_dev *hdev = req->hdev;
2363 struct hci_cp_write_local_name cp; 2364 struct hci_cp_write_local_name cp;
2364 2365
2365 memcpy(cp.name, name, sizeof(cp.name)); 2366 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
2366 2367
2367 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp); 2368 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
2368} 2369}
2369 2370
2371static void set_name_complete(struct hci_dev *hdev, u8 status)
2372{
2373 struct mgmt_cp_set_local_name *cp;
2374 struct pending_cmd *cmd;
2375
2376 BT_DBG("status 0x%02x", status);
2377
2378 hci_dev_lock(hdev);
2379
2380 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
2381 if (!cmd)
2382 goto unlock;
2383
2384 cp = cmd->param;
2385
2386 if (status)
2387 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
2388 mgmt_status(status));
2389 else
2390 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
2391 cp, sizeof(*cp));
2392
2393 mgmt_pending_remove(cmd);
2394
2395unlock:
2396 hci_dev_unlock(hdev);
2397}
2398
2370static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, 2399static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
2371 u16 len) 2400 u16 len)
2372{ 2401{
@@ -2401,9 +2430,12 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
2401 goto failed; 2430 goto failed;
2402 } 2431 }
2403 2432
2433 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
2434
2404 hci_req_init(&req, hdev); 2435 hci_req_init(&req, hdev);
2405 update_name(&req, cp->name); 2436 update_name(&req);
2406 err = hci_req_run(&req, NULL); 2437 update_eir(&req);
2438 err = hci_req_run(&req, set_name_complete);
2407 if (err < 0) 2439 if (err < 0)
2408 mgmt_pending_remove(cmd); 2440 mgmt_pending_remove(cmd);
2409 2441
@@ -3208,7 +3240,7 @@ static int powered_update_hci(struct hci_dev *hdev)
3208 if (lmp_bredr_capable(hdev)) { 3240 if (lmp_bredr_capable(hdev)) {
3209 set_bredr_scan(&req); 3241 set_bredr_scan(&req);
3210 update_class(&req); 3242 update_class(&req);
3211 update_name(&req, hdev->dev_name); 3243 update_name(&req);
3212 update_eir(&req); 3244 update_eir(&req);
3213 } 3245 }
3214 3246
@@ -3776,59 +3808,29 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
3776 3808
3777int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) 3809int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
3778{ 3810{
3779 struct pending_cmd *cmd;
3780 struct mgmt_cp_set_local_name ev; 3811 struct mgmt_cp_set_local_name ev;
3781 bool changed = false; 3812 struct pending_cmd *cmd;
3782 int err = 0;
3783 3813
3784 if (memcmp(name, hdev->dev_name, sizeof(hdev->dev_name)) != 0) { 3814 if (status)
3785 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name)); 3815 return 0;
3786 changed = true;
3787 }
3788 3816
3789 memset(&ev, 0, sizeof(ev)); 3817 memset(&ev, 0, sizeof(ev));
3790 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); 3818 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
3791 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH); 3819 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
3792 3820
3793 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); 3821 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3794 if (!cmd) 3822 if (!cmd) {
3795 goto send_event; 3823 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
3796
3797 /* Always assume that either the short or the complete name has
3798 * changed if there was a pending mgmt command */
3799 changed = true;
3800
3801 if (status) {
3802 err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3803 mgmt_status(status));
3804 goto failed;
3805 }
3806
3807 err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, &ev,
3808 sizeof(ev));
3809 if (err < 0)
3810 goto failed;
3811
3812send_event:
3813 if (changed)
3814 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev,
3815 sizeof(ev), cmd ? cmd->sk : NULL);
3816 3824
3817 /* EIR is taken care of separately when powering on the 3825 /* If this is a HCI command related to powering on the
3818 * adapter so only update them here if this is a name change 3826 * HCI dev don't send any mgmt signals.
3819 * unrelated to power on. 3827 */
3820 */ 3828 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
3821 if (!test_bit(HCI_INIT, &hdev->flags)) { 3829 return 0;
3822 struct hci_request req;
3823 hci_req_init(&req, hdev);
3824 update_eir(&req);
3825 hci_req_run(&req, NULL);
3826 } 3830 }
3827 3831
3828failed: 3832 return mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
3829 if (cmd) 3833 cmd ? cmd->sk : NULL);
3830 mgmt_pending_remove(cmd);
3831 return err;
3832} 3834}
3833 3835
3834int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, 3836int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,