diff options
Diffstat (limited to 'net/bluetooth/hci_sync.c')
| -rw-r--r-- | net/bluetooth/hci_sync.c | 68 | 
1 files changed, 48 insertions, 20 deletions
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 117eedb6f709..5a6aa1627791 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -643,6 +643,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)  	cancel_work_sync(&hdev->cmd_sync_work);  	cancel_work_sync(&hdev->reenable_adv_work); +	mutex_lock(&hdev->cmd_sync_work_lock);  	list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {  		if (entry->destroy)  			entry->destroy(hdev, entry->data, -ECANCELED); @@ -650,6 +651,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)  		list_del(&entry->list);  		kfree(entry);  	} +	mutex_unlock(&hdev->cmd_sync_work_lock);  }  void __hci_cmd_sync_cancel(struct hci_dev *hdev, int err) @@ -2367,6 +2369,45 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)  	return err;  } +static int hci_pause_addr_resolution(struct hci_dev *hdev) +{ +	int err; + +	if (!use_ll_privacy(hdev)) +		return 0; + +	if (!hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION)) +		return 0; + +	/* Cannot disable addr resolution if scanning is enabled or +	 * when initiating an LE connection. +	 */ +	if (hci_dev_test_flag(hdev, HCI_LE_SCAN) || +	    hci_lookup_le_connect(hdev)) { +		bt_dev_err(hdev, "Command not allowed when scan/LE connect"); +		return -EPERM; +	} + +	/* Cannot disable addr resolution if advertising is enabled. */ +	err = hci_pause_advertising_sync(hdev); +	if (err) { +		bt_dev_err(hdev, "Pause advertising failed: %d", err); +		return err; +	} + +	err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00); +	if (err) +		bt_dev_err(hdev, "Unable to disable Address Resolution: %d", +			   err); + +	/* Return if address resolution is disabled and RPA is not used. */ +	if (!err && scan_use_rpa(hdev)) +		return err; + +	hci_resume_advertising_sync(hdev); +	return err; +} +  struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev,  					     bool extended, struct sock *sk)  { @@ -2402,7 +2443,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)  	u8 filter_policy;  	int err; -	/* Pause advertising if resolving list can be used as controllers are +	/* Pause advertising if resolving list can be used as controllers  	 * cannot accept resolving list modifications while advertising.  	 */  	if (use_ll_privacy(hdev)) { @@ -3319,6 +3360,7 @@ static const struct hci_init_stage amp_init1[] = {  	HCI_INIT(hci_read_flow_control_mode_sync),  	/* HCI_OP_READ_LOCATION_DATA */  	HCI_INIT(hci_read_location_data_sync), +	{}  };  static int hci_init1_sync(struct hci_dev *hdev) @@ -3353,6 +3395,7 @@ static int hci_init1_sync(struct hci_dev *hdev)  static const struct hci_init_stage amp_init2[] = {  	/* HCI_OP_READ_LOCAL_FEATURES */  	HCI_INIT(hci_read_local_features_sync), +	{}  };  /* Read Buffer Size (ACL mtu, max pkt, etc.) */ @@ -5394,27 +5437,12 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)  	cancel_interleave_scan(hdev); -	/* Pause advertising since active scanning disables address resolution -	 * which advertising depend on in order to generate its RPAs. -	 */ -	if (use_ll_privacy(hdev) && hci_dev_test_flag(hdev, HCI_PRIVACY)) { -		err = hci_pause_advertising_sync(hdev); -		if (err) { -			bt_dev_err(hdev, "pause advertising failed: %d", err); -			goto failed; -		} -	} - -	/* Disable address resolution while doing active scanning since the -	 * accept list shall not be used and all reports shall reach the host -	 * anyway. +	/* Pause address resolution for active scan and stop advertising if +	 * privacy is enabled.  	 */ -	err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00); -	if (err) { -		bt_dev_err(hdev, "Unable to disable Address Resolution: %d", -			   err); +	err = hci_pause_addr_resolution(hdev); +	if (err)  		goto failed; -	}  	/* All active scans will be done with either a resolvable private  	 * address (when privacy feature has been enabled) or non-resolvable  |