diff options
author | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2019-06-03 06:48:42 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2019-07-06 09:38:18 -0400 |
commit | 1d0fac2c38edb25067e8f69195e2f76b67a2717d (patch) | |
tree | ae68e64fbf78fbbc62c10606d167a108f16f3ccc | |
parent | c49a8682fc5d298d44e8d911f4fa14690ea9485e (diff) |
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>
-rw-r--r-- | net/bluetooth/hci_conn.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 3 | ||||
-rw-r--r-- | net/bluetooth/hci_request.c | 40 | ||||
-rw-r--r-- | net/bluetooth/hci_request.h | 2 |
4 files changed, 37 insertions, 10 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 17e5111daa11..ad5b0ac1f9ce 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -915,7 +915,7 @@ static void hci_req_directed_advertising(struct hci_request *req, | |||
915 | sizeof(cp), &cp); | 915 | sizeof(cp), &cp); |
916 | } | 916 | } |
917 | 917 | ||
918 | __hci_req_enable_ext_advertising(req); | 918 | __hci_req_enable_ext_advertising(req, 0x00); |
919 | } else { | 919 | } else { |
920 | struct hci_cp_le_set_adv_param cp; | 920 | struct hci_cp_le_set_adv_param cp; |
921 | 921 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ff9a755f4df3..b9585e7d9d2e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -2827,7 +2827,7 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags, | |||
2827 | memset(adv_instance->scan_rsp_data, 0, | 2827 | memset(adv_instance->scan_rsp_data, 0, |
2828 | sizeof(adv_instance->scan_rsp_data)); | 2828 | sizeof(adv_instance->scan_rsp_data)); |
2829 | } else { | 2829 | } else { |
2830 | if (hdev->adv_instance_cnt >= HCI_MAX_ADV_INSTANCES || | 2830 | if (hdev->adv_instance_cnt >= hdev->le_num_of_adv_sets || |
2831 | instance < 1 || instance > HCI_MAX_ADV_INSTANCES) | 2831 | instance < 1 || instance > HCI_MAX_ADV_INSTANCES) |
2832 | return -EOVERFLOW; | 2832 | return -EOVERFLOW; |
2833 | 2833 | ||
@@ -3195,6 +3195,7 @@ struct hci_dev *hci_alloc_dev(void) | |||
3195 | hdev->le_min_key_size = SMP_MIN_ENC_KEY_SIZE; | 3195 | hdev->le_min_key_size = SMP_MIN_ENC_KEY_SIZE; |
3196 | hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M; | 3196 | hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M; |
3197 | hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M; | 3197 | hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M; |
3198 | hdev->le_num_of_adv_sets = HCI_MAX_ADV_INSTANCES; | ||
3198 | 3199 | ||
3199 | hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT; | 3200 | hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT; |
3200 | hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT; | 3201 | hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT; |
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index e9a95ed65491..621f1a97d803 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -1601,7 +1601,7 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance) | |||
1601 | cp.own_addr_type = own_addr_type; | 1601 | cp.own_addr_type = own_addr_type; |
1602 | cp.channel_map = hdev->le_adv_channel_map; | 1602 | cp.channel_map = hdev->le_adv_channel_map; |
1603 | cp.tx_power = 127; | 1603 | cp.tx_power = 127; |
1604 | cp.handle = 0; | 1604 | cp.handle = instance; |
1605 | 1605 | ||
1606 | if (flags & MGMT_ADV_FLAG_SEC_2M) { | 1606 | if (flags & MGMT_ADV_FLAG_SEC_2M) { |
1607 | cp.primary_phy = HCI_ADV_PHY_1M; | 1607 | cp.primary_phy = HCI_ADV_PHY_1M; |
@@ -1643,11 +1643,21 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance) | |||
1643 | return 0; | 1643 | return 0; |
1644 | } | 1644 | } |
1645 | 1645 | ||
1646 | void __hci_req_enable_ext_advertising(struct hci_request *req) | 1646 | int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance) |
1647 | { | 1647 | { |
1648 | struct hci_dev *hdev = req->hdev; | ||
1648 | struct hci_cp_le_set_ext_adv_enable *cp; | 1649 | struct hci_cp_le_set_ext_adv_enable *cp; |
1649 | struct hci_cp_ext_adv_set *adv_set; | 1650 | struct hci_cp_ext_adv_set *adv_set; |
1650 | u8 data[sizeof(*cp) + sizeof(*adv_set) * 1]; | 1651 | u8 data[sizeof(*cp) + sizeof(*adv_set) * 1]; |
1652 | struct adv_info *adv_instance; | ||
1653 | |||
1654 | if (instance > 0) { | ||
1655 | adv_instance = hci_find_adv_instance(hdev, instance); | ||
1656 | if (!adv_instance) | ||
1657 | return -EINVAL; | ||
1658 | } else { | ||
1659 | adv_instance = NULL; | ||
1660 | } | ||
1651 | 1661 | ||
1652 | cp = (void *) data; | 1662 | cp = (void *) data; |
1653 | adv_set = (void *) cp->data; | 1663 | adv_set = (void *) cp->data; |
@@ -1659,11 +1669,23 @@ void __hci_req_enable_ext_advertising(struct hci_request *req) | |||
1659 | 1669 | ||
1660 | memset(adv_set, 0, sizeof(*adv_set)); | 1670 | memset(adv_set, 0, sizeof(*adv_set)); |
1661 | 1671 | ||
1662 | adv_set->handle = 0; | 1672 | adv_set->handle = instance; |
1673 | |||
1674 | /* Set duration per instance since controller is responsible for | ||
1675 | * scheduling it. | ||
1676 | */ | ||
1677 | if (adv_instance && adv_instance->duration) { | ||
1678 | u16 duration = adv_instance->duration * MSEC_PER_SEC; | ||
1679 | |||
1680 | /* Time = N * 10 ms */ | ||
1681 | adv_set->duration = cpu_to_le16(duration / 10); | ||
1682 | } | ||
1663 | 1683 | ||
1664 | hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE, | 1684 | hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE, |
1665 | sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets, | 1685 | sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets, |
1666 | data); | 1686 | data); |
1687 | |||
1688 | return 0; | ||
1667 | } | 1689 | } |
1668 | 1690 | ||
1669 | int __hci_req_start_ext_adv(struct hci_request *req, u8 instance) | 1691 | 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) | |||
1679 | return err; | 1701 | return err; |
1680 | 1702 | ||
1681 | __hci_req_update_scan_rsp_data(req, instance); | 1703 | __hci_req_update_scan_rsp_data(req, instance); |
1682 | __hci_req_enable_ext_advertising(req); | 1704 | __hci_req_enable_ext_advertising(req, instance); |
1683 | 1705 | ||
1684 | return 0; | 1706 | return 0; |
1685 | } | 1707 | } |
@@ -1723,10 +1745,13 @@ int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance, | |||
1723 | adv_instance->remaining_time = | 1745 | adv_instance->remaining_time = |
1724 | adv_instance->remaining_time - timeout; | 1746 | adv_instance->remaining_time - timeout; |
1725 | 1747 | ||
1726 | hdev->adv_instance_timeout = timeout; | 1748 | /* Only use work for scheduling instances with legacy advertising */ |
1727 | queue_delayed_work(hdev->req_workqueue, | 1749 | if (!ext_adv_capable(hdev)) { |
1750 | hdev->adv_instance_timeout = timeout; | ||
1751 | queue_delayed_work(hdev->req_workqueue, | ||
1728 | &hdev->adv_instance_expire, | 1752 | &hdev->adv_instance_expire, |
1729 | msecs_to_jiffies(timeout * 1000)); | 1753 | msecs_to_jiffies(timeout * 1000)); |
1754 | } | ||
1730 | 1755 | ||
1731 | /* If we're just re-scheduling the same instance again then do not | 1756 | /* If we're just re-scheduling the same instance again then do not |
1732 | * execute any HCI commands. This happens when a single instance is | 1757 | * 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) | |||
2744 | if (!ext_adv_capable(hdev)) | 2769 | if (!ext_adv_capable(hdev)) |
2745 | __hci_req_enable_advertising(req); | 2770 | __hci_req_enable_advertising(req); |
2746 | else if (!err) | 2771 | else if (!err) |
2747 | __hci_req_enable_ext_advertising(req); | 2772 | __hci_req_enable_ext_advertising(req, |
2773 | 0x00); | ||
2748 | } | 2774 | } |
2749 | } else if (!list_empty(&hdev->adv_instances)) { | 2775 | } else if (!list_empty(&hdev->adv_instances)) { |
2750 | struct adv_info *adv_instance; | 2776 | struct adv_info *adv_instance; |
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h index 55b2050cc9ff..a7019fbeadd3 100644 --- a/net/bluetooth/hci_request.h +++ b/net/bluetooth/hci_request.h | |||
@@ -83,7 +83,7 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk, | |||
83 | 83 | ||
84 | int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance); | 84 | int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance); |
85 | int __hci_req_start_ext_adv(struct hci_request *req, u8 instance); | 85 | int __hci_req_start_ext_adv(struct hci_request *req, u8 instance); |
86 | void __hci_req_enable_ext_advertising(struct hci_request *req); | 86 | int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance); |
87 | void __hci_req_clear_ext_adv_sets(struct hci_request *req); | 87 | void __hci_req_clear_ext_adv_sets(struct hci_request *req); |
88 | int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, | 88 | int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, |
89 | bool use_rpa, struct adv_info *adv_instance, | 89 | bool use_rpa, struct adv_info *adv_instance, |