Commit 04b4edcb authored by Johan Hedberg's avatar Johan Hedberg Committed by Gustavo Padovan

Bluetooth: Handle AD updating through an async request

For proper control of the AD update and the related HCI commands it's
best to run the AD update through an async request instead of a
standalone HCI command. This patch changes the hci_update_ad() function
to take a request pointer and updates its users appropriately. E.g. the
function is no longer called after the init sequence but during stage 3
of the init sequence.

The TX power is read during the init sequence, so we don't need an
explicit update whenever it is read and the AD update based on the local
name should be done through the local name mgmt handler. The only other
user is the update based on enabling advertising. This part is still
kept as there is no mgmt API to enable it.
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
parent 13928971
...@@ -740,8 +740,6 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, ...@@ -740,8 +740,6 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
u8 *randomizer); u8 *randomizer);
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_update_ad(struct hci_dev *hdev);
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
int hci_recv_frame(struct sk_buff *skb); int hci_recv_frame(struct sk_buff *skb);
...@@ -1167,6 +1165,8 @@ struct hci_sec_filter { ...@@ -1167,6 +1165,8 @@ struct hci_sec_filter {
#define hci_req_lock(d) mutex_lock(&d->req_lock) #define hci_req_lock(d) mutex_lock(&d->req_lock)
#define hci_req_unlock(d) mutex_unlock(&d->req_lock) #define hci_req_unlock(d) mutex_unlock(&d->req_lock)
void hci_update_ad(struct hci_request *req);
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
u16 latency, u16 to_multiplier); u16 latency, u16 to_multiplier);
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
......
...@@ -492,8 +492,10 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) ...@@ -492,8 +492,10 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
if (hdev->commands[5] & 0x10) if (hdev->commands[5] & 0x10)
hci_setup_link_policy(req); hci_setup_link_policy(req);
if (lmp_le_capable(hdev)) if (lmp_le_capable(hdev)) {
hci_set_le_support(req); hci_set_le_support(req);
hci_update_ad(req);
}
} }
static int __hci_init(struct hci_dev *hdev) static int __hci_init(struct hci_dev *hdev)
...@@ -936,39 +938,29 @@ static u8 create_ad(struct hci_dev *hdev, u8 *ptr) ...@@ -936,39 +938,29 @@ static u8 create_ad(struct hci_dev *hdev, u8 *ptr)
return ad_len; return ad_len;
} }
int hci_update_ad(struct hci_dev *hdev) void hci_update_ad(struct hci_request *req)
{ {
struct hci_dev *hdev = req->hdev;
struct hci_cp_le_set_adv_data cp; struct hci_cp_le_set_adv_data cp;
u8 len; u8 len;
int err;
hci_dev_lock(hdev);
if (!lmp_le_capable(hdev)) { if (!lmp_le_capable(hdev))
err = -EINVAL; return;
goto unlock;
}
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
len = create_ad(hdev, cp.data); len = create_ad(hdev, cp.data);
if (hdev->adv_data_len == len && if (hdev->adv_data_len == len &&
memcmp(cp.data, hdev->adv_data, len) == 0) { memcmp(cp.data, hdev->adv_data, len) == 0)
err = 0; return;
goto unlock;
}
memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
hdev->adv_data_len = len; hdev->adv_data_len = len;
cp.length = len; cp.length = len;
err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
unlock: hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
hci_dev_unlock(hdev);
return err;
} }
/* ---- HCI ioctl helpers ---- */ /* ---- HCI ioctl helpers ---- */
...@@ -1025,7 +1017,6 @@ int hci_dev_open(__u16 dev) ...@@ -1025,7 +1017,6 @@ int hci_dev_open(__u16 dev)
hci_dev_hold(hdev); hci_dev_hold(hdev);
set_bit(HCI_UP, &hdev->flags); set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP); hci_notify(hdev, HCI_DEV_UP);
hci_update_ad(hdev);
if (!test_bit(HCI_SETUP, &hdev->dev_flags) && if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
mgmt_valid_hdev(hdev)) { mgmt_valid_hdev(hdev)) {
hci_dev_lock(hdev); hci_dev_lock(hdev);
......
...@@ -223,9 +223,6 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -223,9 +223,6 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
if (!status && !test_bit(HCI_INIT, &hdev->flags))
hci_update_ad(hdev);
} }
static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
...@@ -776,11 +773,8 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, ...@@ -776,11 +773,8 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
if (!rp->status) { if (!rp->status)
hdev->adv_tx_power = rp->tx_power; hdev->adv_tx_power = rp->tx_power;
if (!test_bit(HCI_INIT, &hdev->flags))
hci_update_ad(hdev);
}
} }
static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
...@@ -877,10 +871,15 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -877,10 +871,15 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
} }
hci_dev_unlock(hdev); if (!test_bit(HCI_INIT, &hdev->flags)) {
struct hci_request req;
if (!test_bit(HCI_INIT, &hdev->flags)) hci_req_init(&req, hdev);
hci_update_ad(hdev); hci_update_ad(&req);
hci_req_run(&req, NULL);
}
hci_dev_unlock(hdev);
} }
static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment