Commit 85b56857 authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz Committed by Marcel Holtmann

Bluetooth: hci_sync: Add support for waiting specific LE subevents

This adds support for waiting for specific LE subevents instead of
command status which may only indicate that the commands is in progress
and a different event is used to complete the operation.
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 8e8b92ee
......@@ -412,6 +412,7 @@ struct bt_skb_cb {
#define hci_skb_pkt_type(skb) bt_cb((skb))->pkt_type
#define hci_skb_expect(skb) bt_cb((skb))->expect
#define hci_skb_opcode(skb) bt_cb((skb))->hci.opcode
#define hci_skb_event(skb) bt_cb((skb))->hci.req_event
#define hci_skb_sk(skb) bt_cb((skb))->hci.sk
static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how)
......
......@@ -4038,16 +4038,15 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, void *data,
* (since for this kind of commands there will not be a command
* complete event).
*/
if (ev->status ||
(hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->hci.req_event))
if (ev->status || (hdev->sent_cmd && !hci_skb_event(hdev->sent_cmd))) {
hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
req_complete_skb);
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
bt_dev_err(hdev,
"unexpected event for opcode 0x%4.4x", *opcode);
bt_dev_err(hdev, "unexpected event for opcode 0x%4.4x",
*opcode);
return;
}
}
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
queue_work(hdev->workqueue, &hdev->cmd_work);
......@@ -6464,13 +6463,24 @@ static const struct hci_le_ev {
};
static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
struct sk_buff *skb, u16 *opcode, u8 *status,
hci_req_complete_t *req_complete,
hci_req_complete_skb_t *req_complete_skb)
{
struct hci_ev_le_meta *ev = data;
const struct hci_le_ev *subev;
bt_dev_dbg(hdev, "subevent 0x%2.2x", ev->subevent);
/* Only match event if command OGF is for LE */
if (hdev->sent_cmd &&
hci_opcode_ogf(hci_skb_opcode(hdev->sent_cmd)) == 0x08 &&
hci_skb_event(hdev->sent_cmd) == ev->subevent) {
*opcode = hci_skb_opcode(hdev->sent_cmd);
hci_req_cmd_complete(hdev, *opcode, 0x00, req_complete,
req_complete_skb);
}
subev = &hci_le_ev_table[ev->subevent];
if (!subev->func)
return;
......@@ -6764,7 +6774,7 @@ static const struct hci_ev {
HCI_EV(HCI_EV_REMOTE_HOST_FEATURES, hci_remote_host_features_evt,
sizeof(struct hci_ev_remote_host_features)),
/* [0x3e = HCI_EV_LE_META] */
HCI_EV_VL(HCI_EV_LE_META, hci_le_meta_evt,
HCI_EV_REQ_VL(HCI_EV_LE_META, hci_le_meta_evt,
sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
#if IS_ENABLED(CONFIG_BT_HS)
/* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */
......@@ -6849,11 +6859,12 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
goto done;
}
if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->hci.req_event == event) {
struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
opcode = __le16_to_cpu(cmd_hdr->opcode);
hci_req_cmd_complete(hdev, opcode, status, &req_complete,
&req_complete_skb);
/* Only match event if command OGF is not for LE */
if (hdev->sent_cmd &&
hci_opcode_ogf(hci_skb_opcode(hdev->sent_cmd)) != 0x08 &&
hci_skb_event(hdev->sent_cmd) == event) {
hci_req_cmd_complete(hdev, hci_skb_opcode(hdev->sent_cmd),
status, &req_complete, &req_complete_skb);
req_evt = event;
}
......
......@@ -103,7 +103,7 @@ static void hci_cmd_sync_add(struct hci_request *req, u16 opcode, u32 plen,
if (skb_queue_empty(&req->cmd_q))
bt_cb(skb)->hci.req_flags |= HCI_REQ_START;
bt_cb(skb)->hci.req_event = event;
hci_skb_event(skb) = event;
skb_queue_tail(&req->cmd_q, 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