summaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2015-11-25 09:15:44 -0500
committerMarcel Holtmann <marcel@holtmann.org>2015-12-09 18:51:49 -0500
commit2ff13894cfb877cb3d02d96a8402202f0a6f3efd (patch)
treefeb1092db11f30427f75af9694909fbdf6178c9a /net/bluetooth
parentbf943cbf76ecd3b9838a80d5e08777b0f4ccc665 (diff)
Bluetooth: Perform HCI update for power on synchronously
The request to update HCI during power on is always coming either from hdev->req_workqueue or through an ioctl, so it's safe to use hci_req_sync for it. This way we also eliminate potential races with incoming mgmt commands or other actions while powering on. Part of this refactoring is the splitting of mgmt_powered() into mgmt_power_on() and __mgmt_power_off() functions. The main reason is the different requirements as far as hdev locking is concerned, as highlighted with the __ prefix of the power off API. Since the power on in the case of clearing the AUTO_OFF flag cannot be done synchronously in the set_powered mgmt handler, the hci_power_on work callback is extended to cover this (which also simplifies the set_powered helper a lot). Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_core.c21
-rw-r--r--net/bluetooth/hci_request.c100
-rw-r--r--net/bluetooth/hci_request.h2
-rw-r--r--net/bluetooth/mgmt.c136
4 files changed, 126 insertions, 133 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 484c75f3332c..eac3f6fa1272 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1399,10 +1399,10 @@ static int hci_dev_do_open(struct hci_dev *hdev)
1399 !hci_dev_test_flag(hdev, HCI_CONFIG) && 1399 !hci_dev_test_flag(hdev, HCI_CONFIG) &&
1400 !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && 1400 !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
1401 !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && 1401 !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
1402 hci_dev_test_flag(hdev, HCI_MGMT) &&
1402 hdev->dev_type == HCI_BREDR) { 1403 hdev->dev_type == HCI_BREDR) {
1403 hci_dev_lock(hdev); 1404 ret = __hci_req_hci_power_on(hdev);
1404 mgmt_powered(hdev, 1); 1405 mgmt_power_on(hdev, ret);
1405 hci_dev_unlock(hdev);
1406 } 1406 }
1407 } else { 1407 } else {
1408 /* Init failed, cleanup */ 1408 /* Init failed, cleanup */
@@ -1559,8 +1559,9 @@ int hci_dev_do_close(struct hci_dev *hdev)
1559 1559
1560 auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF); 1560 auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF);
1561 1561
1562 if (!auto_off && hdev->dev_type == HCI_BREDR) 1562 if (!auto_off && hdev->dev_type == HCI_BREDR &&
1563 mgmt_powered(hdev, 0); 1563 hci_dev_test_flag(hdev, HCI_MGMT))
1564 __mgmt_power_off(hdev);
1564 1565
1565 hci_inquiry_cache_flush(hdev); 1566 hci_inquiry_cache_flush(hdev);
1566 hci_pend_le_actions_clear(hdev); 1567 hci_pend_le_actions_clear(hdev);
@@ -2013,6 +2014,16 @@ static void hci_power_on(struct work_struct *work)
2013 2014
2014 BT_DBG("%s", hdev->name); 2015 BT_DBG("%s", hdev->name);
2015 2016
2017 if (test_bit(HCI_UP, &hdev->flags) &&
2018 hci_dev_test_flag(hdev, HCI_MGMT) &&
2019 hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
2020 hci_req_sync_lock(hdev);
2021 err = __hci_req_hci_power_on(hdev);
2022 hci_req_sync_unlock(hdev);
2023 mgmt_power_on(hdev, err);
2024 return;
2025 }
2026
2016 err = hci_dev_do_open(hdev); 2027 err = hci_dev_do_open(hdev);
2017 if (err < 0) { 2028 if (err < 0) {
2018 hci_dev_lock(hdev); 2029 hci_dev_lock(hdev);
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 0abd83ddd4fb..7cc24f1448bd 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -2181,6 +2181,106 @@ static void discov_off(struct work_struct *work)
2181 mgmt_new_settings(hdev); 2181 mgmt_new_settings(hdev);
2182} 2182}
2183 2183
2184static int powered_update_hci(struct hci_request *req, unsigned long opt)
2185{
2186 struct hci_dev *hdev = req->hdev;
2187 struct adv_info *adv_instance;
2188 u8 link_sec;
2189
2190 hci_dev_lock(hdev);
2191
2192 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
2193 !lmp_host_ssp_capable(hdev)) {
2194 u8 mode = 0x01;
2195
2196 hci_req_add(req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
2197
2198 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
2199 u8 support = 0x01;
2200
2201 hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT,
2202 sizeof(support), &support);
2203 }
2204 }
2205
2206 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2207 lmp_bredr_capable(hdev)) {
2208 struct hci_cp_write_le_host_supported cp;
2209
2210 cp.le = 0x01;
2211 cp.simul = 0x00;
2212
2213 /* Check first if we already have the right
2214 * host state (host features set)
2215 */
2216 if (cp.le != lmp_host_le_capable(hdev) ||
2217 cp.simul != lmp_host_le_br_capable(hdev))
2218 hci_req_add(req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
2219 sizeof(cp), &cp);
2220 }
2221
2222 if (lmp_le_capable(hdev)) {
2223 /* Make sure the controller has a good default for
2224 * advertising data. This also applies to the case
2225 * where BR/EDR was toggled during the AUTO_OFF phase.
2226 */
2227 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2228 (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
2229 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))) {
2230 __hci_req_update_adv_data(req, HCI_ADV_CURRENT);
2231 __hci_req_update_scan_rsp_data(req, HCI_ADV_CURRENT);
2232 }
2233
2234 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
2235 hdev->cur_adv_instance == 0x00 &&
2236 !list_empty(&hdev->adv_instances)) {
2237 adv_instance = list_first_entry(&hdev->adv_instances,
2238 struct adv_info, list);
2239 hdev->cur_adv_instance = adv_instance->instance;
2240 }
2241
2242 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
2243 __hci_req_enable_advertising(req);
2244 else if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
2245 hdev->cur_adv_instance)
2246 __hci_req_schedule_adv_instance(req,
2247 hdev->cur_adv_instance,
2248 true);
2249 }
2250
2251 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
2252 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
2253 hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE,
2254 sizeof(link_sec), &link_sec);
2255
2256 if (lmp_bredr_capable(hdev)) {
2257 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
2258 __hci_req_write_fast_connectable(req, true);
2259 else
2260 __hci_req_write_fast_connectable(req, false);
2261 __hci_req_update_scan(req);
2262 __hci_req_update_class(req);
2263 __hci_req_update_name(req);
2264 __hci_req_update_eir(req);
2265 }
2266
2267 hci_dev_unlock(hdev);
2268 return 0;
2269}
2270
2271int __hci_req_hci_power_on(struct hci_dev *hdev)
2272{
2273 /* Register the available SMP channels (BR/EDR and LE) only when
2274 * successfully powering on the controller. This late
2275 * registration is required so that LE SMP can clearly decide if
2276 * the public address or static address is used.
2277 */
2278 smp_register(hdev);
2279
2280 return __hci_req_sync(hdev, powered_update_hci, 0, HCI_CMD_TIMEOUT,
2281 NULL);
2282}
2283
2184void hci_request_setup(struct hci_dev *hdev) 2284void hci_request_setup(struct hci_dev *hdev)
2185{ 2285{
2186 INIT_WORK(&hdev->discov_update, discov_update); 2286 INIT_WORK(&hdev->discov_update, discov_update);
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
index d3dd24deca74..a24d3b55094c 100644
--- a/net/bluetooth/hci_request.h
+++ b/net/bluetooth/hci_request.h
@@ -55,6 +55,8 @@ void hci_req_sync_cancel(struct hci_dev *hdev, int err);
55struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, 55struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen,
56 const void *param); 56 const void *param);
57 57
58int __hci_req_hci_power_on(struct hci_dev *hdev);
59
58void __hci_req_write_fast_connectable(struct hci_request *req, bool enable); 60void __hci_req_write_fast_connectable(struct hci_request *req, bool enable);
59void __hci_req_update_name(struct hci_request *req); 61void __hci_req_update_name(struct hci_request *req);
60void __hci_req_update_eir(struct hci_request *req); 62void __hci_req_update_eir(struct hci_request *req);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 0a7e6f4de383..468402ad933c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -961,17 +961,6 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
961 goto failed; 961 goto failed;
962 } 962 }
963 963
964 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
965 cancel_delayed_work(&hdev->power_off);
966
967 if (cp->val) {
968 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
969 data, len);
970 err = mgmt_powered(hdev, 1);
971 goto failed;
972 }
973 }
974
975 if (!!cp->val == hdev_is_powered(hdev)) { 964 if (!!cp->val == hdev_is_powered(hdev)) {
976 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev); 965 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
977 goto failed; 966 goto failed;
@@ -6434,139 +6423,33 @@ static void restart_le_actions(struct hci_dev *hdev)
6434 } 6423 }
6435} 6424}
6436 6425
6437static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode) 6426void mgmt_power_on(struct hci_dev *hdev, int err)
6438{ 6427{
6439 struct cmd_lookup match = { NULL, hdev }; 6428 struct cmd_lookup match = { NULL, hdev };
6440 6429
6441 BT_DBG("status 0x%02x", status); 6430 BT_DBG("err %d", err);
6442 6431
6443 if (!status) { 6432 hci_dev_lock(hdev);
6433
6434 if (!err) {
6444 restart_le_actions(hdev); 6435 restart_le_actions(hdev);
6445 hci_update_background_scan(hdev); 6436 hci_update_background_scan(hdev);
6446 } 6437 }
6447 6438
6448 hci_dev_lock(hdev);
6449
6450 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); 6439 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6451 6440
6452 new_settings(hdev, match.sk); 6441 new_settings(hdev, match.sk);
6453 6442
6454 hci_dev_unlock(hdev);
6455
6456 if (match.sk) 6443 if (match.sk)
6457 sock_put(match.sk); 6444 sock_put(match.sk);
6458}
6459 6445
6460static int powered_update_hci(struct hci_dev *hdev) 6446 hci_dev_unlock(hdev);
6461{
6462 struct hci_request req;
6463 struct adv_info *adv_instance;
6464 u8 link_sec;
6465
6466 hci_req_init(&req, hdev);
6467
6468 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
6469 !lmp_host_ssp_capable(hdev)) {
6470 u8 mode = 0x01;
6471
6472 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
6473
6474 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6475 u8 support = 0x01;
6476
6477 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6478 sizeof(support), &support);
6479 }
6480 }
6481
6482 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
6483 lmp_bredr_capable(hdev)) {
6484 struct hci_cp_write_le_host_supported cp;
6485
6486 cp.le = 0x01;
6487 cp.simul = 0x00;
6488
6489 /* Check first if we already have the right
6490 * host state (host features set)
6491 */
6492 if (cp.le != lmp_host_le_capable(hdev) ||
6493 cp.simul != lmp_host_le_br_capable(hdev))
6494 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6495 sizeof(cp), &cp);
6496 }
6497
6498 if (lmp_le_capable(hdev)) {
6499 /* Make sure the controller has a good default for
6500 * advertising data. This also applies to the case
6501 * where BR/EDR was toggled during the AUTO_OFF phase.
6502 */
6503 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
6504 (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
6505 !hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE))) {
6506 __hci_req_update_adv_data(&req, HCI_ADV_CURRENT);
6507 __hci_req_update_scan_rsp_data(&req, HCI_ADV_CURRENT);
6508 }
6509
6510 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
6511 hdev->cur_adv_instance == 0x00 &&
6512 !list_empty(&hdev->adv_instances)) {
6513 adv_instance = list_first_entry(&hdev->adv_instances,
6514 struct adv_info, list);
6515 hdev->cur_adv_instance = adv_instance->instance;
6516 }
6517
6518 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6519 __hci_req_enable_advertising(&req);
6520 else if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
6521 hdev->cur_adv_instance)
6522 __hci_req_schedule_adv_instance(&req,
6523 hdev->cur_adv_instance,
6524 true);
6525 }
6526
6527 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
6528 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
6529 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6530 sizeof(link_sec), &link_sec);
6531
6532 if (lmp_bredr_capable(hdev)) {
6533 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
6534 __hci_req_write_fast_connectable(&req, true);
6535 else
6536 __hci_req_write_fast_connectable(&req, false);
6537 __hci_req_update_scan(&req);
6538 __hci_req_update_class(&req);
6539 __hci_req_update_name(&req);
6540 __hci_req_update_eir(&req);
6541 }
6542
6543 return hci_req_run(&req, powered_complete);
6544} 6447}
6545 6448
6546int mgmt_powered(struct hci_dev *hdev, u8 powered) 6449void __mgmt_power_off(struct hci_dev *hdev)
6547{ 6450{
6548 struct cmd_lookup match = { NULL, hdev }; 6451 struct cmd_lookup match = { NULL, hdev };
6549 u8 status, zero_cod[] = { 0, 0, 0 }; 6452 u8 status, zero_cod[] = { 0, 0, 0 };
6550 int err;
6551
6552 if (!hci_dev_test_flag(hdev, HCI_MGMT))
6553 return 0;
6554
6555 if (powered) {
6556 /* Register the available SMP channels (BR/EDR and LE) only
6557 * when successfully powering on the controller. This late
6558 * registration is required so that LE SMP can clearly
6559 * decide if the public address or static address is used.
6560 */
6561 smp_register(hdev);
6562
6563 if (powered_update_hci(hdev) == 0)
6564 return 0;
6565
6566 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6567 &match);
6568 goto new_settings;
6569 }
6570 6453
6571 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); 6454 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6572 6455
@@ -6588,13 +6471,10 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
6588 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, 6471 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6589 zero_cod, sizeof(zero_cod), NULL); 6472 zero_cod, sizeof(zero_cod), NULL);
6590 6473
6591new_settings: 6474 new_settings(hdev, match.sk);
6592 err = new_settings(hdev, match.sk);
6593 6475
6594 if (match.sk) 6476 if (match.sk)
6595 sock_put(match.sk); 6477 sock_put(match.sk);
6596
6597 return err;
6598} 6478}
6599 6479
6600void mgmt_set_powered_failed(struct hci_dev *hdev, int err) 6480void mgmt_set_powered_failed(struct hci_dev *hdev, int err)