Skip to content

Commit

Permalink
Bluetooth: hci_sync: Add support for waiting specific LE subevents
Browse files Browse the repository at this point in the history
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: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Luiz Augusto von Dentz authored and Marcel Holtmann committed Dec 22, 2021
1 parent 8e8b92e commit 85b5685
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 16 deletions.
1 change: 1 addition & 0 deletions include/net/bluetooth/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
41 changes: 26 additions & 15 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -4038,15 +4038,14 @@ 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);
return;
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
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))
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -6764,8 +6774,8 @@ 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,
sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
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] */
HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt,
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/hci_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down

0 comments on commit 85b5685

Please sign in to comment.