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 /net/bluetooth/hci_request.c | |
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>
Diffstat (limited to 'net/bluetooth/hci_request.c')
-rw-r--r-- | net/bluetooth/hci_request.c | 40 |
1 files changed, 33 insertions, 7 deletions
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; |