Bluetooth: Use controller sets when available
This makes use of controller sets when using Extended Advertising feature thus offloading the scheduling to the controller. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
Родитель
c49a8682fc
Коммит
1d0fac2c38
|
@ -915,7 +915,7 @@ static void hci_req_directed_advertising(struct hci_request *req,
|
|||
sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
__hci_req_enable_ext_advertising(req);
|
||||
__hci_req_enable_ext_advertising(req, 0x00);
|
||||
} else {
|
||||
struct hci_cp_le_set_adv_param cp;
|
||||
|
||||
|
|
|
@ -2827,7 +2827,7 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
|
|||
memset(adv_instance->scan_rsp_data, 0,
|
||||
sizeof(adv_instance->scan_rsp_data));
|
||||
} else {
|
||||
if (hdev->adv_instance_cnt >= HCI_MAX_ADV_INSTANCES ||
|
||||
if (hdev->adv_instance_cnt >= hdev->le_num_of_adv_sets ||
|
||||
instance < 1 || instance > HCI_MAX_ADV_INSTANCES)
|
||||
return -EOVERFLOW;
|
||||
|
||||
|
@ -3195,6 +3195,7 @@ struct hci_dev *hci_alloc_dev(void)
|
|||
hdev->le_min_key_size = SMP_MIN_ENC_KEY_SIZE;
|
||||
hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M;
|
||||
hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M;
|
||||
hdev->le_num_of_adv_sets = HCI_MAX_ADV_INSTANCES;
|
||||
|
||||
hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT;
|
||||
hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT;
|
||||
|
|
|
@ -1601,7 +1601,7 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
|
|||
cp.own_addr_type = own_addr_type;
|
||||
cp.channel_map = hdev->le_adv_channel_map;
|
||||
cp.tx_power = 127;
|
||||
cp.handle = 0;
|
||||
cp.handle = instance;
|
||||
|
||||
if (flags & MGMT_ADV_FLAG_SEC_2M) {
|
||||
cp.primary_phy = HCI_ADV_PHY_1M;
|
||||
|
@ -1643,11 +1643,21 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void __hci_req_enable_ext_advertising(struct hci_request *req)
|
||||
int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance)
|
||||
{
|
||||
struct hci_dev *hdev = req->hdev;
|
||||
struct hci_cp_le_set_ext_adv_enable *cp;
|
||||
struct hci_cp_ext_adv_set *adv_set;
|
||||
u8 data[sizeof(*cp) + sizeof(*adv_set) * 1];
|
||||
struct adv_info *adv_instance;
|
||||
|
||||
if (instance > 0) {
|
||||
adv_instance = hci_find_adv_instance(hdev, instance);
|
||||
if (!adv_instance)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
adv_instance = NULL;
|
||||
}
|
||||
|
||||
cp = (void *) data;
|
||||
adv_set = (void *) cp->data;
|
||||
|
@ -1659,11 +1669,23 @@ void __hci_req_enable_ext_advertising(struct hci_request *req)
|
|||
|
||||
memset(adv_set, 0, sizeof(*adv_set));
|
||||
|
||||
adv_set->handle = 0;
|
||||
adv_set->handle = instance;
|
||||
|
||||
/* Set duration per instance since controller is responsible for
|
||||
* scheduling it.
|
||||
*/
|
||||
if (adv_instance && adv_instance->duration) {
|
||||
u16 duration = adv_instance->duration * MSEC_PER_SEC;
|
||||
|
||||
/* Time = N * 10 ms */
|
||||
adv_set->duration = cpu_to_le16(duration / 10);
|
||||
}
|
||||
|
||||
hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE,
|
||||
sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets,
|
||||
data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
|
||||
|
@ -1679,7 +1701,7 @@ int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
|
|||
return err;
|
||||
|
||||
__hci_req_update_scan_rsp_data(req, instance);
|
||||
__hci_req_enable_ext_advertising(req);
|
||||
__hci_req_enable_ext_advertising(req, instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1723,10 +1745,13 @@ int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
|
|||
adv_instance->remaining_time =
|
||||
adv_instance->remaining_time - timeout;
|
||||
|
||||
hdev->adv_instance_timeout = timeout;
|
||||
queue_delayed_work(hdev->req_workqueue,
|
||||
/* Only use work for scheduling instances with legacy advertising */
|
||||
if (!ext_adv_capable(hdev)) {
|
||||
hdev->adv_instance_timeout = timeout;
|
||||
queue_delayed_work(hdev->req_workqueue,
|
||||
&hdev->adv_instance_expire,
|
||||
msecs_to_jiffies(timeout * 1000));
|
||||
}
|
||||
|
||||
/* If we're just re-scheduling the same instance again then do not
|
||||
* execute any HCI commands. This happens when a single instance is
|
||||
|
@ -2744,7 +2769,8 @@ static int powered_update_hci(struct hci_request *req, unsigned long opt)
|
|||
if (!ext_adv_capable(hdev))
|
||||
__hci_req_enable_advertising(req);
|
||||
else if (!err)
|
||||
__hci_req_enable_ext_advertising(req);
|
||||
__hci_req_enable_ext_advertising(req,
|
||||
0x00);
|
||||
}
|
||||
} else if (!list_empty(&hdev->adv_instances)) {
|
||||
struct adv_info *adv_instance;
|
||||
|
|
|
@ -83,7 +83,7 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
|
|||
|
||||
int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance);
|
||||
int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
|
||||
void __hci_req_enable_ext_advertising(struct hci_request *req);
|
||||
int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance);
|
||||
void __hci_req_clear_ext_adv_sets(struct hci_request *req);
|
||||
int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
|
||||
bool use_rpa, struct adv_info *adv_instance,
|
||||
|
|
Загрузка…
Ссылка в новой задаче