All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] Rework parsing of HCI events
@ 2021-12-01  0:02 Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 01/15] skbuff: introduce skb_pull_data Luiz Augusto von Dentz
                   ` (14 more replies)
  0 siblings, 15 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This reworks the parsing of HCI events using skb_pull_data to check
event length, in addition to that it does introduce function tables to
handle events, LE subevents, Command Complete and Command Status which
simplify the callback by adding a common code that uses skb_pull_data
when parsing such events.

Luiz Augusto von Dentz (15):
  skbuff: introduce skb_pull_data
  Bluetooth: HCI: Use skb_pull_data to parse BR/EDR events
  Bluetooth: HCI: Use skb_pull_data to parse Command Complete event
  Bluetooth: HCI: Use skb_pull_data to parse Number of Complete Packets
    event
  Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result event
  Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result with RSSI
    event
  Bluetooth: HCI: Use skb_pull_data to parse Extended Inquiry Result
    event
  Bluetooth: HCI: Use skb_pull_data to parse LE Metaevents
  Bluetooth: HCI: Use skb_pull_data to parse LE Advertising Report event
  Bluetooth: HCI: Use skb_pull_data to parse LE Ext Advertising Report
    event
  Bluetooth: HCI: Use skb_pull_data to parse LE Direct Advertising
    Report event
  Bluetooth: hci_event: Use of a function table to handle HCI events
  Bluetooth: hci_event: Use of a function table to handle LE subevents
  Bluetooth: hci_event: Use of a function table to handle Command
    Complete
  Bluetooth: hci_event: Use of a function table to handle Command Status

 include/linux/skbuff.h      |    2 +
 include/net/bluetooth/hci.h |   59 +-
 net/bluetooth/hci_event.c   | 3031 +++++++++++++++++++----------------
 net/bluetooth/msft.c        |    2 +-
 net/bluetooth/msft.h        |    2 +-
 net/core/skbuff.c           |   23 +
 6 files changed, 1689 insertions(+), 1430 deletions(-)

-- 
2.33.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH 01/15] skbuff: introduce skb_pull_data
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  1:11   ` Jakub Kicinski
  2021-12-01  5:20   ` Dan Carpenter
  2021-12-01  0:02 ` [PATCH 02/15] Bluetooth: HCI: Use skb_pull_data to parse BR/EDR events Luiz Augusto von Dentz
                   ` (13 subsequent siblings)
  14 siblings, 2 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Like skb_pull but returns the original data pointer before pulling the
data after performing a check against sbk->len.

This allows to change code that does "struct foo *p = (void *)skb->data;"
which is hard to audit and error prone, to:

        p = skb_pull_data(skb, sizeof(*p));
        if (!p)
                return;

Which is both safer and cleaner.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
 include/linux/skbuff.h |  2 ++
 net/core/skbuff.c      | 23 +++++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index eba256af64a5..877dda38684a 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2373,6 +2373,8 @@ static inline void *skb_pull_inline(struct sk_buff *skb, unsigned int len)
 	return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
 }
 
+void *skb_pull_data(struct sk_buff *skb, size_t len);
+
 void *__pskb_pull_tail(struct sk_buff *skb, int delta);
 
 static inline void *__pskb_pull(struct sk_buff *skb, unsigned int len)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index a33247fdb8f5..0b19833ffbce 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2023,6 +2023,29 @@ void *skb_pull(struct sk_buff *skb, unsigned int len)
 }
 EXPORT_SYMBOL(skb_pull);
 
+/**
+ *	skb_pull_data - remove data from the start of a buffer returning its
+ *	original position.
+ *	@skb: buffer to use
+ *	@len: amount of data to remove
+ *
+ *	This function removes data from the start of a buffer, returning
+ *	the memory to the headroom. A pointer to the original data in the buffer
+ *	is returned after checking if there is enough data to pull. Once the
+ *	data has been pulled future pushes will overwrite the old data.
+ */
+void *skb_pull_data(struct sk_buff *skb, size_t len)
+{
+	void *data = skb->data;
+
+	if (skb->len < len)
+		return NULL;
+
+	skb_pull(skb, len);
+
+	return data;
+}
+
 /**
  *	skb_trim - remove end from a buffer
  *	@skb: buffer to alter
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 02/15] Bluetooth: HCI: Use skb_pull_data to parse BR/EDR events
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 01/15] skbuff: introduce skb_pull_data Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01 15:06     ` kernel test robot
  2021-12-01  0:02 ` [PATCH 03/15] Bluetooth: HCI: Use skb_pull_data to parse Command Complete event Luiz Augusto von Dentz
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses skb_pull_data to check the BR/EDR events received have the
minimum required length.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci.h |   4 +
 net/bluetooth/hci_event.c   | 260 +++++++++++++++++++++++++++++-------
 2 files changed, 217 insertions(+), 47 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 0d2a9216869b..ba89b078ceb5 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -2012,6 +2012,10 @@ struct hci_cp_le_reject_cis {
 } __packed;
 
 /* ---- HCI Events ---- */
+struct hci_ev_status {
+	__u8    status;
+} __packed;
+
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
 #define HCI_EV_INQUIRY_RESULT		0x02
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 9d8d2d9e5d1f..0266eab8a18c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -45,6 +45,18 @@
 
 /* Handle HCI Event packets */
 
+static void *hci_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,
+			     u8 ev, size_t len)
+{
+	void *data;
+
+	data = skb_pull_data(skb, len);
+	if (!data)
+		bt_dev_err(hdev, "Malformed Event: 0x%2.2x", ev);
+
+	return data;
+}
+
 static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
 				  u8 *new_status)
 {
@@ -2682,11 +2694,15 @@ static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
 
 static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *ev;
 	struct discovery_state *discov = &hdev->discovery;
 	struct inquiry_entry *e;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_COMPLETE, sizeof(*ev));
+	if (!ev)
+		return;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_conn_check_pending(hdev);
 
@@ -2780,9 +2796,13 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_conn_complete *ev = (void *) skb->data;
+	struct hci_ev_conn_complete *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CONN_COMPLETE, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -2904,12 +2924,16 @@ static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr)
 
 static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_conn_request *ev = (void *) skb->data;
+	struct hci_ev_conn_request *ev;
 	int mask = hdev->link_mode;
 	struct inquiry_entry *ie;
 	struct hci_conn *conn;
 	__u8 flags = 0;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CONN_REQUEST, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
 	       ev->link_type);
 
@@ -3015,12 +3039,16 @@ static u8 hci_to_mgmt_reason(u8 err)
 
 static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_disconn_complete *ev = (void *) skb->data;
+	struct hci_ev_disconn_complete *ev;
 	u8 reason;
 	struct hci_conn_params *params;
 	struct hci_conn *conn;
 	bool mgmt_connected;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_COMPLETE, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -3099,9 +3127,13 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_auth_complete *ev = (void *) skb->data;
+	struct hci_ev_auth_complete *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_AUTH_COMPLETE, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -3169,9 +3201,13 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_remote_name *ev = (void *) skb->data;
+	struct hci_ev_remote_name *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_NAME, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_conn_check_pending(hdev);
@@ -3252,9 +3288,13 @@ static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status,
 
 static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_encrypt_change *ev = (void *) skb->data;
+	struct hci_ev_encrypt_change *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_ENCRYPT_CHANGE, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -3367,9 +3407,14 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
 					     struct sk_buff *skb)
 {
-	struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
+	struct hci_ev_change_link_key_complete *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CHANGE_LINK_KEY_COMPLETE,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -3390,9 +3435,13 @@ static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
 static void hci_remote_features_evt(struct hci_dev *hdev,
 				    struct sk_buff *skb)
 {
-	struct hci_ev_remote_features *ev = (void *) skb->data;
+	struct hci_ev_remote_features *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_FEATURES, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -3841,9 +3890,11 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
 			       hci_req_complete_t *req_complete,
 			       hci_req_complete_skb_t *req_complete_skb)
 {
-	struct hci_ev_cmd_status *ev = (void *) skb->data;
+	struct hci_ev_cmd_status *ev;
 
-	skb_pull(skb, sizeof(*ev));
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CMD_STATUS, sizeof(*ev));
+	if (!ev)
+		return;
 
 	*opcode = __le16_to_cpu(ev->opcode);
 	*status = ev->status;
@@ -3951,7 +4002,11 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
 
 static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_hardware_error *ev = (void *) skb->data;
+	struct hci_ev_hardware_error *ev;
+
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_HARDWARE_ERROR, sizeof(*ev));
+	if (!ev)
+		return;
 
 	hdev->hw_error_code = ev->code;
 
@@ -3960,9 +4015,13 @@ static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_role_change *ev = (void *) skb->data;
+	struct hci_ev_role_change *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_ROLE_CHANGE, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -4070,17 +4129,19 @@ static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
 
 static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
+	struct hci_ev_num_comp_blocks *ev;
 	int i;
 
-	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
-		bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS, sizeof(*ev));
+	if (!ev)
 		return;
-	}
 
-	if (skb->len < sizeof(*ev) ||
-	    skb->len < struct_size(ev, handles, ev->num_hndl)) {
-		BT_DBG("%s bad parameters", hdev->name);
+	if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS,
+			     flex_array_size(ev, handles, ev->num_hndl)))
+		return;
+
+	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
+		bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
 		return;
 	}
 
@@ -4121,9 +4182,13 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_mode_change *ev = (void *) skb->data;
+	struct hci_ev_mode_change *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_MODE_CHANGE, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -4149,9 +4214,13 @@ static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_pin_code_req *ev = (void *) skb->data;
+	struct hci_ev_pin_code_req *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PIN_CODE_REQ, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -4219,11 +4288,15 @@ static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
 
 static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_link_key_req *ev = (void *) skb->data;
+	struct hci_ev_link_key_req *ev;
 	struct hci_cp_link_key_reply cp;
 	struct hci_conn *conn;
 	struct link_key *key;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LINK_KEY_REQ, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
@@ -4279,12 +4352,16 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_link_key_notify *ev = (void *) skb->data;
+	struct hci_ev_link_key_notify *ev;
 	struct hci_conn *conn;
 	struct link_key *key;
 	bool persistent;
 	u8 pin_len = 0;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LINK_KEY_NOTIFY, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -4339,9 +4416,13 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_clock_offset *ev = (void *) skb->data;
+	struct hci_ev_clock_offset *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CLOCK_OFFSET, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -4362,9 +4443,13 @@ static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_pkt_type_change *ev = (void *) skb->data;
+	struct hci_ev_pkt_type_change *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PKT_TYPE_CHANGE, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -4378,9 +4463,13 @@ static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
+	struct hci_ev_pscan_rep_mode *ev;
 	struct inquiry_entry *ie;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PSCAN_REP_MODE, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -4468,9 +4557,14 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
 static void hci_remote_ext_features_evt(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
-	struct hci_ev_remote_ext_features *ev = (void *) skb->data;
+	struct hci_ev_remote_ext_features *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_EXT_FEATURES,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -4532,9 +4626,13 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
 static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
 				       struct sk_buff *skb)
 {
-	struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
+	struct hci_ev_sync_conn_complete *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_SYNC_CONN_COMPLETE, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -4697,9 +4795,14 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
 static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
+	struct hci_ev_key_refresh_complete *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_KEY_REFRESH_COMPLETE,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
 	       __le16_to_cpu(ev->handle));
 
@@ -4806,9 +4909,13 @@ static u8 bredr_oob_data_present(struct hci_conn *conn)
 
 static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_io_capa_request *ev = (void *) skb->data;
+	struct hci_ev_io_capa_request *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_IO_CAPA_REQUEST, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -4875,9 +4982,13 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
+	struct hci_ev_io_capa_reply *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_IO_CAPA_REPLY, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -4896,10 +5007,15 @@ static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_user_confirm_request_evt(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
+	struct hci_ev_user_confirm_req *ev;
 	int loc_mitm, rem_mitm, confirm_hint = 0;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_CONFIRM_REQUEST,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -4981,7 +5097,12 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
 static void hci_user_passkey_request_evt(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_user_passkey_req *ev = (void *) skb->data;
+	struct hci_ev_user_passkey_req *ev;
+
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_PASSKEY_REQUEST,
+			     sizeof(*ev));
+	if (!ev)
+		return;
 
 	BT_DBG("%s", hdev->name);
 
@@ -4992,9 +5113,14 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev,
 static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
-	struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
+	struct hci_ev_user_passkey_notify *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_PASSKEY_NOTIFY,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
@@ -5012,9 +5138,13 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
 
 static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_keypress_notify *ev = (void *) skb->data;
+	struct hci_ev_keypress_notify *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_KEYPRESS_NOTIFY, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
@@ -5051,9 +5181,14 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
+	struct hci_ev_simple_pair_complete *ev;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_SIMPLE_PAIR_COMPLETE,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -5082,10 +5217,15 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
 static void hci_remote_host_features_evt(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_remote_host_features *ev = (void *) skb->data;
+	struct hci_ev_remote_host_features *ev;
 	struct inquiry_entry *ie;
 	struct hci_conn *conn;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_HOST_FEATURES,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -5104,9 +5244,14 @@ static void hci_remote_host_features_evt(struct hci_dev *hdev,
 static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
 					    struct sk_buff *skb)
 {
-	struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
+	struct hci_ev_remote_oob_data_request *ev;
 	struct oob_data *data;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_OOB_DATA_REQUEST,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
@@ -5158,12 +5303,14 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
 #if IS_ENABLED(CONFIG_BT_HS)
 static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_channel_selected *ev = (void *)skb->data;
+	struct hci_ev_channel_selected *ev;
 	struct hci_conn *hcon;
 
-	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CHANNEL_SELECTED, sizeof(*ev));
+	if (!ev)
+		return;
 
-	skb_pull(skb, sizeof(*ev));
+	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
 
 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
 	if (!hcon)
@@ -5175,9 +5322,13 @@ static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_phy_link_complete_evt(struct hci_dev *hdev,
 				      struct sk_buff *skb)
 {
-	struct hci_ev_phy_link_complete *ev = (void *) skb->data;
+	struct hci_ev_phy_link_complete *ev;
 	struct hci_conn *hcon, *bredr_hcon;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PHY_LINK_COMPLETE, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
 	       ev->status);
 
@@ -5215,11 +5366,16 @@ static void hci_phy_link_complete_evt(struct hci_dev *hdev,
 
 static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_logical_link_complete *ev = (void *) skb->data;
+	struct hci_ev_logical_link_complete *ev;
 	struct hci_conn *hcon;
 	struct hci_chan *hchan;
 	struct amp_mgr *mgr;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LOGICAL_LINK_COMPLETE,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
 	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
 	       ev->status);
@@ -5255,9 +5411,14 @@ static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
 					     struct sk_buff *skb)
 {
-	struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
+	struct hci_ev_disconn_logical_link_complete *ev;
 	struct hci_chan *hchan;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
 	       le16_to_cpu(ev->handle), ev->status);
 
@@ -5279,9 +5440,14 @@ static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
 static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
 					     struct sk_buff *skb)
 {
-	struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
+	struct hci_ev_disconn_phy_link_complete *ev;
 	struct hci_conn *hcon;
 
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_PHY_LINK_COMPLETE,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	if (ev->status)
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 03/15] Bluetooth: HCI: Use skb_pull_data to parse Command Complete event
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 01/15] skbuff: introduce skb_pull_data Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 02/15] Bluetooth: HCI: Use skb_pull_data to parse BR/EDR events Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 04/15] Bluetooth: HCI: Use skb_pull_data to parse Number of Complete Packets event Luiz Augusto von Dentz
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses skb_pull_data to check the Command Complete events received
have the minimum required length.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 net/bluetooth/hci_event.c | 904 ++++++++++++++++++++++++++++----------
 1 file changed, 663 insertions(+), 241 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0266eab8a18c..09d7d997c4b1 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -57,12 +57,28 @@ static void *hci_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,
 	return data;
 }
 
+static void *hci_cc_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,
+			     u16 op, size_t len)
+{
+	void *data;
+
+	data = skb_pull_data(skb, len);
+	if (!data)
+		bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x", op);
+
+	return data;
+}
+
 static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
 				  u8 *new_status)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_INQUIRY_CANCEL, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	/* It is possible that we receive Inquiry Complete event right
 	 * before we receive Inquiry Cancel Command Complete event, in
@@ -71,14 +87,14 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
 	 * we actually achieve what Inquiry Cancel wants to achieve,
 	 * which is to end the last Inquiry session.
 	 */
-	if (status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) {
+	if (rp->status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) {
 		bt_dev_warn(hdev, "Ignoring error of Inquiry Cancel command");
-		status = 0x00;
+		rp->status = 0x00;
 	}
 
-	*new_status = status;
+	*new_status = rp->status;
 
-	if (status)
+	if (rp->status)
 		return;
 
 	clear_bit(HCI_INQUIRY, &hdev->flags);
@@ -99,11 +115,15 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
 
 static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PERIODIC_INQ, sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	hci_dev_set_flag(hdev, HCI_PERIODIC_INQ);
@@ -111,11 +131,15 @@ static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_EXIT_PERIODIC_INQ, sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ);
@@ -126,15 +150,26 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
 					  struct sk_buff *skb)
 {
-	BT_DBG("%s", hdev->name);
+	struct hci_ev_status *rp;
+
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_REMOTE_NAME_REQ_CANCEL,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 }
 
 static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_role_discovery *rp = (void *) skb->data;
+	struct hci_rp_role_discovery *rp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_ROLE_DISCOVERY, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -150,10 +185,14 @@ static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_read_link_policy *rp = (void *) skb->data;
+	struct hci_rp_read_link_policy *rp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LINK_POLICY, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -169,11 +208,15 @@ static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_write_link_policy *rp = (void *) skb->data;
+	struct hci_rp_write_link_policy *rp;
 	struct hci_conn *conn;
 	void *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LINK_POLICY, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -194,9 +237,14 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
-	struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
+	struct hci_rp_read_def_link_policy *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DEF_LINK_POLICY,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -207,12 +255,17 @@ static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
 static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	void *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_DEF_LINK_POLICY,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
@@ -224,13 +277,17 @@ static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
 
 static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_RESET, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	clear_bit(HCI_RESET, &hdev->flags);
 
-	if (status)
+	if (rp->status)
 		return;
 
 	/* Reset all non-persistent flags */
@@ -258,10 +315,15 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_read_stored_link_key(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
-	struct hci_rp_read_stored_link_key *rp = (void *)skb->data;
+	struct hci_rp_read_stored_link_key *rp;
 	struct hci_cp_read_stored_link_key *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_STORED_LINK_KEY,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY);
 	if (!sent)
@@ -276,9 +338,14 @@ static void hci_cc_read_stored_link_key(struct hci_dev *hdev,
 static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
 					  struct sk_buff *skb)
 {
-	struct hci_rp_delete_stored_link_key *rp = (void *)skb->data;
+	struct hci_rp_delete_stored_link_key *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_DELETE_STORED_LINK_KEY,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -291,10 +358,14 @@ static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
 
 static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	void *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LOCAL_NAME, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
 	if (!sent)
@@ -303,8 +374,8 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_lock(hdev);
 
 	if (hci_dev_test_flag(hdev, HCI_MGMT))
-		mgmt_set_local_name_complete(hdev, sent, status);
-	else if (!status)
+		mgmt_set_local_name_complete(hdev, sent, rp->status);
+	else if (!rp->status)
 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
 
 	hci_dev_unlock(hdev);
@@ -312,9 +383,13 @@ static void hci_cc_write_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)
 {
-	struct hci_rp_read_local_name *rp = (void *) skb->data;
+	struct hci_rp_read_local_name *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_NAME, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -326,10 +401,14 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	void *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_AUTH_ENABLE, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
 	if (!sent)
@@ -337,7 +416,7 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hci_dev_lock(hdev);
 
-	if (!status) {
+	if (!rp->status) {
 		__u8 param = *((__u8 *) sent);
 
 		if (param == AUTH_ENABLED)
@@ -347,20 +426,24 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 
 	if (hci_dev_test_flag(hdev, HCI_MGMT))
-		mgmt_auth_enable_complete(hdev, status);
+		mgmt_auth_enable_complete(hdev, rp->status);
 
 	hci_dev_unlock(hdev);
 }
 
 static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	__u8 param;
 	void *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_ENCRYPT_MODE, sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
@@ -377,11 +460,15 @@ static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	__u8 param;
 	void *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SCAN_ENABLE, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
 	if (!sent)
@@ -391,7 +478,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hci_dev_lock(hdev);
 
-	if (status) {
+	if (rp->status) {
 		hdev->discov_timeout = 0;
 		goto done;
 	}
@@ -412,13 +499,17 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *)skb->data);
+	struct hci_ev_status *rp;
 	struct hci_cp_set_event_filter *cp;
 	void *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SCAN_ENABLE, sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_SET_EVENT_FLT);
@@ -435,25 +526,33 @@ static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_read_class_of_dev *rp = (void *) skb->data;
+	struct hci_rp_read_class_of_dev *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLASS_OF_DEV, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
 
 	memcpy(hdev->dev_class, rp->dev_class, 3);
 
-	BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
-	       hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
+	bt_dev_dbg(hdev, "class 0x%.2x%.2x%.2x", hdev->dev_class[2],
+		   hdev->dev_class[1], hdev->dev_class[0]);
 }
 
 static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	void *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLASS_OF_DEV, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
 	if (!sent)
@@ -461,21 +560,25 @@ static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hci_dev_lock(hdev);
 
-	if (status == 0)
+	if (!rp->status)
 		memcpy(hdev->dev_class, sent, 3);
 
 	if (hci_dev_test_flag(hdev, HCI_MGMT))
-		mgmt_set_class_of_dev_complete(hdev, sent, status);
+		mgmt_set_class_of_dev_complete(hdev, sent, rp->status);
 
 	hci_dev_unlock(hdev);
 }
 
 static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_read_voice_setting *rp = (void *) skb->data;
+	struct hci_rp_read_voice_setting *rp;
 	__u16 setting;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_VOICE_SETTING, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -487,7 +590,7 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hdev->voice_setting = setting;
 
-	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
+	bt_dev_dbg(hdev, "voice setting 0x%4.4x", setting);
 
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
@@ -496,13 +599,18 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_write_voice_setting(struct hci_dev *hdev,
 				       struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	__u16 setting;
 	void *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_VOICE_SETTING,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
@@ -516,7 +624,7 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev,
 
 	hdev->voice_setting = setting;
 
-	BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting);
+	bt_dev_dbg(hdev, "voice setting 0x%4.4x", setting);
 
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
@@ -525,24 +633,33 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev,
 static void hci_cc_read_num_supported_iac(struct hci_dev *hdev,
 					  struct sk_buff *skb)
 {
-	struct hci_rp_read_num_supported_iac *rp = (void *) skb->data;
+	struct hci_rp_read_num_supported_iac *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_NUM_SUPPORTED_IAC,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
 
 	hdev->num_iac = rp->num_iac;
 
-	BT_DBG("%s num iac %d", hdev->name, hdev->num_iac);
+	bt_dev_dbg(hdev, "num iac %d", hdev->num_iac);
 }
 
 static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	struct hci_cp_write_ssp_mode *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SSP_MODE, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
 	if (!sent)
@@ -550,14 +667,14 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hci_dev_lock(hdev);
 
-	if (!status) {
+	if (!rp->status) {
 		if (sent->mode)
 			hdev->features[1][0] |= LMP_HOST_SSP;
 		else
 			hdev->features[1][0] &= ~LMP_HOST_SSP;
 	}
 
-	if (!status) {
+	if (!rp->status) {
 		if (sent->mode)
 			hci_dev_set_flag(hdev, HCI_SSP_ENABLED);
 		else
@@ -569,10 +686,14 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	u8 status = *((u8 *) skb->data);
+	struct hci_ev_status *rp;
 	struct hci_cp_write_sc_support *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SC_SUPPORT, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
 	if (!sent)
@@ -580,14 +701,14 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hci_dev_lock(hdev);
 
-	if (!status) {
+	if (!rp->status) {
 		if (sent->support)
 			hdev->features[1][0] |= LMP_HOST_SC;
 		else
 			hdev->features[1][0] &= ~LMP_HOST_SC;
 	}
 
-	if (!hci_dev_test_flag(hdev, HCI_MGMT) && !status) {
+	if (!hci_dev_test_flag(hdev, HCI_MGMT) && !rp->status) {
 		if (sent->support)
 			hci_dev_set_flag(hdev, HCI_SC_ENABLED);
 		else
@@ -599,9 +720,13 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_read_local_version *rp = (void *) skb->data;
+	struct hci_rp_read_local_version *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_VERSION, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -619,9 +744,14 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_read_local_commands(struct hci_dev *hdev,
 				       struct sk_buff *skb)
 {
-	struct hci_rp_read_local_commands *rp = (void *) skb->data;
+	struct hci_rp_read_local_commands *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_COMMANDS,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -634,10 +764,15 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev,
 static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev,
 					     struct sk_buff *skb)
 {
-	struct hci_rp_read_auth_payload_to *rp = (void *)skb->data;
+	struct hci_rp_read_auth_payload_to *rp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_AUTH_PAYLOAD_TO,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -654,11 +789,15 @@ static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev,
 static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev,
 					      struct sk_buff *skb)
 {
-	struct hci_rp_write_auth_payload_to *rp = (void *)skb->data;
+	struct hci_rp_write_auth_payload_to *rp;
 	struct hci_conn *conn;
 	void *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_AUTH_PAYLOAD_TO, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -679,9 +818,14 @@ static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev,
 static void hci_cc_read_local_features(struct hci_dev *hdev,
 				       struct sk_buff *skb)
 {
-	struct hci_rp_read_local_features *rp = (void *) skb->data;
+	struct hci_rp_read_local_features *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_FEATURES,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -729,9 +873,14 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
 static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
-	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
+	struct hci_rp_read_local_ext_features *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_EXT_FEATURES,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -746,9 +895,14 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
 static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
 					  struct sk_buff *skb)
 {
-	struct hci_rp_read_flow_control_mode *rp = (void *) skb->data;
+	struct hci_rp_read_flow_control_mode *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_FLOW_CONTROL_MODE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -758,9 +912,13 @@ static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
 
 static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
+	struct hci_rp_read_buffer_size *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_BUFFER_SIZE, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -784,9 +942,13 @@ static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_read_bd_addr *rp = (void *) skb->data;
+	struct hci_rp_read_bd_addr *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_BD_ADDR, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -801,9 +963,14 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_read_local_pairing_opts(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
-	struct hci_rp_read_local_pairing_opts *rp = (void *) skb->data;
+	struct hci_rp_read_local_pairing_opts *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_PAIRING_OPTS,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -818,9 +985,14 @@ static void hci_cc_read_local_pairing_opts(struct hci_dev *hdev,
 static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
-	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
+	struct hci_rp_read_page_scan_activity *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_ACTIVITY,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -834,12 +1006,17 @@ static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
 static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
 					    struct sk_buff *skb)
 {
-	u8 status = *((u8 *) skb->data);
+	struct hci_ev_status *rp;
 	struct hci_cp_write_page_scan_activity *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_ACTIVITY,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
@@ -853,9 +1030,14 @@ static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
 static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
-	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
+	struct hci_rp_read_page_scan_type *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_TYPE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -867,12 +1049,17 @@ static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
 static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
-	u8 status = *((u8 *) skb->data);
+	struct hci_ev_status *rp;
 	u8 *type;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_PAGE_SCAN_TYPE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
@@ -883,9 +1070,14 @@ static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
 static void hci_cc_read_data_block_size(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
-	struct hci_rp_read_data_block_size *rp = (void *) skb->data;
+	struct hci_rp_read_data_block_size *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DATA_BLOCK_SIZE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -902,15 +1094,18 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev,
 
 static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_read_clock *rp = (void *) skb->data;
+	struct hci_rp_read_clock *rp;
 	struct hci_cp_read_clock *cp;
 	struct hci_conn *conn;
 
 	BT_DBG("%s", hdev->name);
 
-	if (skb->len < sizeof(*rp))
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLOCK, sizeof(*rp));
+	if (!rp)
 		return;
 
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
 	if (rp->status)
 		return;
 
@@ -938,9 +1133,14 @@ static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
 				       struct sk_buff *skb)
 {
-	struct hci_rp_read_local_amp_info *rp = (void *) skb->data;
+	struct hci_rp_read_local_amp_info *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_AMP_INFO,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -960,9 +1160,14 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
 static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
-	struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
+	struct hci_rp_read_inq_rsp_tx_power *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_INQ_RSP_TX_POWER,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -973,9 +1178,14 @@ static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
 static void hci_cc_read_def_err_data_reporting(struct hci_dev *hdev,
 					       struct sk_buff *skb)
 {
-	struct hci_rp_read_def_err_data_reporting *rp = (void *)skb->data;
+	struct hci_rp_read_def_err_data_reporting *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DEF_ERR_DATA_REPORTING,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -986,12 +1196,17 @@ static void hci_cc_read_def_err_data_reporting(struct hci_dev *hdev,
 static void hci_cc_write_def_err_data_reporting(struct hci_dev *hdev,
 						struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *)skb->data);
+	struct hci_ev_status *rp;
 	struct hci_cp_write_def_err_data_reporting *cp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING);
@@ -1003,11 +1218,15 @@ static void hci_cc_write_def_err_data_reporting(struct hci_dev *hdev,
 
 static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
+	struct hci_rp_pin_code_reply *rp;
 	struct hci_cp_pin_code_reply *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PIN_CODE_REPLY, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	hci_dev_lock(hdev);
 
@@ -1031,9 +1250,13 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
+	struct hci_rp_pin_code_neg_reply *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	hci_dev_lock(hdev);
 
@@ -1047,9 +1270,14 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
 				       struct sk_buff *skb)
 {
-	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
+	struct hci_rp_le_read_buffer_size *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_BUFFER_SIZE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -1065,7 +1293,12 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
 static void hci_cc_le_read_local_features(struct hci_dev *hdev,
 					  struct sk_buff *skb)
 {
-	struct hci_rp_le_read_local_features *rp = (void *) skb->data;
+	struct hci_rp_le_read_local_features *rp;
+
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_LOCAL_FEATURES,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
@@ -1078,9 +1311,14 @@ static void hci_cc_le_read_local_features(struct hci_dev *hdev,
 static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
-	struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
+	struct hci_rp_le_read_adv_tx_power *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_ADV_TX_POWER,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -1090,9 +1328,13 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
 
 static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
+	struct hci_rp_user_confirm_reply *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_CONFIRM_REPLY, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	hci_dev_lock(hdev);
 
@@ -1106,9 +1348,14 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
 					  struct sk_buff *skb)
 {
-	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
+	struct hci_rp_user_confirm_reply *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_CONFIRM_NEG_REPLY,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	hci_dev_lock(hdev);
 
@@ -1121,9 +1368,13 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
 
 static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
+	struct hci_rp_user_confirm_reply *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_PASSKEY_REPLY, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	hci_dev_lock(hdev);
 
@@ -1137,9 +1388,13 @@ static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
 					  struct sk_buff *skb)
 {
-	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
+	struct hci_rp_user_confirm_reply *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_PASSKEY_NEG_REPLY, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	hci_dev_lock(hdev);
 
@@ -1153,27 +1408,39 @@ static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
 static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
 				       struct sk_buff *skb)
 {
-	struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
+	struct hci_rp_read_local_oob_data *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_OOB_DATA, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 }
 
 static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
-	struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
+	struct hci_rp_read_local_oob_ext_data *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_OOB_EXT_DATA, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 }
 
 static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	bdaddr_t *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_RANDOM_ADDR, sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
@@ -1195,12 +1462,16 @@ static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	struct hci_cp_le_set_default_phy *cp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_DEFAULT_PHY, sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY);
@@ -1218,11 +1489,18 @@ static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
                                               struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	struct hci_cp_le_set_adv_set_rand_addr *cp;
 	struct adv_info *adv;
 
-	if (status)
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_SET_RAND_ADDR,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR);
@@ -1251,11 +1529,17 @@ static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
 
 static void hci_cc_le_remove_adv_set(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *)skb->data);
+	struct hci_ev_status *rp;
 	u8 *instance;
 	int err;
 
-	if (status)
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_REMOVE_ADV_SET, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	instance = hci_sent_cmd_data(hdev, HCI_OP_LE_REMOVE_ADV_SET);
@@ -1274,11 +1558,17 @@ static void hci_cc_le_remove_adv_set(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_le_clear_adv_sets(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *)skb->data);
+	struct hci_ev_status *rp;
 	struct adv_info *adv, *n;
 	int err;
 
-	if (status)
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_ADV_SETS, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	if (!hci_sent_cmd_data(hdev, HCI_OP_LE_CLEAR_ADV_SETS))
@@ -1301,9 +1591,14 @@ static void hci_cc_le_clear_adv_sets(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_le_read_transmit_power(struct hci_dev *hdev,
 					  struct sk_buff *skb)
 {
-	struct hci_rp_le_read_transmit_power *rp = (void *)skb->data;
+	struct hci_rp_le_read_transmit_power *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_TRANSMIT_POWER,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -1314,11 +1609,16 @@ static void hci_cc_le_read_transmit_power(struct hci_dev *hdev,
 
 static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 *sent, status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
+	__u8 *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_ENABLE, sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
@@ -1352,12 +1652,17 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
 {
 	struct hci_cp_le_set_ext_adv_enable *cp;
 	struct hci_cp_ext_adv_set *set;
-	__u8 status = *((__u8 *) skb->data);
 	struct adv_info *adv = NULL, *n;
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_ADV_ENABLE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE);
@@ -1414,11 +1719,15 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
 static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_cp_le_set_scan_param *cp;
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_SCAN_PARAM, sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM);
@@ -1436,12 +1745,17 @@ static void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
 	struct hci_cp_le_set_ext_scan_params *cp;
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 	struct hci_cp_le_scan_phy_params *phy_param;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_SCAN_PARAMS,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS);
@@ -1544,11 +1858,16 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 				      struct sk_buff *skb)
 {
 	struct hci_cp_le_set_scan_enable *cp;
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_SCAN_ENABLE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
@@ -1562,11 +1881,16 @@ static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev,
 				      struct sk_buff *skb)
 {
 	struct hci_cp_le_set_ext_scan_enable *cp;
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_SCAN_ENABLE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_ENABLE);
@@ -1579,10 +1903,15 @@ static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev,
 static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev,
 				      struct sk_buff *skb)
 {
-	struct hci_rp_le_read_num_supported_adv_sets *rp = (void *) skb->data;
+	struct hci_rp_le_read_num_supported_adv_sets *rp;
+
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	BT_DBG("%s status 0x%2.2x No of Adv sets %u", hdev->name, rp->status,
-	       rp->num_of_sets);
+	bt_dev_dbg(hdev, "status 0x%2.2x No of Adv sets %u", rp->status,
+		   rp->num_of_sets);
 
 	if (rp->status)
 		return;
@@ -1593,9 +1922,14 @@ static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev,
 static void hci_cc_le_read_accept_list_size(struct hci_dev *hdev,
 					    struct sk_buff *skb)
 {
-	struct hci_rp_le_read_accept_list_size *rp = (void *)skb->data;
+	struct hci_rp_le_read_accept_list_size *rp;
 
-	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_ACCEPT_LIST_SIZE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x size %u", rp->status, rp->size);
 
 	if (rp->status)
 		return;
@@ -1606,11 +1940,16 @@ static void hci_cc_le_read_accept_list_size(struct hci_dev *hdev,
 static void hci_cc_le_clear_accept_list(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_ACCEPT_LIST,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	hci_bdaddr_list_clear(&hdev->le_accept_list);
@@ -1620,11 +1959,16 @@ static void hci_cc_le_add_to_accept_list(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
 	struct hci_cp_le_add_to_accept_list *sent;
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_ADD_TO_ACCEPT_LIST,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST);
@@ -1639,11 +1983,16 @@ static void hci_cc_le_del_from_accept_list(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
 	struct hci_cp_le_del_from_accept_list *sent;
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_DEL_FROM_ACCEPT_LIST,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_ACCEPT_LIST);
@@ -1657,9 +2006,14 @@ static void hci_cc_le_del_from_accept_list(struct hci_dev *hdev,
 static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
 					    struct sk_buff *skb)
 {
-	struct hci_rp_le_read_supported_states *rp = (void *) skb->data;
+	struct hci_rp_le_read_supported_states *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_SUPPORTED_STATES,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -1670,9 +2024,14 @@ static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
 static void hci_cc_le_read_def_data_len(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
-	struct hci_rp_le_read_def_data_len *rp = (void *) skb->data;
+	struct hci_rp_le_read_def_data_len *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_DEF_DATA_LEN,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -1685,11 +2044,16 @@ static void hci_cc_le_write_def_data_len(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
 	struct hci_cp_le_write_def_data_len *sent;
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_WRITE_DEF_DATA_LEN,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN);
@@ -1704,11 +2068,16 @@ static void hci_cc_le_add_to_resolv_list(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
 	struct hci_cp_le_add_to_resolv_list *sent;
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_ADD_TO_RESOLV_LIST,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST);
@@ -1724,11 +2093,16 @@ static void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev,
 					  struct sk_buff *skb)
 {
 	struct hci_cp_le_del_from_resolv_list *sent;
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_DEL_FROM_RESOLV_LIST,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLV_LIST);
@@ -1742,11 +2116,16 @@ static void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev,
 static void hci_cc_le_clear_resolv_list(struct hci_dev *hdev,
 				       struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_RESOLV_LIST,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	hci_bdaddr_list_clear(&hdev->le_resolv_list);
@@ -1755,9 +2134,14 @@ static void hci_cc_le_clear_resolv_list(struct hci_dev *hdev,
 static void hci_cc_le_read_resolv_list_size(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
-	struct hci_rp_le_read_resolv_list_size *rp = (void *) skb->data;
+	struct hci_rp_le_read_resolv_list_size *rp;
 
-	BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_RESOLV_LIST_SIZE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x size %u", rp->status, rp->size);
 
 	if (rp->status)
 		return;
@@ -1768,11 +2152,17 @@ static void hci_cc_le_read_resolv_list_size(struct hci_dev *hdev,
 static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev,
 						struct sk_buff *skb)
 {
-	__u8 *sent, status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
+	__u8 *sent;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE);
@@ -1792,9 +2182,14 @@ static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev,
 static void hci_cc_le_read_max_data_len(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
-	struct hci_rp_le_read_max_data_len *rp = (void *) skb->data;
+	struct hci_rp_le_read_max_data_len *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_MAX_DATA_LEN,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -1809,11 +2204,16 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
 	struct hci_cp_write_le_host_supported *sent;
-	__u8 status = *((__u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LE_HOST_SUPPORTED,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
@@ -1842,11 +2242,15 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
 static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_cp_le_set_adv_param *cp;
-	u8 status = *((u8 *) skb->data);
+	struct hci_ev_status *rp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_PARAM, sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
@@ -1860,11 +2264,16 @@ static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_le_set_ext_adv_params *rp = (void *) skb->data;
+	struct hci_rp_le_set_ext_adv_params *rp;
 	struct hci_cp_le_set_ext_adv_params *cp;
 	struct adv_info *adv_instance;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_ADV_PARAMS,
+			     sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -1891,10 +2300,14 @@ static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_rp_read_rssi *rp = (void *) skb->data;
+	struct hci_rp_read_rssi *rp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_RSSI, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -1911,10 +2324,14 @@ static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_cp_read_tx_power *sent;
-	struct hci_rp_read_tx_power *rp = (void *) skb->data;
+	struct hci_rp_read_tx_power *rp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_TX_POWER, sizeof(*rp));
+	if (!rp)
+		return;
+
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
 		return;
@@ -1944,12 +2361,17 @@ static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	u8 status = *((u8 *) skb->data);
+	struct hci_ev_status *rp;
 	u8 *mode;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SSP_DEBUG_MODE,
+			     sizeof(*rp));
+	if (!rp)
+		return;
 
-	if (status)
+	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	if (rp->status)
 		return;
 
 	mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE);
@@ -3505,12 +3927,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
 				 hci_req_complete_t *req_complete,
 				 hci_req_complete_skb_t *req_complete_skb)
 {
-	struct hci_ev_cmd_complete *ev = (void *) skb->data;
+	struct hci_ev_cmd_complete *ev;
 
-	*opcode = __le16_to_cpu(ev->opcode);
-	*status = skb->data[sizeof(*ev)];
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CMD_COMPLETE, sizeof(*ev));
+	if (!ev)
+		return;
 
-	skb_pull(skb, sizeof(*ev));
+	*opcode = __le16_to_cpu(ev->opcode);
+	*status = skb->data[0];
 
 	switch (*opcode) {
 	case HCI_OP_INQUIRY_CANCEL:
@@ -6466,13 +6890,9 @@ static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
 	if (!skb)
 		return false;
 
-	if (skb->len < sizeof(*hdr)) {
-		bt_dev_err(hdev, "too short HCI event");
+	hdr = hci_ev_skb_pull(hdev, skb, event, sizeof(*hdr));
+	if (!hdr)
 		return false;
-	}
-
-	hdr = (void *) skb->data;
-	skb_pull(skb, HCI_EVENT_HDR_SIZE);
 
 	if (event) {
 		if (hdr->evt != event)
@@ -6492,13 +6912,9 @@ static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
 		return false;
 	}
 
-	if (skb->len < sizeof(*ev)) {
-		bt_dev_err(hdev, "too short cmd_complete event");
+	ev = hci_cc_skb_pull(hdev, skb, opcode, sizeof(*ev));
+	if (!ev)
 		return false;
-	}
-
-	ev = (void *) skb->data;
-	skb_pull(skb, sizeof(*ev));
 
 	if (opcode != __le16_to_cpu(ev->opcode)) {
 		BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode,
@@ -6584,9 +7000,15 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_req_complete_t req_complete = NULL;
 	hci_req_complete_skb_t req_complete_skb = NULL;
 	struct sk_buff *orig_skb = NULL;
-	u8 status = 0, event = hdr->evt, req_evt = 0;
+	u8 status = 0, event, req_evt = 0;
 	u16 opcode = HCI_OP_NOP;
 
+	if (skb->len < sizeof(*hdr)) {
+		bt_dev_err(hdev, "Malformed HCI Event");
+		goto done;
+	}
+
+	event = hdr->evt;
 	if (!event) {
 		bt_dev_warn(hdev, "Received unexpected HCI Event 00000000");
 		goto done;
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 04/15] Bluetooth: HCI: Use skb_pull_data to parse Number of Complete Packets event
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 03/15] Bluetooth: HCI: Use skb_pull_data to parse Command Complete event Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 05/15] Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result event Luiz Augusto von Dentz
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses skb_pull_data to check the Number of Complete Packets events
received have the minimum required length.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci.h |  2 +-
 net/bluetooth/hci_event.c   | 20 +++++++++++---------
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index ba89b078ceb5..3f57fd677b67 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -2139,7 +2139,7 @@ struct hci_comp_pkts_info {
 } __packed;
 
 struct hci_ev_num_comp_pkts {
-	__u8     num_hndl;
+	__u8     num;
 	struct hci_comp_pkts_info handles[];
 } __packed;
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 09d7d997c4b1..b27a4ad647ca 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4465,23 +4465,25 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
+	struct hci_ev_num_comp_pkts *ev;
 	int i;
 
-	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
-		bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_PKTS, sizeof(*ev));
+	if (!ev)
 		return;
-	}
 
-	if (skb->len < sizeof(*ev) ||
-	    skb->len < struct_size(ev, handles, ev->num_hndl)) {
-		BT_DBG("%s bad parameters", hdev->name);
+	if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_PKTS,
+			     flex_array_size(ev, handles, ev->num)))
+		return;
+
+	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
+		bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
 		return;
 	}
 
-	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
+	BT_DBG("%s num %d", hdev->name, ev->num);
 
-	for (i = 0; i < ev->num_hndl; i++) {
+	for (i = 0; i < ev->num; i++) {
 		struct hci_comp_pkts_info *info = &ev->handles[i];
 		struct hci_conn *conn;
 		__u16  handle, count;
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 05/15] Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result event
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (3 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 04/15] Bluetooth: HCI: Use skb_pull_data to parse Number of Complete Packets event Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 06/15] Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result with RSSI event Luiz Augusto von Dentz
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses skb_pull_data to check the Inquiry Result events received
have the minimum required length.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci.h |  5 +++++
 net/bluetooth/hci_event.c   | 19 ++++++++++++++-----
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 3f57fd677b67..55466bfb972a 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -2028,6 +2028,11 @@ struct inquiry_info {
 	__le16   clock_offset;
 } __packed;
 
+struct hci_ev_inquiry_result {
+	__u8    num;
+	struct inquiry_info info[];
+};
+
 #define HCI_EV_CONN_COMPLETE		0x03
 struct hci_ev_conn_complete {
 	__u8     status;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b27a4ad647ca..0bf062f6f262 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3180,13 +3180,21 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
+	struct hci_ev_inquiry_result *ev;
 	struct inquiry_data data;
-	struct inquiry_info *info = (void *) (skb->data + 1);
-	int num_rsp = *((__u8 *) skb->data);
+	int i;
 
-	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT, sizeof(*ev));
+	if (!ev)
+		return;
 
-	if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1)
+	if (!hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT,
+			     flex_array_size(ev, info, ev->num)))
+		return;
+
+	BT_DBG("%s num %d", hdev->name, ev->num);
+
+	if (!ev->num)
 		return;
 
 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
@@ -3194,7 +3202,8 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hci_dev_lock(hdev);
 
-	for (; num_rsp; num_rsp--, info++) {
+	for (i = 0; i < ev->num; i++) {
+		struct inquiry_info *info = &ev->info[i];
 		u32 flags;
 
 		bacpy(&data.bdaddr, &info->bdaddr);
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 06/15] Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result with RSSI event
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (4 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 05/15] Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result event Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 07/15] Bluetooth: HCI: Use skb_pull_data to parse Extended Inquiry Result event Luiz Augusto von Dentz
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses skb_pull_data to check the Inquiry Result with RSSI events
received have the minimum required length.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci.h | 12 +++++++++--
 net/bluetooth/hci_event.c   | 40 +++++++++++++++++++++----------------
 2 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 55466bfb972a..d25afd92a46e 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -2194,7 +2194,7 @@ struct hci_ev_pscan_rep_mode {
 } __packed;
 
 #define HCI_EV_INQUIRY_RESULT_WITH_RSSI	0x22
-struct inquiry_info_with_rssi {
+struct inquiry_info_rssi {
 	bdaddr_t bdaddr;
 	__u8     pscan_rep_mode;
 	__u8     pscan_period_mode;
@@ -2202,7 +2202,7 @@ struct inquiry_info_with_rssi {
 	__le16   clock_offset;
 	__s8     rssi;
 } __packed;
-struct inquiry_info_with_rssi_and_pscan_mode {
+struct inquiry_info_rssi_pscan {
 	bdaddr_t bdaddr;
 	__u8     pscan_rep_mode;
 	__u8     pscan_period_mode;
@@ -2211,6 +2211,14 @@ struct inquiry_info_with_rssi_and_pscan_mode {
 	__le16   clock_offset;
 	__s8     rssi;
 } __packed;
+struct hci_ev_inquiry_result_rssi {
+	__u8     num;
+	struct inquiry_info_rssi info[];
+} __packed;
+struct hci_ev_inquiry_result_rssi_pscan {
+	__u8     num;
+	struct inquiry_info_rssi_pscan info[];
+} __packed;
 
 #define HCI_EV_REMOTE_EXT_FEATURES	0x23
 struct hci_ev_remote_ext_features {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0bf062f6f262..6560dca8c5ce 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4921,12 +4921,21 @@ static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
 					     struct sk_buff *skb)
 {
+	union {
+		struct hci_ev_inquiry_result_rssi *res1;
+		struct hci_ev_inquiry_result_rssi_pscan *res2;
+	} *ev;
 	struct inquiry_data data;
-	int num_rsp = *((__u8 *) skb->data);
+	int i;
 
-	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT_WITH_RSSI,
+			     sizeof(*ev));
+	if (!ev)
+		return;
+
+	BT_DBG("%s num_rsp %d", hdev->name, ev->res1->num);
 
-	if (!num_rsp)
+	if (!ev->res1->num)
 		return;
 
 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
@@ -4934,16 +4943,13 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
 
 	hci_dev_lock(hdev);
 
-	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
-		struct inquiry_info_with_rssi_and_pscan_mode *info;
-		info = (void *) (skb->data + 1);
+	if (skb->len == flex_array_size(ev, res2->info, ev->res2->num)) {
+		struct inquiry_info_rssi_pscan *info;
 
-		if (skb->len < num_rsp * sizeof(*info) + 1)
-			goto unlock;
-
-		for (; num_rsp; num_rsp--, info++) {
+		for (i = 0; i < ev->res2->num; i++) {
 			u32 flags;
 
+			info = &ev->res2->info[i];
 			bacpy(&data.bdaddr, &info->bdaddr);
 			data.pscan_rep_mode	= info->pscan_rep_mode;
 			data.pscan_period_mode	= info->pscan_period_mode;
@@ -4959,15 +4965,13 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
 					  info->dev_class, info->rssi,
 					  flags, NULL, 0, NULL, 0);
 		}
-	} else {
-		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
+	} else if (skb->len == flex_array_size(ev, res1->info, ev->res1->num)) {
+		struct inquiry_info_rssi *info;
 
-		if (skb->len < num_rsp * sizeof(*info) + 1)
-			goto unlock;
-
-		for (; num_rsp; num_rsp--, info++) {
+		for (i = 0; i < ev->res1->num; i++) {
 			u32 flags;
 
+			info = &ev->res1->info[i];
 			bacpy(&data.bdaddr, &info->bdaddr);
 			data.pscan_rep_mode	= info->pscan_rep_mode;
 			data.pscan_period_mode	= info->pscan_period_mode;
@@ -4983,9 +4987,11 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
 					  info->dev_class, info->rssi,
 					  flags, NULL, 0, NULL, 0);
 		}
+	} else {
+		bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+			   HCI_EV_INQUIRY_RESULT_WITH_RSSI);
 	}
 
-unlock:
 	hci_dev_unlock(hdev);
 }
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 07/15] Bluetooth: HCI: Use skb_pull_data to parse Extended Inquiry Result event
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (5 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 06/15] Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result with RSSI event Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 08/15] Bluetooth: HCI: Use skb_pull_data to parse LE Metaevents Luiz Augusto von Dentz
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses skb_pull_data to check the Extended Inquiry Result events
received have the minimum required length.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci.h |  5 +++++
 net/bluetooth/hci_event.c   | 20 +++++++++++++++-----
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index d25afd92a46e..9e721e6efef3 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -2273,6 +2273,11 @@ struct extended_inquiry_info {
 	__u8     data[240];
 } __packed;
 
+struct hci_ev_ext_inquiry_result {
+	__u8     num;
+	struct extended_inquiry_info info[];
+} __packed;
+
 #define HCI_EV_KEY_REFRESH_COMPLETE	0x30
 struct hci_ev_key_refresh_complete {
 	__u8	status;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6560dca8c5ce..89c263c1883f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -5186,14 +5186,23 @@ static inline size_t eir_get_length(u8 *eir, size_t eir_len)
 static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
 					    struct sk_buff *skb)
 {
+	struct hci_ev_ext_inquiry_result *ev;
 	struct inquiry_data data;
-	struct extended_inquiry_info *info = (void *) (skb->data + 1);
-	int num_rsp = *((__u8 *) skb->data);
 	size_t eir_len;
+	int i;
 
-	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_EXTENDED_INQUIRY_RESULT,
+			     sizeof(*ev));
+	if (!ev)
+		return;
 
-	if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1)
+	if (!hci_ev_skb_pull(hdev, skb, HCI_EV_EXTENDED_INQUIRY_RESULT,
+			     flex_array_size(ev, info, ev->num)))
+		return;
+
+	BT_DBG("%s num %d", hdev->name, ev->num);
+
+	if (!ev->num)
 		return;
 
 	if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
@@ -5201,7 +5210,8 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
 
 	hci_dev_lock(hdev);
 
-	for (; num_rsp; num_rsp--, info++) {
+	for (i = 0; i < ev->num; i++) {
+		struct extended_inquiry_info *info = &ev->info[i];
 		u32 flags;
 		bool name_known;
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 08/15] Bluetooth: HCI: Use skb_pull_data to parse LE Metaevents
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (6 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 07/15] Bluetooth: HCI: Use skb_pull_data to parse Extended Inquiry Result event Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 09/15] Bluetooth: HCI: Use skb_pull_data to parse LE Advertising Report event Luiz Augusto von Dentz
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses skb_pull_data to check the LE Metaevents received have the
minimum required length.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 net/bluetooth/hci_event.c | 75 +++++++++++++++++++++++++++++++++------
 1 file changed, 64 insertions(+), 11 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 89c263c1883f..d30e77f66376 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -69,6 +69,18 @@ static void *hci_cc_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,
 	return data;
 }
 
+static void *hci_le_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,
+				u8 ev, size_t len)
+{
+	void *data;
+
+	data = skb_pull_data(skb, len);
+	if (!data)
+		bt_dev_err(hdev, "Malformed LE Event: 0x%2.2x", ev);
+
+	return data;
+}
+
 static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
 				  u8 *new_status)
 {
@@ -6119,7 +6131,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
 
 static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
+	struct hci_ev_le_conn_complete *ev;
+
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_CONN_COMPLETE,
+				sizeof(*ev));
+	if (!ev)
+		return;
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
@@ -6133,7 +6150,12 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_le_enh_conn_complete *ev = (void *) skb->data;
+	struct hci_ev_le_enh_conn_complete *ev;
+
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ENHANCED_CONN_COMPLETE,
+				sizeof(*ev));
+	if (!ev)
+		return;
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
@@ -6146,10 +6168,15 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
 
 static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_evt_le_ext_adv_set_term *ev = (void *) skb->data;
+	struct hci_evt_le_ext_adv_set_term *ev;
 	struct hci_conn *conn;
 	struct adv_info *adv, *n;
 
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_SET_TERM,
+				sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	adv = hci_find_adv_instance(hdev, ev->handle);
@@ -6211,9 +6238,14 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
 					    struct sk_buff *skb)
 {
-	struct hci_ev_le_conn_update_complete *ev = (void *) skb->data;
+	struct hci_ev_le_conn_update_complete *ev;
 	struct hci_conn *conn;
 
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_CONN_UPDATE_COMPLETE,
+				sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	if (ev->status)
@@ -6636,9 +6668,14 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
 					    struct sk_buff *skb)
 {
-	struct hci_ev_le_remote_feat_complete *ev = (void *)skb->data;
+	struct hci_ev_le_remote_feat_complete *ev;
 	struct hci_conn *conn;
 
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT,
+				sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	hci_dev_lock(hdev);
@@ -6677,12 +6714,16 @@ static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
 
 static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
+	struct hci_ev_le_ltk_req *ev;
 	struct hci_cp_le_ltk_reply cp;
 	struct hci_cp_le_ltk_neg_reply neg;
 	struct hci_conn *conn;
 	struct smp_ltk *ltk;
 
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_LTK_REQ, sizeof(*ev));
+	if (!ev)
+		return;
+
 	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
 
 	hci_dev_lock(hdev);
@@ -6754,11 +6795,16 @@ static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
 static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
 					     struct sk_buff *skb)
 {
-	struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data;
+	struct hci_ev_le_remote_conn_param_req *ev;
 	struct hci_cp_le_conn_param_req_reply cp;
 	struct hci_conn *hcon;
 	u16 handle, min, max, latency, timeout;
 
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_REMOTE_CONN_PARAM_REQ,
+				sizeof(*ev));
+	if (!ev)
+		return;
+
 	handle = le16_to_cpu(ev->handle);
 	min = le16_to_cpu(ev->interval_min);
 	max = le16_to_cpu(ev->interval_max);
@@ -6831,9 +6877,14 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
 
 static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_le_phy_update_complete *ev = (void *) skb->data;
+	struct hci_ev_le_phy_update_complete *ev;
 	struct hci_conn *conn;
 
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_PHY_UPDATE_COMPLETE,
+				sizeof(*ev));
+	if (ev)
+		return;
+
 	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
 	if (ev->status)
@@ -6854,11 +6905,13 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_ev_le_meta *le_ev = (void *) skb->data;
+	struct hci_ev_le_meta *ev;
 
-	skb_pull(skb, sizeof(*le_ev));
+	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LE_META, sizeof(*ev));
+	if (!ev)
+		return;
 
-	switch (le_ev->subevent) {
+	switch (ev->subevent) {
 	case HCI_EV_LE_CONN_COMPLETE:
 		hci_le_conn_complete_evt(hdev, skb);
 		break;
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 09/15] Bluetooth: HCI: Use skb_pull_data to parse LE Advertising Report event
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (7 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 08/15] Bluetooth: HCI: Use skb_pull_data to parse LE Metaevents Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 10/15] Bluetooth: HCI: Use skb_pull_data to parse LE Ext " Luiz Augusto von Dentz
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses skb_pull_data to check the LE Advertising Report events
received have the minimum required length.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci.h |  7 ++++++-
 net/bluetooth/hci_event.c   | 39 +++++++++++++++++++++++--------------
 2 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 9e721e6efef3..c005b1ccdbc5 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -2445,13 +2445,18 @@ struct hci_ev_le_conn_complete {
 
 #define HCI_EV_LE_ADVERTISING_REPORT	0x02
 struct hci_ev_le_advertising_info {
-	__u8	 evt_type;
+	__u8	 type;
 	__u8	 bdaddr_type;
 	bdaddr_t bdaddr;
 	__u8	 length;
 	__u8	 data[];
 } __packed;
 
+struct hci_ev_le_advertising_report {
+	__u8    num;
+	struct hci_ev_le_advertising_info info[];
+} __packed;
+
 #define HCI_EV_LE_CONN_UPDATE_COMPLETE	0x03
 struct hci_ev_le_conn_update_complete {
 	__u8     status;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d30e77f66376..42ffd5df6d4b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -6564,31 +6564,40 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
 
 static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	u8 num_reports = skb->data[0];
-	void *ptr = &skb->data[1];
+	struct hci_ev_le_advertising_report *ev;
+
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ADVERTISING_REPORT,
+				sizeof(*ev));
+	if (!ev)
+		return;
+
+	if (!ev->num)
+		return;
 
 	hci_dev_lock(hdev);
 
-	while (num_reports--) {
-		struct hci_ev_le_advertising_info *ev = ptr;
+	while (ev->num--) {
+		struct hci_ev_le_advertising_info *info;
 		s8 rssi;
 
-		if (ptr > (void *)skb_tail_pointer(skb) - sizeof(*ev)) {
-			bt_dev_err(hdev, "Malicious advertising data.");
+		info = hci_le_ev_skb_pull(hdev, skb,
+					  HCI_EV_LE_ADVERTISING_REPORT,
+					  sizeof(*info));
+		if (!info)
 			break;
-		}
 
-		if (ev->length <= HCI_MAX_AD_LENGTH &&
-		    ev->data + ev->length <= skb_tail_pointer(skb)) {
-			rssi = ev->data[ev->length];
-			process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
-					   ev->bdaddr_type, NULL, 0, rssi,
-					   ev->data, ev->length, false);
+		if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ADVERTISING_REPORT,
+					info->length + 1))
+			break;
+
+		if (info->length <= HCI_MAX_AD_LENGTH) {
+			rssi = info->data[info->length];
+			process_adv_report(hdev, info->type, &info->bdaddr,
+					   info->bdaddr_type, NULL, 0, rssi,
+					   info->data, info->length, false);
 		} else {
 			bt_dev_err(hdev, "Dropping invalid advertising data");
 		}
-
-		ptr += sizeof(*ev) + ev->length + 1;
 	}
 
 	hci_dev_unlock(hdev);
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 10/15] Bluetooth: HCI: Use skb_pull_data to parse LE Ext Advertising Report event
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (8 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 09/15] Bluetooth: HCI: Use skb_pull_data to parse LE Advertising Report event Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 11/15] Bluetooth: HCI: Use skb_pull_data to parse LE Direct " Luiz Augusto von Dentz
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses skb_pull_data to check the LE Extended Advertising Report
events received have the minimum required length.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci.h | 17 +++++++++++------
 net/bluetooth/hci_event.c   | 36 +++++++++++++++++++++++++-----------
 2 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index c005b1ccdbc5..d3f2da9b2ac2 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -2517,8 +2517,8 @@ struct hci_ev_le_phy_update_complete {
 } __packed;
 
 #define HCI_EV_LE_EXT_ADV_REPORT    0x0d
-struct hci_ev_le_ext_adv_report {
-	__le16 	 evt_type;
+struct hci_ev_le_ext_adv_info {
+	__le16   type;
 	__u8	 bdaddr_type;
 	bdaddr_t bdaddr;
 	__u8	 primary_phy;
@@ -2526,11 +2526,16 @@ struct hci_ev_le_ext_adv_report {
 	__u8	 sid;
 	__u8	 tx_power;
 	__s8	 rssi;
-	__le16 	 interval;
-	__u8  	 direct_addr_type;
+	__le16   interval;
+	__u8     direct_addr_type;
 	bdaddr_t direct_addr;
-	__u8  	 length;
-	__u8	 data[];
+	__u8     length;
+	__u8     data[];
+} __packed;
+
+struct hci_ev_le_ext_adv_report {
+	__u8     num;
+	struct hci_ev_le_ext_adv_info info[];
 } __packed;
 
 #define HCI_EV_LE_ENHANCED_CONN_COMPLETE    0x0a
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 42ffd5df6d4b..23cfcb1c0ca3 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -6649,26 +6649,40 @@ static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type)
 
 static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	u8 num_reports = skb->data[0];
-	void *ptr = &skb->data[1];
+	struct hci_ev_le_ext_adv_report *ev;
+
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT,
+				sizeof(*ev));
+	if (!ev)
+		return;
+
+	if (!ev->num)
+		return;
 
 	hci_dev_lock(hdev);
 
-	while (num_reports--) {
-		struct hci_ev_le_ext_adv_report *ev = ptr;
+	while (ev->num--) {
+		struct hci_ev_le_ext_adv_info *info;
 		u8 legacy_evt_type;
 		u16 evt_type;
 
-		evt_type = __le16_to_cpu(ev->evt_type);
+		info = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT,
+					  sizeof(*info));
+		if (!info)
+			break;
+
+		if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT,
+					info->length))
+			break;
+
+		evt_type = __le16_to_cpu(info->type);
 		legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type);
 		if (legacy_evt_type != LE_ADV_INVALID) {
-			process_adv_report(hdev, legacy_evt_type, &ev->bdaddr,
-					   ev->bdaddr_type, NULL, 0, ev->rssi,
-					   ev->data, ev->length,
+			process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
+					   info->bdaddr_type, NULL, 0,
+					   info->rssi, info->data, info->length,
 					   !(evt_type & LE_EXT_ADV_LEGACY_PDU));
 		}
-
-		ptr += sizeof(*ev) + ev->length;
 	}
 
 	hci_dev_unlock(hdev);
@@ -7019,7 +7033,7 @@ static void hci_store_wake_reason(struct hci_dev *hdev, u8 event,
 {
 	struct hci_ev_le_advertising_info *adv;
 	struct hci_ev_le_direct_adv_info *direct_adv;
-	struct hci_ev_le_ext_adv_report *ext_adv;
+	struct hci_ev_le_ext_adv_info *ext_adv;
 	const struct hci_ev_conn_complete *conn_complete = (void *)skb->data;
 	const struct hci_ev_conn_request *conn_request = (void *)skb->data;
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 11/15] Bluetooth: HCI: Use skb_pull_data to parse LE Direct Advertising Report event
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (9 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 10/15] Bluetooth: HCI: Use skb_pull_data to parse LE Ext " Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events Luiz Augusto von Dentz
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This uses skb_pull_data to check the LE Direct Advertising Report
events received have the minimum required length.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci.h |  7 ++++++-
 net/bluetooth/hci_event.c   | 26 +++++++++++++++++++-------
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index d3f2da9b2ac2..4343f79bd02c 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -2500,7 +2500,7 @@ struct hci_ev_le_data_len_change {
 
 #define HCI_EV_LE_DIRECT_ADV_REPORT	0x0B
 struct hci_ev_le_direct_adv_info {
-	__u8	 evt_type;
+	__u8	 type;
 	__u8	 bdaddr_type;
 	bdaddr_t bdaddr;
 	__u8	 direct_addr_type;
@@ -2508,6 +2508,11 @@ struct hci_ev_le_direct_adv_info {
 	__s8	 rssi;
 } __packed;
 
+struct hci_ev_le_direct_adv_report {
+	__u8	 num;
+	struct hci_ev_le_direct_adv_info info[];
+} __packed;
+
 #define HCI_EV_LE_PHY_UPDATE_COMPLETE	0x0c
 struct hci_ev_le_phy_update_complete {
 	__u8  status;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 23cfcb1c0ca3..8f21405997d1 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -6881,19 +6881,31 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
 static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
 					 struct sk_buff *skb)
 {
-	u8 num_reports = skb->data[0];
-	struct hci_ev_le_direct_adv_info *ev = (void *)&skb->data[1];
+	struct hci_ev_le_direct_adv_report *ev;
+	int i;
+
+	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT,
+				sizeof(*ev));
+	if (!ev)
+		return;
 
-	if (!num_reports || skb->len < num_reports * sizeof(*ev) + 1)
+	if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT,
+				flex_array_size(ev, info, ev->num)))
+		return;
+
+	if (!ev->num)
 		return;
 
 	hci_dev_lock(hdev);
 
-	for (; num_reports; num_reports--, ev++)
-		process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
-				   ev->bdaddr_type, &ev->direct_addr,
-				   ev->direct_addr_type, ev->rssi, NULL, 0,
+	for (i = 0; i < ev->num; i++) {
+		struct hci_ev_le_direct_adv_info *info = &ev->info[i];
+
+		process_adv_report(hdev, info->type, &info->bdaddr,
+				   info->bdaddr_type, &info->direct_addr,
+				   info->direct_addr_type, info->rssi, NULL, 0,
 				   false);
+	}
 
 	hci_dev_unlock(hdev);
 }
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (10 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 11/15] Bluetooth: HCI: Use skb_pull_data to parse LE Direct " Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  1:54     ` kernel test robot
                     ` (3 more replies)
  2021-12-01  0:02 ` [PATCH 13/15] Bluetooth: hci_event: Use of a function table to handle LE subevents Luiz Augusto von Dentz
                   ` (2 subsequent siblings)
  14 siblings, 4 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This change the use of switch statement to a function table
which is easier to extend and can include min/max length of each HCI
event.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 net/bluetooth/hci_event.c | 903 ++++++++++++++++----------------------
 net/bluetooth/msft.c      |   2 +-
 net/bluetooth/msft.h      |   2 +-
 3 files changed, 391 insertions(+), 516 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8f21405997d1..6fbb16997849 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3126,17 +3126,14 @@ static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_inquiry_complete_evt(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_ev_status *ev;
+	struct hci_ev_status *ev = data;
 	struct discovery_state *discov = &hdev->discovery;
 	struct inquiry_entry *e;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_COMPLETE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_conn_check_pending(hdev);
 
@@ -3190,21 +3187,18 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_inquiry_result_evt(struct hci_dev *hdev, void *edata,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_inquiry_result *ev;
+	struct hci_ev_inquiry_result *ev = edata;
 	struct inquiry_data data;
 	int i;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT, sizeof(*ev));
-	if (!ev)
-		return;
-
 	if (!hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT,
 			     flex_array_size(ev, info, ev->num)))
 		return;
 
-	BT_DBG("%s num %d", hdev->name, ev->num);
+	bt_dev_dbg(hdev, "num %d", ev->num);
 
 	if (!ev->num)
 		return;
@@ -3237,16 +3231,13 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_ev_conn_complete *ev;
+	struct hci_ev_conn_complete *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CONN_COMPLETE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -3365,20 +3356,16 @@ static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr)
 	hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
 }
 
-static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
+				 struct sk_buff *skb)
 {
-	struct hci_ev_conn_request *ev;
+	struct hci_ev_conn_request *ev = data;
 	int mask = hdev->link_mode;
 	struct inquiry_entry *ie;
 	struct hci_conn *conn;
 	__u8 flags = 0;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CONN_REQUEST, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
-	       ev->link_type);
+	bt_dev_dbg(hdev, "bdaddr %pMR type 0x%x", &ev->bdaddr, ev->link_type);
 
 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
 				      &flags);
@@ -3480,19 +3467,16 @@ static u8 hci_to_mgmt_reason(u8 err)
 	}
 }
 
-static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_ev_disconn_complete *ev;
+	struct hci_ev_disconn_complete *ev = data;
 	u8 reason;
 	struct hci_conn_params *params;
 	struct hci_conn *conn;
 	bool mgmt_connected;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_COMPLETE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -3568,16 +3552,13 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_auth_complete_evt(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_ev_auth_complete *ev;
+	struct hci_ev_auth_complete *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_AUTH_COMPLETE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -3642,16 +3623,13 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_remote_name_evt(struct hci_dev *hdev, void *data,
+				struct sk_buff *skb)
 {
-	struct hci_ev_remote_name *ev;
+	struct hci_ev_remote_name *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_NAME, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_conn_check_pending(hdev);
 
@@ -3729,16 +3707,13 @@ static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_encrypt_change *ev;
+	struct hci_ev_encrypt_change *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_ENCRYPT_CHANGE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -3847,18 +3822,13 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
+static void hci_change_link_key_complete_evt(struct hci_dev *hdev, void *data,
 					     struct sk_buff *skb)
 {
-	struct hci_ev_change_link_key_complete *ev;
+	struct hci_ev_change_link_key_complete *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CHANGE_LINK_KEY_COMPLETE,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -3875,17 +3845,13 @@ static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_remote_features_evt(struct hci_dev *hdev,
+static void hci_remote_features_evt(struct hci_dev *hdev, void *data,
 				    struct sk_buff *skb)
 {
-	struct hci_ev_remote_features *ev;
+	struct hci_ev_remote_features *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_FEATURES, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -3943,16 +3909,12 @@ static inline void handle_cmd_cnt_and_timer(struct hci_dev *hdev, u8 ncmd)
 	}
 }
 
-static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
-				 u16 *opcode, u8 *status,
+static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
+				 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_cmd_complete *ev;
-
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CMD_COMPLETE, sizeof(*ev));
-	if (!ev)
-		return;
+	struct hci_ev_cmd_complete *ev = data;
 
 	*opcode = __le16_to_cpu(ev->opcode);
 	*status = skb->data[0];
@@ -4330,16 +4292,12 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
 		queue_work(hdev->workqueue, &hdev->cmd_work);
 }
 
-static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
-			       u16 *opcode, u8 *status,
+static void hci_cmd_status_evt(struct hci_dev *hdev, void *data,
+			       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_cmd_status *ev;
-
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CMD_STATUS, sizeof(*ev));
-	if (!ev)
-		return;
+	struct hci_ev_cmd_status *ev = data;
 
 	*opcode = __le16_to_cpu(ev->opcode);
 	*status = ev->status;
@@ -4445,29 +4403,25 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
 		queue_work(hdev->workqueue, &hdev->cmd_work);
 }
 
-static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_hardware_error_evt(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_hardware_error *ev;
+	struct hci_ev_hardware_error *ev = data;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_HARDWARE_ERROR, sizeof(*ev));
-	if (!ev)
-		return;
+	bt_dev_dbg(hdev, "code 0x%2.2x", ev->code);
 
 	hdev->hw_error_code = ev->code;
 
 	queue_work(hdev->req_workqueue, &hdev->error_reset);
 }
 
-static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_role_change_evt(struct hci_dev *hdev, void *data,
+				struct sk_buff *skb)
 {
-	struct hci_ev_role_change *ev;
+	struct hci_ev_role_change *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_ROLE_CHANGE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -4484,15 +4438,12 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_ev_num_comp_pkts *ev;
+	struct hci_ev_num_comp_pkts *ev = data;
 	int i;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_PKTS, sizeof(*ev));
-	if (!ev)
-		return;
-
 	if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_PKTS,
 			     flex_array_size(ev, handles, ev->num)))
 		return;
@@ -4502,7 +4453,7 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		return;
 	}
 
-	BT_DBG("%s num %d", hdev->name, ev->num);
+	bt_dev_dbg(hdev, "num %d", ev->num);
 
 	for (i = 0; i < ev->num; i++) {
 		struct hci_comp_pkts_info *info = &ev->handles[i];
@@ -4574,26 +4525,24 @@ static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
 	return NULL;
 }
 
-static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_num_comp_blocks_evt(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_ev_num_comp_blocks *ev;
+	struct hci_ev_num_comp_blocks *ev = data;
 	int i;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS, sizeof(*ev));
-	if (!ev)
-		return;
-
 	if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS,
 			     flex_array_size(ev, handles, ev->num_hndl)))
 		return;
 
 	if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
-		bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
+		bt_dev_err(hdev, "wrong event for mode %d",
+			   hdev->flow_ctl_mode);
 		return;
 	}
 
-	BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks,
-	       ev->num_hndl);
+	bt_dev_dbg(hdev, "num_blocks %d num_hndl %d", ev->num_blocks,
+		   ev->num_hndl);
 
 	for (i = 0; i < ev->num_hndl; i++) {
 		struct hci_comp_blocks_info *info = &ev->handles[i];
@@ -4627,16 +4576,13 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	queue_work(hdev->workqueue, &hdev->tx_work);
 }
 
-static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_mode_change_evt(struct hci_dev *hdev, void *data,
+				struct sk_buff *skb)
 {
-	struct hci_ev_mode_change *ev;
+	struct hci_ev_mode_change *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_MODE_CHANGE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -4659,16 +4605,13 @@ static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_pin_code_request_evt(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_ev_pin_code_req *ev;
+	struct hci_ev_pin_code_req *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PIN_CODE_REQ, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	hci_dev_lock(hdev);
 
@@ -4733,18 +4676,15 @@ static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
 	}
 }
 
-static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_link_key_request_evt(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_ev_link_key_req *ev;
+	struct hci_ev_link_key_req *ev = data;
 	struct hci_cp_link_key_reply cp;
 	struct hci_conn *conn;
 	struct link_key *key;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LINK_KEY_REQ, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	if (!hci_dev_test_flag(hdev, HCI_MGMT))
 		return;
@@ -4753,13 +4693,11 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
 	key = hci_find_link_key(hdev, &ev->bdaddr);
 	if (!key) {
-		BT_DBG("%s link key not found for %pMR", hdev->name,
-		       &ev->bdaddr);
+		bt_dev_dbg(hdev, "link key not found for %pMR", &ev->bdaddr);
 		goto not_found;
 	}
 
-	BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
-	       &ev->bdaddr);
+	bt_dev_dbg(hdev, "found key type %u for %pMR", key->type, &ev->bdaddr);
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
 	if (conn) {
@@ -4768,15 +4706,14 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
 		     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
 		    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
-			BT_DBG("%s ignoring unauthenticated key", hdev->name);
+			bt_dev_dbg(hdev, "ignoring unauthenticated key");
 			goto not_found;
 		}
 
 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
 		    (conn->pending_sec_level == BT_SECURITY_HIGH ||
 		     conn->pending_sec_level == BT_SECURITY_FIPS)) {
-			BT_DBG("%s ignoring key unauthenticated for high security",
-			       hdev->name);
+			bt_dev_dbg(hdev, "ignoring key unauthenticated for high security");
 			goto not_found;
 		}
 
@@ -4797,19 +4734,16 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_link_key_notify_evt(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_ev_link_key_notify *ev;
+	struct hci_ev_link_key_notify *ev = data;
 	struct hci_conn *conn;
 	struct link_key *key;
 	bool persistent;
 	u8 pin_len = 0;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LINK_KEY_NOTIFY, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	hci_dev_lock(hdev);
 
@@ -4861,16 +4795,13 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_clock_offset_evt(struct hci_dev *hdev, void *data,
+				 struct sk_buff *skb)
 {
-	struct hci_ev_clock_offset *ev;
+	struct hci_ev_clock_offset *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CLOCK_OFFSET, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -4888,16 +4819,13 @@ static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_pkt_type_change_evt(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_ev_pkt_type_change *ev;
+	struct hci_ev_pkt_type_change *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PKT_TYPE_CHANGE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -4908,16 +4836,13 @@ static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_pscan_rep_mode *ev;
+	struct hci_ev_pscan_rep_mode *ev = data;
 	struct inquiry_entry *ie;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PSCAN_REP_MODE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	hci_dev_lock(hdev);
 
@@ -4930,22 +4855,17 @@ static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
+static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, void *edata,
 					     struct sk_buff *skb)
 {
 	union {
 		struct hci_ev_inquiry_result_rssi *res1;
 		struct hci_ev_inquiry_result_rssi_pscan *res2;
-	} *ev;
+	} *ev = edata;
 	struct inquiry_data data;
 	int i;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT_WITH_RSSI,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s num_rsp %d", hdev->name, ev->res1->num);
+	bt_dev_dbg(hdev, "num_rsp %d", ev->res1->num);
 
 	if (!ev->res1->num)
 		return;
@@ -5007,18 +4927,13 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_remote_ext_features_evt(struct hci_dev *hdev,
+static void hci_remote_ext_features_evt(struct hci_dev *hdev, void *data,
 					struct sk_buff *skb)
 {
-	struct hci_ev_remote_ext_features *ev;
+	struct hci_ev_remote_ext_features *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_EXT_FEATURES,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -5076,17 +4991,13 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
+static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
 				       struct sk_buff *skb)
 {
-	struct hci_ev_sync_conn_complete *ev;
+	struct hci_ev_sync_conn_complete *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_SYNC_CONN_COMPLETE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -5195,24 +5106,19 @@ static inline size_t eir_get_length(u8 *eir, size_t eir_len)
 	return eir_len;
 }
 
-static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
+static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, void *edata,
 					    struct sk_buff *skb)
 {
-	struct hci_ev_ext_inquiry_result *ev;
+	struct hci_ev_ext_inquiry_result *ev = edata;
 	struct inquiry_data data;
 	size_t eir_len;
 	int i;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_EXTENDED_INQUIRY_RESULT,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
 	if (!hci_ev_skb_pull(hdev, skb, HCI_EV_EXTENDED_INQUIRY_RESULT,
 			     flex_array_size(ev, info, ev->num)))
 		return;
 
-	BT_DBG("%s num %d", hdev->name, ev->num);
+	bt_dev_dbg(hdev, "num %d", ev->num);
 
 	if (!ev->num)
 		return;
@@ -5255,19 +5161,14 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
+static void hci_key_refresh_complete_evt(struct hci_dev *hdev, void *data,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_key_refresh_complete *ev;
+	struct hci_ev_key_refresh_complete *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_KEY_REFRESH_COMPLETE,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
-	       __le16_to_cpu(ev->handle));
+	bt_dev_dbg(hdev, "status 0x%2.2x handle 0x%4.4x", ev->status,
+		   __le16_to_cpu(ev->handle));
 
 	hci_dev_lock(hdev);
 
@@ -5370,16 +5271,13 @@ static u8 bredr_oob_data_present(struct hci_conn *conn)
 	return 0x01;
 }
 
-static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_io_capa_request_evt(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_ev_io_capa_request *ev;
+	struct hci_ev_io_capa_request *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_IO_CAPA_REQUEST, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	hci_dev_lock(hdev);
 
@@ -5443,16 +5341,13 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_io_capa_reply_evt(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_ev_io_capa_reply *ev;
+	struct hci_ev_io_capa_reply *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_IO_CAPA_REPLY, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	hci_dev_lock(hdev);
 
@@ -5467,19 +5362,14 @@ static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_user_confirm_request_evt(struct hci_dev *hdev,
+static void hci_user_confirm_request_evt(struct hci_dev *hdev, void *data,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_user_confirm_req *ev;
+	struct hci_ev_user_confirm_req *ev = data;
 	int loc_mitm, rem_mitm, confirm_hint = 0;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_CONFIRM_REQUEST,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	hci_dev_lock(hdev);
 
@@ -5500,7 +5390,7 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
 	 */
 	if (conn->pending_sec_level > BT_SECURITY_MEDIUM &&
 	    conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
-		BT_DBG("Rejecting request: remote device can't provide MITM");
+		bt_dev_dbg(hdev, "Rejecting request: remote device can't provide MITM");
 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
 			     sizeof(ev->bdaddr), &ev->bdaddr);
 		goto unlock;
@@ -5519,7 +5409,7 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
 		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
 		    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
 		    (loc_mitm || rem_mitm)) {
-			BT_DBG("Confirming auto-accept as acceptor");
+			bt_dev_dbg(hdev, "Confirming auto-accept as acceptor");
 			confirm_hint = 1;
 			goto confirm;
 		}
@@ -5557,34 +5447,24 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_user_passkey_request_evt(struct hci_dev *hdev,
+static void hci_user_passkey_request_evt(struct hci_dev *hdev, void *data,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_user_passkey_req *ev;
-
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_PASSKEY_REQUEST,
-			     sizeof(*ev));
-	if (!ev)
-		return;
+	struct hci_ev_user_passkey_req *ev = data;
 
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	if (hci_dev_test_flag(hdev, HCI_MGMT))
 		mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
 }
 
-static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
+static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data,
 					struct sk_buff *skb)
 {
-	struct hci_ev_user_passkey_notify *ev;
+	struct hci_ev_user_passkey_notify *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_PASSKEY_NOTIFY,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
 	if (!conn)
@@ -5599,16 +5479,13 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
 					 conn->passkey_entered);
 }
 
-static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_ev_keypress_notify *ev;
+	struct hci_ev_keypress_notify *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_KEYPRESS_NOTIFY, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
 	if (!conn)
@@ -5641,18 +5518,13 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
 					 conn->passkey_entered);
 }
 
-static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
+static void hci_simple_pair_complete_evt(struct hci_dev *hdev, void *data,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_simple_pair_complete *ev;
+	struct hci_ev_simple_pair_complete *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_SIMPLE_PAIR_COMPLETE,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	hci_dev_lock(hdev);
 
@@ -5677,19 +5549,14 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_remote_host_features_evt(struct hci_dev *hdev,
+static void hci_remote_host_features_evt(struct hci_dev *hdev, void *data,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_remote_host_features *ev;
+	struct hci_ev_remote_host_features *ev = data;
 	struct inquiry_entry *ie;
 	struct hci_conn *conn;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_HOST_FEATURES,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	hci_dev_lock(hdev);
 
@@ -5704,18 +5571,13 @@ static void hci_remote_host_features_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
+static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, void *edata,
 					    struct sk_buff *skb)
 {
-	struct hci_ev_remote_oob_data_request *ev;
+	struct hci_ev_remote_oob_data_request *ev = edata;
 	struct oob_data *data;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_OOB_DATA_REQUEST,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s", hdev->name);
+	bt_dev_dbg(hdev, "");
 
 	hci_dev_lock(hdev);
 
@@ -5764,16 +5626,13 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
 }
 
 #if IS_ENABLED(CONFIG_BT_HS)
-static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_chan_selected_evt(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_ev_channel_selected *ev;
+	struct hci_ev_channel_selected *ev = data;
 	struct hci_conn *hcon;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CHANNEL_SELECTED, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
+	bt_dev_dbg(hdev, "handle 0x%2.2x", ev->phy_handle);
 
 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
 	if (!hcon)
@@ -5782,18 +5641,14 @@ static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	amp_read_loc_assoc_final_data(hdev, hcon);
 }
 
-static void hci_phy_link_complete_evt(struct hci_dev *hdev,
+static void hci_phy_link_complete_evt(struct hci_dev *hdev, void *data,
 				      struct sk_buff *skb)
 {
-	struct hci_ev_phy_link_complete *ev;
+	struct hci_ev_phy_link_complete *ev = data;
 	struct hci_conn *hcon, *bredr_hcon;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PHY_LINK_COMPLETE, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
-	       ev->status);
+	bt_dev_dbg(hdev, "handle 0x%2.2x status 0x%2.2x", ev->phy_handle,
+		   ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -5827,21 +5682,16 @@ static void hci_phy_link_complete_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_loglink_complete_evt(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_ev_logical_link_complete *ev;
+	struct hci_ev_logical_link_complete *ev = data;
 	struct hci_conn *hcon;
 	struct hci_chan *hchan;
 	struct amp_mgr *mgr;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LOGICAL_LINK_COMPLETE,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
-	       hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
-	       ev->status);
+	bt_dev_dbg(hdev, "log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
+		   le16_to_cpu(ev->handle), ev->phy_handle, ev->status);
 
 	hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
 	if (!hcon)
@@ -5871,19 +5721,14 @@ static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 }
 
-static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
+static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, void *data,
 					     struct sk_buff *skb)
 {
-	struct hci_ev_disconn_logical_link_complete *ev;
+	struct hci_ev_disconn_logical_link_complete *ev = data;
 	struct hci_chan *hchan;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
-	       le16_to_cpu(ev->handle), ev->status);
+	bt_dev_dbg(hdev, "handle 0x%4.4x status 0x%2.2x",
+		   le16_to_cpu(ev->handle), ev->status);
 
 	if (ev->status)
 		return;
@@ -5900,18 +5745,13 @@ static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
+static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, void *data,
 					     struct sk_buff *skb)
 {
-	struct hci_ev_disconn_phy_link_complete *ev;
+	struct hci_ev_disconn_phy_link_complete *ev = data;
 	struct hci_conn *hcon;
 
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_PHY_LINK_COMPLETE,
-			     sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	if (ev->status)
 		return;
@@ -6938,13 +6778,10 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
+			    struct sk_buff *skb)
 {
-	struct hci_ev_le_meta *ev;
-
-	ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LE_META, sizeof(*ev));
-	if (!ev)
-		return;
+	struct hci_ev_le_meta *ev = data;
 
 	switch (ev->subevent) {
 	case HCI_EV_LE_CONN_COMPLETE:
@@ -7109,6 +6946,224 @@ static void hci_store_wake_reason(struct hci_dev *hdev, u8 event,
 	hci_dev_unlock(hdev);
 }
 
+#define HCI_EV_VL(_op, _func, _min_len, _max_len) \
+[_op] = { \
+	.req = false, \
+	.func = _func, \
+	.min_len = _min_len, \
+	.max_len = _max_len, \
+}
+
+#define HCI_EV(_op, _func, _len) \
+	HCI_EV_VL(_op, _func, _len, _len)
+
+#define HCI_EV_STATUS(_op, _func) \
+	HCI_EV(_op, _func, sizeof(struct hci_ev_status))
+
+#define HCI_EV_REQ_VL(_op, _func, _min_len, _max_len) \
+[_op] = { \
+	.req = true, \
+	.func_req = _func, \
+	.min_len = _min_len, \
+	.max_len = _max_len, \
+}
+
+#define HCI_EV_REQ(_op, _func, _len) \
+	HCI_EV_REQ_VL(_op, _func, _len, _len)
+
+/* Entries in this table shall have their position according to the event opcode
+ * they handle so the use of the macros above is recommend since it does attempt
+ * to initialize at its proper index using Designated Initializers that way
+ * events without a callback function don't have entered.
+ */
+static const struct hci_ev {
+	bool req;
+	union {
+		void (*func)(struct hci_dev *hdev, void *data,
+			     struct sk_buff *skb);
+		void (*func_req)(struct hci_dev *hdev, void *data,
+				 struct sk_buff *skb, u16 *opcode, u8 *status,
+				 hci_req_complete_t *req_complete,
+				 hci_req_complete_skb_t *req_complete_skb);
+	};
+	u16  min_len;
+	u16  max_len;
+} hci_ev_table[U8_MAX + 1] = {
+	/* [0x01 = HCI_EV_INQUIRY_COMPLETE] */
+	HCI_EV_STATUS(HCI_EV_INQUIRY_COMPLETE, hci_inquiry_complete_evt),
+	/* [0x02 = HCI_EV_INQUIRY_RESULT] */
+	HCI_EV_VL(HCI_EV_INQUIRY_RESULT, hci_inquiry_result_evt,
+		  sizeof(struct hci_ev_inquiry_result), HCI_MAX_EVENT_SIZE),
+	/* [0x03 = HCI_EV_CONN_COMPLETE] */
+	HCI_EV(HCI_EV_CONN_COMPLETE, hci_conn_complete_evt,
+	       sizeof(struct hci_ev_conn_complete)),
+	/* [0x04 = HCI_EV_CONN_REQUEST] */
+	HCI_EV(HCI_EV_CONN_REQUEST, hci_conn_request_evt,
+	       sizeof(struct hci_ev_conn_request)),
+	/* [0x05 = HCI_EV_DISCONN_COMPLETE] */
+	HCI_EV(HCI_EV_DISCONN_COMPLETE, hci_disconn_complete_evt,
+	       sizeof(struct hci_ev_disconn_complete)),
+	/* [0x06 = HCI_EV_AUTH_COMPLETE] */
+	HCI_EV(HCI_EV_AUTH_COMPLETE, hci_auth_complete_evt,
+	       sizeof(struct hci_ev_auth_complete)),
+	/* [0x07 = HCI_EV_REMOTE_NAME] */
+	HCI_EV(HCI_EV_REMOTE_NAME, hci_remote_name_evt,
+	       sizeof(struct hci_ev_remote_name)),
+	/* [0x08 = HCI_EV_ENCRYPT_CHANGE] */
+	HCI_EV(HCI_EV_ENCRYPT_CHANGE, hci_encrypt_change_evt,
+	       sizeof(struct hci_ev_encrypt_change)),
+	/* [0x09 = HCI_EV_CHANGE_LINK_KEY_COMPLETE] */
+	HCI_EV(HCI_EV_CHANGE_LINK_KEY_COMPLETE,
+	       hci_change_link_key_complete_evt,
+	       sizeof(struct hci_ev_change_link_key_complete)),
+	/* [0x0b = HCI_EV_REMOTE_FEATURES] */
+	HCI_EV(HCI_EV_REMOTE_FEATURES, hci_remote_features_evt,
+	       sizeof(struct hci_ev_remote_features)),
+	/* [0x0e = HCI_EV_CMD_COMPLETE] */
+	HCI_EV_REQ_VL(HCI_EV_CMD_COMPLETE, hci_cmd_complete_evt,
+		      sizeof(struct hci_ev_cmd_complete), HCI_MAX_EVENT_SIZE),
+	/* [0x0f = HCI_EV_CMD_STATUS] */
+	HCI_EV_REQ(HCI_EV_CMD_STATUS, hci_cmd_status_evt,
+		   sizeof(struct hci_ev_cmd_status)),
+	/* [0x10 = HCI_EV_CMD_STATUS] */
+	HCI_EV(HCI_EV_HARDWARE_ERROR, hci_hardware_error_evt,
+	       sizeof(struct hci_ev_hardware_error)),
+	/* [0x12 = HCI_EV_ROLE_CHANGE] */
+	HCI_EV(HCI_EV_ROLE_CHANGE, hci_role_change_evt,
+	       sizeof(struct hci_ev_role_change)),
+	/* [0x13 = HCI_EV_NUM_COMP_PKTS] */
+	HCI_EV_VL(HCI_EV_NUM_COMP_PKTS, hci_num_comp_pkts_evt,
+		  sizeof(struct hci_ev_num_comp_pkts), HCI_MAX_EVENT_SIZE),
+	/* [0x14 = HCI_EV_MODE_CHANGE] */
+	HCI_EV(HCI_EV_MODE_CHANGE, hci_mode_change_evt,
+	       sizeof(struct hci_ev_mode_change)),
+	/* [0x16 = HCI_EV_PIN_CODE_REQ] */
+	HCI_EV(HCI_EV_PIN_CODE_REQ, hci_pin_code_request_evt,
+	       sizeof(struct hci_ev_pin_code_req)),
+	/* [0x17 = HCI_EV_LINK_KEY_REQ] */
+	HCI_EV(HCI_EV_LINK_KEY_REQ, hci_link_key_request_evt,
+	       sizeof(struct hci_ev_link_key_req)),
+	/* [0x18 = HCI_EV_LINK_KEY_NOTIFY] */
+	HCI_EV(HCI_EV_LINK_KEY_NOTIFY, hci_link_key_notify_evt,
+	       sizeof(struct hci_ev_link_key_notify)),
+	/* [0x1c = HCI_EV_CLOCK_OFFSET] */
+	HCI_EV(HCI_EV_CLOCK_OFFSET, hci_clock_offset_evt,
+	       sizeof(struct hci_ev_clock_offset)),
+	/* [0x1d = HCI_EV_PKT_TYPE_CHANGE] */
+	HCI_EV(HCI_EV_PKT_TYPE_CHANGE, hci_pkt_type_change_evt,
+	       sizeof(struct hci_ev_pkt_type_change)),
+	/* [0x20 = HCI_EV_PSCAN_REP_MODE] */
+	HCI_EV(HCI_EV_PSCAN_REP_MODE, hci_pscan_rep_mode_evt,
+	       sizeof(struct hci_ev_pscan_rep_mode)),
+	/* [0x22 = HCI_EV_INQUIRY_RESULT_WITH_RSSI] */
+	HCI_EV_VL(HCI_EV_INQUIRY_RESULT_WITH_RSSI,
+		  hci_inquiry_result_with_rssi_evt,
+		  sizeof(struct hci_ev_inquiry_result_rssi),
+		  HCI_MAX_EVENT_SIZE),
+	/* [0x23 = HCI_EV_REMOTE_EXT_FEATURES] */
+	HCI_EV(HCI_EV_REMOTE_EXT_FEATURES, hci_remote_ext_features_evt,
+	       sizeof(struct hci_ev_remote_ext_features)),
+	/* [0x2c = HCI_EV_SYNC_CONN_COMPLETE] */
+	HCI_EV(HCI_EV_SYNC_CONN_COMPLETE, hci_sync_conn_complete_evt,
+	       sizeof(struct hci_ev_sync_conn_complete)),
+	/* [0x2d = HCI_EV_EXTENDED_INQUIRY_RESULT] */
+	HCI_EV_VL(HCI_EV_EXTENDED_INQUIRY_RESULT,
+		  hci_extended_inquiry_result_evt,
+		  sizeof(struct hci_ev_ext_inquiry_result), HCI_MAX_EVENT_SIZE),
+	/* [0x30 = HCI_EV_KEY_REFRESH_COMPLETE] */
+	HCI_EV(HCI_EV_KEY_REFRESH_COMPLETE, hci_key_refresh_complete_evt,
+	       sizeof(struct hci_ev_key_refresh_complete)),
+	/* [0x31 = HCI_EV_IO_CAPA_REQUEST] */
+	HCI_EV(HCI_EV_IO_CAPA_REQUEST, hci_io_capa_request_evt,
+	       sizeof(struct hci_ev_io_capa_request)),
+	/* [0x32 = HCI_EV_IO_CAPA_REPLY] */
+	HCI_EV(HCI_EV_IO_CAPA_REPLY, hci_io_capa_reply_evt,
+	       sizeof(struct hci_ev_io_capa_reply)),
+	/* [0x33 = HCI_EV_USER_CONFIRM_REQUEST] */
+	HCI_EV(HCI_EV_USER_CONFIRM_REQUEST, hci_user_confirm_request_evt,
+	       sizeof(struct hci_ev_user_confirm_req)),
+	/* [0x34 = HCI_EV_USER_PASSKEY_REQUEST] */
+	HCI_EV(HCI_EV_USER_PASSKEY_REQUEST, hci_user_passkey_request_evt,
+	       sizeof(struct hci_ev_user_passkey_req)),
+	/* [0x35 = HCI_EV_REMOTE_OOB_DATA_REQUEST] */
+	HCI_EV(HCI_EV_REMOTE_OOB_DATA_REQUEST, hci_remote_oob_data_request_evt,
+	       sizeof(struct hci_ev_remote_oob_data_request)),
+	/* [0x36 = HCI_EV_SIMPLE_PAIR_COMPLETE] */
+	HCI_EV(HCI_EV_SIMPLE_PAIR_COMPLETE, hci_simple_pair_complete_evt,
+	       sizeof(struct hci_ev_simple_pair_complete)),
+	/* [0x3b = HCI_EV_USER_PASSKEY_NOTIFY] */
+	HCI_EV(HCI_EV_USER_PASSKEY_NOTIFY, hci_user_passkey_notify_evt,
+	       sizeof(struct hci_ev_user_passkey_notify)),
+	/* [0x3c = HCI_EV_KEYPRESS_NOTIFY] */
+	HCI_EV(HCI_EV_KEYPRESS_NOTIFY, hci_keypress_notify_evt,
+	       sizeof(struct hci_ev_keypress_notify)),
+	/* [0x3d = HCI_EV_REMOTE_HOST_FEATURES] */
+	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),
+#if IS_ENABLED(CONFIG_BT_HS)
+	/* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */
+	HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt,
+	       sizeof(struct hci_ev_phy_link_complete)),
+	/* [0x41 = HCI_EV_CHANNEL_SELECTED] */
+	HCI_EV(HCI_EV_CHANNEL_SELECTED, hci_chan_selected_evt,
+	       sizeof(struct hci_ev_channel_selected)),
+	/* [0x42 = HCI_EV_DISCONN_PHY_LINK_COMPLETE] */
+	HCI_EV(HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
+	       hci_disconn_loglink_complete_evt,
+	       sizeof(struct hci_ev_disconn_logical_link_complete)),
+	/* [0x45 = HCI_EV_LOGICAL_LINK_COMPLETE] */
+	HCI_EV(HCI_EV_LOGICAL_LINK_COMPLETE, hci_loglink_complete_evt,
+	       sizeof(struct hci_ev_logical_link_complete)),
+	/* [0x46 = HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE] */
+	HCI_EV(HCI_EV_DISCONN_PHY_LINK_COMPLETE,
+	       hci_disconn_phylink_complete_evt,
+	       sizeof(struct hci_ev_disconn_phy_link_complete)),
+#endif
+	/* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */
+	HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt,
+	       sizeof(struct hci_ev_num_comp_blocks)),
+	/* [0xff = HCI_EV_VENDOR] */
+	HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
+};
+
+void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
+		    u16 *opcode, u8 *status, hci_req_complete_t *req_complete,
+		    hci_req_complete_skb_t *req_complete_skb)
+{
+	const struct hci_ev *ev = &hci_ev_table[event];
+	void *data;
+
+	if (!ev->func)
+		return;
+
+	if (skb->len < ev->min_len) {
+		bt_dev_err(hdev, "unexpected event 0x%2.2x length: %u < %u",
+			   event, skb->len, ev->min_len);
+		return;
+	}
+
+	/* Just warn if the length is over max_len size it still be
+	 * possible to partially parse the event so leave to callback to
+	 * decide if that is acceptable.
+	 */
+	if (skb->len > ev->max_len)
+		bt_dev_warn(hdev, "unexpected event 0x%2.2x length: %u > %u",
+			    event, skb->len, ev->max_len);
+
+	data = hci_ev_skb_pull(hdev, skb, event, ev->min_len);
+	if (!data)
+		return;
+
+	if (ev->req)
+		ev->func_req(hdev, data, skb, opcode, status, req_complete,
+			     req_complete_skb);
+	else
+		ev->func(hdev, data, skb);
+}
+
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_event_hdr *hdr = (void *) skb->data;
@@ -7125,7 +7180,8 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 
 	event = hdr->evt;
 	if (!event) {
-		bt_dev_warn(hdev, "Received unexpected HCI Event 00000000");
+		bt_dev_warn(hdev, "Received unexpected HCI Event 0x%2.2x",
+			    event);
 		goto done;
 	}
 
@@ -7151,191 +7207,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 	/* Store wake reason if we're suspended */
 	hci_store_wake_reason(hdev, event, skb);
 
-	switch (event) {
-	case HCI_EV_INQUIRY_COMPLETE:
-		hci_inquiry_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_INQUIRY_RESULT:
-		hci_inquiry_result_evt(hdev, skb);
-		break;
-
-	case HCI_EV_CONN_COMPLETE:
-		hci_conn_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_CONN_REQUEST:
-		hci_conn_request_evt(hdev, skb);
-		break;
-
-	case HCI_EV_DISCONN_COMPLETE:
-		hci_disconn_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_AUTH_COMPLETE:
-		hci_auth_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_REMOTE_NAME:
-		hci_remote_name_evt(hdev, skb);
-		break;
-
-	case HCI_EV_ENCRYPT_CHANGE:
-		hci_encrypt_change_evt(hdev, skb);
-		break;
-
-	case HCI_EV_CHANGE_LINK_KEY_COMPLETE:
-		hci_change_link_key_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_REMOTE_FEATURES:
-		hci_remote_features_evt(hdev, skb);
-		break;
-
-	case HCI_EV_CMD_COMPLETE:
-		hci_cmd_complete_evt(hdev, skb, &opcode, &status,
-				     &req_complete, &req_complete_skb);
-		break;
+	bt_dev_dbg(hdev, "event 0x%2.2x", event);
 
-	case HCI_EV_CMD_STATUS:
-		hci_cmd_status_evt(hdev, skb, &opcode, &status, &req_complete,
-				   &req_complete_skb);
-		break;
-
-	case HCI_EV_HARDWARE_ERROR:
-		hci_hardware_error_evt(hdev, skb);
-		break;
-
-	case HCI_EV_ROLE_CHANGE:
-		hci_role_change_evt(hdev, skb);
-		break;
-
-	case HCI_EV_NUM_COMP_PKTS:
-		hci_num_comp_pkts_evt(hdev, skb);
-		break;
-
-	case HCI_EV_MODE_CHANGE:
-		hci_mode_change_evt(hdev, skb);
-		break;
-
-	case HCI_EV_PIN_CODE_REQ:
-		hci_pin_code_request_evt(hdev, skb);
-		break;
-
-	case HCI_EV_LINK_KEY_REQ:
-		hci_link_key_request_evt(hdev, skb);
-		break;
-
-	case HCI_EV_LINK_KEY_NOTIFY:
-		hci_link_key_notify_evt(hdev, skb);
-		break;
-
-	case HCI_EV_CLOCK_OFFSET:
-		hci_clock_offset_evt(hdev, skb);
-		break;
-
-	case HCI_EV_PKT_TYPE_CHANGE:
-		hci_pkt_type_change_evt(hdev, skb);
-		break;
-
-	case HCI_EV_PSCAN_REP_MODE:
-		hci_pscan_rep_mode_evt(hdev, skb);
-		break;
-
-	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
-		hci_inquiry_result_with_rssi_evt(hdev, skb);
-		break;
-
-	case HCI_EV_REMOTE_EXT_FEATURES:
-		hci_remote_ext_features_evt(hdev, skb);
-		break;
-
-	case HCI_EV_SYNC_CONN_COMPLETE:
-		hci_sync_conn_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_EXTENDED_INQUIRY_RESULT:
-		hci_extended_inquiry_result_evt(hdev, skb);
-		break;
-
-	case HCI_EV_KEY_REFRESH_COMPLETE:
-		hci_key_refresh_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_IO_CAPA_REQUEST:
-		hci_io_capa_request_evt(hdev, skb);
-		break;
-
-	case HCI_EV_IO_CAPA_REPLY:
-		hci_io_capa_reply_evt(hdev, skb);
-		break;
-
-	case HCI_EV_USER_CONFIRM_REQUEST:
-		hci_user_confirm_request_evt(hdev, skb);
-		break;
-
-	case HCI_EV_USER_PASSKEY_REQUEST:
-		hci_user_passkey_request_evt(hdev, skb);
-		break;
-
-	case HCI_EV_USER_PASSKEY_NOTIFY:
-		hci_user_passkey_notify_evt(hdev, skb);
-		break;
-
-	case HCI_EV_KEYPRESS_NOTIFY:
-		hci_keypress_notify_evt(hdev, skb);
-		break;
-
-	case HCI_EV_SIMPLE_PAIR_COMPLETE:
-		hci_simple_pair_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_REMOTE_HOST_FEATURES:
-		hci_remote_host_features_evt(hdev, skb);
-		break;
-
-	case HCI_EV_LE_META:
-		hci_le_meta_evt(hdev, skb);
-		break;
-
-	case HCI_EV_REMOTE_OOB_DATA_REQUEST:
-		hci_remote_oob_data_request_evt(hdev, skb);
-		break;
-
-#if IS_ENABLED(CONFIG_BT_HS)
-	case HCI_EV_CHANNEL_SELECTED:
-		hci_chan_selected_evt(hdev, skb);
-		break;
-
-	case HCI_EV_PHY_LINK_COMPLETE:
-		hci_phy_link_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_LOGICAL_LINK_COMPLETE:
-		hci_loglink_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
-		hci_disconn_loglink_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
-		hci_disconn_phylink_complete_evt(hdev, skb);
-		break;
-#endif
-
-	case HCI_EV_NUM_COMP_BLOCKS:
-		hci_num_comp_blocks_evt(hdev, skb);
-		break;
-
-	case HCI_EV_VENDOR:
-		msft_vendor_evt(hdev, skb);
-		break;
-
-	default:
-		BT_DBG("%s event 0x%2.2x", hdev->name, event);
-		break;
-	}
+	hci_event_func(hdev, event, skb, &opcode, &status, &req_complete,
+		       &req_complete_skb);
 
 	if (req_complete) {
 		req_complete(hdev, status, opcode);
diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
index 1122097e1e49..6a943634b31a 100644
--- a/net/bluetooth/msft.c
+++ b/net/bluetooth/msft.c
@@ -590,7 +590,7 @@ void msft_unregister(struct hci_dev *hdev)
 	kfree(msft);
 }
 
-void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb)
+void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb)
 {
 	struct msft_data *msft = hdev->msft_data;
 	u8 event;
diff --git a/net/bluetooth/msft.h b/net/bluetooth/msft.h
index b59b63dc0ea8..7fefc0655b6f 100644
--- a/net/bluetooth/msft.h
+++ b/net/bluetooth/msft.h
@@ -17,7 +17,7 @@ void msft_register(struct hci_dev *hdev);
 void msft_unregister(struct hci_dev *hdev);
 void msft_do_open(struct hci_dev *hdev);
 void msft_do_close(struct hci_dev *hdev);
-void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb);
+void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb);
 __u64 msft_get_features(struct hci_dev *hdev);
 int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor);
 int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 13/15] Bluetooth: hci_event: Use of a function table to handle LE subevents
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (11 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 14/15] Bluetooth: hci_event: Use of a function table to handle Command Complete Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 15/15] Bluetooth: hci_event: Use of a function table to handle Command Status Luiz Augusto von Dentz
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This change the use of switch statement to a function table which is
easier to extend and can include min/max length of each subevent.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 net/bluetooth/hci_event.c | 247 +++++++++++++++++++-------------------
 1 file changed, 122 insertions(+), 125 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6fbb16997849..c39f5ea1736a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -5969,16 +5969,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_le_conn_complete_evt(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_ev_le_conn_complete *ev;
-
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_CONN_COMPLETE,
-				sizeof(*ev));
-	if (!ev)
-		return;
+	struct hci_ev_le_conn_complete *ev = data;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
 			     NULL, ev->role, le16_to_cpu(ev->handle),
@@ -5987,17 +5983,12 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 			     le16_to_cpu(ev->supervision_timeout));
 }
 
-static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
+static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, void *data,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_le_enh_conn_complete *ev;
+	struct hci_ev_le_enh_conn_complete *ev = data;
 
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ENHANCED_CONN_COMPLETE,
-				sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
 			     &ev->local_rpa, ev->role, le16_to_cpu(ev->handle),
@@ -6006,18 +5997,14 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
 			     le16_to_cpu(ev->supervision_timeout));
 }
 
-static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_evt_le_ext_adv_set_term *ev;
+	struct hci_evt_le_ext_adv_set_term *ev = data;
 	struct hci_conn *conn;
 	struct adv_info *adv, *n;
 
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_SET_TERM,
-				sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	adv = hci_find_adv_instance(hdev, ev->handle);
 
@@ -6075,18 +6062,13 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 }
 
-static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
+static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, void *data,
 					    struct sk_buff *skb)
 {
-	struct hci_ev_le_conn_update_complete *ev;
+	struct hci_ev_le_conn_update_complete *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_CONN_UPDATE_COMPLETE,
-				sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	if (ev->status)
 		return;
@@ -6402,14 +6384,10 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
 	clear_pending_adv_report(hdev);
 }
 
-static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_ev_le_advertising_report *ev;
-
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ADVERTISING_REPORT,
-				sizeof(*ev));
-	if (!ev)
-		return;
+	struct hci_ev_le_advertising_report *ev = data;
 
 	if (!ev->num)
 		return;
@@ -6487,14 +6465,10 @@ static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type)
 	return LE_ADV_INVALID;
 }
 
-static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_ev_le_ext_adv_report *ev;
-
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT,
-				sizeof(*ev));
-	if (!ev)
-		return;
+	struct hci_ev_le_ext_adv_report *ev = data;
 
 	if (!ev->num)
 		return;
@@ -6528,18 +6502,13 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
+static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, void *data,
 					    struct sk_buff *skb)
 {
-	struct hci_ev_le_remote_feat_complete *ev;
+	struct hci_ev_le_remote_feat_complete *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT,
-				sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	hci_dev_lock(hdev);
 
@@ -6575,19 +6544,16 @@ static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_le_ltk_request_evt(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_le_ltk_req *ev;
+	struct hci_ev_le_ltk_req *ev = data;
 	struct hci_cp_le_ltk_reply cp;
 	struct hci_cp_le_ltk_neg_reply neg;
 	struct hci_conn *conn;
 	struct smp_ltk *ltk;
 
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_LTK_REQ, sizeof(*ev));
-	if (!ev)
-		return;
-
-	BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
+	bt_dev_dbg(hdev, "handle 0x%4.4x", __le16_to_cpu(ev->handle));
 
 	hci_dev_lock(hdev);
 
@@ -6655,18 +6621,15 @@ static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
 		     &cp);
 }
 
-static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
+static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, void *data,
 					     struct sk_buff *skb)
 {
-	struct hci_ev_le_remote_conn_param_req *ev;
+	struct hci_ev_le_remote_conn_param_req *ev = data;
 	struct hci_cp_le_conn_param_req_reply cp;
 	struct hci_conn *hcon;
 	u16 handle, min, max, latency, timeout;
 
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_REMOTE_CONN_PARAM_REQ,
-				sizeof(*ev));
-	if (!ev)
-		return;
+	bt_dev_dbg(hdev, "handle 0x%4.4x", __le16_to_cpu(ev->handle));
 
 	handle = le16_to_cpu(ev->handle);
 	min = le16_to_cpu(ev->interval_min);
@@ -6718,17 +6681,12 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
 	hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
 }
 
-static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
+static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data,
 					 struct sk_buff *skb)
 {
-	struct hci_ev_le_direct_adv_report *ev;
+	struct hci_ev_le_direct_adv_report *ev = data;
 	int i;
 
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT,
-				sizeof(*ev));
-	if (!ev)
-		return;
-
 	if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT,
 				flex_array_size(ev, info, ev->num)))
 		return;
@@ -6750,17 +6708,13 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
 	hci_dev_unlock(hdev);
 }
 
-static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
+static void hci_le_phy_update_evt(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_ev_le_phy_update_complete *ev;
+	struct hci_ev_le_phy_update_complete *ev = data;
 	struct hci_conn *conn;
 
-	ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_PHY_UPDATE_COMPLETE,
-				sizeof(*ev));
-	if (ev)
-		return;
-
-	BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 
 	if (ev->status)
 		return;
@@ -6778,59 +6732,102 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
-			    struct sk_buff *skb)
-{
-	struct hci_ev_le_meta *ev = data;
-
-	switch (ev->subevent) {
-	case HCI_EV_LE_CONN_COMPLETE:
-		hci_le_conn_complete_evt(hdev, skb);
-		break;
-
-	case HCI_EV_LE_CONN_UPDATE_COMPLETE:
-		hci_le_conn_update_complete_evt(hdev, skb);
-		break;
+#define HCI_LE_EV_VL(_op, _func, _min_len, _max_len) \
+[_op] = { \
+	.func = _func, \
+	.min_len = _min_len, \
+	.max_len = _max_len, \
+}
 
-	case HCI_EV_LE_ADVERTISING_REPORT:
-		hci_le_adv_report_evt(hdev, skb);
-		break;
+#define HCI_LE_EV(_op, _func, _len) \
+	HCI_LE_EV_VL(_op, _func, _len, _len)
 
-	case HCI_EV_LE_REMOTE_FEAT_COMPLETE:
-		hci_le_remote_feat_complete_evt(hdev, skb);
-		break;
+#define HCI_LE_EV_STATUS(_op, _func) \
+	HCI_LE_EV(_op, _func, sizeof(struct hci_ev_status))
 
-	case HCI_EV_LE_LTK_REQ:
-		hci_le_ltk_request_evt(hdev, skb);
-		break;
+/* Entries in this table shall have their position according to the subevent
+ * opcode they handle so the use of the macros above is recommend since it does
+ * attempt to initialize at its proper index using Designated Initializers that
+ * way events without a callback function can be ommited.
+ */
+static const struct hci_le_ev {
+	void (*func)(struct hci_dev *hdev, void *data, struct sk_buff *skb);
+	u16  min_len;
+	u16  max_len;
+} hci_le_ev_table[U8_MAX + 1] = {
+	/* [0x01 = HCI_EV_LE_CONN_COMPLETE] */
+	HCI_LE_EV(HCI_EV_LE_CONN_COMPLETE, hci_le_conn_complete_evt,
+		  sizeof(struct hci_ev_le_conn_complete)),
+	/* [0x02 = HCI_EV_LE_ADVERTISING_REPORT] */
+	HCI_LE_EV_VL(HCI_EV_LE_ADVERTISING_REPORT, hci_le_adv_report_evt,
+		     sizeof(struct hci_ev_le_advertising_report),
+		     HCI_MAX_EVENT_SIZE),
+	/* [0x03 = HCI_EV_LE_CONN_UPDATE_COMPLETE] */
+	HCI_LE_EV(HCI_EV_LE_CONN_UPDATE_COMPLETE,
+		  hci_le_conn_update_complete_evt,
+		  sizeof(struct hci_ev_le_conn_update_complete)),
+	/* [0x04 = HCI_EV_LE_REMOTE_FEAT_COMPLETE] */
+	HCI_LE_EV(HCI_EV_LE_REMOTE_FEAT_COMPLETE,
+		  hci_le_remote_feat_complete_evt,
+		  sizeof(struct hci_ev_le_remote_feat_complete)),
+	/* [0x05 = HCI_EV_LE_LTK_REQ] */
+	HCI_LE_EV(HCI_EV_LE_LTK_REQ, hci_le_ltk_request_evt,
+		  sizeof(struct hci_ev_le_ltk_req)),
+	/* [0x06 = HCI_EV_LE_REMOTE_CONN_PARAM_REQ] */
+	HCI_LE_EV(HCI_EV_LE_REMOTE_CONN_PARAM_REQ,
+		  hci_le_remote_conn_param_req_evt,
+		  sizeof(struct hci_ev_le_remote_conn_param_req)),
+	/* [0x0a = HCI_EV_LE_ENHANCED_CONN_COMPLETE] */
+	HCI_LE_EV(HCI_EV_LE_ENHANCED_CONN_COMPLETE,
+		  hci_le_enh_conn_complete_evt,
+		  sizeof(struct hci_ev_le_enh_conn_complete)),
+	/* [0x0b = HCI_EV_LE_DIRECT_ADV_REPORT] */
+	HCI_LE_EV_VL(HCI_EV_LE_DIRECT_ADV_REPORT, hci_le_direct_adv_report_evt,
+		     sizeof(struct hci_ev_le_direct_adv_report),
+		     HCI_MAX_EVENT_SIZE),
+	/* [0x0c = HCI_EV_LE_PHY_UPDATE_COMPLETE] */
+	HCI_LE_EV(HCI_EV_LE_PHY_UPDATE_COMPLETE, hci_le_phy_update_evt,
+		  sizeof(struct hci_ev_le_phy_update_complete)),
+	/* [0x0d = HCI_EV_LE_EXT_ADV_REPORT] */
+	HCI_LE_EV_VL(HCI_EV_LE_EXT_ADV_REPORT, hci_le_ext_adv_report_evt,
+		     sizeof(struct hci_ev_le_ext_adv_report),
+		     HCI_MAX_EVENT_SIZE),
+	/* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */
+	HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt,
+		  sizeof(struct hci_evt_le_ext_adv_set_term)),
+};
 
-	case HCI_EV_LE_REMOTE_CONN_PARAM_REQ:
-		hci_le_remote_conn_param_req_evt(hdev, skb);
-		break;
+static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
+			    struct sk_buff *skb)
+{
+	struct hci_ev_le_meta *ev = data;
+	const struct hci_le_ev *subev;
 
-	case HCI_EV_LE_DIRECT_ADV_REPORT:
-		hci_le_direct_adv_report_evt(hdev, skb);
-		break;
+	bt_dev_dbg(hdev, "subevent 0x%2.2x", ev->subevent);
 
-	case HCI_EV_LE_PHY_UPDATE_COMPLETE:
-		hci_le_phy_update_evt(hdev, skb);
-		break;
+	subev = &hci_le_ev_table[ev->subevent];
+	if (!subev->func)
+		return;
 
-	case HCI_EV_LE_EXT_ADV_REPORT:
-		hci_le_ext_adv_report_evt(hdev, skb);
-		break;
+	if (skb->len < subev->min_len) {
+		bt_dev_err(hdev, "unexpected subevent 0x%2.2x length: %u < %u",
+			   ev->subevent, skb->len, subev->min_len);
+		return;
+	}
 
-	case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
-		hci_le_enh_conn_complete_evt(hdev, skb);
-		break;
+	/* Just warn if the length is over max_len size it still be
+	 * possible to partially parse the event so leave to callback to
+	 * decide if that is acceptable.
+	 */
+	if (skb->len > subev->max_len)
+		bt_dev_warn(hdev, "unexpected subevent 0x%2.2x length: %u > %u",
+			    ev->subevent, skb->len, subev->max_len);
 
-	case HCI_EV_LE_EXT_ADV_SET_TERM:
-		hci_le_ext_adv_term_evt(hdev, skb);
-		break;
+	data = hci_le_ev_skb_pull(hdev, skb, ev->subevent, subev->min_len);
+	if (!data)
+		return;
 
-	default:
-		break;
-	}
+	subev->func(hdev, data, skb);
 }
 
 static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 14/15] Bluetooth: hci_event: Use of a function table to handle Command Complete
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (12 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 13/15] Bluetooth: hci_event: Use of a function table to handle LE subevents Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  2021-12-01  0:02 ` [PATCH 15/15] Bluetooth: hci_event: Use of a function table to handle Command Status Luiz Augusto von Dentz
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This change the use of switch statement to a function table which is
easier to extend and can include min/max length of each command.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 net/bluetooth/hci_event.c | 1848 +++++++++++++++----------------------
 1 file changed, 752 insertions(+), 1096 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c39f5ea1736a..0b69d527ca4e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -81,14 +81,10 @@ static void *hci_le_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,
 	return data;
 }
 
-static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
-				  u8 *new_status)
+static u8 hci_cc_inquiry_cancel(struct hci_dev *hdev, void *data,
+				struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_INQUIRY_CANCEL, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
@@ -104,10 +100,8 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
 		rp->status = 0x00;
 	}
 
-	*new_status = rp->status;
-
 	if (rp->status)
-		return;
+		return rp->status;
 
 	clear_bit(HCI_INQUIRY, &hdev->flags);
 	smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
@@ -123,68 +117,62 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
 	hci_dev_unlock(hdev);
 
 	hci_conn_check_pending(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_periodic_inq(struct hci_dev *hdev, void *data,
+			      struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PERIODIC_INQ, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hci_dev_set_flag(hdev, HCI_PERIODIC_INQ);
+
+	return rp->status;
 }
 
-static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_exit_periodic_inq(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_EXIT_PERIODIC_INQ, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ);
 
 	hci_conn_check_pending(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
-					  struct sk_buff *skb)
+static u8 hci_cc_remote_name_req_cancel(struct hci_dev *hdev, void *data,
+					struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_REMOTE_NAME_REQ_CANCEL,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	return rp->status;
 }
 
-static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_role_discovery(struct hci_dev *hdev, void *data,
+				struct sk_buff *skb)
 {
-	struct hci_rp_role_discovery *rp;
+	struct hci_rp_role_discovery *rp = data;
 	struct hci_conn *conn;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_ROLE_DISCOVERY, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -193,21 +181,20 @@ static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
 		conn->role = rp->role;
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_read_link_policy(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_rp_read_link_policy *rp;
+	struct hci_rp_read_link_policy *rp = data;
 	struct hci_conn *conn;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LINK_POLICY, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -216,26 +203,25 @@ static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
 		conn->link_policy = __le16_to_cpu(rp->policy);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_write_link_policy(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_rp_write_link_policy *rp;
+	struct hci_rp_write_link_policy *rp = data;
 	struct hci_conn *conn;
 	void *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LINK_POLICY, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -244,63 +230,55 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
 		conn->link_policy = get_unaligned_le16(sent + 2);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
-					struct sk_buff *skb)
+static u8 hci_cc_read_def_link_policy(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_rp_read_def_link_policy *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DEF_LINK_POLICY,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_def_link_policy *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->link_policy = __le16_to_cpu(rp->policy);
+
+	return rp->status;
 }
 
-static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
-					 struct sk_buff *skb)
+static u8 hci_cc_write_def_link_policy(struct hci_dev *hdev, void *data,
+				       struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	void *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_DEF_LINK_POLICY,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hdev->link_policy = get_unaligned_le16(sent);
+
+	return rp->status;
 }
 
-static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_reset(struct hci_dev *hdev, void *data, struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_RESET, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	clear_bit(HCI_RESET, &hdev->flags);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	/* Reset all non-persistent flags */
 	hci_dev_clear_volatile_flags(hdev);
@@ -322,66 +300,59 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hci_bdaddr_list_clear(&hdev->le_accept_list);
 	hci_bdaddr_list_clear(&hdev->le_resolv_list);
+
+	return rp->status;
 }
 
-static void hci_cc_read_stored_link_key(struct hci_dev *hdev,
-					struct sk_buff *skb)
+static u8 hci_cc_read_stored_link_key(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_rp_read_stored_link_key *rp;
+	struct hci_rp_read_stored_link_key *rp = data;
 	struct hci_cp_read_stored_link_key *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_STORED_LINK_KEY,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY);
 	if (!sent)
-		return;
+		return rp->status;
 
 	if (!rp->status && sent->read_all == 0x01) {
 		hdev->stored_max_keys = le16_to_cpu(rp->max_keys);
 		hdev->stored_num_keys = le16_to_cpu(rp->num_keys);
 	}
+
+	return rp->status;
 }
 
-static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
-					  struct sk_buff *skb)
+static u8 hci_cc_delete_stored_link_key(struct hci_dev *hdev, void *data,
+					struct sk_buff *skb)
 {
-	struct hci_rp_delete_stored_link_key *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_DELETE_STORED_LINK_KEY,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_delete_stored_link_key *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	if (rp->num_keys <= hdev->stored_num_keys)
 		hdev->stored_num_keys -= le16_to_cpu(rp->num_keys);
 	else
 		hdev->stored_num_keys = 0;
+
+	return rp->status;
 }
 
-static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_write_local_name(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	void *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LOCAL_NAME, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -391,40 +362,38 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_read_local_name(struct hci_dev *hdev, void *data,
+				 struct sk_buff *skb)
 {
-	struct hci_rp_read_local_name *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_NAME, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_local_name *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
 	    hci_dev_test_flag(hdev, HCI_CONFIG))
 		memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
+
+	return rp->status;
 }
 
-static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_write_auth_enable(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	void *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_AUTH_ENABLE, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -441,26 +410,25 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
 		mgmt_auth_enable_complete(hdev, rp->status);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_write_encrypt_mode(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	__u8 param;
 	void *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_ENCRYPT_MODE, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
 	if (!sent)
-		return;
+		return rp->status;
 
 	param = *((__u8 *) sent);
 
@@ -468,23 +436,22 @@ static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
 		set_bit(HCI_ENCRYPT, &hdev->flags);
 	else
 		clear_bit(HCI_ENCRYPT, &hdev->flags);
+
+	return rp->status;
 }
 
-static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_write_scan_enable(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	__u8 param;
 	void *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SCAN_ENABLE, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
 	if (!sent)
-		return;
+		return rp->status;
 
 	param = *((__u8 *) sent);
 
@@ -507,26 +474,25 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
 
 done:
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_set_event_filter(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	struct hci_cp_set_event_filter *cp;
 	void *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SCAN_ENABLE, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_SET_EVENT_FLT);
 	if (!sent)
-		return;
+		return rp->status;
 
 	cp = (struct hci_cp_set_event_filter *)sent;
 
@@ -534,41 +500,39 @@ static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_dev_clear_flag(hdev, HCI_EVENT_FILTER_CONFIGURED);
 	else
 		hci_dev_set_flag(hdev, HCI_EVENT_FILTER_CONFIGURED);
+
+	return rp->status;
 }
 
-static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_read_class_of_dev(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_rp_read_class_of_dev *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLASS_OF_DEV, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_class_of_dev *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	memcpy(hdev->dev_class, rp->dev_class, 3);
 
 	bt_dev_dbg(hdev, "class 0x%.2x%.2x%.2x", hdev->dev_class[2],
 		   hdev->dev_class[1], hdev->dev_class[0]);
+
+	return rp->status;
 }
 
-static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_write_class_of_dev(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	void *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLASS_OF_DEV, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -579,26 +543,25 @@ static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
 		mgmt_set_class_of_dev_complete(hdev, sent, rp->status);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_read_voice_setting(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_rp_read_voice_setting *rp;
+	struct hci_rp_read_voice_setting *rp = data;
 	__u16 setting;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_VOICE_SETTING, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	setting = __le16_to_cpu(rp->voice_setting);
 
 	if (hdev->voice_setting == setting)
-		return;
+		return rp->status;
 
 	hdev->voice_setting = setting;
 
@@ -606,33 +569,30 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
 
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
+
+	return rp->status;
 }
 
-static void hci_cc_write_voice_setting(struct hci_dev *hdev,
-				       struct sk_buff *skb)
+static u8 hci_cc_write_voice_setting(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	__u16 setting;
 	void *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_VOICE_SETTING,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
 	if (!sent)
-		return;
+		return rp->status;
 
 	setting = get_unaligned_le16(sent);
 
 	if (hdev->voice_setting == setting)
-		return;
+		return rp->status;
 
 	hdev->voice_setting = setting;
 
@@ -640,42 +600,38 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev,
 
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
+
+	return rp->status;
 }
 
-static void hci_cc_read_num_supported_iac(struct hci_dev *hdev,
-					  struct sk_buff *skb)
+static u8 hci_cc_read_num_supported_iac(struct hci_dev *hdev, void *data,
+					struct sk_buff *skb)
 {
-	struct hci_rp_read_num_supported_iac *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_NUM_SUPPORTED_IAC,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_num_supported_iac *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->num_iac = rp->num_iac;
 
 	bt_dev_dbg(hdev, "num iac %d", hdev->num_iac);
+
+	return rp->status;
 }
 
-static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_write_ssp_mode(struct hci_dev *hdev, void *data,
+				struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	struct hci_cp_write_ssp_mode *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SSP_MODE, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -694,22 +650,21 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_write_sc_support(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	struct hci_cp_write_sc_support *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SC_SUPPORT, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -728,20 +683,19 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_read_local_version(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_rp_read_local_version *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_VERSION, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_local_version *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
 	    hci_dev_test_flag(hdev, HCI_CONFIG)) {
@@ -751,43 +705,37 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
 		hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
 		hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
 	}
+
+	return rp->status;
 }
 
-static void hci_cc_read_local_commands(struct hci_dev *hdev,
-				       struct sk_buff *skb)
+static u8 hci_cc_read_local_commands(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_rp_read_local_commands *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_COMMANDS,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_local_commands *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
 	    hci_dev_test_flag(hdev, HCI_CONFIG))
 		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
+
+	return rp->status;
 }
 
-static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev,
-					     struct sk_buff *skb)
+static u8 hci_cc_read_auth_payload_timeout(struct hci_dev *hdev, void *data,
+					   struct sk_buff *skb)
 {
-	struct hci_rp_read_auth_payload_to *rp;
+	struct hci_rp_read_auth_payload_to *rp = data;
 	struct hci_conn *conn;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_AUTH_PAYLOAD_TO,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -796,27 +744,25 @@ static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev,
 		conn->auth_payload_timeout = __le16_to_cpu(rp->timeout);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev,
-					      struct sk_buff *skb)
+static u8 hci_cc_write_auth_payload_timeout(struct hci_dev *hdev, void *data,
+					    struct sk_buff *skb)
 {
-	struct hci_rp_write_auth_payload_to *rp;
+	struct hci_rp_write_auth_payload_to *rp = data;
 	struct hci_conn *conn;
 	void *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_AUTH_PAYLOAD_TO, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -825,22 +771,19 @@ static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev,
 		conn->auth_payload_timeout = get_unaligned_le16(sent + 2);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_read_local_features(struct hci_dev *hdev,
-				       struct sk_buff *skb)
+static u8 hci_cc_read_local_features(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_rp_read_local_features *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_FEATURES,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_local_features *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	memcpy(hdev->features, rp->features, 8);
 
@@ -880,60 +823,53 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
 
 	if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
 		hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
+
+	return rp->status;
 }
 
-static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
-					   struct sk_buff *skb)
+static u8 hci_cc_read_local_ext_features(struct hci_dev *hdev, void *data,
+					 struct sk_buff *skb)
 {
-	struct hci_rp_read_local_ext_features *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_EXT_FEATURES,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_local_ext_features *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	if (hdev->max_page < rp->max_page)
 		hdev->max_page = rp->max_page;
 
 	if (rp->page < HCI_MAX_PAGES)
 		memcpy(hdev->features[rp->page], rp->features, 8);
+
+	return rp->status;
 }
 
-static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
-					  struct sk_buff *skb)
+static u8 hci_cc_read_flow_control_mode(struct hci_dev *hdev, void *data,
+					struct sk_buff *skb)
 {
-	struct hci_rp_read_flow_control_mode *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_FLOW_CONTROL_MODE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_flow_control_mode *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->flow_ctl_mode = rp->mode;
+
+	return rp->status;
 }
 
-static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data,
+				  struct sk_buff *skb)
 {
-	struct hci_rp_read_buffer_size *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_BUFFER_SIZE, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_buffer_size *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->acl_mtu  = __le16_to_cpu(rp->acl_mtu);
 	hdev->sco_mtu  = rp->sco_mtu;
@@ -950,149 +886,130 @@ static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
 
 	BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
 	       hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
+
+	return rp->status;
 }
 
-static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_read_bd_addr(struct hci_dev *hdev, void *data,
+			      struct sk_buff *skb)
 {
-	struct hci_rp_read_bd_addr *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_BD_ADDR, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_bd_addr *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	if (test_bit(HCI_INIT, &hdev->flags))
 		bacpy(&hdev->bdaddr, &rp->bdaddr);
 
 	if (hci_dev_test_flag(hdev, HCI_SETUP))
 		bacpy(&hdev->setup_addr, &rp->bdaddr);
+
+	return rp->status;
 }
 
-static void hci_cc_read_local_pairing_opts(struct hci_dev *hdev,
-					   struct sk_buff *skb)
+static u8 hci_cc_read_local_pairing_opts(struct hci_dev *hdev, void *data,
+					 struct sk_buff *skb)
 {
-	struct hci_rp_read_local_pairing_opts *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_PAIRING_OPTS,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_local_pairing_opts *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
 	    hci_dev_test_flag(hdev, HCI_CONFIG)) {
 		hdev->pairing_opts = rp->pairing_opts;
 		hdev->max_enc_key_size = rp->max_key_size;
 	}
+
+	return rp->status;
 }
 
-static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
-					   struct sk_buff *skb)
+static u8 hci_cc_read_page_scan_activity(struct hci_dev *hdev, void *data,
+					 struct sk_buff *skb)
 {
-	struct hci_rp_read_page_scan_activity *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_ACTIVITY,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_page_scan_activity *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	if (test_bit(HCI_INIT, &hdev->flags)) {
 		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
 		hdev->page_scan_window = __le16_to_cpu(rp->window);
 	}
+
+	return rp->status;
 }
 
-static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
-					    struct sk_buff *skb)
+static u8 hci_cc_write_page_scan_activity(struct hci_dev *hdev, void *data,
+					  struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	struct hci_cp_write_page_scan_activity *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_ACTIVITY,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
 	hdev->page_scan_window = __le16_to_cpu(sent->window);
+
+	return rp->status;
 }
 
-static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
-					   struct sk_buff *skb)
+static u8 hci_cc_read_page_scan_type(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_rp_read_page_scan_type *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_TYPE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_page_scan_type *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	if (test_bit(HCI_INIT, &hdev->flags))
 		hdev->page_scan_type = rp->type;
+
+	return rp->status;
 }
 
-static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
-					struct sk_buff *skb)
+static u8 hci_cc_write_page_scan_type(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	u8 *type;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_PAGE_SCAN_TYPE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
 	if (type)
 		hdev->page_scan_type = *type;
+
+	return rp->status;
 }
 
-static void hci_cc_read_data_block_size(struct hci_dev *hdev,
-					struct sk_buff *skb)
+static u8 hci_cc_read_data_block_size(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_rp_read_data_block_size *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DATA_BLOCK_SIZE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_data_block_size *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
 	hdev->block_len = __le16_to_cpu(rp->block_len);
@@ -1102,24 +1019,21 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev,
 
 	BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
 	       hdev->block_cnt, hdev->block_len);
+
+	return rp->status;
 }
 
-static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_read_clock(struct hci_dev *hdev, void *data,
+			    struct sk_buff *skb)
 {
-	struct hci_rp_read_clock *rp;
+	struct hci_rp_read_clock *rp = data;
 	struct hci_cp_read_clock *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s", hdev->name);
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLOCK, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -1140,22 +1054,18 @@ static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb)
 
 unlock:
 	hci_dev_unlock(hdev);
+	return rp->status;
 }
 
-static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
-				       struct sk_buff *skb)
+static u8 hci_cc_read_local_amp_info(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_rp_read_local_amp_info *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_AMP_INFO,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_local_amp_info *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->amp_status = rp->amp_status;
 	hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
@@ -1167,77 +1077,67 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
 	hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
 	hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
 	hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
+
+	return rp->status;
 }
 
-static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
-					 struct sk_buff *skb)
+static u8 hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, void *data,
+				       struct sk_buff *skb)
 {
-	struct hci_rp_read_inq_rsp_tx_power *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_INQ_RSP_TX_POWER,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_inq_rsp_tx_power *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->inq_tx_power = rp->tx_power;
+
+	return rp->status;
 }
 
-static void hci_cc_read_def_err_data_reporting(struct hci_dev *hdev,
-					       struct sk_buff *skb)
+static u8 hci_cc_read_def_err_data_reporting(struct hci_dev *hdev, void *data,
+					     struct sk_buff *skb)
 {
-	struct hci_rp_read_def_err_data_reporting *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DEF_ERR_DATA_REPORTING,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_def_err_data_reporting *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->err_data_reporting = rp->err_data_reporting;
+
+	return rp->status;
 }
 
-static void hci_cc_write_def_err_data_reporting(struct hci_dev *hdev,
-						struct sk_buff *skb)
+static u8 hci_cc_write_def_err_data_reporting(struct hci_dev *hdev, void *data,
+					      struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	struct hci_cp_write_def_err_data_reporting *cp;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING);
 	if (!cp)
-		return;
+		return rp->status;
 
 	hdev->err_data_reporting = cp->err_data_reporting;
+
+	return rp->status;
 }
 
-static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_pin_code_reply(struct hci_dev *hdev, void *data,
+				struct sk_buff *skb)
 {
-	struct hci_rp_pin_code_reply *rp;
+	struct hci_rp_pin_code_reply *rp = data;
 	struct hci_cp_pin_code_reply *cp;
 	struct hci_conn *conn;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PIN_CODE_REPLY, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	hci_dev_lock(hdev);
@@ -1258,15 +1158,13 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb)
 
 unlock:
 	hci_dev_unlock(hdev);
+	return rp->status;
 }
 
-static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_pin_code_neg_reply(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_rp_pin_code_neg_reply *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_pin_code_neg_reply *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
@@ -1277,22 +1175,19 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
 						 rp->status);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
-				       struct sk_buff *skb)
+static u8 hci_cc_le_read_buffer_size(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_rp_le_read_buffer_size *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_BUFFER_SIZE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_le_read_buffer_size *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
 	hdev->le_pkts = rp->le_max_pkt;
@@ -1300,51 +1195,44 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
 	hdev->le_cnt = hdev->le_pkts;
 
 	BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
+
+	return rp->status;
 }
 
-static void hci_cc_le_read_local_features(struct hci_dev *hdev,
-					  struct sk_buff *skb)
+static u8 hci_cc_le_read_local_features(struct hci_dev *hdev, void *data,
+					struct sk_buff *skb)
 {
-	struct hci_rp_le_read_local_features *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_LOCAL_FEATURES,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_le_read_local_features *rp = data;
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	memcpy(hdev->le_features, rp->features, 8);
+
+	return rp->status;
 }
 
-static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
-					struct sk_buff *skb)
+static u8 hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_rp_le_read_adv_tx_power *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_ADV_TX_POWER,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_le_read_adv_tx_power *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->adv_tx_power = rp->tx_power;
+
+	return rp->status;
 }
 
-static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_user_confirm_reply(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_rp_user_confirm_reply *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_CONFIRM_REPLY, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_user_confirm_reply *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
@@ -1355,17 +1243,14 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
 						 rp->status);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
-					  struct sk_buff *skb)
+static u8 hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, void *data,
+					struct sk_buff *skb)
 {
-	struct hci_rp_user_confirm_reply *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_CONFIRM_NEG_REPLY,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_user_confirm_reply *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
@@ -1376,15 +1261,14 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
 						     ACL_LINK, 0, rp->status);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_user_passkey_reply(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_rp_user_confirm_reply *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_PASSKEY_REPLY, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_user_confirm_reply *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
@@ -1395,16 +1279,14 @@ static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
 						 0, rp->status);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
-					  struct sk_buff *skb)
+static u8 hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, void *data,
+					struct sk_buff *skb)
 {
-	struct hci_rp_user_confirm_reply *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_PASSKEY_NEG_REPLY, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_user_confirm_reply *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
@@ -1415,49 +1297,44 @@ static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
 						     ACL_LINK, 0, rp->status);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
-				       struct sk_buff *skb)
+static u8 hci_cc_read_local_oob_data(struct hci_dev *hdev, void *data,
+				     struct sk_buff *skb)
 {
-	struct hci_rp_read_local_oob_data *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_OOB_DATA, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_local_oob_data *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	return rp->status;
 }
 
-static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
-					   struct sk_buff *skb)
+static u8 hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, void *data,
+					 struct sk_buff *skb)
 {
-	struct hci_rp_read_local_oob_ext_data *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_OOB_EXT_DATA, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_read_local_oob_ext_data *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+
+	return rp->status;
 }
 
-static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_le_set_random_addr(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	bdaddr_t *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_RANDOM_ADDR, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -1470,25 +1347,24 @@ static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_le_set_default_phy(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	struct hci_cp_le_set_default_phy *cp;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_DEFAULT_PHY, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY);
 	if (!cp)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -1496,24 +1372,21 @@ static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb)
 	hdev->le_rx_def_phys = cp->rx_phys;
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
-                                              struct sk_buff *skb)
+static u8 hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev, void *data,
+					    struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	struct hci_cp_le_set_adv_set_rand_addr *cp;
 	struct adv_info *adv;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_SET_RAND_ADDR,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR);
 	/* Update only in case the adv instance since handle 0x00 shall be using
@@ -1521,7 +1394,7 @@ static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
 	 * non-extended adverting.
 	 */
 	if (!cp || !cp->handle)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -1537,26 +1410,25 @@ static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev,
 	}
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_le_remove_adv_set(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_le_remove_adv_set(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	u8 *instance;
 	int err;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_REMOVE_ADV_SET, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	instance = hci_sent_cmd_data(hdev, HCI_OP_LE_REMOVE_ADV_SET);
 	if (!instance)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -1566,25 +1438,24 @@ static void hci_cc_le_remove_adv_set(struct hci_dev *hdev, struct sk_buff *skb)
 					 *instance);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_le_clear_adv_sets(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_le_clear_adv_sets(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	struct adv_info *adv, *n;
 	int err;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_ADV_SETS, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	if (!hci_sent_cmd_data(hdev, HCI_OP_LE_CLEAR_ADV_SETS))
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -1598,44 +1469,40 @@ static void hci_cc_le_clear_adv_sets(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_le_read_transmit_power(struct hci_dev *hdev,
-					  struct sk_buff *skb)
+static u8 hci_cc_le_read_transmit_power(struct hci_dev *hdev, void *data,
+					struct sk_buff *skb)
 {
-	struct hci_rp_le_read_transmit_power *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_TRANSMIT_POWER,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_le_read_transmit_power *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->min_le_tx_power = rp->min_le_tx_power;
 	hdev->max_le_tx_power = rp->max_le_tx_power;
+
+	return rp->status;
 }
 
-static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_le_set_adv_enable(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	__u8 *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_ENABLE, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -1657,29 +1524,26 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
-					 struct sk_buff *skb)
+static u8 hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, void *data,
+				       struct sk_buff *skb)
 {
 	struct hci_cp_le_set_ext_adv_enable *cp;
 	struct hci_cp_ext_adv_set *set;
 	struct adv_info *adv = NULL, *n;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_ADV_ENABLE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE);
 	if (!cp)
-		return;
+		return rp->status;
 
 	set = (void *)cp->data;
 
@@ -1726,53 +1590,48 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
 
 unlock:
 	hci_dev_unlock(hdev);
+	return rp->status;
 }
 
-static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_le_set_scan_param(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
 	struct hci_cp_le_set_scan_param *cp;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_SCAN_PARAM, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM);
 	if (!cp)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
 	hdev->le_scan_type = cp->type;
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev,
-					 struct sk_buff *skb)
+static u8 hci_cc_le_set_ext_scan_param(struct hci_dev *hdev, void *data,
+				       struct sk_buff *skb)
 {
 	struct hci_cp_le_set_ext_scan_params *cp;
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	struct hci_cp_le_scan_phy_params *phy_param;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_SCAN_PARAMS,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS);
 	if (!cp)
-		return;
+		return rp->status;
 
 	phy_param = (void *)cp->data;
 
@@ -1781,6 +1640,8 @@ static void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev,
 	hdev->le_scan_type = phy_param->type;
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
 static bool has_pending_adv_report(struct hci_dev *hdev)
@@ -1866,320 +1727,273 @@ static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable)
 	hci_dev_unlock(hdev);
 }
 
-static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
-				      struct sk_buff *skb)
+static u8 hci_cc_le_set_scan_enable(struct hci_dev *hdev, void *data,
+				    struct sk_buff *skb)
 {
 	struct hci_cp_le_set_scan_enable *cp;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_SCAN_ENABLE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
 	if (!cp)
-		return;
+		return rp->status;
 
 	le_set_scan_enable_complete(hdev, cp->enable);
+
+	return rp->status;
 }
 
-static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev,
-				      struct sk_buff *skb)
+static u8 hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev, void *data,
+					struct sk_buff *skb)
 {
 	struct hci_cp_le_set_ext_scan_enable *cp;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_SCAN_ENABLE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_ENABLE);
 	if (!cp)
-		return;
+		return rp->status;
 
 	le_set_scan_enable_complete(hdev, cp->enable);
+
+	return rp->status;
 }
 
-static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev,
+static u8 hci_cc_le_read_num_adv_sets(struct hci_dev *hdev, void *data,
 				      struct sk_buff *skb)
 {
-	struct hci_rp_le_read_num_supported_adv_sets *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_le_read_num_supported_adv_sets *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x No of Adv sets %u", rp->status,
 		   rp->num_of_sets);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->le_num_of_adv_sets = rp->num_of_sets;
+
+	return rp->status;
 }
 
-static void hci_cc_le_read_accept_list_size(struct hci_dev *hdev,
-					    struct sk_buff *skb)
+static u8 hci_cc_le_read_accept_list_size(struct hci_dev *hdev, void *data,
+					  struct sk_buff *skb)
 {
-	struct hci_rp_le_read_accept_list_size *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_ACCEPT_LIST_SIZE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_le_read_accept_list_size *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x size %u", rp->status, rp->size);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->le_accept_list_size = rp->size;
+
+	return rp->status;
 }
 
-static void hci_cc_le_clear_accept_list(struct hci_dev *hdev,
-					struct sk_buff *skb)
+static u8 hci_cc_le_clear_accept_list(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_ACCEPT_LIST,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hci_bdaddr_list_clear(&hdev->le_accept_list);
+
+	return rp->status;
 }
 
-static void hci_cc_le_add_to_accept_list(struct hci_dev *hdev,
-					 struct sk_buff *skb)
+static u8 hci_cc_le_add_to_accept_list(struct hci_dev *hdev, void *data,
+				       struct sk_buff *skb)
 {
 	struct hci_cp_le_add_to_accept_list *sent;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_ADD_TO_ACCEPT_LIST,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_bdaddr_list_add(&hdev->le_accept_list, &sent->bdaddr,
 			    sent->bdaddr_type);
+
+	return rp->status;
 }
 
-static void hci_cc_le_del_from_accept_list(struct hci_dev *hdev,
-					   struct sk_buff *skb)
+static u8 hci_cc_le_del_from_accept_list(struct hci_dev *hdev, void *data,
+					 struct sk_buff *skb)
 {
 	struct hci_cp_le_del_from_accept_list *sent;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_DEL_FROM_ACCEPT_LIST,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_ACCEPT_LIST);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_bdaddr_list_del(&hdev->le_accept_list, &sent->bdaddr,
 			    sent->bdaddr_type);
+
+	return rp->status;
 }
 
-static void hci_cc_le_read_supported_states(struct hci_dev *hdev,
-					    struct sk_buff *skb)
+static u8 hci_cc_le_read_supported_states(struct hci_dev *hdev, void *data,
+					  struct sk_buff *skb)
 {
-	struct hci_rp_le_read_supported_states *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_SUPPORTED_STATES,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_le_read_supported_states *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	memcpy(hdev->le_states, rp->le_states, 8);
+
+	return rp->status;
 }
 
-static void hci_cc_le_read_def_data_len(struct hci_dev *hdev,
-					struct sk_buff *skb)
+static u8 hci_cc_le_read_def_data_len(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_rp_le_read_def_data_len *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_DEF_DATA_LEN,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_le_read_def_data_len *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->le_def_tx_len = le16_to_cpu(rp->tx_len);
 	hdev->le_def_tx_time = le16_to_cpu(rp->tx_time);
+
+	return rp->status;
 }
 
-static void hci_cc_le_write_def_data_len(struct hci_dev *hdev,
-					 struct sk_buff *skb)
+static u8 hci_cc_le_write_def_data_len(struct hci_dev *hdev, void *data,
+				       struct sk_buff *skb)
 {
 	struct hci_cp_le_write_def_data_len *sent;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_WRITE_DEF_DATA_LEN,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hdev->le_def_tx_len = le16_to_cpu(sent->tx_len);
 	hdev->le_def_tx_time = le16_to_cpu(sent->tx_time);
+
+	return rp->status;
 }
 
-static void hci_cc_le_add_to_resolv_list(struct hci_dev *hdev,
-					 struct sk_buff *skb)
+static u8 hci_cc_le_add_to_resolv_list(struct hci_dev *hdev, void *data,
+				       struct sk_buff *skb)
 {
 	struct hci_cp_le_add_to_resolv_list *sent;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_ADD_TO_RESOLV_LIST,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_bdaddr_list_add_with_irk(&hdev->le_resolv_list, &sent->bdaddr,
 				sent->bdaddr_type, sent->peer_irk,
 				sent->local_irk);
+
+	return rp->status;
 }
 
-static void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev,
-					  struct sk_buff *skb)
+static u8 hci_cc_le_del_from_resolv_list(struct hci_dev *hdev, void *data,
+					 struct sk_buff *skb)
 {
 	struct hci_cp_le_del_from_resolv_list *sent;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_DEL_FROM_RESOLV_LIST,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLV_LIST);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_bdaddr_list_del_with_irk(&hdev->le_resolv_list, &sent->bdaddr,
 			    sent->bdaddr_type);
+
+	return rp->status;
 }
 
-static void hci_cc_le_clear_resolv_list(struct hci_dev *hdev,
-				       struct sk_buff *skb)
+static u8 hci_cc_le_clear_resolv_list(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_RESOLV_LIST,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hci_bdaddr_list_clear(&hdev->le_resolv_list);
+
+	return rp->status;
 }
 
-static void hci_cc_le_read_resolv_list_size(struct hci_dev *hdev,
-					   struct sk_buff *skb)
+static u8 hci_cc_le_read_resolv_list_size(struct hci_dev *hdev, void *data,
+					  struct sk_buff *skb)
 {
-	struct hci_rp_le_read_resolv_list_size *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_RESOLV_LIST_SIZE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_le_read_resolv_list_size *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x size %u", rp->status, rp->size);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->le_resolv_list_size = rp->size;
+
+	return rp->status;
 }
 
-static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev,
-						struct sk_buff *skb)
+static u8 hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev, void *data,
+					       struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	__u8 *sent;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -2189,48 +2003,42 @@ static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev,
 		hci_dev_clear_flag(hdev, HCI_LL_RPA_RESOLUTION);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_le_read_max_data_len(struct hci_dev *hdev,
-					struct sk_buff *skb)
+static u8 hci_cc_le_read_max_data_len(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_rp_le_read_max_data_len *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_MAX_DATA_LEN,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_rp_le_read_max_data_len *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hdev->le_max_tx_len = le16_to_cpu(rp->tx_len);
 	hdev->le_max_tx_time = le16_to_cpu(rp->tx_time);
 	hdev->le_max_rx_len = le16_to_cpu(rp->rx_len);
 	hdev->le_max_rx_time = le16_to_cpu(rp->rx_time);
+
+	return rp->status;
 }
 
-static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
-					   struct sk_buff *skb)
+static u8 hci_cc_write_le_host_supported(struct hci_dev *hdev, void *data,
+					 struct sk_buff *skb)
 {
 	struct hci_cp_write_le_host_supported *sent;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LE_HOST_SUPPORTED,
-			     sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -2249,50 +2057,47 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
 		hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_set_adv_param(struct hci_dev *hdev, void *data,
+			       struct sk_buff *skb)
 {
 	struct hci_cp_le_set_adv_param *cp;
-	struct hci_ev_status *rp;
-
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_PARAM, sizeof(*rp));
-	if (!rp)
-		return;
+	struct hci_ev_status *rp = data;
 
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
 	if (!cp)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 	hdev->adv_addr_type = cp->own_address_type;
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_set_ext_adv_param(struct hci_dev *hdev, void *data,
+				   struct sk_buff *skb)
 {
-	struct hci_rp_le_set_ext_adv_params *rp;
+	struct hci_rp_le_set_ext_adv_params *rp = data;
 	struct hci_cp_le_set_ext_adv_params *cp;
 	struct adv_info *adv_instance;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_ADV_PARAMS,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS);
 	if (!cp)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 	hdev->adv_addr_type = cp->own_addr_type;
@@ -2308,21 +2113,20 @@ static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_req_update_adv_data(hdev, cp->handle);
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_read_rssi(struct hci_dev *hdev, void *data,
+			   struct sk_buff *skb)
 {
-	struct hci_rp_read_rssi *rp;
+	struct hci_rp_read_rssi *rp = data;
 	struct hci_conn *conn;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_RSSI, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -2331,26 +2135,25 @@ static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
 		conn->rssi = rp->rssi;
 
 	hci_dev_unlock(hdev);
+
+	return rp->status;
 }
 
-static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_read_tx_power(struct hci_dev *hdev, void *data,
+			       struct sk_buff *skb)
 {
 	struct hci_cp_read_tx_power *sent;
-	struct hci_rp_read_tx_power *rp;
+	struct hci_rp_read_tx_power *rp = data;
 	struct hci_conn *conn;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_TX_POWER, sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
 	if (!sent)
-		return;
+		return rp->status;
 
 	hci_dev_lock(hdev);
 
@@ -2369,26 +2172,25 @@ static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb)
 
 unlock:
 	hci_dev_unlock(hdev);
+	return rp->status;
 }
 
-static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb)
+static u8 hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, void *data,
+				      struct sk_buff *skb)
 {
-	struct hci_ev_status *rp;
+	struct hci_ev_status *rp = data;
 	u8 *mode;
 
-	rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SSP_DEBUG_MODE,
-			     sizeof(*rp));
-	if (!rp)
-		return;
-
 	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
 
 	if (rp->status)
-		return;
+		return rp->status;
 
 	mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE);
 	if (mode)
 		hdev->ssp_debug_mode = *mode;
+
+	return rp->status;
 }
 
 static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
@@ -3909,372 +3711,226 @@ static inline void handle_cmd_cnt_and_timer(struct hci_dev *hdev, u8 ncmd)
 	}
 }
 
-static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
-				 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_cmd_complete *ev = data;
-
-	*opcode = __le16_to_cpu(ev->opcode);
-	*status = skb->data[0];
-
-	switch (*opcode) {
-	case HCI_OP_INQUIRY_CANCEL:
-		hci_cc_inquiry_cancel(hdev, skb, status);
-		break;
-
-	case HCI_OP_PERIODIC_INQ:
-		hci_cc_periodic_inq(hdev, skb);
-		break;
-
-	case HCI_OP_EXIT_PERIODIC_INQ:
-		hci_cc_exit_periodic_inq(hdev, skb);
-		break;
-
-	case HCI_OP_REMOTE_NAME_REQ_CANCEL:
-		hci_cc_remote_name_req_cancel(hdev, skb);
-		break;
-
-	case HCI_OP_ROLE_DISCOVERY:
-		hci_cc_role_discovery(hdev, skb);
-		break;
-
-	case HCI_OP_READ_LINK_POLICY:
-		hci_cc_read_link_policy(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_LINK_POLICY:
-		hci_cc_write_link_policy(hdev, skb);
-		break;
-
-	case HCI_OP_READ_DEF_LINK_POLICY:
-		hci_cc_read_def_link_policy(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_DEF_LINK_POLICY:
-		hci_cc_write_def_link_policy(hdev, skb);
-		break;
-
-	case HCI_OP_RESET:
-		hci_cc_reset(hdev, skb);
-		break;
-
-	case HCI_OP_READ_STORED_LINK_KEY:
-		hci_cc_read_stored_link_key(hdev, skb);
-		break;
-
-	case HCI_OP_DELETE_STORED_LINK_KEY:
-		hci_cc_delete_stored_link_key(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_LOCAL_NAME:
-		hci_cc_write_local_name(hdev, skb);
-		break;
-
-	case HCI_OP_READ_LOCAL_NAME:
-		hci_cc_read_local_name(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_AUTH_ENABLE:
-		hci_cc_write_auth_enable(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_ENCRYPT_MODE:
-		hci_cc_write_encrypt_mode(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_SCAN_ENABLE:
-		hci_cc_write_scan_enable(hdev, skb);
-		break;
-
-	case HCI_OP_SET_EVENT_FLT:
-		hci_cc_set_event_filter(hdev, skb);
-		break;
-
-	case HCI_OP_READ_CLASS_OF_DEV:
-		hci_cc_read_class_of_dev(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_CLASS_OF_DEV:
-		hci_cc_write_class_of_dev(hdev, skb);
-		break;
-
-	case HCI_OP_READ_VOICE_SETTING:
-		hci_cc_read_voice_setting(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_VOICE_SETTING:
-		hci_cc_write_voice_setting(hdev, skb);
-		break;
-
-	case HCI_OP_READ_NUM_SUPPORTED_IAC:
-		hci_cc_read_num_supported_iac(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_SSP_MODE:
-		hci_cc_write_ssp_mode(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_SC_SUPPORT:
-		hci_cc_write_sc_support(hdev, skb);
-		break;
-
-	case HCI_OP_READ_AUTH_PAYLOAD_TO:
-		hci_cc_read_auth_payload_timeout(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_AUTH_PAYLOAD_TO:
-		hci_cc_write_auth_payload_timeout(hdev, skb);
-		break;
-
-	case HCI_OP_READ_LOCAL_VERSION:
-		hci_cc_read_local_version(hdev, skb);
-		break;
-
-	case HCI_OP_READ_LOCAL_COMMANDS:
-		hci_cc_read_local_commands(hdev, skb);
-		break;
-
-	case HCI_OP_READ_LOCAL_FEATURES:
-		hci_cc_read_local_features(hdev, skb);
-		break;
-
-	case HCI_OP_READ_LOCAL_EXT_FEATURES:
-		hci_cc_read_local_ext_features(hdev, skb);
-		break;
-
-	case HCI_OP_READ_BUFFER_SIZE:
-		hci_cc_read_buffer_size(hdev, skb);
-		break;
-
-	case HCI_OP_READ_BD_ADDR:
-		hci_cc_read_bd_addr(hdev, skb);
-		break;
-
-	case HCI_OP_READ_LOCAL_PAIRING_OPTS:
-		hci_cc_read_local_pairing_opts(hdev, skb);
-		break;
-
-	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
-		hci_cc_read_page_scan_activity(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
-		hci_cc_write_page_scan_activity(hdev, skb);
-		break;
-
-	case HCI_OP_READ_PAGE_SCAN_TYPE:
-		hci_cc_read_page_scan_type(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
-		hci_cc_write_page_scan_type(hdev, skb);
-		break;
-
-	case HCI_OP_READ_DATA_BLOCK_SIZE:
-		hci_cc_read_data_block_size(hdev, skb);
-		break;
-
-	case HCI_OP_READ_FLOW_CONTROL_MODE:
-		hci_cc_read_flow_control_mode(hdev, skb);
-		break;
-
-	case HCI_OP_READ_LOCAL_AMP_INFO:
-		hci_cc_read_local_amp_info(hdev, skb);
-		break;
-
-	case HCI_OP_READ_CLOCK:
-		hci_cc_read_clock(hdev, skb);
-		break;
-
-	case HCI_OP_READ_INQ_RSP_TX_POWER:
-		hci_cc_read_inq_rsp_tx_power(hdev, skb);
-		break;
-
-	case HCI_OP_READ_DEF_ERR_DATA_REPORTING:
-		hci_cc_read_def_err_data_reporting(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_DEF_ERR_DATA_REPORTING:
-		hci_cc_write_def_err_data_reporting(hdev, skb);
-		break;
-
-	case HCI_OP_PIN_CODE_REPLY:
-		hci_cc_pin_code_reply(hdev, skb);
-		break;
-
-	case HCI_OP_PIN_CODE_NEG_REPLY:
-		hci_cc_pin_code_neg_reply(hdev, skb);
-		break;
-
-	case HCI_OP_READ_LOCAL_OOB_DATA:
-		hci_cc_read_local_oob_data(hdev, skb);
-		break;
-
-	case HCI_OP_READ_LOCAL_OOB_EXT_DATA:
-		hci_cc_read_local_oob_ext_data(hdev, skb);
-		break;
-
-	case HCI_OP_LE_READ_BUFFER_SIZE:
-		hci_cc_le_read_buffer_size(hdev, skb);
-		break;
-
-	case HCI_OP_LE_READ_LOCAL_FEATURES:
-		hci_cc_le_read_local_features(hdev, skb);
-		break;
-
-	case HCI_OP_LE_READ_ADV_TX_POWER:
-		hci_cc_le_read_adv_tx_power(hdev, skb);
-		break;
-
-	case HCI_OP_USER_CONFIRM_REPLY:
-		hci_cc_user_confirm_reply(hdev, skb);
-		break;
-
-	case HCI_OP_USER_CONFIRM_NEG_REPLY:
-		hci_cc_user_confirm_neg_reply(hdev, skb);
-		break;
-
-	case HCI_OP_USER_PASSKEY_REPLY:
-		hci_cc_user_passkey_reply(hdev, skb);
-		break;
-
-	case HCI_OP_USER_PASSKEY_NEG_REPLY:
-		hci_cc_user_passkey_neg_reply(hdev, skb);
-		break;
-
-	case HCI_OP_LE_SET_RANDOM_ADDR:
-		hci_cc_le_set_random_addr(hdev, skb);
-		break;
-
-	case HCI_OP_LE_SET_ADV_ENABLE:
-		hci_cc_le_set_adv_enable(hdev, skb);
-		break;
-
-	case HCI_OP_LE_SET_SCAN_PARAM:
-		hci_cc_le_set_scan_param(hdev, skb);
-		break;
-
-	case HCI_OP_LE_SET_SCAN_ENABLE:
-		hci_cc_le_set_scan_enable(hdev, skb);
-		break;
-
-	case HCI_OP_LE_READ_ACCEPT_LIST_SIZE:
-		hci_cc_le_read_accept_list_size(hdev, skb);
-		break;
-
-	case HCI_OP_LE_CLEAR_ACCEPT_LIST:
-		hci_cc_le_clear_accept_list(hdev, skb);
-		break;
-
-	case HCI_OP_LE_ADD_TO_ACCEPT_LIST:
-		hci_cc_le_add_to_accept_list(hdev, skb);
-		break;
-
-	case HCI_OP_LE_DEL_FROM_ACCEPT_LIST:
-		hci_cc_le_del_from_accept_list(hdev, skb);
-		break;
-
-	case HCI_OP_LE_READ_SUPPORTED_STATES:
-		hci_cc_le_read_supported_states(hdev, skb);
-		break;
-
-	case HCI_OP_LE_READ_DEF_DATA_LEN:
-		hci_cc_le_read_def_data_len(hdev, skb);
-		break;
-
-	case HCI_OP_LE_WRITE_DEF_DATA_LEN:
-		hci_cc_le_write_def_data_len(hdev, skb);
-		break;
-
-	case HCI_OP_LE_ADD_TO_RESOLV_LIST:
-		hci_cc_le_add_to_resolv_list(hdev, skb);
-		break;
-
-	case HCI_OP_LE_DEL_FROM_RESOLV_LIST:
-		hci_cc_le_del_from_resolv_list(hdev, skb);
-		break;
-
-	case HCI_OP_LE_CLEAR_RESOLV_LIST:
-		hci_cc_le_clear_resolv_list(hdev, skb);
-		break;
-
-	case HCI_OP_LE_READ_RESOLV_LIST_SIZE:
-		hci_cc_le_read_resolv_list_size(hdev, skb);
-		break;
-
-	case HCI_OP_LE_SET_ADDR_RESOLV_ENABLE:
-		hci_cc_le_set_addr_resolution_enable(hdev, skb);
-		break;
-
-	case HCI_OP_LE_READ_MAX_DATA_LEN:
-		hci_cc_le_read_max_data_len(hdev, skb);
-		break;
-
-	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
-		hci_cc_write_le_host_supported(hdev, skb);
-		break;
-
-	case HCI_OP_LE_SET_ADV_PARAM:
-		hci_cc_set_adv_param(hdev, skb);
-		break;
-
-	case HCI_OP_READ_RSSI:
-		hci_cc_read_rssi(hdev, skb);
-		break;
-
-	case HCI_OP_READ_TX_POWER:
-		hci_cc_read_tx_power(hdev, skb);
-		break;
+#define HCI_CC_VL(_op, _func, _min, _max) \
+{ \
+	.op = _op, \
+	.func = _func, \
+	.min_len = _min, \
+	.max_len = _max, \
+}
 
-	case HCI_OP_WRITE_SSP_DEBUG_MODE:
-		hci_cc_write_ssp_debug_mode(hdev, skb);
-		break;
+#define HCI_CC(_op, _func, _len) \
+	HCI_CC_VL(_op, _func, _len, _len)
 
-	case HCI_OP_LE_SET_EXT_SCAN_PARAMS:
-		hci_cc_le_set_ext_scan_param(hdev, skb);
-		break;
+#define HCI_CC_STATUS(_op, _func) \
+	HCI_CC(_op, _func, sizeof(struct hci_ev_status))
 
-	case HCI_OP_LE_SET_EXT_SCAN_ENABLE:
-		hci_cc_le_set_ext_scan_enable(hdev, skb);
-		break;
+static const struct hci_cc {
+	u16  op;
+	u8 (*func)(struct hci_dev *hdev, void *data, struct sk_buff *skb);
+	u16  min_len;
+	u16  max_len;
+} hci_cc_table[] = {
+	HCI_CC_STATUS(HCI_OP_INQUIRY_CANCEL, hci_cc_inquiry_cancel),
+	HCI_CC_STATUS(HCI_OP_PERIODIC_INQ, hci_cc_periodic_inq),
+	HCI_CC_STATUS(HCI_OP_EXIT_PERIODIC_INQ, hci_cc_exit_periodic_inq),
+	HCI_CC_STATUS(HCI_OP_REMOTE_NAME_REQ_CANCEL,
+		      hci_cc_remote_name_req_cancel),
+	HCI_CC(HCI_OP_ROLE_DISCOVERY, hci_cc_role_discovery,
+	       sizeof(struct hci_rp_role_discovery)),
+	HCI_CC(HCI_OP_READ_LINK_POLICY, hci_cc_read_link_policy,
+	       sizeof(struct hci_rp_read_link_policy)),
+	HCI_CC(HCI_OP_WRITE_LINK_POLICY, hci_cc_write_link_policy,
+	       sizeof(struct hci_rp_write_link_policy)),
+	HCI_CC(HCI_OP_READ_DEF_LINK_POLICY, hci_cc_read_def_link_policy,
+	       sizeof(struct hci_rp_read_def_link_policy)),
+	HCI_CC_STATUS(HCI_OP_WRITE_DEF_LINK_POLICY,
+		      hci_cc_write_def_link_policy),
+	HCI_CC_STATUS(HCI_OP_RESET, hci_cc_reset),
+	HCI_CC(HCI_OP_READ_STORED_LINK_KEY, hci_cc_read_stored_link_key,
+	       sizeof(struct hci_rp_read_stored_link_key)),
+	HCI_CC(HCI_OP_DELETE_STORED_LINK_KEY, hci_cc_delete_stored_link_key,
+	       sizeof(struct hci_rp_delete_stored_link_key)),
+	HCI_CC_STATUS(HCI_OP_WRITE_LOCAL_NAME, hci_cc_write_local_name),
+	HCI_CC(HCI_OP_READ_LOCAL_NAME, hci_cc_read_local_name,
+	       sizeof(struct hci_rp_read_local_name)),
+	HCI_CC_STATUS(HCI_OP_WRITE_AUTH_ENABLE, hci_cc_write_auth_enable),
+	HCI_CC_STATUS(HCI_OP_WRITE_ENCRYPT_MODE, hci_cc_write_encrypt_mode),
+	HCI_CC_STATUS(HCI_OP_WRITE_SCAN_ENABLE, hci_cc_write_scan_enable),
+	HCI_CC_STATUS(HCI_OP_SET_EVENT_FLT, hci_cc_set_event_filter),
+	HCI_CC(HCI_OP_READ_CLASS_OF_DEV, hci_cc_read_class_of_dev,
+	       sizeof(struct hci_rp_read_class_of_dev)),
+	HCI_CC_STATUS(HCI_OP_WRITE_CLASS_OF_DEV, hci_cc_write_class_of_dev),
+	HCI_CC(HCI_OP_READ_VOICE_SETTING, hci_cc_read_voice_setting,
+	       sizeof(struct hci_rp_read_voice_setting)),
+	HCI_CC_STATUS(HCI_OP_WRITE_VOICE_SETTING, hci_cc_write_voice_setting),
+	HCI_CC(HCI_OP_READ_NUM_SUPPORTED_IAC, hci_cc_read_num_supported_iac,
+	       sizeof(struct hci_rp_read_num_supported_iac)),
+	HCI_CC_STATUS(HCI_OP_WRITE_SSP_MODE, hci_cc_write_ssp_mode),
+	HCI_CC_STATUS(HCI_OP_WRITE_SC_SUPPORT, hci_cc_write_sc_support),
+	HCI_CC(HCI_OP_READ_AUTH_PAYLOAD_TO, hci_cc_read_auth_payload_timeout,
+	       sizeof(struct hci_rp_read_auth_payload_to)),
+	HCI_CC(HCI_OP_WRITE_AUTH_PAYLOAD_TO, hci_cc_write_auth_payload_timeout,
+	       sizeof(struct hci_rp_write_auth_payload_to)),
+	HCI_CC(HCI_OP_READ_LOCAL_VERSION, hci_cc_read_local_version,
+	       sizeof(struct hci_rp_read_local_version)),
+	HCI_CC(HCI_OP_READ_LOCAL_COMMANDS, hci_cc_read_local_commands,
+	       sizeof(struct hci_rp_read_local_commands)),
+	HCI_CC(HCI_OP_READ_LOCAL_FEATURES, hci_cc_read_local_features,
+	       sizeof(struct hci_rp_read_local_features)),
+	HCI_CC(HCI_OP_READ_LOCAL_EXT_FEATURES, hci_cc_read_local_ext_features,
+	       sizeof(struct hci_rp_read_local_ext_features)),
+	HCI_CC(HCI_OP_READ_BUFFER_SIZE, hci_cc_read_buffer_size,
+	       sizeof(struct hci_rp_read_buffer_size)),
+	HCI_CC(HCI_OP_READ_BD_ADDR, hci_cc_read_bd_addr,
+	       sizeof(struct hci_rp_read_bd_addr)),
+	HCI_CC(HCI_OP_READ_LOCAL_PAIRING_OPTS, hci_cc_read_local_pairing_opts,
+	       sizeof(struct hci_rp_read_local_pairing_opts)),
+	HCI_CC(HCI_OP_READ_PAGE_SCAN_ACTIVITY, hci_cc_read_page_scan_activity,
+	       sizeof(struct hci_rp_read_page_scan_activity)),
+	HCI_CC_STATUS(HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
+		      hci_cc_write_page_scan_activity),
+	HCI_CC(HCI_OP_READ_PAGE_SCAN_TYPE, hci_cc_read_page_scan_type,
+	       sizeof(struct hci_rp_read_page_scan_type)),
+	HCI_CC_STATUS(HCI_OP_WRITE_PAGE_SCAN_TYPE, hci_cc_write_page_scan_type),
+	HCI_CC(HCI_OP_READ_DATA_BLOCK_SIZE, hci_cc_read_data_block_size,
+	       sizeof(struct hci_rp_read_data_block_size)),
+	HCI_CC(HCI_OP_READ_FLOW_CONTROL_MODE, hci_cc_read_flow_control_mode,
+	       sizeof(struct hci_rp_read_flow_control_mode)),
+	HCI_CC(HCI_OP_READ_LOCAL_AMP_INFO, hci_cc_read_local_amp_info,
+	       sizeof(struct hci_rp_read_local_amp_info)),
+	HCI_CC(HCI_OP_READ_CLOCK, hci_cc_read_clock,
+	       sizeof(struct hci_rp_read_clock)),
+	HCI_CC(HCI_OP_READ_INQ_RSP_TX_POWER, hci_cc_read_inq_rsp_tx_power,
+	       sizeof(struct hci_rp_read_inq_rsp_tx_power)),
+	HCI_CC(HCI_OP_READ_DEF_ERR_DATA_REPORTING,
+	       hci_cc_read_def_err_data_reporting,
+	       sizeof(struct hci_rp_read_def_err_data_reporting)),
+	HCI_CC_STATUS(HCI_OP_WRITE_DEF_ERR_DATA_REPORTING,
+		      hci_cc_write_def_err_data_reporting),
+	HCI_CC(HCI_OP_PIN_CODE_REPLY, hci_cc_pin_code_reply,
+	       sizeof(struct hci_rp_pin_code_reply)),
+	HCI_CC(HCI_OP_PIN_CODE_NEG_REPLY, hci_cc_pin_code_neg_reply,
+	       sizeof(struct hci_rp_pin_code_neg_reply)),
+	HCI_CC(HCI_OP_READ_LOCAL_OOB_DATA, hci_cc_read_local_oob_data,
+	       sizeof(struct hci_rp_read_local_oob_data)),
+	HCI_CC(HCI_OP_READ_LOCAL_OOB_EXT_DATA, hci_cc_read_local_oob_ext_data,
+	       sizeof(struct hci_rp_read_local_oob_ext_data)),
+	HCI_CC(HCI_OP_LE_READ_BUFFER_SIZE, hci_cc_le_read_buffer_size,
+	       sizeof(struct hci_rp_le_read_buffer_size)),
+	HCI_CC(HCI_OP_LE_READ_LOCAL_FEATURES, hci_cc_le_read_local_features,
+	       sizeof(struct hci_rp_le_read_local_features)),
+	HCI_CC(HCI_OP_LE_READ_ADV_TX_POWER, hci_cc_le_read_adv_tx_power,
+	       sizeof(struct hci_rp_le_read_adv_tx_power)),
+	HCI_CC(HCI_OP_USER_CONFIRM_REPLY, hci_cc_user_confirm_reply,
+	       sizeof(struct hci_rp_user_confirm_reply)),
+	HCI_CC(HCI_OP_USER_CONFIRM_NEG_REPLY, hci_cc_user_confirm_neg_reply,
+	       sizeof(struct hci_rp_user_confirm_reply)),
+	HCI_CC(HCI_OP_USER_PASSKEY_REPLY, hci_cc_user_passkey_reply,
+	       sizeof(struct hci_rp_user_confirm_reply)),
+	HCI_CC(HCI_OP_USER_PASSKEY_NEG_REPLY, hci_cc_user_passkey_neg_reply,
+	       sizeof(struct hci_rp_user_confirm_reply)),
+	HCI_CC_STATUS(HCI_OP_LE_SET_RANDOM_ADDR, hci_cc_le_set_random_addr),
+	HCI_CC_STATUS(HCI_OP_LE_SET_ADV_ENABLE, hci_cc_le_set_adv_enable),
+	HCI_CC_STATUS(HCI_OP_LE_SET_SCAN_PARAM, hci_cc_le_set_scan_param),
+	HCI_CC_STATUS(HCI_OP_LE_SET_SCAN_ENABLE, hci_cc_le_set_scan_enable),
+	HCI_CC(HCI_OP_LE_READ_ACCEPT_LIST_SIZE,
+	       hci_cc_le_read_accept_list_size,
+	       sizeof(struct hci_rp_le_read_accept_list_size)),
+	HCI_CC_STATUS(HCI_OP_LE_CLEAR_ACCEPT_LIST, hci_cc_le_clear_accept_list),
+	HCI_CC_STATUS(HCI_OP_LE_ADD_TO_ACCEPT_LIST,
+		      hci_cc_le_add_to_accept_list),
+	HCI_CC_STATUS(HCI_OP_LE_DEL_FROM_ACCEPT_LIST,
+		      hci_cc_le_del_from_accept_list),
+	HCI_CC(HCI_OP_LE_READ_SUPPORTED_STATES, hci_cc_le_read_supported_states,
+	       sizeof(struct hci_rp_le_read_supported_states)),
+	HCI_CC(HCI_OP_LE_READ_DEF_DATA_LEN, hci_cc_le_read_def_data_len,
+	       sizeof(struct hci_rp_le_read_def_data_len)),
+	HCI_CC_STATUS(HCI_OP_LE_WRITE_DEF_DATA_LEN,
+		      hci_cc_le_write_def_data_len),
+	HCI_CC_STATUS(HCI_OP_LE_ADD_TO_RESOLV_LIST,
+		      hci_cc_le_add_to_resolv_list),
+	HCI_CC_STATUS(HCI_OP_LE_DEL_FROM_RESOLV_LIST,
+		      hci_cc_le_del_from_resolv_list),
+	HCI_CC_STATUS(HCI_OP_LE_CLEAR_RESOLV_LIST,
+		      hci_cc_le_clear_resolv_list),
+	HCI_CC(HCI_OP_LE_READ_RESOLV_LIST_SIZE, hci_cc_le_read_resolv_list_size,
+	       sizeof(struct hci_rp_le_read_resolv_list_size)),
+	HCI_CC_STATUS(HCI_OP_LE_SET_ADDR_RESOLV_ENABLE,
+		      hci_cc_le_set_addr_resolution_enable),
+	HCI_CC(HCI_OP_LE_READ_MAX_DATA_LEN, hci_cc_le_read_max_data_len,
+	       sizeof(struct hci_rp_le_read_max_data_len)),
+	HCI_CC_STATUS(HCI_OP_WRITE_LE_HOST_SUPPORTED,
+		      hci_cc_write_le_host_supported),
+	HCI_CC_STATUS(HCI_OP_LE_SET_ADV_PARAM, hci_cc_set_adv_param),
+	HCI_CC(HCI_OP_READ_RSSI, hci_cc_read_rssi,
+	       sizeof(struct hci_rp_read_rssi)),
+	HCI_CC(HCI_OP_READ_TX_POWER, hci_cc_read_tx_power,
+	       sizeof(struct hci_rp_read_tx_power)),
+	HCI_CC_STATUS(HCI_OP_WRITE_SSP_DEBUG_MODE, hci_cc_write_ssp_debug_mode),
+	HCI_CC_STATUS(HCI_OP_LE_SET_EXT_SCAN_PARAMS,
+		      hci_cc_le_set_ext_scan_param),
+	HCI_CC_STATUS(HCI_OP_LE_SET_EXT_SCAN_ENABLE,
+		      hci_cc_le_set_ext_scan_enable),
+	HCI_CC_STATUS(HCI_OP_LE_SET_DEFAULT_PHY, hci_cc_le_set_default_phy),
+	HCI_CC(HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS,
+	       hci_cc_le_read_num_adv_sets,
+	       sizeof(struct hci_rp_le_read_num_supported_adv_sets)),
+	HCI_CC(HCI_OP_LE_SET_EXT_ADV_PARAMS, hci_cc_set_ext_adv_param,
+	       sizeof(struct hci_rp_le_set_ext_adv_params)),
+	HCI_CC_STATUS(HCI_OP_LE_SET_EXT_ADV_ENABLE,
+		      hci_cc_le_set_ext_adv_enable),
+	HCI_CC_STATUS(HCI_OP_LE_SET_ADV_SET_RAND_ADDR,
+		      hci_cc_le_set_adv_set_random_addr),
+	HCI_CC_STATUS(HCI_OP_LE_REMOVE_ADV_SET, hci_cc_le_remove_adv_set),
+	HCI_CC_STATUS(HCI_OP_LE_CLEAR_ADV_SETS, hci_cc_le_clear_adv_sets),
+	HCI_CC(HCI_OP_LE_READ_TRANSMIT_POWER, hci_cc_le_read_transmit_power,
+	       sizeof(struct hci_rp_le_read_transmit_power))
+};
 
-	case HCI_OP_LE_SET_DEFAULT_PHY:
-		hci_cc_le_set_default_phy(hdev, skb);
-		break;
+static u8 hci_cc_func(struct hci_dev *hdev, const struct hci_cc *cc,
+		      struct sk_buff *skb)
+{
+	void *data;
 
-	case HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS:
-		hci_cc_le_read_num_adv_sets(hdev, skb);
-		break;
+	if (skb->len < cc->min_len) {
+		bt_dev_err(hdev, "unexpected cc 0x%4.4x length: %u < %u",
+			   cc->op, skb->len, cc->min_len);
+		return HCI_ERROR_UNSPECIFIED;
+	}
 
-	case HCI_OP_LE_SET_EXT_ADV_PARAMS:
-		hci_cc_set_ext_adv_param(hdev, skb);
-		break;
+	/* Just warn if the length is over max_len size it still be possible to
+	 * partially parse the cc so leave to callback to decide if that is
+	 * acceptable.
+	 */
+	if (skb->len > cc->max_len)
+		bt_dev_warn(hdev, "unexpected cc 0x%4.4x length: %u > %u",
+			    cc->op, skb->len, cc->max_len);
 
-	case HCI_OP_LE_SET_EXT_ADV_ENABLE:
-		hci_cc_le_set_ext_adv_enable(hdev, skb);
-		break;
+	data = hci_cc_skb_pull(hdev, skb, cc->op, cc->min_len);
+	if (!data)
+		return HCI_ERROR_UNSPECIFIED;
 
-	case HCI_OP_LE_SET_ADV_SET_RAND_ADDR:
-		hci_cc_le_set_adv_set_random_addr(hdev, skb);
-		break;
+	return cc->func(hdev, data, skb);
+}
 
-	case HCI_OP_LE_REMOVE_ADV_SET:
-		hci_cc_le_remove_adv_set(hdev, skb);
-		break;
+static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
+				 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_cmd_complete *ev = data;
+	int i;
 
-	case HCI_OP_LE_CLEAR_ADV_SETS:
-		hci_cc_le_clear_adv_sets(hdev, skb);
-		break;
+	*opcode = __le16_to_cpu(ev->opcode);
 
-	case HCI_OP_LE_READ_TRANSMIT_POWER:
-		hci_cc_le_read_transmit_power(hdev, skb);
-		break;
+	bt_dev_dbg(hdev, "opcode 0x%4.4x", *opcode);
 
-	default:
-		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
-		break;
+	for (i = 0; i < ARRAY_SIZE(hci_cc_table); i++) {
+		if (hci_cc_table[i].op == *opcode) {
+			*status = hci_cc_func(hdev, &hci_cc_table[i], skb);
+			break;
+		}
 	}
 
 	handle_cmd_cnt_and_timer(hdev, ev->ncmd);
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 15/15] Bluetooth: hci_event: Use of a function table to handle Command Status
  2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
                   ` (13 preceding siblings ...)
  2021-12-01  0:02 ` [PATCH 14/15] Bluetooth: hci_event: Use of a function table to handle Command Complete Luiz Augusto von Dentz
@ 2021-12-01  0:02 ` Luiz Augusto von Dentz
  14 siblings, 0 replies; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  0:02 UTC (permalink / raw)
  To: davem, kuba
  Cc: linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This change the use of switch statement to a function table which is
easier to extend.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 net/bluetooth/hci_event.c | 152 +++++++++++++++-----------------------
 1 file changed, 59 insertions(+), 93 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0b69d527ca4e..3f485d181eb6 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2195,7 +2195,7 @@ static u8 hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, void *data,
 
 static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (status) {
 		hci_conn_check_pending(hdev);
@@ -2210,7 +2210,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
 	struct hci_cp_create_conn *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
 	if (!cp)
@@ -2220,7 +2220,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
 
-	BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
+	bt_dev_dbg(hdev, "bdaddr %pMR hcon %p", &cp->bdaddr, conn);
 
 	if (status) {
 		if (conn && conn->state == BT_CONNECT) {
@@ -2249,7 +2249,7 @@ static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
 	struct hci_conn *acl, *sco;
 	__u16 handle;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (!status)
 		return;
@@ -2260,7 +2260,7 @@ static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
 
 	handle = __le16_to_cpu(cp->handle);
 
-	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
+	bt_dev_dbg(hdev, "handle 0x%4.4x", handle);
 
 	hci_dev_lock(hdev);
 
@@ -2283,7 +2283,7 @@ static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
 	struct hci_cp_auth_requested *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (!status)
 		return;
@@ -2310,7 +2310,7 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
 	struct hci_cp_set_conn_encrypt *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (!status)
 		return;
@@ -2446,7 +2446,7 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
 	struct hci_cp_remote_name_req *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	/* If successful wait for the name req complete event before
 	 * checking for the need to do authentication */
@@ -2489,7 +2489,7 @@ static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
 	struct hci_cp_read_remote_features *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (!status)
 		return;
@@ -2516,7 +2516,7 @@ static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
 	struct hci_cp_read_remote_ext_features *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (!status)
 		return;
@@ -2544,7 +2544,7 @@ static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
 	struct hci_conn *acl, *sco;
 	__u16 handle;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (!status)
 		return;
@@ -2555,7 +2555,7 @@ static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
 
 	handle = __le16_to_cpu(cp->handle);
 
-	BT_DBG("%s handle 0x%4.4x", hdev->name, handle);
+	bt_dev_dbg(hdev, "handle 0x%4.4x", handle);
 
 	hci_dev_lock(hdev);
 
@@ -2613,7 +2613,7 @@ static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
 	struct hci_cp_sniff_mode *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (!status)
 		return;
@@ -2640,7 +2640,7 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
 	struct hci_cp_exit_sniff_mode *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (!status)
 		return;
@@ -2669,6 +2669,8 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
 	struct hci_conn *conn;
 	bool mgmt_conn;
 
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
+
 	/* Wait for HCI_EV_DISCONN_COMPLETE if status 0x00 and not suspended
 	 * otherwise cleanup the connection immediately.
 	 */
@@ -2802,7 +2804,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
 {
 	struct hci_cp_le_create_conn *cp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	/* All connection failure handling is taken care of by the
 	 * hci_le_conn_failed function which is triggered by the HCI
@@ -2827,7 +2829,7 @@ static void hci_cs_le_ext_create_conn(struct hci_dev *hdev, u8 status)
 {
 	struct hci_cp_le_ext_create_conn *cp;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	/* All connection failure handling is taken care of by the
 	 * hci_le_conn_failed function which is triggered by the HCI
@@ -2853,7 +2855,7 @@ static void hci_cs_le_read_remote_features(struct hci_dev *hdev, u8 status)
 	struct hci_cp_le_read_remote_features *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (!status)
 		return;
@@ -2880,7 +2882,7 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
 	struct hci_cp_le_start_enc *cp;
 	struct hci_conn *conn;
 
-	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+	bt_dev_dbg(hdev, "status 0x%2.2x", status);
 
 	if (!status)
 		return;
@@ -3948,92 +3950,56 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
 		queue_work(hdev->workqueue, &hdev->cmd_work);
 }
 
+#define HCI_CS(_op, _func) \
+{ \
+	.op = _op, \
+	.func = _func, \
+}
+
+static const struct hci_cs {
+	u16  op;
+	void (*func)(struct hci_dev *hdev, __u8 status);
+} hci_cs_table[] = {
+	HCI_CS(HCI_OP_INQUIRY, hci_cs_inquiry),
+	HCI_CS(HCI_OP_CREATE_CONN, hci_cs_create_conn),
+	HCI_CS(HCI_OP_DISCONNECT, hci_cs_disconnect),
+	HCI_CS(HCI_OP_ADD_SCO, hci_cs_add_sco),
+	HCI_CS(HCI_OP_AUTH_REQUESTED, hci_cs_auth_requested),
+	HCI_CS(HCI_OP_SET_CONN_ENCRYPT, hci_cs_set_conn_encrypt),
+	HCI_CS(HCI_OP_REMOTE_NAME_REQ, hci_cs_remote_name_req),
+	HCI_CS(HCI_OP_READ_REMOTE_FEATURES, hci_cs_read_remote_features),
+	HCI_CS(HCI_OP_READ_REMOTE_EXT_FEATURES,
+	       hci_cs_read_remote_ext_features),
+	HCI_CS(HCI_OP_SETUP_SYNC_CONN, hci_cs_setup_sync_conn),
+	HCI_CS(HCI_OP_ENHANCED_SETUP_SYNC_CONN,
+	       hci_cs_enhanced_setup_sync_conn),
+	HCI_CS(HCI_OP_SNIFF_MODE, hci_cs_sniff_mode),
+	HCI_CS(HCI_OP_EXIT_SNIFF_MODE, hci_cs_exit_sniff_mode),
+	HCI_CS(HCI_OP_SWITCH_ROLE, hci_cs_switch_role),
+	HCI_CS(HCI_OP_LE_CREATE_CONN, hci_cs_le_create_conn),
+	HCI_CS(HCI_OP_LE_READ_REMOTE_FEATURES, hci_cs_le_read_remote_features),
+	HCI_CS(HCI_OP_LE_START_ENC, hci_cs_le_start_enc),
+	HCI_CS(HCI_OP_LE_EXT_CREATE_CONN, hci_cs_le_ext_create_conn)
+};
+
 static void hci_cmd_status_evt(struct hci_dev *hdev, void *data,
 			       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_cmd_status *ev = data;
+	int i;
 
 	*opcode = __le16_to_cpu(ev->opcode);
 	*status = ev->status;
 
-	switch (*opcode) {
-	case HCI_OP_INQUIRY:
-		hci_cs_inquiry(hdev, ev->status);
-		break;
-
-	case HCI_OP_CREATE_CONN:
-		hci_cs_create_conn(hdev, ev->status);
-		break;
-
-	case HCI_OP_DISCONNECT:
-		hci_cs_disconnect(hdev, ev->status);
-		break;
-
-	case HCI_OP_ADD_SCO:
-		hci_cs_add_sco(hdev, ev->status);
-		break;
-
-	case HCI_OP_AUTH_REQUESTED:
-		hci_cs_auth_requested(hdev, ev->status);
-		break;
-
-	case HCI_OP_SET_CONN_ENCRYPT:
-		hci_cs_set_conn_encrypt(hdev, ev->status);
-		break;
-
-	case HCI_OP_REMOTE_NAME_REQ:
-		hci_cs_remote_name_req(hdev, ev->status);
-		break;
-
-	case HCI_OP_READ_REMOTE_FEATURES:
-		hci_cs_read_remote_features(hdev, ev->status);
-		break;
-
-	case HCI_OP_READ_REMOTE_EXT_FEATURES:
-		hci_cs_read_remote_ext_features(hdev, ev->status);
-		break;
-
-	case HCI_OP_SETUP_SYNC_CONN:
-		hci_cs_setup_sync_conn(hdev, ev->status);
-		break;
-
-	case HCI_OP_ENHANCED_SETUP_SYNC_CONN:
-		hci_cs_enhanced_setup_sync_conn(hdev, ev->status);
-		break;
-
-	case HCI_OP_SNIFF_MODE:
-		hci_cs_sniff_mode(hdev, ev->status);
-		break;
-
-	case HCI_OP_EXIT_SNIFF_MODE:
-		hci_cs_exit_sniff_mode(hdev, ev->status);
-		break;
-
-	case HCI_OP_SWITCH_ROLE:
-		hci_cs_switch_role(hdev, ev->status);
-		break;
-
-	case HCI_OP_LE_CREATE_CONN:
-		hci_cs_le_create_conn(hdev, ev->status);
-		break;
-
-	case HCI_OP_LE_READ_REMOTE_FEATURES:
-		hci_cs_le_read_remote_features(hdev, ev->status);
-		break;
-
-	case HCI_OP_LE_START_ENC:
-		hci_cs_le_start_enc(hdev, ev->status);
-		break;
-
-	case HCI_OP_LE_EXT_CREATE_CONN:
-		hci_cs_le_ext_create_conn(hdev, ev->status);
-		break;
+	bt_dev_dbg(hdev, "opcode 0x%4.4x", *opcode);
 
-	default:
-		BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
-		break;
+	for (i = 0; i < ARRAY_SIZE(hci_cs_table); i++) {
+		if (hci_cs_table[i].op == *opcode) {
+			hci_cs_table[i].func(hdev, ev->status);
+			break;
+		}
 	}
 
 	handle_cmd_cnt_and_timer(hdev, ev->ncmd);
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH 01/15] skbuff: introduce skb_pull_data
  2021-12-01  0:02 ` [PATCH 01/15] skbuff: introduce skb_pull_data Luiz Augusto von Dentz
@ 2021-12-01  1:11   ` Jakub Kicinski
  2021-12-01  2:16     ` Luiz Augusto von Dentz
  2021-12-01  5:20   ` Dan Carpenter
  1 sibling, 1 reply; 34+ messages in thread
From: Jakub Kicinski @ 2021-12-01  1:11 UTC (permalink / raw)
  To: Luiz Augusto von Dentz
  Cc: davem, linux-bluetooth, netdev, dan.carpenter, Luiz Augusto von Dentz

On Tue, 30 Nov 2021 16:02:01 -0800 Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> Like skb_pull but returns the original data pointer before pulling the
> data after performing a check against sbk->len.
> 
> This allows to change code that does "struct foo *p = (void *)skb->data;"
> which is hard to audit and error prone, to:
> 
>         p = skb_pull_data(skb, sizeof(*p));
>         if (!p)
>                 return;
> 
> Which is both safer and cleaner.

It doesn't take a data pointer, so not really analogous to
skb_put_data() and friends which come to mind. But I have 
no better naming suggestions. You will need to respin, tho,
if you want us to apply these directly, the patches as posted 
don't apply to either netdev tree.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
  2021-12-01  0:02 ` [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events Luiz Augusto von Dentz
@ 2021-12-01  1:54     ` kernel test robot
  2021-12-01  3:22     ` kernel test robot
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 34+ messages in thread
From: kernel test robot @ 2021-12-01  1:54 UTC (permalink / raw)
  To: Luiz Augusto von Dentz, davem, kuba
  Cc: kbuild-all, linux-bluetooth, netdev, dan.carpenter,
	Luiz Augusto von Dentz

Hi Luiz,

I love your patch! Yet something to improve:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20211130]
[cannot apply to net-next/master net/master linus/master v5.16-rc3]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: riscv-randconfig-r042-20211128 (https://download.01.org/0day-ci/archive/20211201/202112010916.SwsMdzpu-lkp@intel.com/config)
compiler: riscv32-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
        git checkout bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=riscv SHELL=/bin/bash net/bluetooth/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> net/bluetooth/hci_event.c:7129:31: error: initialization of 'void (*)(struct hci_dev *, void *, struct sk_buff *)' from incompatible pointer type 'void (*)(struct hci_dev *, struct sk_buff *)' [-Werror=incompatible-pointer-types]
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |                               ^~~~~~~~~~~~~~~
   net/bluetooth/hci_event.c:6952:17: note: in definition of macro 'HCI_EV_VL'
    6952 |         .func = _func, \
         |                 ^~~~~
   net/bluetooth/hci_event.c:7129:9: note: in expansion of macro 'HCI_EV'
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |         ^~~~~~
   net/bluetooth/hci_event.c:7129:31: note: (near initialization for 'hci_ev_table[255].<anonymous>.func')
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |                               ^~~~~~~~~~~~~~~
   net/bluetooth/hci_event.c:6952:17: note: in definition of macro 'HCI_EV_VL'
    6952 |         .func = _func, \
         |                 ^~~~~
   net/bluetooth/hci_event.c:7129:9: note: in expansion of macro 'HCI_EV'
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |         ^~~~~~
   net/bluetooth/hci_event.c:7132:6: warning: no previous prototype for 'hci_event_func' [-Wmissing-prototypes]
    7132 | void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
         |      ^~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +7129 net/bluetooth/hci_event.c

  6970	
  6971	#define HCI_EV_REQ(_op, _func, _len) \
  6972		HCI_EV_REQ_VL(_op, _func, _len, _len)
  6973	
  6974	/* Entries in this table shall have their position according to the event opcode
  6975	 * they handle so the use of the macros above is recommend since it does attempt
  6976	 * to initialize at its proper index using Designated Initializers that way
  6977	 * events without a callback function don't have entered.
  6978	 */
  6979	static const struct hci_ev {
  6980		bool req;
  6981		union {
  6982			void (*func)(struct hci_dev *hdev, void *data,
  6983				     struct sk_buff *skb);
  6984			void (*func_req)(struct hci_dev *hdev, void *data,
  6985					 struct sk_buff *skb, u16 *opcode, u8 *status,
  6986					 hci_req_complete_t *req_complete,
  6987					 hci_req_complete_skb_t *req_complete_skb);
  6988		};
  6989		u16  min_len;
  6990		u16  max_len;
  6991	} hci_ev_table[U8_MAX + 1] = {
  6992		/* [0x01 = HCI_EV_INQUIRY_COMPLETE] */
  6993		HCI_EV_STATUS(HCI_EV_INQUIRY_COMPLETE, hci_inquiry_complete_evt),
  6994		/* [0x02 = HCI_EV_INQUIRY_RESULT] */
  6995		HCI_EV_VL(HCI_EV_INQUIRY_RESULT, hci_inquiry_result_evt,
  6996			  sizeof(struct hci_ev_inquiry_result), HCI_MAX_EVENT_SIZE),
  6997		/* [0x03 = HCI_EV_CONN_COMPLETE] */
  6998		HCI_EV(HCI_EV_CONN_COMPLETE, hci_conn_complete_evt,
  6999		       sizeof(struct hci_ev_conn_complete)),
  7000		/* [0x04 = HCI_EV_CONN_REQUEST] */
  7001		HCI_EV(HCI_EV_CONN_REQUEST, hci_conn_request_evt,
  7002		       sizeof(struct hci_ev_conn_request)),
  7003		/* [0x05 = HCI_EV_DISCONN_COMPLETE] */
  7004		HCI_EV(HCI_EV_DISCONN_COMPLETE, hci_disconn_complete_evt,
  7005		       sizeof(struct hci_ev_disconn_complete)),
  7006		/* [0x06 = HCI_EV_AUTH_COMPLETE] */
  7007		HCI_EV(HCI_EV_AUTH_COMPLETE, hci_auth_complete_evt,
  7008		       sizeof(struct hci_ev_auth_complete)),
  7009		/* [0x07 = HCI_EV_REMOTE_NAME] */
  7010		HCI_EV(HCI_EV_REMOTE_NAME, hci_remote_name_evt,
  7011		       sizeof(struct hci_ev_remote_name)),
  7012		/* [0x08 = HCI_EV_ENCRYPT_CHANGE] */
  7013		HCI_EV(HCI_EV_ENCRYPT_CHANGE, hci_encrypt_change_evt,
  7014		       sizeof(struct hci_ev_encrypt_change)),
  7015		/* [0x09 = HCI_EV_CHANGE_LINK_KEY_COMPLETE] */
  7016		HCI_EV(HCI_EV_CHANGE_LINK_KEY_COMPLETE,
  7017		       hci_change_link_key_complete_evt,
  7018		       sizeof(struct hci_ev_change_link_key_complete)),
  7019		/* [0x0b = HCI_EV_REMOTE_FEATURES] */
  7020		HCI_EV(HCI_EV_REMOTE_FEATURES, hci_remote_features_evt,
  7021		       sizeof(struct hci_ev_remote_features)),
  7022		/* [0x0e = HCI_EV_CMD_COMPLETE] */
  7023		HCI_EV_REQ_VL(HCI_EV_CMD_COMPLETE, hci_cmd_complete_evt,
  7024			      sizeof(struct hci_ev_cmd_complete), HCI_MAX_EVENT_SIZE),
  7025		/* [0x0f = HCI_EV_CMD_STATUS] */
  7026		HCI_EV_REQ(HCI_EV_CMD_STATUS, hci_cmd_status_evt,
  7027			   sizeof(struct hci_ev_cmd_status)),
  7028		/* [0x10 = HCI_EV_CMD_STATUS] */
  7029		HCI_EV(HCI_EV_HARDWARE_ERROR, hci_hardware_error_evt,
  7030		       sizeof(struct hci_ev_hardware_error)),
  7031		/* [0x12 = HCI_EV_ROLE_CHANGE] */
  7032		HCI_EV(HCI_EV_ROLE_CHANGE, hci_role_change_evt,
  7033		       sizeof(struct hci_ev_role_change)),
  7034		/* [0x13 = HCI_EV_NUM_COMP_PKTS] */
  7035		HCI_EV_VL(HCI_EV_NUM_COMP_PKTS, hci_num_comp_pkts_evt,
  7036			  sizeof(struct hci_ev_num_comp_pkts), HCI_MAX_EVENT_SIZE),
  7037		/* [0x14 = HCI_EV_MODE_CHANGE] */
  7038		HCI_EV(HCI_EV_MODE_CHANGE, hci_mode_change_evt,
  7039		       sizeof(struct hci_ev_mode_change)),
  7040		/* [0x16 = HCI_EV_PIN_CODE_REQ] */
  7041		HCI_EV(HCI_EV_PIN_CODE_REQ, hci_pin_code_request_evt,
  7042		       sizeof(struct hci_ev_pin_code_req)),
  7043		/* [0x17 = HCI_EV_LINK_KEY_REQ] */
  7044		HCI_EV(HCI_EV_LINK_KEY_REQ, hci_link_key_request_evt,
  7045		       sizeof(struct hci_ev_link_key_req)),
  7046		/* [0x18 = HCI_EV_LINK_KEY_NOTIFY] */
  7047		HCI_EV(HCI_EV_LINK_KEY_NOTIFY, hci_link_key_notify_evt,
  7048		       sizeof(struct hci_ev_link_key_notify)),
  7049		/* [0x1c = HCI_EV_CLOCK_OFFSET] */
  7050		HCI_EV(HCI_EV_CLOCK_OFFSET, hci_clock_offset_evt,
  7051		       sizeof(struct hci_ev_clock_offset)),
  7052		/* [0x1d = HCI_EV_PKT_TYPE_CHANGE] */
  7053		HCI_EV(HCI_EV_PKT_TYPE_CHANGE, hci_pkt_type_change_evt,
  7054		       sizeof(struct hci_ev_pkt_type_change)),
  7055		/* [0x20 = HCI_EV_PSCAN_REP_MODE] */
  7056		HCI_EV(HCI_EV_PSCAN_REP_MODE, hci_pscan_rep_mode_evt,
  7057		       sizeof(struct hci_ev_pscan_rep_mode)),
  7058		/* [0x22 = HCI_EV_INQUIRY_RESULT_WITH_RSSI] */
  7059		HCI_EV_VL(HCI_EV_INQUIRY_RESULT_WITH_RSSI,
  7060			  hci_inquiry_result_with_rssi_evt,
  7061			  sizeof(struct hci_ev_inquiry_result_rssi),
  7062			  HCI_MAX_EVENT_SIZE),
  7063		/* [0x23 = HCI_EV_REMOTE_EXT_FEATURES] */
  7064		HCI_EV(HCI_EV_REMOTE_EXT_FEATURES, hci_remote_ext_features_evt,
  7065		       sizeof(struct hci_ev_remote_ext_features)),
  7066		/* [0x2c = HCI_EV_SYNC_CONN_COMPLETE] */
  7067		HCI_EV(HCI_EV_SYNC_CONN_COMPLETE, hci_sync_conn_complete_evt,
  7068		       sizeof(struct hci_ev_sync_conn_complete)),
  7069		/* [0x2d = HCI_EV_EXTENDED_INQUIRY_RESULT] */
  7070		HCI_EV_VL(HCI_EV_EXTENDED_INQUIRY_RESULT,
  7071			  hci_extended_inquiry_result_evt,
  7072			  sizeof(struct hci_ev_ext_inquiry_result), HCI_MAX_EVENT_SIZE),
  7073		/* [0x30 = HCI_EV_KEY_REFRESH_COMPLETE] */
  7074		HCI_EV(HCI_EV_KEY_REFRESH_COMPLETE, hci_key_refresh_complete_evt,
  7075		       sizeof(struct hci_ev_key_refresh_complete)),
  7076		/* [0x31 = HCI_EV_IO_CAPA_REQUEST] */
  7077		HCI_EV(HCI_EV_IO_CAPA_REQUEST, hci_io_capa_request_evt,
  7078		       sizeof(struct hci_ev_io_capa_request)),
  7079		/* [0x32 = HCI_EV_IO_CAPA_REPLY] */
  7080		HCI_EV(HCI_EV_IO_CAPA_REPLY, hci_io_capa_reply_evt,
  7081		       sizeof(struct hci_ev_io_capa_reply)),
  7082		/* [0x33 = HCI_EV_USER_CONFIRM_REQUEST] */
  7083		HCI_EV(HCI_EV_USER_CONFIRM_REQUEST, hci_user_confirm_request_evt,
  7084		       sizeof(struct hci_ev_user_confirm_req)),
  7085		/* [0x34 = HCI_EV_USER_PASSKEY_REQUEST] */
  7086		HCI_EV(HCI_EV_USER_PASSKEY_REQUEST, hci_user_passkey_request_evt,
  7087		       sizeof(struct hci_ev_user_passkey_req)),
  7088		/* [0x35 = HCI_EV_REMOTE_OOB_DATA_REQUEST] */
  7089		HCI_EV(HCI_EV_REMOTE_OOB_DATA_REQUEST, hci_remote_oob_data_request_evt,
  7090		       sizeof(struct hci_ev_remote_oob_data_request)),
  7091		/* [0x36 = HCI_EV_SIMPLE_PAIR_COMPLETE] */
  7092		HCI_EV(HCI_EV_SIMPLE_PAIR_COMPLETE, hci_simple_pair_complete_evt,
  7093		       sizeof(struct hci_ev_simple_pair_complete)),
  7094		/* [0x3b = HCI_EV_USER_PASSKEY_NOTIFY] */
  7095		HCI_EV(HCI_EV_USER_PASSKEY_NOTIFY, hci_user_passkey_notify_evt,
  7096		       sizeof(struct hci_ev_user_passkey_notify)),
  7097		/* [0x3c = HCI_EV_KEYPRESS_NOTIFY] */
  7098		HCI_EV(HCI_EV_KEYPRESS_NOTIFY, hci_keypress_notify_evt,
  7099		       sizeof(struct hci_ev_keypress_notify)),
  7100		/* [0x3d = HCI_EV_REMOTE_HOST_FEATURES] */
  7101		HCI_EV(HCI_EV_REMOTE_HOST_FEATURES, hci_remote_host_features_evt,
  7102		       sizeof(struct hci_ev_remote_host_features)),
  7103		/* [0x3e = HCI_EV_LE_META] */
  7104		HCI_EV_VL(HCI_EV_LE_META, hci_le_meta_evt,
  7105			  sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
  7106	#if IS_ENABLED(CONFIG_BT_HS)
  7107		/* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */
  7108		HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt,
  7109		       sizeof(struct hci_ev_phy_link_complete)),
  7110		/* [0x41 = HCI_EV_CHANNEL_SELECTED] */
  7111		HCI_EV(HCI_EV_CHANNEL_SELECTED, hci_chan_selected_evt,
  7112		       sizeof(struct hci_ev_channel_selected)),
  7113		/* [0x42 = HCI_EV_DISCONN_PHY_LINK_COMPLETE] */
  7114		HCI_EV(HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
  7115		       hci_disconn_loglink_complete_evt,
  7116		       sizeof(struct hci_ev_disconn_logical_link_complete)),
  7117		/* [0x45 = HCI_EV_LOGICAL_LINK_COMPLETE] */
  7118		HCI_EV(HCI_EV_LOGICAL_LINK_COMPLETE, hci_loglink_complete_evt,
  7119		       sizeof(struct hci_ev_logical_link_complete)),
  7120		/* [0x46 = HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE] */
  7121		HCI_EV(HCI_EV_DISCONN_PHY_LINK_COMPLETE,
  7122		       hci_disconn_phylink_complete_evt,
  7123		       sizeof(struct hci_ev_disconn_phy_link_complete)),
  7124	#endif
  7125		/* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */
  7126		HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt,
  7127		       sizeof(struct hci_ev_num_comp_blocks)),
  7128		/* [0xff = HCI_EV_VENDOR] */
> 7129		HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
  7130	};
  7131	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
@ 2021-12-01  1:54     ` kernel test robot
  0 siblings, 0 replies; 34+ messages in thread
From: kernel test robot @ 2021-12-01  1:54 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 11994 bytes --]

Hi Luiz,

I love your patch! Yet something to improve:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20211130]
[cannot apply to net-next/master net/master linus/master v5.16-rc3]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: riscv-randconfig-r042-20211128 (https://download.01.org/0day-ci/archive/20211201/202112010916.SwsMdzpu-lkp(a)intel.com/config)
compiler: riscv32-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
        git checkout bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=riscv SHELL=/bin/bash net/bluetooth/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> net/bluetooth/hci_event.c:7129:31: error: initialization of 'void (*)(struct hci_dev *, void *, struct sk_buff *)' from incompatible pointer type 'void (*)(struct hci_dev *, struct sk_buff *)' [-Werror=incompatible-pointer-types]
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |                               ^~~~~~~~~~~~~~~
   net/bluetooth/hci_event.c:6952:17: note: in definition of macro 'HCI_EV_VL'
    6952 |         .func = _func, \
         |                 ^~~~~
   net/bluetooth/hci_event.c:7129:9: note: in expansion of macro 'HCI_EV'
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |         ^~~~~~
   net/bluetooth/hci_event.c:7129:31: note: (near initialization for 'hci_ev_table[255].<anonymous>.func')
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |                               ^~~~~~~~~~~~~~~
   net/bluetooth/hci_event.c:6952:17: note: in definition of macro 'HCI_EV_VL'
    6952 |         .func = _func, \
         |                 ^~~~~
   net/bluetooth/hci_event.c:7129:9: note: in expansion of macro 'HCI_EV'
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |         ^~~~~~
   net/bluetooth/hci_event.c:7132:6: warning: no previous prototype for 'hci_event_func' [-Wmissing-prototypes]
    7132 | void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
         |      ^~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +7129 net/bluetooth/hci_event.c

  6970	
  6971	#define HCI_EV_REQ(_op, _func, _len) \
  6972		HCI_EV_REQ_VL(_op, _func, _len, _len)
  6973	
  6974	/* Entries in this table shall have their position according to the event opcode
  6975	 * they handle so the use of the macros above is recommend since it does attempt
  6976	 * to initialize at its proper index using Designated Initializers that way
  6977	 * events without a callback function don't have entered.
  6978	 */
  6979	static const struct hci_ev {
  6980		bool req;
  6981		union {
  6982			void (*func)(struct hci_dev *hdev, void *data,
  6983				     struct sk_buff *skb);
  6984			void (*func_req)(struct hci_dev *hdev, void *data,
  6985					 struct sk_buff *skb, u16 *opcode, u8 *status,
  6986					 hci_req_complete_t *req_complete,
  6987					 hci_req_complete_skb_t *req_complete_skb);
  6988		};
  6989		u16  min_len;
  6990		u16  max_len;
  6991	} hci_ev_table[U8_MAX + 1] = {
  6992		/* [0x01 = HCI_EV_INQUIRY_COMPLETE] */
  6993		HCI_EV_STATUS(HCI_EV_INQUIRY_COMPLETE, hci_inquiry_complete_evt),
  6994		/* [0x02 = HCI_EV_INQUIRY_RESULT] */
  6995		HCI_EV_VL(HCI_EV_INQUIRY_RESULT, hci_inquiry_result_evt,
  6996			  sizeof(struct hci_ev_inquiry_result), HCI_MAX_EVENT_SIZE),
  6997		/* [0x03 = HCI_EV_CONN_COMPLETE] */
  6998		HCI_EV(HCI_EV_CONN_COMPLETE, hci_conn_complete_evt,
  6999		       sizeof(struct hci_ev_conn_complete)),
  7000		/* [0x04 = HCI_EV_CONN_REQUEST] */
  7001		HCI_EV(HCI_EV_CONN_REQUEST, hci_conn_request_evt,
  7002		       sizeof(struct hci_ev_conn_request)),
  7003		/* [0x05 = HCI_EV_DISCONN_COMPLETE] */
  7004		HCI_EV(HCI_EV_DISCONN_COMPLETE, hci_disconn_complete_evt,
  7005		       sizeof(struct hci_ev_disconn_complete)),
  7006		/* [0x06 = HCI_EV_AUTH_COMPLETE] */
  7007		HCI_EV(HCI_EV_AUTH_COMPLETE, hci_auth_complete_evt,
  7008		       sizeof(struct hci_ev_auth_complete)),
  7009		/* [0x07 = HCI_EV_REMOTE_NAME] */
  7010		HCI_EV(HCI_EV_REMOTE_NAME, hci_remote_name_evt,
  7011		       sizeof(struct hci_ev_remote_name)),
  7012		/* [0x08 = HCI_EV_ENCRYPT_CHANGE] */
  7013		HCI_EV(HCI_EV_ENCRYPT_CHANGE, hci_encrypt_change_evt,
  7014		       sizeof(struct hci_ev_encrypt_change)),
  7015		/* [0x09 = HCI_EV_CHANGE_LINK_KEY_COMPLETE] */
  7016		HCI_EV(HCI_EV_CHANGE_LINK_KEY_COMPLETE,
  7017		       hci_change_link_key_complete_evt,
  7018		       sizeof(struct hci_ev_change_link_key_complete)),
  7019		/* [0x0b = HCI_EV_REMOTE_FEATURES] */
  7020		HCI_EV(HCI_EV_REMOTE_FEATURES, hci_remote_features_evt,
  7021		       sizeof(struct hci_ev_remote_features)),
  7022		/* [0x0e = HCI_EV_CMD_COMPLETE] */
  7023		HCI_EV_REQ_VL(HCI_EV_CMD_COMPLETE, hci_cmd_complete_evt,
  7024			      sizeof(struct hci_ev_cmd_complete), HCI_MAX_EVENT_SIZE),
  7025		/* [0x0f = HCI_EV_CMD_STATUS] */
  7026		HCI_EV_REQ(HCI_EV_CMD_STATUS, hci_cmd_status_evt,
  7027			   sizeof(struct hci_ev_cmd_status)),
  7028		/* [0x10 = HCI_EV_CMD_STATUS] */
  7029		HCI_EV(HCI_EV_HARDWARE_ERROR, hci_hardware_error_evt,
  7030		       sizeof(struct hci_ev_hardware_error)),
  7031		/* [0x12 = HCI_EV_ROLE_CHANGE] */
  7032		HCI_EV(HCI_EV_ROLE_CHANGE, hci_role_change_evt,
  7033		       sizeof(struct hci_ev_role_change)),
  7034		/* [0x13 = HCI_EV_NUM_COMP_PKTS] */
  7035		HCI_EV_VL(HCI_EV_NUM_COMP_PKTS, hci_num_comp_pkts_evt,
  7036			  sizeof(struct hci_ev_num_comp_pkts), HCI_MAX_EVENT_SIZE),
  7037		/* [0x14 = HCI_EV_MODE_CHANGE] */
  7038		HCI_EV(HCI_EV_MODE_CHANGE, hci_mode_change_evt,
  7039		       sizeof(struct hci_ev_mode_change)),
  7040		/* [0x16 = HCI_EV_PIN_CODE_REQ] */
  7041		HCI_EV(HCI_EV_PIN_CODE_REQ, hci_pin_code_request_evt,
  7042		       sizeof(struct hci_ev_pin_code_req)),
  7043		/* [0x17 = HCI_EV_LINK_KEY_REQ] */
  7044		HCI_EV(HCI_EV_LINK_KEY_REQ, hci_link_key_request_evt,
  7045		       sizeof(struct hci_ev_link_key_req)),
  7046		/* [0x18 = HCI_EV_LINK_KEY_NOTIFY] */
  7047		HCI_EV(HCI_EV_LINK_KEY_NOTIFY, hci_link_key_notify_evt,
  7048		       sizeof(struct hci_ev_link_key_notify)),
  7049		/* [0x1c = HCI_EV_CLOCK_OFFSET] */
  7050		HCI_EV(HCI_EV_CLOCK_OFFSET, hci_clock_offset_evt,
  7051		       sizeof(struct hci_ev_clock_offset)),
  7052		/* [0x1d = HCI_EV_PKT_TYPE_CHANGE] */
  7053		HCI_EV(HCI_EV_PKT_TYPE_CHANGE, hci_pkt_type_change_evt,
  7054		       sizeof(struct hci_ev_pkt_type_change)),
  7055		/* [0x20 = HCI_EV_PSCAN_REP_MODE] */
  7056		HCI_EV(HCI_EV_PSCAN_REP_MODE, hci_pscan_rep_mode_evt,
  7057		       sizeof(struct hci_ev_pscan_rep_mode)),
  7058		/* [0x22 = HCI_EV_INQUIRY_RESULT_WITH_RSSI] */
  7059		HCI_EV_VL(HCI_EV_INQUIRY_RESULT_WITH_RSSI,
  7060			  hci_inquiry_result_with_rssi_evt,
  7061			  sizeof(struct hci_ev_inquiry_result_rssi),
  7062			  HCI_MAX_EVENT_SIZE),
  7063		/* [0x23 = HCI_EV_REMOTE_EXT_FEATURES] */
  7064		HCI_EV(HCI_EV_REMOTE_EXT_FEATURES, hci_remote_ext_features_evt,
  7065		       sizeof(struct hci_ev_remote_ext_features)),
  7066		/* [0x2c = HCI_EV_SYNC_CONN_COMPLETE] */
  7067		HCI_EV(HCI_EV_SYNC_CONN_COMPLETE, hci_sync_conn_complete_evt,
  7068		       sizeof(struct hci_ev_sync_conn_complete)),
  7069		/* [0x2d = HCI_EV_EXTENDED_INQUIRY_RESULT] */
  7070		HCI_EV_VL(HCI_EV_EXTENDED_INQUIRY_RESULT,
  7071			  hci_extended_inquiry_result_evt,
  7072			  sizeof(struct hci_ev_ext_inquiry_result), HCI_MAX_EVENT_SIZE),
  7073		/* [0x30 = HCI_EV_KEY_REFRESH_COMPLETE] */
  7074		HCI_EV(HCI_EV_KEY_REFRESH_COMPLETE, hci_key_refresh_complete_evt,
  7075		       sizeof(struct hci_ev_key_refresh_complete)),
  7076		/* [0x31 = HCI_EV_IO_CAPA_REQUEST] */
  7077		HCI_EV(HCI_EV_IO_CAPA_REQUEST, hci_io_capa_request_evt,
  7078		       sizeof(struct hci_ev_io_capa_request)),
  7079		/* [0x32 = HCI_EV_IO_CAPA_REPLY] */
  7080		HCI_EV(HCI_EV_IO_CAPA_REPLY, hci_io_capa_reply_evt,
  7081		       sizeof(struct hci_ev_io_capa_reply)),
  7082		/* [0x33 = HCI_EV_USER_CONFIRM_REQUEST] */
  7083		HCI_EV(HCI_EV_USER_CONFIRM_REQUEST, hci_user_confirm_request_evt,
  7084		       sizeof(struct hci_ev_user_confirm_req)),
  7085		/* [0x34 = HCI_EV_USER_PASSKEY_REQUEST] */
  7086		HCI_EV(HCI_EV_USER_PASSKEY_REQUEST, hci_user_passkey_request_evt,
  7087		       sizeof(struct hci_ev_user_passkey_req)),
  7088		/* [0x35 = HCI_EV_REMOTE_OOB_DATA_REQUEST] */
  7089		HCI_EV(HCI_EV_REMOTE_OOB_DATA_REQUEST, hci_remote_oob_data_request_evt,
  7090		       sizeof(struct hci_ev_remote_oob_data_request)),
  7091		/* [0x36 = HCI_EV_SIMPLE_PAIR_COMPLETE] */
  7092		HCI_EV(HCI_EV_SIMPLE_PAIR_COMPLETE, hci_simple_pair_complete_evt,
  7093		       sizeof(struct hci_ev_simple_pair_complete)),
  7094		/* [0x3b = HCI_EV_USER_PASSKEY_NOTIFY] */
  7095		HCI_EV(HCI_EV_USER_PASSKEY_NOTIFY, hci_user_passkey_notify_evt,
  7096		       sizeof(struct hci_ev_user_passkey_notify)),
  7097		/* [0x3c = HCI_EV_KEYPRESS_NOTIFY] */
  7098		HCI_EV(HCI_EV_KEYPRESS_NOTIFY, hci_keypress_notify_evt,
  7099		       sizeof(struct hci_ev_keypress_notify)),
  7100		/* [0x3d = HCI_EV_REMOTE_HOST_FEATURES] */
  7101		HCI_EV(HCI_EV_REMOTE_HOST_FEATURES, hci_remote_host_features_evt,
  7102		       sizeof(struct hci_ev_remote_host_features)),
  7103		/* [0x3e = HCI_EV_LE_META] */
  7104		HCI_EV_VL(HCI_EV_LE_META, hci_le_meta_evt,
  7105			  sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
  7106	#if IS_ENABLED(CONFIG_BT_HS)
  7107		/* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */
  7108		HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt,
  7109		       sizeof(struct hci_ev_phy_link_complete)),
  7110		/* [0x41 = HCI_EV_CHANNEL_SELECTED] */
  7111		HCI_EV(HCI_EV_CHANNEL_SELECTED, hci_chan_selected_evt,
  7112		       sizeof(struct hci_ev_channel_selected)),
  7113		/* [0x42 = HCI_EV_DISCONN_PHY_LINK_COMPLETE] */
  7114		HCI_EV(HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
  7115		       hci_disconn_loglink_complete_evt,
  7116		       sizeof(struct hci_ev_disconn_logical_link_complete)),
  7117		/* [0x45 = HCI_EV_LOGICAL_LINK_COMPLETE] */
  7118		HCI_EV(HCI_EV_LOGICAL_LINK_COMPLETE, hci_loglink_complete_evt,
  7119		       sizeof(struct hci_ev_logical_link_complete)),
  7120		/* [0x46 = HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE] */
  7121		HCI_EV(HCI_EV_DISCONN_PHY_LINK_COMPLETE,
  7122		       hci_disconn_phylink_complete_evt,
  7123		       sizeof(struct hci_ev_disconn_phy_link_complete)),
  7124	#endif
  7125		/* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */
  7126		HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt,
  7127		       sizeof(struct hci_ev_num_comp_blocks)),
  7128		/* [0xff = HCI_EV_VENDOR] */
> 7129		HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
  7130	};
  7131	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 01/15] skbuff: introduce skb_pull_data
  2021-12-01  1:11   ` Jakub Kicinski
@ 2021-12-01  2:16     ` Luiz Augusto von Dentz
  2021-12-01  2:27       ` Jakub Kicinski
  0 siblings, 1 reply; 34+ messages in thread
From: Luiz Augusto von Dentz @ 2021-12-01  2:16 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: David Miller, linux-bluetooth, open list:NETWORKING [GENERAL],
	Dan Carpenter, Luiz Augusto von Dentz

Hi Jakub,

On Tue, Nov 30, 2021 at 5:11 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Tue, 30 Nov 2021 16:02:01 -0800 Luiz Augusto von Dentz wrote:
> > From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> >
> > Like skb_pull but returns the original data pointer before pulling the
> > data after performing a check against sbk->len.
> >
> > This allows to change code that does "struct foo *p = (void *)skb->data;"
> > which is hard to audit and error prone, to:
> >
> >         p = skb_pull_data(skb, sizeof(*p));
> >         if (!p)
> >                 return;
> >
> > Which is both safer and cleaner.
>
> It doesn't take a data pointer, so not really analogous to
> skb_put_data() and friends which come to mind. But I have
> no better naming suggestions. You will need to respin, tho,
> if you want us to apply these directly, the patches as posted
> don't apply to either netdev tree.

I cross posted it to net-dev just in case you guys had some strong
opinions on introducing such a function, it was in fact suggested by
Dan but I also didn't find a better name so I went with it, if you
guys prefer we can merge it in bluetooth-next first as usual.

-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 01/15] skbuff: introduce skb_pull_data
  2021-12-01  2:16     ` Luiz Augusto von Dentz
@ 2021-12-01  2:27       ` Jakub Kicinski
  2021-12-01  7:22         ` Marcel Holtmann
  0 siblings, 1 reply; 34+ messages in thread
From: Jakub Kicinski @ 2021-12-01  2:27 UTC (permalink / raw)
  To: Luiz Augusto von Dentz
  Cc: David Miller, linux-bluetooth, open list:NETWORKING [GENERAL],
	Dan Carpenter, Luiz Augusto von Dentz

On Tue, 30 Nov 2021 18:16:02 -0800 Luiz Augusto von Dentz wrote:
> > It doesn't take a data pointer, so not really analogous to
> > skb_put_data() and friends which come to mind. But I have
> > no better naming suggestions. You will need to respin, tho,
> > if you want us to apply these directly, the patches as posted
> > don't apply to either netdev tree.  
> 
> I cross posted it to net-dev just in case you guys had some strong
> opinions on introducing such a function,

Someone else still may, I don't :)

> it was in fact suggested by Dan but I also didn't find a better name
> so I went with it, if you guys prefer we can merge it in
> bluetooth-next first as usual.

Going via bluetooth-next sounds good!

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
  2021-12-01  0:02 ` [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events Luiz Augusto von Dentz
@ 2021-12-01  3:22     ` kernel test robot
  2021-12-01  3:22     ` kernel test robot
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 34+ messages in thread
From: kernel test robot @ 2021-12-01  3:22 UTC (permalink / raw)
  To: Luiz Augusto von Dentz, davem, kuba
  Cc: llvm, kbuild-all, linux-bluetooth, netdev, dan.carpenter,
	Luiz Augusto von Dentz

Hi Luiz,

I love your patch! Yet something to improve:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20211130]
[cannot apply to net-next/master net/master linus/master bluetooth/master v5.16-rc3]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: hexagon-randconfig-r026-20211130 (https://download.01.org/0day-ci/archive/20211201/202112011149.SZaZiW8X-lkp@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 25eb7fa01d7ebbe67648ea03841cda55b4239ab2)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
        git checkout bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash net/bluetooth/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

>> net/bluetooth/hci_event.c:7129:24: error: incompatible function pointer types initializing 'void (*)(struct hci_dev *, void *, struct sk_buff *)' with an expression of type 'void (struct hci_dev *, struct sk_buff *)' [-Werror,-Wincompatible-function-pointer-types]
           HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
                                 ^~~~~~~~~~~~~~~
   net/bluetooth/hci_event.c:6958:17: note: expanded from macro 'HCI_EV'
           HCI_EV_VL(_op, _func, _len, _len)
                          ^~~~~
   net/bluetooth/hci_event.c:6952:10: note: expanded from macro 'HCI_EV_VL'
           .func = _func, \
                   ^~~~~
>> net/bluetooth/hci_event.c:7132:6: warning: no previous prototype for function 'hci_event_func' [-Wmissing-prototypes]
   void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
        ^
   net/bluetooth/hci_event.c:7132:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
   ^
   static 
   1 warning and 1 error generated.


vim +7129 net/bluetooth/hci_event.c

  6970	
  6971	#define HCI_EV_REQ(_op, _func, _len) \
  6972		HCI_EV_REQ_VL(_op, _func, _len, _len)
  6973	
  6974	/* Entries in this table shall have their position according to the event opcode
  6975	 * they handle so the use of the macros above is recommend since it does attempt
  6976	 * to initialize at its proper index using Designated Initializers that way
  6977	 * events without a callback function don't have entered.
  6978	 */
  6979	static const struct hci_ev {
  6980		bool req;
  6981		union {
  6982			void (*func)(struct hci_dev *hdev, void *data,
  6983				     struct sk_buff *skb);
  6984			void (*func_req)(struct hci_dev *hdev, void *data,
  6985					 struct sk_buff *skb, u16 *opcode, u8 *status,
  6986					 hci_req_complete_t *req_complete,
  6987					 hci_req_complete_skb_t *req_complete_skb);
  6988		};
  6989		u16  min_len;
  6990		u16  max_len;
  6991	} hci_ev_table[U8_MAX + 1] = {
  6992		/* [0x01 = HCI_EV_INQUIRY_COMPLETE] */
  6993		HCI_EV_STATUS(HCI_EV_INQUIRY_COMPLETE, hci_inquiry_complete_evt),
  6994		/* [0x02 = HCI_EV_INQUIRY_RESULT] */
  6995		HCI_EV_VL(HCI_EV_INQUIRY_RESULT, hci_inquiry_result_evt,
  6996			  sizeof(struct hci_ev_inquiry_result), HCI_MAX_EVENT_SIZE),
  6997		/* [0x03 = HCI_EV_CONN_COMPLETE] */
  6998		HCI_EV(HCI_EV_CONN_COMPLETE, hci_conn_complete_evt,
  6999		       sizeof(struct hci_ev_conn_complete)),
  7000		/* [0x04 = HCI_EV_CONN_REQUEST] */
  7001		HCI_EV(HCI_EV_CONN_REQUEST, hci_conn_request_evt,
  7002		       sizeof(struct hci_ev_conn_request)),
  7003		/* [0x05 = HCI_EV_DISCONN_COMPLETE] */
  7004		HCI_EV(HCI_EV_DISCONN_COMPLETE, hci_disconn_complete_evt,
  7005		       sizeof(struct hci_ev_disconn_complete)),
  7006		/* [0x06 = HCI_EV_AUTH_COMPLETE] */
  7007		HCI_EV(HCI_EV_AUTH_COMPLETE, hci_auth_complete_evt,
  7008		       sizeof(struct hci_ev_auth_complete)),
  7009		/* [0x07 = HCI_EV_REMOTE_NAME] */
  7010		HCI_EV(HCI_EV_REMOTE_NAME, hci_remote_name_evt,
  7011		       sizeof(struct hci_ev_remote_name)),
  7012		/* [0x08 = HCI_EV_ENCRYPT_CHANGE] */
  7013		HCI_EV(HCI_EV_ENCRYPT_CHANGE, hci_encrypt_change_evt,
  7014		       sizeof(struct hci_ev_encrypt_change)),
  7015		/* [0x09 = HCI_EV_CHANGE_LINK_KEY_COMPLETE] */
  7016		HCI_EV(HCI_EV_CHANGE_LINK_KEY_COMPLETE,
  7017		       hci_change_link_key_complete_evt,
  7018		       sizeof(struct hci_ev_change_link_key_complete)),
  7019		/* [0x0b = HCI_EV_REMOTE_FEATURES] */
  7020		HCI_EV(HCI_EV_REMOTE_FEATURES, hci_remote_features_evt,
  7021		       sizeof(struct hci_ev_remote_features)),
  7022		/* [0x0e = HCI_EV_CMD_COMPLETE] */
  7023		HCI_EV_REQ_VL(HCI_EV_CMD_COMPLETE, hci_cmd_complete_evt,
  7024			      sizeof(struct hci_ev_cmd_complete), HCI_MAX_EVENT_SIZE),
  7025		/* [0x0f = HCI_EV_CMD_STATUS] */
  7026		HCI_EV_REQ(HCI_EV_CMD_STATUS, hci_cmd_status_evt,
  7027			   sizeof(struct hci_ev_cmd_status)),
  7028		/* [0x10 = HCI_EV_CMD_STATUS] */
  7029		HCI_EV(HCI_EV_HARDWARE_ERROR, hci_hardware_error_evt,
  7030		       sizeof(struct hci_ev_hardware_error)),
  7031		/* [0x12 = HCI_EV_ROLE_CHANGE] */
  7032		HCI_EV(HCI_EV_ROLE_CHANGE, hci_role_change_evt,
  7033		       sizeof(struct hci_ev_role_change)),
  7034		/* [0x13 = HCI_EV_NUM_COMP_PKTS] */
  7035		HCI_EV_VL(HCI_EV_NUM_COMP_PKTS, hci_num_comp_pkts_evt,
  7036			  sizeof(struct hci_ev_num_comp_pkts), HCI_MAX_EVENT_SIZE),
  7037		/* [0x14 = HCI_EV_MODE_CHANGE] */
  7038		HCI_EV(HCI_EV_MODE_CHANGE, hci_mode_change_evt,
  7039		       sizeof(struct hci_ev_mode_change)),
  7040		/* [0x16 = HCI_EV_PIN_CODE_REQ] */
  7041		HCI_EV(HCI_EV_PIN_CODE_REQ, hci_pin_code_request_evt,
  7042		       sizeof(struct hci_ev_pin_code_req)),
  7043		/* [0x17 = HCI_EV_LINK_KEY_REQ] */
  7044		HCI_EV(HCI_EV_LINK_KEY_REQ, hci_link_key_request_evt,
  7045		       sizeof(struct hci_ev_link_key_req)),
  7046		/* [0x18 = HCI_EV_LINK_KEY_NOTIFY] */
  7047		HCI_EV(HCI_EV_LINK_KEY_NOTIFY, hci_link_key_notify_evt,
  7048		       sizeof(struct hci_ev_link_key_notify)),
  7049		/* [0x1c = HCI_EV_CLOCK_OFFSET] */
  7050		HCI_EV(HCI_EV_CLOCK_OFFSET, hci_clock_offset_evt,
  7051		       sizeof(struct hci_ev_clock_offset)),
  7052		/* [0x1d = HCI_EV_PKT_TYPE_CHANGE] */
  7053		HCI_EV(HCI_EV_PKT_TYPE_CHANGE, hci_pkt_type_change_evt,
  7054		       sizeof(struct hci_ev_pkt_type_change)),
  7055		/* [0x20 = HCI_EV_PSCAN_REP_MODE] */
  7056		HCI_EV(HCI_EV_PSCAN_REP_MODE, hci_pscan_rep_mode_evt,
  7057		       sizeof(struct hci_ev_pscan_rep_mode)),
  7058		/* [0x22 = HCI_EV_INQUIRY_RESULT_WITH_RSSI] */
  7059		HCI_EV_VL(HCI_EV_INQUIRY_RESULT_WITH_RSSI,
  7060			  hci_inquiry_result_with_rssi_evt,
  7061			  sizeof(struct hci_ev_inquiry_result_rssi),
  7062			  HCI_MAX_EVENT_SIZE),
  7063		/* [0x23 = HCI_EV_REMOTE_EXT_FEATURES] */
  7064		HCI_EV(HCI_EV_REMOTE_EXT_FEATURES, hci_remote_ext_features_evt,
  7065		       sizeof(struct hci_ev_remote_ext_features)),
  7066		/* [0x2c = HCI_EV_SYNC_CONN_COMPLETE] */
  7067		HCI_EV(HCI_EV_SYNC_CONN_COMPLETE, hci_sync_conn_complete_evt,
  7068		       sizeof(struct hci_ev_sync_conn_complete)),
  7069		/* [0x2d = HCI_EV_EXTENDED_INQUIRY_RESULT] */
  7070		HCI_EV_VL(HCI_EV_EXTENDED_INQUIRY_RESULT,
  7071			  hci_extended_inquiry_result_evt,
  7072			  sizeof(struct hci_ev_ext_inquiry_result), HCI_MAX_EVENT_SIZE),
  7073		/* [0x30 = HCI_EV_KEY_REFRESH_COMPLETE] */
  7074		HCI_EV(HCI_EV_KEY_REFRESH_COMPLETE, hci_key_refresh_complete_evt,
  7075		       sizeof(struct hci_ev_key_refresh_complete)),
  7076		/* [0x31 = HCI_EV_IO_CAPA_REQUEST] */
  7077		HCI_EV(HCI_EV_IO_CAPA_REQUEST, hci_io_capa_request_evt,
  7078		       sizeof(struct hci_ev_io_capa_request)),
  7079		/* [0x32 = HCI_EV_IO_CAPA_REPLY] */
  7080		HCI_EV(HCI_EV_IO_CAPA_REPLY, hci_io_capa_reply_evt,
  7081		       sizeof(struct hci_ev_io_capa_reply)),
  7082		/* [0x33 = HCI_EV_USER_CONFIRM_REQUEST] */
  7083		HCI_EV(HCI_EV_USER_CONFIRM_REQUEST, hci_user_confirm_request_evt,
  7084		       sizeof(struct hci_ev_user_confirm_req)),
  7085		/* [0x34 = HCI_EV_USER_PASSKEY_REQUEST] */
  7086		HCI_EV(HCI_EV_USER_PASSKEY_REQUEST, hci_user_passkey_request_evt,
  7087		       sizeof(struct hci_ev_user_passkey_req)),
  7088		/* [0x35 = HCI_EV_REMOTE_OOB_DATA_REQUEST] */
  7089		HCI_EV(HCI_EV_REMOTE_OOB_DATA_REQUEST, hci_remote_oob_data_request_evt,
  7090		       sizeof(struct hci_ev_remote_oob_data_request)),
  7091		/* [0x36 = HCI_EV_SIMPLE_PAIR_COMPLETE] */
  7092		HCI_EV(HCI_EV_SIMPLE_PAIR_COMPLETE, hci_simple_pair_complete_evt,
  7093		       sizeof(struct hci_ev_simple_pair_complete)),
  7094		/* [0x3b = HCI_EV_USER_PASSKEY_NOTIFY] */
  7095		HCI_EV(HCI_EV_USER_PASSKEY_NOTIFY, hci_user_passkey_notify_evt,
  7096		       sizeof(struct hci_ev_user_passkey_notify)),
  7097		/* [0x3c = HCI_EV_KEYPRESS_NOTIFY] */
  7098		HCI_EV(HCI_EV_KEYPRESS_NOTIFY, hci_keypress_notify_evt,
  7099		       sizeof(struct hci_ev_keypress_notify)),
  7100		/* [0x3d = HCI_EV_REMOTE_HOST_FEATURES] */
  7101		HCI_EV(HCI_EV_REMOTE_HOST_FEATURES, hci_remote_host_features_evt,
  7102		       sizeof(struct hci_ev_remote_host_features)),
  7103		/* [0x3e = HCI_EV_LE_META] */
  7104		HCI_EV_VL(HCI_EV_LE_META, hci_le_meta_evt,
  7105			  sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
  7106	#if IS_ENABLED(CONFIG_BT_HS)
  7107		/* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */
  7108		HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt,
  7109		       sizeof(struct hci_ev_phy_link_complete)),
  7110		/* [0x41 = HCI_EV_CHANNEL_SELECTED] */
  7111		HCI_EV(HCI_EV_CHANNEL_SELECTED, hci_chan_selected_evt,
  7112		       sizeof(struct hci_ev_channel_selected)),
  7113		/* [0x42 = HCI_EV_DISCONN_PHY_LINK_COMPLETE] */
  7114		HCI_EV(HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
  7115		       hci_disconn_loglink_complete_evt,
  7116		       sizeof(struct hci_ev_disconn_logical_link_complete)),
  7117		/* [0x45 = HCI_EV_LOGICAL_LINK_COMPLETE] */
  7118		HCI_EV(HCI_EV_LOGICAL_LINK_COMPLETE, hci_loglink_complete_evt,
  7119		       sizeof(struct hci_ev_logical_link_complete)),
  7120		/* [0x46 = HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE] */
  7121		HCI_EV(HCI_EV_DISCONN_PHY_LINK_COMPLETE,
  7122		       hci_disconn_phylink_complete_evt,
  7123		       sizeof(struct hci_ev_disconn_phy_link_complete)),
  7124	#endif
  7125		/* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */
  7126		HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt,
  7127		       sizeof(struct hci_ev_num_comp_blocks)),
  7128		/* [0xff = HCI_EV_VENDOR] */
> 7129		HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
  7130	};
  7131	
> 7132	void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
  7133			    u16 *opcode, u8 *status, hci_req_complete_t *req_complete,
  7134			    hci_req_complete_skb_t *req_complete_skb)
  7135	{
  7136		const struct hci_ev *ev = &hci_ev_table[event];
  7137		void *data;
  7138	
  7139		if (!ev->func)
  7140			return;
  7141	
  7142		if (skb->len < ev->min_len) {
  7143			bt_dev_err(hdev, "unexpected event 0x%2.2x length: %u < %u",
  7144				   event, skb->len, ev->min_len);
  7145			return;
  7146		}
  7147	
  7148		/* Just warn if the length is over max_len size it still be
  7149		 * possible to partially parse the event so leave to callback to
  7150		 * decide if that is acceptable.
  7151		 */
  7152		if (skb->len > ev->max_len)
  7153			bt_dev_warn(hdev, "unexpected event 0x%2.2x length: %u > %u",
  7154				    event, skb->len, ev->max_len);
  7155	
  7156		data = hci_ev_skb_pull(hdev, skb, event, ev->min_len);
  7157		if (!data)
  7158			return;
  7159	
  7160		if (ev->req)
  7161			ev->func_req(hdev, data, skb, opcode, status, req_complete,
  7162				     req_complete_skb);
  7163		else
  7164			ev->func(hdev, data, skb);
  7165	}
  7166	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
@ 2021-12-01  3:22     ` kernel test robot
  0 siblings, 0 replies; 34+ messages in thread
From: kernel test robot @ 2021-12-01  3:22 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 12958 bytes --]

Hi Luiz,

I love your patch! Yet something to improve:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20211130]
[cannot apply to net-next/master net/master linus/master bluetooth/master v5.16-rc3]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: hexagon-randconfig-r026-20211130 (https://download.01.org/0day-ci/archive/20211201/202112011149.SZaZiW8X-lkp(a)intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 25eb7fa01d7ebbe67648ea03841cda55b4239ab2)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
        git checkout bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash net/bluetooth/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

>> net/bluetooth/hci_event.c:7129:24: error: incompatible function pointer types initializing 'void (*)(struct hci_dev *, void *, struct sk_buff *)' with an expression of type 'void (struct hci_dev *, struct sk_buff *)' [-Werror,-Wincompatible-function-pointer-types]
           HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
                                 ^~~~~~~~~~~~~~~
   net/bluetooth/hci_event.c:6958:17: note: expanded from macro 'HCI_EV'
           HCI_EV_VL(_op, _func, _len, _len)
                          ^~~~~
   net/bluetooth/hci_event.c:6952:10: note: expanded from macro 'HCI_EV_VL'
           .func = _func, \
                   ^~~~~
>> net/bluetooth/hci_event.c:7132:6: warning: no previous prototype for function 'hci_event_func' [-Wmissing-prototypes]
   void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
        ^
   net/bluetooth/hci_event.c:7132:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
   ^
   static 
   1 warning and 1 error generated.


vim +7129 net/bluetooth/hci_event.c

  6970	
  6971	#define HCI_EV_REQ(_op, _func, _len) \
  6972		HCI_EV_REQ_VL(_op, _func, _len, _len)
  6973	
  6974	/* Entries in this table shall have their position according to the event opcode
  6975	 * they handle so the use of the macros above is recommend since it does attempt
  6976	 * to initialize at its proper index using Designated Initializers that way
  6977	 * events without a callback function don't have entered.
  6978	 */
  6979	static const struct hci_ev {
  6980		bool req;
  6981		union {
  6982			void (*func)(struct hci_dev *hdev, void *data,
  6983				     struct sk_buff *skb);
  6984			void (*func_req)(struct hci_dev *hdev, void *data,
  6985					 struct sk_buff *skb, u16 *opcode, u8 *status,
  6986					 hci_req_complete_t *req_complete,
  6987					 hci_req_complete_skb_t *req_complete_skb);
  6988		};
  6989		u16  min_len;
  6990		u16  max_len;
  6991	} hci_ev_table[U8_MAX + 1] = {
  6992		/* [0x01 = HCI_EV_INQUIRY_COMPLETE] */
  6993		HCI_EV_STATUS(HCI_EV_INQUIRY_COMPLETE, hci_inquiry_complete_evt),
  6994		/* [0x02 = HCI_EV_INQUIRY_RESULT] */
  6995		HCI_EV_VL(HCI_EV_INQUIRY_RESULT, hci_inquiry_result_evt,
  6996			  sizeof(struct hci_ev_inquiry_result), HCI_MAX_EVENT_SIZE),
  6997		/* [0x03 = HCI_EV_CONN_COMPLETE] */
  6998		HCI_EV(HCI_EV_CONN_COMPLETE, hci_conn_complete_evt,
  6999		       sizeof(struct hci_ev_conn_complete)),
  7000		/* [0x04 = HCI_EV_CONN_REQUEST] */
  7001		HCI_EV(HCI_EV_CONN_REQUEST, hci_conn_request_evt,
  7002		       sizeof(struct hci_ev_conn_request)),
  7003		/* [0x05 = HCI_EV_DISCONN_COMPLETE] */
  7004		HCI_EV(HCI_EV_DISCONN_COMPLETE, hci_disconn_complete_evt,
  7005		       sizeof(struct hci_ev_disconn_complete)),
  7006		/* [0x06 = HCI_EV_AUTH_COMPLETE] */
  7007		HCI_EV(HCI_EV_AUTH_COMPLETE, hci_auth_complete_evt,
  7008		       sizeof(struct hci_ev_auth_complete)),
  7009		/* [0x07 = HCI_EV_REMOTE_NAME] */
  7010		HCI_EV(HCI_EV_REMOTE_NAME, hci_remote_name_evt,
  7011		       sizeof(struct hci_ev_remote_name)),
  7012		/* [0x08 = HCI_EV_ENCRYPT_CHANGE] */
  7013		HCI_EV(HCI_EV_ENCRYPT_CHANGE, hci_encrypt_change_evt,
  7014		       sizeof(struct hci_ev_encrypt_change)),
  7015		/* [0x09 = HCI_EV_CHANGE_LINK_KEY_COMPLETE] */
  7016		HCI_EV(HCI_EV_CHANGE_LINK_KEY_COMPLETE,
  7017		       hci_change_link_key_complete_evt,
  7018		       sizeof(struct hci_ev_change_link_key_complete)),
  7019		/* [0x0b = HCI_EV_REMOTE_FEATURES] */
  7020		HCI_EV(HCI_EV_REMOTE_FEATURES, hci_remote_features_evt,
  7021		       sizeof(struct hci_ev_remote_features)),
  7022		/* [0x0e = HCI_EV_CMD_COMPLETE] */
  7023		HCI_EV_REQ_VL(HCI_EV_CMD_COMPLETE, hci_cmd_complete_evt,
  7024			      sizeof(struct hci_ev_cmd_complete), HCI_MAX_EVENT_SIZE),
  7025		/* [0x0f = HCI_EV_CMD_STATUS] */
  7026		HCI_EV_REQ(HCI_EV_CMD_STATUS, hci_cmd_status_evt,
  7027			   sizeof(struct hci_ev_cmd_status)),
  7028		/* [0x10 = HCI_EV_CMD_STATUS] */
  7029		HCI_EV(HCI_EV_HARDWARE_ERROR, hci_hardware_error_evt,
  7030		       sizeof(struct hci_ev_hardware_error)),
  7031		/* [0x12 = HCI_EV_ROLE_CHANGE] */
  7032		HCI_EV(HCI_EV_ROLE_CHANGE, hci_role_change_evt,
  7033		       sizeof(struct hci_ev_role_change)),
  7034		/* [0x13 = HCI_EV_NUM_COMP_PKTS] */
  7035		HCI_EV_VL(HCI_EV_NUM_COMP_PKTS, hci_num_comp_pkts_evt,
  7036			  sizeof(struct hci_ev_num_comp_pkts), HCI_MAX_EVENT_SIZE),
  7037		/* [0x14 = HCI_EV_MODE_CHANGE] */
  7038		HCI_EV(HCI_EV_MODE_CHANGE, hci_mode_change_evt,
  7039		       sizeof(struct hci_ev_mode_change)),
  7040		/* [0x16 = HCI_EV_PIN_CODE_REQ] */
  7041		HCI_EV(HCI_EV_PIN_CODE_REQ, hci_pin_code_request_evt,
  7042		       sizeof(struct hci_ev_pin_code_req)),
  7043		/* [0x17 = HCI_EV_LINK_KEY_REQ] */
  7044		HCI_EV(HCI_EV_LINK_KEY_REQ, hci_link_key_request_evt,
  7045		       sizeof(struct hci_ev_link_key_req)),
  7046		/* [0x18 = HCI_EV_LINK_KEY_NOTIFY] */
  7047		HCI_EV(HCI_EV_LINK_KEY_NOTIFY, hci_link_key_notify_evt,
  7048		       sizeof(struct hci_ev_link_key_notify)),
  7049		/* [0x1c = HCI_EV_CLOCK_OFFSET] */
  7050		HCI_EV(HCI_EV_CLOCK_OFFSET, hci_clock_offset_evt,
  7051		       sizeof(struct hci_ev_clock_offset)),
  7052		/* [0x1d = HCI_EV_PKT_TYPE_CHANGE] */
  7053		HCI_EV(HCI_EV_PKT_TYPE_CHANGE, hci_pkt_type_change_evt,
  7054		       sizeof(struct hci_ev_pkt_type_change)),
  7055		/* [0x20 = HCI_EV_PSCAN_REP_MODE] */
  7056		HCI_EV(HCI_EV_PSCAN_REP_MODE, hci_pscan_rep_mode_evt,
  7057		       sizeof(struct hci_ev_pscan_rep_mode)),
  7058		/* [0x22 = HCI_EV_INQUIRY_RESULT_WITH_RSSI] */
  7059		HCI_EV_VL(HCI_EV_INQUIRY_RESULT_WITH_RSSI,
  7060			  hci_inquiry_result_with_rssi_evt,
  7061			  sizeof(struct hci_ev_inquiry_result_rssi),
  7062			  HCI_MAX_EVENT_SIZE),
  7063		/* [0x23 = HCI_EV_REMOTE_EXT_FEATURES] */
  7064		HCI_EV(HCI_EV_REMOTE_EXT_FEATURES, hci_remote_ext_features_evt,
  7065		       sizeof(struct hci_ev_remote_ext_features)),
  7066		/* [0x2c = HCI_EV_SYNC_CONN_COMPLETE] */
  7067		HCI_EV(HCI_EV_SYNC_CONN_COMPLETE, hci_sync_conn_complete_evt,
  7068		       sizeof(struct hci_ev_sync_conn_complete)),
  7069		/* [0x2d = HCI_EV_EXTENDED_INQUIRY_RESULT] */
  7070		HCI_EV_VL(HCI_EV_EXTENDED_INQUIRY_RESULT,
  7071			  hci_extended_inquiry_result_evt,
  7072			  sizeof(struct hci_ev_ext_inquiry_result), HCI_MAX_EVENT_SIZE),
  7073		/* [0x30 = HCI_EV_KEY_REFRESH_COMPLETE] */
  7074		HCI_EV(HCI_EV_KEY_REFRESH_COMPLETE, hci_key_refresh_complete_evt,
  7075		       sizeof(struct hci_ev_key_refresh_complete)),
  7076		/* [0x31 = HCI_EV_IO_CAPA_REQUEST] */
  7077		HCI_EV(HCI_EV_IO_CAPA_REQUEST, hci_io_capa_request_evt,
  7078		       sizeof(struct hci_ev_io_capa_request)),
  7079		/* [0x32 = HCI_EV_IO_CAPA_REPLY] */
  7080		HCI_EV(HCI_EV_IO_CAPA_REPLY, hci_io_capa_reply_evt,
  7081		       sizeof(struct hci_ev_io_capa_reply)),
  7082		/* [0x33 = HCI_EV_USER_CONFIRM_REQUEST] */
  7083		HCI_EV(HCI_EV_USER_CONFIRM_REQUEST, hci_user_confirm_request_evt,
  7084		       sizeof(struct hci_ev_user_confirm_req)),
  7085		/* [0x34 = HCI_EV_USER_PASSKEY_REQUEST] */
  7086		HCI_EV(HCI_EV_USER_PASSKEY_REQUEST, hci_user_passkey_request_evt,
  7087		       sizeof(struct hci_ev_user_passkey_req)),
  7088		/* [0x35 = HCI_EV_REMOTE_OOB_DATA_REQUEST] */
  7089		HCI_EV(HCI_EV_REMOTE_OOB_DATA_REQUEST, hci_remote_oob_data_request_evt,
  7090		       sizeof(struct hci_ev_remote_oob_data_request)),
  7091		/* [0x36 = HCI_EV_SIMPLE_PAIR_COMPLETE] */
  7092		HCI_EV(HCI_EV_SIMPLE_PAIR_COMPLETE, hci_simple_pair_complete_evt,
  7093		       sizeof(struct hci_ev_simple_pair_complete)),
  7094		/* [0x3b = HCI_EV_USER_PASSKEY_NOTIFY] */
  7095		HCI_EV(HCI_EV_USER_PASSKEY_NOTIFY, hci_user_passkey_notify_evt,
  7096		       sizeof(struct hci_ev_user_passkey_notify)),
  7097		/* [0x3c = HCI_EV_KEYPRESS_NOTIFY] */
  7098		HCI_EV(HCI_EV_KEYPRESS_NOTIFY, hci_keypress_notify_evt,
  7099		       sizeof(struct hci_ev_keypress_notify)),
  7100		/* [0x3d = HCI_EV_REMOTE_HOST_FEATURES] */
  7101		HCI_EV(HCI_EV_REMOTE_HOST_FEATURES, hci_remote_host_features_evt,
  7102		       sizeof(struct hci_ev_remote_host_features)),
  7103		/* [0x3e = HCI_EV_LE_META] */
  7104		HCI_EV_VL(HCI_EV_LE_META, hci_le_meta_evt,
  7105			  sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
  7106	#if IS_ENABLED(CONFIG_BT_HS)
  7107		/* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */
  7108		HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt,
  7109		       sizeof(struct hci_ev_phy_link_complete)),
  7110		/* [0x41 = HCI_EV_CHANNEL_SELECTED] */
  7111		HCI_EV(HCI_EV_CHANNEL_SELECTED, hci_chan_selected_evt,
  7112		       sizeof(struct hci_ev_channel_selected)),
  7113		/* [0x42 = HCI_EV_DISCONN_PHY_LINK_COMPLETE] */
  7114		HCI_EV(HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
  7115		       hci_disconn_loglink_complete_evt,
  7116		       sizeof(struct hci_ev_disconn_logical_link_complete)),
  7117		/* [0x45 = HCI_EV_LOGICAL_LINK_COMPLETE] */
  7118		HCI_EV(HCI_EV_LOGICAL_LINK_COMPLETE, hci_loglink_complete_evt,
  7119		       sizeof(struct hci_ev_logical_link_complete)),
  7120		/* [0x46 = HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE] */
  7121		HCI_EV(HCI_EV_DISCONN_PHY_LINK_COMPLETE,
  7122		       hci_disconn_phylink_complete_evt,
  7123		       sizeof(struct hci_ev_disconn_phy_link_complete)),
  7124	#endif
  7125		/* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */
  7126		HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt,
  7127		       sizeof(struct hci_ev_num_comp_blocks)),
  7128		/* [0xff = HCI_EV_VENDOR] */
> 7129		HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
  7130	};
  7131	
> 7132	void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
  7133			    u16 *opcode, u8 *status, hci_req_complete_t *req_complete,
  7134			    hci_req_complete_skb_t *req_complete_skb)
  7135	{
  7136		const struct hci_ev *ev = &hci_ev_table[event];
  7137		void *data;
  7138	
  7139		if (!ev->func)
  7140			return;
  7141	
  7142		if (skb->len < ev->min_len) {
  7143			bt_dev_err(hdev, "unexpected event 0x%2.2x length: %u < %u",
  7144				   event, skb->len, ev->min_len);
  7145			return;
  7146		}
  7147	
  7148		/* Just warn if the length is over max_len size it still be
  7149		 * possible to partially parse the event so leave to callback to
  7150		 * decide if that is acceptable.
  7151		 */
  7152		if (skb->len > ev->max_len)
  7153			bt_dev_warn(hdev, "unexpected event 0x%2.2x length: %u > %u",
  7154				    event, skb->len, ev->max_len);
  7155	
  7156		data = hci_ev_skb_pull(hdev, skb, event, ev->min_len);
  7157		if (!data)
  7158			return;
  7159	
  7160		if (ev->req)
  7161			ev->func_req(hdev, data, skb, opcode, status, req_complete,
  7162				     req_complete_skb);
  7163		else
  7164			ev->func(hdev, data, skb);
  7165	}
  7166	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
  2021-12-01  0:02 ` [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events Luiz Augusto von Dentz
@ 2021-12-01  3:22     ` kernel test robot
  2021-12-01  3:22     ` kernel test robot
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 34+ messages in thread
From: kernel test robot @ 2021-12-01  3:22 UTC (permalink / raw)
  To: Luiz Augusto von Dentz, davem, kuba
  Cc: kbuild-all, linux-bluetooth, netdev, dan.carpenter,
	Luiz Augusto von Dentz

Hi Luiz,

I love your patch! Yet something to improve:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20211130]
[cannot apply to net-next/master net/master linus/master bluetooth/master v5.16-rc3]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: h8300-randconfig-r022-20211130 (https://download.01.org/0day-ci/archive/20211201/202112011107.rTK0mEYG-lkp@intel.com/config)
compiler: h8300-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
        git checkout bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=h8300 SHELL=/bin/bash net/bluetooth/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

>> net/bluetooth/hci_event.c:7129:31: error: initialization of 'void (*)(struct hci_dev *, void *, struct sk_buff *)' from incompatible pointer type 'void (*)(struct hci_dev *, struct sk_buff *)' [-Werror=incompatible-pointer-types]
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |                               ^~~~~~~~~~~~~~~
   net/bluetooth/hci_event.c:6952:17: note: in definition of macro 'HCI_EV_VL'
    6952 |         .func = _func, \
         |                 ^~~~~
   net/bluetooth/hci_event.c:7129:9: note: in expansion of macro 'HCI_EV'
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |         ^~~~~~
   net/bluetooth/hci_event.c:7129:31: note: (near initialization for 'hci_ev_table[255].<anonymous>.func')
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |                               ^~~~~~~~~~~~~~~
   net/bluetooth/hci_event.c:6952:17: note: in definition of macro 'HCI_EV_VL'
    6952 |         .func = _func, \
         |                 ^~~~~
   net/bluetooth/hci_event.c:7129:9: note: in expansion of macro 'HCI_EV'
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |         ^~~~~~
>> net/bluetooth/hci_event.c:7132:6: warning: no previous prototype for 'hci_event_func' [-Wmissing-prototypes]
    7132 | void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
         |      ^~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +7129 net/bluetooth/hci_event.c

  6970	
  6971	#define HCI_EV_REQ(_op, _func, _len) \
  6972		HCI_EV_REQ_VL(_op, _func, _len, _len)
  6973	
  6974	/* Entries in this table shall have their position according to the event opcode
  6975	 * they handle so the use of the macros above is recommend since it does attempt
  6976	 * to initialize at its proper index using Designated Initializers that way
  6977	 * events without a callback function don't have entered.
  6978	 */
  6979	static const struct hci_ev {
  6980		bool req;
  6981		union {
  6982			void (*func)(struct hci_dev *hdev, void *data,
  6983				     struct sk_buff *skb);
  6984			void (*func_req)(struct hci_dev *hdev, void *data,
  6985					 struct sk_buff *skb, u16 *opcode, u8 *status,
  6986					 hci_req_complete_t *req_complete,
  6987					 hci_req_complete_skb_t *req_complete_skb);
  6988		};
  6989		u16  min_len;
  6990		u16  max_len;
  6991	} hci_ev_table[U8_MAX + 1] = {
  6992		/* [0x01 = HCI_EV_INQUIRY_COMPLETE] */
  6993		HCI_EV_STATUS(HCI_EV_INQUIRY_COMPLETE, hci_inquiry_complete_evt),
  6994		/* [0x02 = HCI_EV_INQUIRY_RESULT] */
  6995		HCI_EV_VL(HCI_EV_INQUIRY_RESULT, hci_inquiry_result_evt,
  6996			  sizeof(struct hci_ev_inquiry_result), HCI_MAX_EVENT_SIZE),
  6997		/* [0x03 = HCI_EV_CONN_COMPLETE] */
  6998		HCI_EV(HCI_EV_CONN_COMPLETE, hci_conn_complete_evt,
  6999		       sizeof(struct hci_ev_conn_complete)),
  7000		/* [0x04 = HCI_EV_CONN_REQUEST] */
  7001		HCI_EV(HCI_EV_CONN_REQUEST, hci_conn_request_evt,
  7002		       sizeof(struct hci_ev_conn_request)),
  7003		/* [0x05 = HCI_EV_DISCONN_COMPLETE] */
  7004		HCI_EV(HCI_EV_DISCONN_COMPLETE, hci_disconn_complete_evt,
  7005		       sizeof(struct hci_ev_disconn_complete)),
  7006		/* [0x06 = HCI_EV_AUTH_COMPLETE] */
  7007		HCI_EV(HCI_EV_AUTH_COMPLETE, hci_auth_complete_evt,
  7008		       sizeof(struct hci_ev_auth_complete)),
  7009		/* [0x07 = HCI_EV_REMOTE_NAME] */
  7010		HCI_EV(HCI_EV_REMOTE_NAME, hci_remote_name_evt,
  7011		       sizeof(struct hci_ev_remote_name)),
  7012		/* [0x08 = HCI_EV_ENCRYPT_CHANGE] */
  7013		HCI_EV(HCI_EV_ENCRYPT_CHANGE, hci_encrypt_change_evt,
  7014		       sizeof(struct hci_ev_encrypt_change)),
  7015		/* [0x09 = HCI_EV_CHANGE_LINK_KEY_COMPLETE] */
  7016		HCI_EV(HCI_EV_CHANGE_LINK_KEY_COMPLETE,
  7017		       hci_change_link_key_complete_evt,
  7018		       sizeof(struct hci_ev_change_link_key_complete)),
  7019		/* [0x0b = HCI_EV_REMOTE_FEATURES] */
  7020		HCI_EV(HCI_EV_REMOTE_FEATURES, hci_remote_features_evt,
  7021		       sizeof(struct hci_ev_remote_features)),
  7022		/* [0x0e = HCI_EV_CMD_COMPLETE] */
  7023		HCI_EV_REQ_VL(HCI_EV_CMD_COMPLETE, hci_cmd_complete_evt,
  7024			      sizeof(struct hci_ev_cmd_complete), HCI_MAX_EVENT_SIZE),
  7025		/* [0x0f = HCI_EV_CMD_STATUS] */
  7026		HCI_EV_REQ(HCI_EV_CMD_STATUS, hci_cmd_status_evt,
  7027			   sizeof(struct hci_ev_cmd_status)),
  7028		/* [0x10 = HCI_EV_CMD_STATUS] */
  7029		HCI_EV(HCI_EV_HARDWARE_ERROR, hci_hardware_error_evt,
  7030		       sizeof(struct hci_ev_hardware_error)),
  7031		/* [0x12 = HCI_EV_ROLE_CHANGE] */
  7032		HCI_EV(HCI_EV_ROLE_CHANGE, hci_role_change_evt,
  7033		       sizeof(struct hci_ev_role_change)),
  7034		/* [0x13 = HCI_EV_NUM_COMP_PKTS] */
  7035		HCI_EV_VL(HCI_EV_NUM_COMP_PKTS, hci_num_comp_pkts_evt,
  7036			  sizeof(struct hci_ev_num_comp_pkts), HCI_MAX_EVENT_SIZE),
  7037		/* [0x14 = HCI_EV_MODE_CHANGE] */
  7038		HCI_EV(HCI_EV_MODE_CHANGE, hci_mode_change_evt,
  7039		       sizeof(struct hci_ev_mode_change)),
  7040		/* [0x16 = HCI_EV_PIN_CODE_REQ] */
  7041		HCI_EV(HCI_EV_PIN_CODE_REQ, hci_pin_code_request_evt,
  7042		       sizeof(struct hci_ev_pin_code_req)),
  7043		/* [0x17 = HCI_EV_LINK_KEY_REQ] */
  7044		HCI_EV(HCI_EV_LINK_KEY_REQ, hci_link_key_request_evt,
  7045		       sizeof(struct hci_ev_link_key_req)),
  7046		/* [0x18 = HCI_EV_LINK_KEY_NOTIFY] */
  7047		HCI_EV(HCI_EV_LINK_KEY_NOTIFY, hci_link_key_notify_evt,
  7048		       sizeof(struct hci_ev_link_key_notify)),
  7049		/* [0x1c = HCI_EV_CLOCK_OFFSET] */
  7050		HCI_EV(HCI_EV_CLOCK_OFFSET, hci_clock_offset_evt,
  7051		       sizeof(struct hci_ev_clock_offset)),
  7052		/* [0x1d = HCI_EV_PKT_TYPE_CHANGE] */
  7053		HCI_EV(HCI_EV_PKT_TYPE_CHANGE, hci_pkt_type_change_evt,
  7054		       sizeof(struct hci_ev_pkt_type_change)),
  7055		/* [0x20 = HCI_EV_PSCAN_REP_MODE] */
  7056		HCI_EV(HCI_EV_PSCAN_REP_MODE, hci_pscan_rep_mode_evt,
  7057		       sizeof(struct hci_ev_pscan_rep_mode)),
  7058		/* [0x22 = HCI_EV_INQUIRY_RESULT_WITH_RSSI] */
  7059		HCI_EV_VL(HCI_EV_INQUIRY_RESULT_WITH_RSSI,
  7060			  hci_inquiry_result_with_rssi_evt,
  7061			  sizeof(struct hci_ev_inquiry_result_rssi),
  7062			  HCI_MAX_EVENT_SIZE),
  7063		/* [0x23 = HCI_EV_REMOTE_EXT_FEATURES] */
  7064		HCI_EV(HCI_EV_REMOTE_EXT_FEATURES, hci_remote_ext_features_evt,
  7065		       sizeof(struct hci_ev_remote_ext_features)),
  7066		/* [0x2c = HCI_EV_SYNC_CONN_COMPLETE] */
  7067		HCI_EV(HCI_EV_SYNC_CONN_COMPLETE, hci_sync_conn_complete_evt,
  7068		       sizeof(struct hci_ev_sync_conn_complete)),
  7069		/* [0x2d = HCI_EV_EXTENDED_INQUIRY_RESULT] */
  7070		HCI_EV_VL(HCI_EV_EXTENDED_INQUIRY_RESULT,
  7071			  hci_extended_inquiry_result_evt,
  7072			  sizeof(struct hci_ev_ext_inquiry_result), HCI_MAX_EVENT_SIZE),
  7073		/* [0x30 = HCI_EV_KEY_REFRESH_COMPLETE] */
  7074		HCI_EV(HCI_EV_KEY_REFRESH_COMPLETE, hci_key_refresh_complete_evt,
  7075		       sizeof(struct hci_ev_key_refresh_complete)),
  7076		/* [0x31 = HCI_EV_IO_CAPA_REQUEST] */
  7077		HCI_EV(HCI_EV_IO_CAPA_REQUEST, hci_io_capa_request_evt,
  7078		       sizeof(struct hci_ev_io_capa_request)),
  7079		/* [0x32 = HCI_EV_IO_CAPA_REPLY] */
  7080		HCI_EV(HCI_EV_IO_CAPA_REPLY, hci_io_capa_reply_evt,
  7081		       sizeof(struct hci_ev_io_capa_reply)),
  7082		/* [0x33 = HCI_EV_USER_CONFIRM_REQUEST] */
  7083		HCI_EV(HCI_EV_USER_CONFIRM_REQUEST, hci_user_confirm_request_evt,
  7084		       sizeof(struct hci_ev_user_confirm_req)),
  7085		/* [0x34 = HCI_EV_USER_PASSKEY_REQUEST] */
  7086		HCI_EV(HCI_EV_USER_PASSKEY_REQUEST, hci_user_passkey_request_evt,
  7087		       sizeof(struct hci_ev_user_passkey_req)),
  7088		/* [0x35 = HCI_EV_REMOTE_OOB_DATA_REQUEST] */
  7089		HCI_EV(HCI_EV_REMOTE_OOB_DATA_REQUEST, hci_remote_oob_data_request_evt,
  7090		       sizeof(struct hci_ev_remote_oob_data_request)),
  7091		/* [0x36 = HCI_EV_SIMPLE_PAIR_COMPLETE] */
  7092		HCI_EV(HCI_EV_SIMPLE_PAIR_COMPLETE, hci_simple_pair_complete_evt,
  7093		       sizeof(struct hci_ev_simple_pair_complete)),
  7094		/* [0x3b = HCI_EV_USER_PASSKEY_NOTIFY] */
  7095		HCI_EV(HCI_EV_USER_PASSKEY_NOTIFY, hci_user_passkey_notify_evt,
  7096		       sizeof(struct hci_ev_user_passkey_notify)),
  7097		/* [0x3c = HCI_EV_KEYPRESS_NOTIFY] */
  7098		HCI_EV(HCI_EV_KEYPRESS_NOTIFY, hci_keypress_notify_evt,
  7099		       sizeof(struct hci_ev_keypress_notify)),
  7100		/* [0x3d = HCI_EV_REMOTE_HOST_FEATURES] */
  7101		HCI_EV(HCI_EV_REMOTE_HOST_FEATURES, hci_remote_host_features_evt,
  7102		       sizeof(struct hci_ev_remote_host_features)),
  7103		/* [0x3e = HCI_EV_LE_META] */
  7104		HCI_EV_VL(HCI_EV_LE_META, hci_le_meta_evt,
  7105			  sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
  7106	#if IS_ENABLED(CONFIG_BT_HS)
  7107		/* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */
  7108		HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt,
  7109		       sizeof(struct hci_ev_phy_link_complete)),
  7110		/* [0x41 = HCI_EV_CHANNEL_SELECTED] */
  7111		HCI_EV(HCI_EV_CHANNEL_SELECTED, hci_chan_selected_evt,
  7112		       sizeof(struct hci_ev_channel_selected)),
  7113		/* [0x42 = HCI_EV_DISCONN_PHY_LINK_COMPLETE] */
  7114		HCI_EV(HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
  7115		       hci_disconn_loglink_complete_evt,
  7116		       sizeof(struct hci_ev_disconn_logical_link_complete)),
  7117		/* [0x45 = HCI_EV_LOGICAL_LINK_COMPLETE] */
  7118		HCI_EV(HCI_EV_LOGICAL_LINK_COMPLETE, hci_loglink_complete_evt,
  7119		       sizeof(struct hci_ev_logical_link_complete)),
  7120		/* [0x46 = HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE] */
  7121		HCI_EV(HCI_EV_DISCONN_PHY_LINK_COMPLETE,
  7122		       hci_disconn_phylink_complete_evt,
  7123		       sizeof(struct hci_ev_disconn_phy_link_complete)),
  7124	#endif
  7125		/* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */
  7126		HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt,
  7127		       sizeof(struct hci_ev_num_comp_blocks)),
  7128		/* [0xff = HCI_EV_VENDOR] */
> 7129		HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
  7130	};
  7131	
> 7132	void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
  7133			    u16 *opcode, u8 *status, hci_req_complete_t *req_complete,
  7134			    hci_req_complete_skb_t *req_complete_skb)
  7135	{
  7136		const struct hci_ev *ev = &hci_ev_table[event];
  7137		void *data;
  7138	
  7139		if (!ev->func)
  7140			return;
  7141	
  7142		if (skb->len < ev->min_len) {
  7143			bt_dev_err(hdev, "unexpected event 0x%2.2x length: %u < %u",
  7144				   event, skb->len, ev->min_len);
  7145			return;
  7146		}
  7147	
  7148		/* Just warn if the length is over max_len size it still be
  7149		 * possible to partially parse the event so leave to callback to
  7150		 * decide if that is acceptable.
  7151		 */
  7152		if (skb->len > ev->max_len)
  7153			bt_dev_warn(hdev, "unexpected event 0x%2.2x length: %u > %u",
  7154				    event, skb->len, ev->max_len);
  7155	
  7156		data = hci_ev_skb_pull(hdev, skb, event, ev->min_len);
  7157		if (!data)
  7158			return;
  7159	
  7160		if (ev->req)
  7161			ev->func_req(hdev, data, skb, opcode, status, req_complete,
  7162				     req_complete_skb);
  7163		else
  7164			ev->func(hdev, data, skb);
  7165	}
  7166	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
@ 2021-12-01  3:22     ` kernel test robot
  0 siblings, 0 replies; 34+ messages in thread
From: kernel test robot @ 2021-12-01  3:22 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 13238 bytes --]

Hi Luiz,

I love your patch! Yet something to improve:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20211130]
[cannot apply to net-next/master net/master linus/master bluetooth/master v5.16-rc3]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: h8300-randconfig-r022-20211130 (https://download.01.org/0day-ci/archive/20211201/202112011107.rTK0mEYG-lkp(a)intel.com/config)
compiler: h8300-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
        git checkout bd4b2eeacef50f9df8f08056e9f6523083ac96f3
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=h8300 SHELL=/bin/bash net/bluetooth/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

>> net/bluetooth/hci_event.c:7129:31: error: initialization of 'void (*)(struct hci_dev *, void *, struct sk_buff *)' from incompatible pointer type 'void (*)(struct hci_dev *, struct sk_buff *)' [-Werror=incompatible-pointer-types]
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |                               ^~~~~~~~~~~~~~~
   net/bluetooth/hci_event.c:6952:17: note: in definition of macro 'HCI_EV_VL'
    6952 |         .func = _func, \
         |                 ^~~~~
   net/bluetooth/hci_event.c:7129:9: note: in expansion of macro 'HCI_EV'
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |         ^~~~~~
   net/bluetooth/hci_event.c:7129:31: note: (near initialization for 'hci_ev_table[255].<anonymous>.func')
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |                               ^~~~~~~~~~~~~~~
   net/bluetooth/hci_event.c:6952:17: note: in definition of macro 'HCI_EV_VL'
    6952 |         .func = _func, \
         |                 ^~~~~
   net/bluetooth/hci_event.c:7129:9: note: in expansion of macro 'HCI_EV'
    7129 |         HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
         |         ^~~~~~
>> net/bluetooth/hci_event.c:7132:6: warning: no previous prototype for 'hci_event_func' [-Wmissing-prototypes]
    7132 | void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
         |      ^~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +7129 net/bluetooth/hci_event.c

  6970	
  6971	#define HCI_EV_REQ(_op, _func, _len) \
  6972		HCI_EV_REQ_VL(_op, _func, _len, _len)
  6973	
  6974	/* Entries in this table shall have their position according to the event opcode
  6975	 * they handle so the use of the macros above is recommend since it does attempt
  6976	 * to initialize at its proper index using Designated Initializers that way
  6977	 * events without a callback function don't have entered.
  6978	 */
  6979	static const struct hci_ev {
  6980		bool req;
  6981		union {
  6982			void (*func)(struct hci_dev *hdev, void *data,
  6983				     struct sk_buff *skb);
  6984			void (*func_req)(struct hci_dev *hdev, void *data,
  6985					 struct sk_buff *skb, u16 *opcode, u8 *status,
  6986					 hci_req_complete_t *req_complete,
  6987					 hci_req_complete_skb_t *req_complete_skb);
  6988		};
  6989		u16  min_len;
  6990		u16  max_len;
  6991	} hci_ev_table[U8_MAX + 1] = {
  6992		/* [0x01 = HCI_EV_INQUIRY_COMPLETE] */
  6993		HCI_EV_STATUS(HCI_EV_INQUIRY_COMPLETE, hci_inquiry_complete_evt),
  6994		/* [0x02 = HCI_EV_INQUIRY_RESULT] */
  6995		HCI_EV_VL(HCI_EV_INQUIRY_RESULT, hci_inquiry_result_evt,
  6996			  sizeof(struct hci_ev_inquiry_result), HCI_MAX_EVENT_SIZE),
  6997		/* [0x03 = HCI_EV_CONN_COMPLETE] */
  6998		HCI_EV(HCI_EV_CONN_COMPLETE, hci_conn_complete_evt,
  6999		       sizeof(struct hci_ev_conn_complete)),
  7000		/* [0x04 = HCI_EV_CONN_REQUEST] */
  7001		HCI_EV(HCI_EV_CONN_REQUEST, hci_conn_request_evt,
  7002		       sizeof(struct hci_ev_conn_request)),
  7003		/* [0x05 = HCI_EV_DISCONN_COMPLETE] */
  7004		HCI_EV(HCI_EV_DISCONN_COMPLETE, hci_disconn_complete_evt,
  7005		       sizeof(struct hci_ev_disconn_complete)),
  7006		/* [0x06 = HCI_EV_AUTH_COMPLETE] */
  7007		HCI_EV(HCI_EV_AUTH_COMPLETE, hci_auth_complete_evt,
  7008		       sizeof(struct hci_ev_auth_complete)),
  7009		/* [0x07 = HCI_EV_REMOTE_NAME] */
  7010		HCI_EV(HCI_EV_REMOTE_NAME, hci_remote_name_evt,
  7011		       sizeof(struct hci_ev_remote_name)),
  7012		/* [0x08 = HCI_EV_ENCRYPT_CHANGE] */
  7013		HCI_EV(HCI_EV_ENCRYPT_CHANGE, hci_encrypt_change_evt,
  7014		       sizeof(struct hci_ev_encrypt_change)),
  7015		/* [0x09 = HCI_EV_CHANGE_LINK_KEY_COMPLETE] */
  7016		HCI_EV(HCI_EV_CHANGE_LINK_KEY_COMPLETE,
  7017		       hci_change_link_key_complete_evt,
  7018		       sizeof(struct hci_ev_change_link_key_complete)),
  7019		/* [0x0b = HCI_EV_REMOTE_FEATURES] */
  7020		HCI_EV(HCI_EV_REMOTE_FEATURES, hci_remote_features_evt,
  7021		       sizeof(struct hci_ev_remote_features)),
  7022		/* [0x0e = HCI_EV_CMD_COMPLETE] */
  7023		HCI_EV_REQ_VL(HCI_EV_CMD_COMPLETE, hci_cmd_complete_evt,
  7024			      sizeof(struct hci_ev_cmd_complete), HCI_MAX_EVENT_SIZE),
  7025		/* [0x0f = HCI_EV_CMD_STATUS] */
  7026		HCI_EV_REQ(HCI_EV_CMD_STATUS, hci_cmd_status_evt,
  7027			   sizeof(struct hci_ev_cmd_status)),
  7028		/* [0x10 = HCI_EV_CMD_STATUS] */
  7029		HCI_EV(HCI_EV_HARDWARE_ERROR, hci_hardware_error_evt,
  7030		       sizeof(struct hci_ev_hardware_error)),
  7031		/* [0x12 = HCI_EV_ROLE_CHANGE] */
  7032		HCI_EV(HCI_EV_ROLE_CHANGE, hci_role_change_evt,
  7033		       sizeof(struct hci_ev_role_change)),
  7034		/* [0x13 = HCI_EV_NUM_COMP_PKTS] */
  7035		HCI_EV_VL(HCI_EV_NUM_COMP_PKTS, hci_num_comp_pkts_evt,
  7036			  sizeof(struct hci_ev_num_comp_pkts), HCI_MAX_EVENT_SIZE),
  7037		/* [0x14 = HCI_EV_MODE_CHANGE] */
  7038		HCI_EV(HCI_EV_MODE_CHANGE, hci_mode_change_evt,
  7039		       sizeof(struct hci_ev_mode_change)),
  7040		/* [0x16 = HCI_EV_PIN_CODE_REQ] */
  7041		HCI_EV(HCI_EV_PIN_CODE_REQ, hci_pin_code_request_evt,
  7042		       sizeof(struct hci_ev_pin_code_req)),
  7043		/* [0x17 = HCI_EV_LINK_KEY_REQ] */
  7044		HCI_EV(HCI_EV_LINK_KEY_REQ, hci_link_key_request_evt,
  7045		       sizeof(struct hci_ev_link_key_req)),
  7046		/* [0x18 = HCI_EV_LINK_KEY_NOTIFY] */
  7047		HCI_EV(HCI_EV_LINK_KEY_NOTIFY, hci_link_key_notify_evt,
  7048		       sizeof(struct hci_ev_link_key_notify)),
  7049		/* [0x1c = HCI_EV_CLOCK_OFFSET] */
  7050		HCI_EV(HCI_EV_CLOCK_OFFSET, hci_clock_offset_evt,
  7051		       sizeof(struct hci_ev_clock_offset)),
  7052		/* [0x1d = HCI_EV_PKT_TYPE_CHANGE] */
  7053		HCI_EV(HCI_EV_PKT_TYPE_CHANGE, hci_pkt_type_change_evt,
  7054		       sizeof(struct hci_ev_pkt_type_change)),
  7055		/* [0x20 = HCI_EV_PSCAN_REP_MODE] */
  7056		HCI_EV(HCI_EV_PSCAN_REP_MODE, hci_pscan_rep_mode_evt,
  7057		       sizeof(struct hci_ev_pscan_rep_mode)),
  7058		/* [0x22 = HCI_EV_INQUIRY_RESULT_WITH_RSSI] */
  7059		HCI_EV_VL(HCI_EV_INQUIRY_RESULT_WITH_RSSI,
  7060			  hci_inquiry_result_with_rssi_evt,
  7061			  sizeof(struct hci_ev_inquiry_result_rssi),
  7062			  HCI_MAX_EVENT_SIZE),
  7063		/* [0x23 = HCI_EV_REMOTE_EXT_FEATURES] */
  7064		HCI_EV(HCI_EV_REMOTE_EXT_FEATURES, hci_remote_ext_features_evt,
  7065		       sizeof(struct hci_ev_remote_ext_features)),
  7066		/* [0x2c = HCI_EV_SYNC_CONN_COMPLETE] */
  7067		HCI_EV(HCI_EV_SYNC_CONN_COMPLETE, hci_sync_conn_complete_evt,
  7068		       sizeof(struct hci_ev_sync_conn_complete)),
  7069		/* [0x2d = HCI_EV_EXTENDED_INQUIRY_RESULT] */
  7070		HCI_EV_VL(HCI_EV_EXTENDED_INQUIRY_RESULT,
  7071			  hci_extended_inquiry_result_evt,
  7072			  sizeof(struct hci_ev_ext_inquiry_result), HCI_MAX_EVENT_SIZE),
  7073		/* [0x30 = HCI_EV_KEY_REFRESH_COMPLETE] */
  7074		HCI_EV(HCI_EV_KEY_REFRESH_COMPLETE, hci_key_refresh_complete_evt,
  7075		       sizeof(struct hci_ev_key_refresh_complete)),
  7076		/* [0x31 = HCI_EV_IO_CAPA_REQUEST] */
  7077		HCI_EV(HCI_EV_IO_CAPA_REQUEST, hci_io_capa_request_evt,
  7078		       sizeof(struct hci_ev_io_capa_request)),
  7079		/* [0x32 = HCI_EV_IO_CAPA_REPLY] */
  7080		HCI_EV(HCI_EV_IO_CAPA_REPLY, hci_io_capa_reply_evt,
  7081		       sizeof(struct hci_ev_io_capa_reply)),
  7082		/* [0x33 = HCI_EV_USER_CONFIRM_REQUEST] */
  7083		HCI_EV(HCI_EV_USER_CONFIRM_REQUEST, hci_user_confirm_request_evt,
  7084		       sizeof(struct hci_ev_user_confirm_req)),
  7085		/* [0x34 = HCI_EV_USER_PASSKEY_REQUEST] */
  7086		HCI_EV(HCI_EV_USER_PASSKEY_REQUEST, hci_user_passkey_request_evt,
  7087		       sizeof(struct hci_ev_user_passkey_req)),
  7088		/* [0x35 = HCI_EV_REMOTE_OOB_DATA_REQUEST] */
  7089		HCI_EV(HCI_EV_REMOTE_OOB_DATA_REQUEST, hci_remote_oob_data_request_evt,
  7090		       sizeof(struct hci_ev_remote_oob_data_request)),
  7091		/* [0x36 = HCI_EV_SIMPLE_PAIR_COMPLETE] */
  7092		HCI_EV(HCI_EV_SIMPLE_PAIR_COMPLETE, hci_simple_pair_complete_evt,
  7093		       sizeof(struct hci_ev_simple_pair_complete)),
  7094		/* [0x3b = HCI_EV_USER_PASSKEY_NOTIFY] */
  7095		HCI_EV(HCI_EV_USER_PASSKEY_NOTIFY, hci_user_passkey_notify_evt,
  7096		       sizeof(struct hci_ev_user_passkey_notify)),
  7097		/* [0x3c = HCI_EV_KEYPRESS_NOTIFY] */
  7098		HCI_EV(HCI_EV_KEYPRESS_NOTIFY, hci_keypress_notify_evt,
  7099		       sizeof(struct hci_ev_keypress_notify)),
  7100		/* [0x3d = HCI_EV_REMOTE_HOST_FEATURES] */
  7101		HCI_EV(HCI_EV_REMOTE_HOST_FEATURES, hci_remote_host_features_evt,
  7102		       sizeof(struct hci_ev_remote_host_features)),
  7103		/* [0x3e = HCI_EV_LE_META] */
  7104		HCI_EV_VL(HCI_EV_LE_META, hci_le_meta_evt,
  7105			  sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
  7106	#if IS_ENABLED(CONFIG_BT_HS)
  7107		/* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */
  7108		HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt,
  7109		       sizeof(struct hci_ev_phy_link_complete)),
  7110		/* [0x41 = HCI_EV_CHANNEL_SELECTED] */
  7111		HCI_EV(HCI_EV_CHANNEL_SELECTED, hci_chan_selected_evt,
  7112		       sizeof(struct hci_ev_channel_selected)),
  7113		/* [0x42 = HCI_EV_DISCONN_PHY_LINK_COMPLETE] */
  7114		HCI_EV(HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
  7115		       hci_disconn_loglink_complete_evt,
  7116		       sizeof(struct hci_ev_disconn_logical_link_complete)),
  7117		/* [0x45 = HCI_EV_LOGICAL_LINK_COMPLETE] */
  7118		HCI_EV(HCI_EV_LOGICAL_LINK_COMPLETE, hci_loglink_complete_evt,
  7119		       sizeof(struct hci_ev_logical_link_complete)),
  7120		/* [0x46 = HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE] */
  7121		HCI_EV(HCI_EV_DISCONN_PHY_LINK_COMPLETE,
  7122		       hci_disconn_phylink_complete_evt,
  7123		       sizeof(struct hci_ev_disconn_phy_link_complete)),
  7124	#endif
  7125		/* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */
  7126		HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt,
  7127		       sizeof(struct hci_ev_num_comp_blocks)),
  7128		/* [0xff = HCI_EV_VENDOR] */
> 7129		HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0),
  7130	};
  7131	
> 7132	void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
  7133			    u16 *opcode, u8 *status, hci_req_complete_t *req_complete,
  7134			    hci_req_complete_skb_t *req_complete_skb)
  7135	{
  7136		const struct hci_ev *ev = &hci_ev_table[event];
  7137		void *data;
  7138	
  7139		if (!ev->func)
  7140			return;
  7141	
  7142		if (skb->len < ev->min_len) {
  7143			bt_dev_err(hdev, "unexpected event 0x%2.2x length: %u < %u",
  7144				   event, skb->len, ev->min_len);
  7145			return;
  7146		}
  7147	
  7148		/* Just warn if the length is over max_len size it still be
  7149		 * possible to partially parse the event so leave to callback to
  7150		 * decide if that is acceptable.
  7151		 */
  7152		if (skb->len > ev->max_len)
  7153			bt_dev_warn(hdev, "unexpected event 0x%2.2x length: %u > %u",
  7154				    event, skb->len, ev->max_len);
  7155	
  7156		data = hci_ev_skb_pull(hdev, skb, event, ev->min_len);
  7157		if (!data)
  7158			return;
  7159	
  7160		if (ev->req)
  7161			ev->func_req(hdev, data, skb, opcode, status, req_complete,
  7162				     req_complete_skb);
  7163		else
  7164			ev->func(hdev, data, skb);
  7165	}
  7166	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 01/15] skbuff: introduce skb_pull_data
  2021-12-01  0:02 ` [PATCH 01/15] skbuff: introduce skb_pull_data Luiz Augusto von Dentz
  2021-12-01  1:11   ` Jakub Kicinski
@ 2021-12-01  5:20   ` Dan Carpenter
  1 sibling, 0 replies; 34+ messages in thread
From: Dan Carpenter @ 2021-12-01  5:20 UTC (permalink / raw)
  To: Luiz Augusto von Dentz
  Cc: davem, kuba, linux-bluetooth, netdev, Luiz Augusto von Dentz

Thanks for following up on this!  I had forgotten about it.  I'm really
happy this is going forward.

regards,
dan carpenter


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 01/15] skbuff: introduce skb_pull_data
  2021-12-01  2:27       ` Jakub Kicinski
@ 2021-12-01  7:22         ` Marcel Holtmann
  2021-12-01 15:22           ` Jakub Kicinski
  0 siblings, 1 reply; 34+ messages in thread
From: Marcel Holtmann @ 2021-12-01  7:22 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Luiz Augusto von Dentz, David S. Miller, linux-bluetooth,
	open list:NETWORKING [GENERAL],
	Dan Carpenter, Luiz Augusto von Dentz

Hi Jakub,

>>> It doesn't take a data pointer, so not really analogous to
>>> skb_put_data() and friends which come to mind. But I have
>>> no better naming suggestions. You will need to respin, tho,
>>> if you want us to apply these directly, the patches as posted
>>> don't apply to either netdev tree.  
>> 
>> I cross posted it to net-dev just in case you guys had some strong
>> opinions on introducing such a function,
> 
> Someone else still may, I don't :)
> 
>> it was in fact suggested by Dan but I also didn't find a better name
>> so I went with it, if you guys prefer we can merge it in
>> bluetooth-next first as usual.
> 
> Going via bluetooth-next sounds good!

if you are ok with this going via bluetooth-next, then I need some sort
of ACK from you or Dave.

Regards

Marcel


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 02/15] Bluetooth: HCI: Use skb_pull_data to parse BR/EDR events
  2021-12-01  0:02 ` [PATCH 02/15] Bluetooth: HCI: Use skb_pull_data to parse BR/EDR events Luiz Augusto von Dentz
@ 2021-12-01 15:06     ` kernel test robot
  0 siblings, 0 replies; 34+ messages in thread
From: kernel test robot @ 2021-12-01 15:06 UTC (permalink / raw)
  To: Luiz Augusto von Dentz, davem, kuba
  Cc: kbuild-all, linux-bluetooth, netdev, dan.carpenter,
	Luiz Augusto von Dentz

Hi Luiz,

I love your patch! Yet something to improve:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on net-next/master net/master linus/master bluetooth/master v5.16-rc3 next-20211201]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: nios2-randconfig-r004-20211201 (https://download.01.org/0day-ci/archive/20211201/202112012251.iGUVb22U-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/ccec11fda2c9e92440427cb397e3fdd8e46b2827
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
        git checkout ccec11fda2c9e92440427cb397e3fdd8e46b2827
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=nios2 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>, old ones prefixed by <<):

ERROR: modpost: "__mulsi3" [net/vmw_vsock/vsock.ko] undefined!
ERROR: modpost: "__mulsi3" [net/mac802154/mac802154.ko] undefined!
ERROR: modpost: "__mulsi3" [net/ieee802154/ieee802154.ko] undefined!
ERROR: modpost: "__mulsi3" [net/atm/lec.ko] undefined!
ERROR: modpost: "__mulsi3" [net/atm/atm.ko] undefined!
>> ERROR: modpost: "skb_pull_data" [net/bluetooth/bluetooth.ko] undefined!
ERROR: modpost: "__mulsi3" [net/bluetooth/bluetooth.ko] undefined!
ERROR: modpost: "__mulsi3" [net/lapb/lapb.ko] undefined!
ERROR: modpost: "__mulsi3" [sound/virtio/virtio_snd.ko] undefined!
ERROR: modpost: "__mulsi3" [sound/hda/snd-hda-core.ko] undefined!
WARNING: modpost: suppressed 804 unresolved symbol warnings because there were too many)

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 02/15] Bluetooth: HCI: Use skb_pull_data to parse BR/EDR events
@ 2021-12-01 15:06     ` kernel test robot
  0 siblings, 0 replies; 34+ messages in thread
From: kernel test robot @ 2021-12-01 15:06 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 2537 bytes --]

Hi Luiz,

I love your patch! Yet something to improve:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on net-next/master net/master linus/master bluetooth/master v5.16-rc3 next-20211201]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: nios2-randconfig-r004-20211201 (https://download.01.org/0day-ci/archive/20211201/202112012251.iGUVb22U-lkp(a)intel.com/config)
compiler: nios2-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/ccec11fda2c9e92440427cb397e3fdd8e46b2827
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Luiz-Augusto-von-Dentz/Rework-parsing-of-HCI-events/20211201-080632
        git checkout ccec11fda2c9e92440427cb397e3fdd8e46b2827
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=nios2 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>, old ones prefixed by <<):

ERROR: modpost: "__mulsi3" [net/vmw_vsock/vsock.ko] undefined!
ERROR: modpost: "__mulsi3" [net/mac802154/mac802154.ko] undefined!
ERROR: modpost: "__mulsi3" [net/ieee802154/ieee802154.ko] undefined!
ERROR: modpost: "__mulsi3" [net/atm/lec.ko] undefined!
ERROR: modpost: "__mulsi3" [net/atm/atm.ko] undefined!
>> ERROR: modpost: "skb_pull_data" [net/bluetooth/bluetooth.ko] undefined!
ERROR: modpost: "__mulsi3" [net/bluetooth/bluetooth.ko] undefined!
ERROR: modpost: "__mulsi3" [net/lapb/lapb.ko] undefined!
ERROR: modpost: "__mulsi3" [sound/virtio/virtio_snd.ko] undefined!
ERROR: modpost: "__mulsi3" [sound/hda/snd-hda-core.ko] undefined!
WARNING: modpost: suppressed 804 unresolved symbol warnings because there were too many)

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 01/15] skbuff: introduce skb_pull_data
  2021-12-01  7:22         ` Marcel Holtmann
@ 2021-12-01 15:22           ` Jakub Kicinski
  0 siblings, 0 replies; 34+ messages in thread
From: Jakub Kicinski @ 2021-12-01 15:22 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Luiz Augusto von Dentz, David S. Miller, linux-bluetooth,
	open list:NETWORKING [GENERAL],
	Dan Carpenter, Luiz Augusto von Dentz

On Wed, 1 Dec 2021 08:22:51 +0100 Marcel Holtmann wrote:
> >> I cross posted it to net-dev just in case you guys had some strong
> >> opinions on introducing such a function,  
> > 
> > Someone else still may, I don't :)
> >   
> >> it was in fact suggested by Dan but I also didn't find a better name
> >> so I went with it, if you guys prefer we can merge it in
> >> bluetooth-next first as usual.  
> > 
> > Going via bluetooth-next sounds good!  
> 
> if you are ok with this going via bluetooth-next, then I need some sort
> of ACK from you or Dave.

Acked-by: Jakub Kicinski <kuba@kernel.org>

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
  2021-12-01  0:02 ` [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events Luiz Augusto von Dentz
                     ` (2 preceding siblings ...)
  2021-12-01  3:22     ` kernel test robot
@ 2022-01-25 14:46   ` Mike Lothian
  2022-03-12  1:56     ` Mike Lothian
  3 siblings, 1 reply; 34+ messages in thread
From: Mike Lothian @ 2022-01-25 14:46 UTC (permalink / raw)
  To: luiz.dentz
  Cc: dan.carpenter, davem, kuba, linux-bluetooth, luiz.von.dentz, netdev

Hi

This patch is causing a lot of spam in my dmesg at boot until it seems my wifi connects (or perhaps the bluetooth manager does something)

Bluetooth: hci0: unexpected event 0xff length: 5 > 0

Thanks

Mike

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
  2022-01-25 14:46   ` Mike Lothian
@ 2022-03-12  1:56     ` Mike Lothian
  2022-03-12 14:45       ` Dan Carpenter
  0 siblings, 1 reply; 34+ messages in thread
From: Mike Lothian @ 2022-03-12  1:56 UTC (permalink / raw)
  To: luiz.dentz
  Cc: dan.carpenter, davem, kuba, linux-bluetooth, luiz.von.dentz, netdev

On Tue, 25 Jan 2022 at 14:46, Mike Lothian <mike@fireburn.co.uk> wrote:
>
> Hi
>
> This patch is causing a lot of spam in my dmesg at boot until it seems my wifi connects (or perhaps the bluetooth manager does something)
>
> Bluetooth: hci0: unexpected event 0xff length: 5 > 0
>
> Thanks
>
> Mike

Hi

Has there been any movement on this issue?

I'm currently running with this patch locally to make the dmesg spam go away

From f786c85baac0ee93730998fa52cbd588c9f39286 Mon Sep 17 00:00:00 2001
From: Mike Lothian <mike@fireburn.co.uk>
Date: Tue, 25 Jan 2022 14:52:00 +0000
Subject: [PATCH] Remove excessive bluetooth warning

---
net/bluetooth/hci_event.c | 8 --------
1 file changed, 8 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index fc30f4c03d29..aa57fccd2e47 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -6818,14 +6818,6 @@ static void hci_event_func(struct hci_dev
*hdev, u8 event, struct sk_buff *skb,
               return;
       }

-       /* Just warn if the length is over max_len size it still be
-        * possible to partially parse the event so leave to callback to
-        * decide if that is acceptable.
-        */
-       if (skb->len > ev->max_len)
-               bt_dev_warn(hdev, "unexpected event 0x%2.2x length: %u > %u",
-                           event, skb->len, ev->max_len);
-
       data = hci_ev_skb_pull(hdev, skb, event, ev->min_len);
       if (!data)
               return;
--
2.35.0

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
  2022-03-12  1:56     ` Mike Lothian
@ 2022-03-12 14:45       ` Dan Carpenter
  2022-03-14 13:14         ` Mike Lothian
  0 siblings, 1 reply; 34+ messages in thread
From: Dan Carpenter @ 2022-03-12 14:45 UTC (permalink / raw)
  To: Mike Lothian
  Cc: luiz.dentz, davem, kuba, linux-bluetooth, luiz.von.dentz, netdev

On Sat, Mar 12, 2022 at 01:56:13AM +0000, Mike Lothian wrote:
> On Tue, 25 Jan 2022 at 14:46, Mike Lothian <mike@fireburn.co.uk> wrote:
> >
> > Hi
> >
> > This patch is causing a lot of spam in my dmesg at boot until it seems my wifi connects (or perhaps the bluetooth manager does something)
> >
> > Bluetooth: hci0: unexpected event 0xff length: 5 > 0
> >
> > Thanks
> >
> > Mike
> 
> Hi
> 
> Has there been any movement on this issue?
> 
> I'm currently running with this patch locally to make the dmesg spam go away
> 
> >From f786c85baac0ee93730998fa52cbd588c9f39286 Mon Sep 17 00:00:00 2001
> From: Mike Lothian <mike@fireburn.co.uk>
> Date: Tue, 25 Jan 2022 14:52:00 +0000
> Subject: [PATCH] Remove excessive bluetooth warning
> 
> ---

It seems reasonable enought to remove a spammy error message.

Can you resend your patch in the proper format with a proper subject,
commit message and signed-off-by line?

regards,
dan carpenter


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events
  2022-03-12 14:45       ` Dan Carpenter
@ 2022-03-14 13:14         ` Mike Lothian
  0 siblings, 0 replies; 34+ messages in thread
From: Mike Lothian @ 2022-03-14 13:14 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: luiz.dentz, davem, kuba, linux-bluetooth, luiz.von.dentz, netdev

On Sat, 12 Mar 2022 at 14:45, Dan Carpenter <dan.carpenter@oracle.com> wrote:
>
> It seems reasonable enought to remove a spammy error message.
>
> Can you resend your patch in the proper format with a proper subject,
> commit message and signed-off-by line?
>
> regards,
> dan carpenter
>

I've done that, but I'm not sure if I need to do anything else

The patch was based against 5.17-rc7, but just let me know if I need
to rebase it to a different tree

Cheers

Mike

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2022-03-14 13:14 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-01  0:02 [PATCH 00/15] Rework parsing of HCI events Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 01/15] skbuff: introduce skb_pull_data Luiz Augusto von Dentz
2021-12-01  1:11   ` Jakub Kicinski
2021-12-01  2:16     ` Luiz Augusto von Dentz
2021-12-01  2:27       ` Jakub Kicinski
2021-12-01  7:22         ` Marcel Holtmann
2021-12-01 15:22           ` Jakub Kicinski
2021-12-01  5:20   ` Dan Carpenter
2021-12-01  0:02 ` [PATCH 02/15] Bluetooth: HCI: Use skb_pull_data to parse BR/EDR events Luiz Augusto von Dentz
2021-12-01 15:06   ` kernel test robot
2021-12-01 15:06     ` kernel test robot
2021-12-01  0:02 ` [PATCH 03/15] Bluetooth: HCI: Use skb_pull_data to parse Command Complete event Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 04/15] Bluetooth: HCI: Use skb_pull_data to parse Number of Complete Packets event Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 05/15] Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result event Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 06/15] Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result with RSSI event Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 07/15] Bluetooth: HCI: Use skb_pull_data to parse Extended Inquiry Result event Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 08/15] Bluetooth: HCI: Use skb_pull_data to parse LE Metaevents Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 09/15] Bluetooth: HCI: Use skb_pull_data to parse LE Advertising Report event Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 10/15] Bluetooth: HCI: Use skb_pull_data to parse LE Ext " Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 11/15] Bluetooth: HCI: Use skb_pull_data to parse LE Direct " Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events Luiz Augusto von Dentz
2021-12-01  1:54   ` kernel test robot
2021-12-01  1:54     ` kernel test robot
2021-12-01  3:22   ` kernel test robot
2021-12-01  3:22     ` kernel test robot
2021-12-01  3:22   ` kernel test robot
2021-12-01  3:22     ` kernel test robot
2022-01-25 14:46   ` Mike Lothian
2022-03-12  1:56     ` Mike Lothian
2022-03-12 14:45       ` Dan Carpenter
2022-03-14 13:14         ` Mike Lothian
2021-12-01  0:02 ` [PATCH 13/15] Bluetooth: hci_event: Use of a function table to handle LE subevents Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 14/15] Bluetooth: hci_event: Use of a function table to handle Command Complete Luiz Augusto von Dentz
2021-12-01  0:02 ` [PATCH 15/15] Bluetooth: hci_event: Use of a function table to handle Command Status Luiz Augusto von Dentz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.