From: Johan Hedberg <johan.hedberg@xxxxxxxxx> We should only notify user space that the adapter has been powered on after all HCI commands related to the action have completed. This patch fixes the issue by instating an async request complete callback for these HCI commands and only notifies user space in the callback. Signed-off-by: Johan Hedberg <johan.hedberg@xxxxxxxxx> --- net/bluetooth/mgmt.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index dd62700..18d4d7e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3087,6 +3087,24 @@ static int set_bredr_scan(struct hci_request *req) return hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); } +static void powered_complete(struct hci_dev *hdev, u8 status) +{ + struct cmd_lookup match = { NULL, hdev }; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); + + new_settings(hdev, match.sk); + + hci_dev_unlock(hdev); + + if (match.sk) + sock_put(match.sk); +} + static int powered_update_hci(struct hci_dev *hdev) { struct hci_request req; @@ -3128,32 +3146,36 @@ static int powered_update_hci(struct hci_dev *hdev) update_eir(&req); } - return hci_req_run(&req, NULL); + return hci_req_run(&req, powered_complete); } int mgmt_powered(struct hci_dev *hdev, u8 powered) { struct cmd_lookup match = { NULL, hdev }; + u8 status_not_powered = MGMT_STATUS_NOT_POWERED; + u8 zero_cod[] = { 0, 0, 0 }; int err; if (!test_bit(HCI_MGMT, &hdev->dev_flags)) return 0; - mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); - if (powered) { - powered_update_hci(hdev); - } else { - u8 status = MGMT_STATUS_NOT_POWERED; - u8 zero_cod[] = { 0, 0, 0 }; - - mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); + if (powered_update_hci(hdev) == 0) + return 0; - if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) - mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, - zero_cod, sizeof(zero_cod), NULL); + mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, + &match); + goto new_settings; } + mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); + mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered); + + if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) + mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, + zero_cod, sizeof(zero_cod), NULL); + +new_settings: err = new_settings(hdev, match.sk); if (match.sk) -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html