mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 07:04:10 +08:00
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:
parent
c49a8682fc
commit
1d0fac2c38
@ -915,7 +915,7 @@ static void hci_req_directed_advertising(struct hci_request *req,
|
|||||||
sizeof(cp), &cp);
|
sizeof(cp), &cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
__hci_req_enable_ext_advertising(req);
|
__hci_req_enable_ext_advertising(req, 0x00);
|
||||||
} else {
|
} else {
|
||||||
struct hci_cp_le_set_adv_param cp;
|
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,
|
memset(adv_instance->scan_rsp_data, 0,
|
||||||
sizeof(adv_instance->scan_rsp_data));
|
sizeof(adv_instance->scan_rsp_data));
|
||||||
} else {
|
} 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)
|
instance < 1 || instance > HCI_MAX_ADV_INSTANCES)
|
||||||
return -EOVERFLOW;
|
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_min_key_size = SMP_MIN_ENC_KEY_SIZE;
|
||||||
hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M;
|
hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M;
|
||||||
hdev->le_rx_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->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT;
|
||||||
hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_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.own_addr_type = own_addr_type;
|
||||||
cp.channel_map = hdev->le_adv_channel_map;
|
cp.channel_map = hdev->le_adv_channel_map;
|
||||||
cp.tx_power = 127;
|
cp.tx_power = 127;
|
||||||
cp.handle = 0;
|
cp.handle = instance;
|
||||||
|
|
||||||
if (flags & MGMT_ADV_FLAG_SEC_2M) {
|
if (flags & MGMT_ADV_FLAG_SEC_2M) {
|
||||||
cp.primary_phy = HCI_ADV_PHY_1M;
|
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;
|
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_le_set_ext_adv_enable *cp;
|
||||||
struct hci_cp_ext_adv_set *adv_set;
|
struct hci_cp_ext_adv_set *adv_set;
|
||||||
u8 data[sizeof(*cp) + sizeof(*adv_set) * 1];
|
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;
|
cp = (void *) data;
|
||||||
adv_set = (void *) cp->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));
|
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,
|
hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE,
|
||||||
sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets,
|
sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets,
|
||||||
data);
|
data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
|
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;
|
return err;
|
||||||
|
|
||||||
__hci_req_update_scan_rsp_data(req, instance);
|
__hci_req_update_scan_rsp_data(req, instance);
|
||||||
__hci_req_enable_ext_advertising(req);
|
__hci_req_enable_ext_advertising(req, instance);
|
||||||
|
|
||||||
return 0;
|
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 =
|
||||||
adv_instance->remaining_time - timeout;
|
adv_instance->remaining_time - timeout;
|
||||||
|
|
||||||
hdev->adv_instance_timeout = timeout;
|
/* Only use work for scheduling instances with legacy advertising */
|
||||||
queue_delayed_work(hdev->req_workqueue,
|
if (!ext_adv_capable(hdev)) {
|
||||||
|
hdev->adv_instance_timeout = timeout;
|
||||||
|
queue_delayed_work(hdev->req_workqueue,
|
||||||
&hdev->adv_instance_expire,
|
&hdev->adv_instance_expire,
|
||||||
msecs_to_jiffies(timeout * 1000));
|
msecs_to_jiffies(timeout * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
/* If we're just re-scheduling the same instance again then do not
|
/* If we're just re-scheduling the same instance again then do not
|
||||||
* execute any HCI commands. This happens when a single instance is
|
* 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))
|
if (!ext_adv_capable(hdev))
|
||||||
__hci_req_enable_advertising(req);
|
__hci_req_enable_advertising(req);
|
||||||
else if (!err)
|
else if (!err)
|
||||||
__hci_req_enable_ext_advertising(req);
|
__hci_req_enable_ext_advertising(req,
|
||||||
|
0x00);
|
||||||
}
|
}
|
||||||
} else if (!list_empty(&hdev->adv_instances)) {
|
} else if (!list_empty(&hdev->adv_instances)) {
|
||||||
struct adv_info *adv_instance;
|
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_setup_ext_adv_instance(struct hci_request *req, u8 instance);
|
||||||
int __hci_req_start_ext_adv(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);
|
void __hci_req_clear_ext_adv_sets(struct hci_request *req);
|
||||||
int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
|
int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
|
||||||
bool use_rpa, struct adv_info *adv_instance,
|
bool use_rpa, struct adv_info *adv_instance,
|
||||||
|
Loading…
Reference in New Issue
Block a user