All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] Bluetooth: Add helper for serialized HCI command execution
@ 2021-05-20 16:42 Luiz Augusto von Dentz
  2021-05-20 16:42 ` [PATCH 2/2] Bluetooth: hci_sync: Make use of hci_cmd_sync_queue Luiz Augusto von Dentz
  2021-05-20 17:49 ` [1/2] Bluetooth: Add helper for serialized HCI command execution bluez.test.bot
  0 siblings, 2 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2021-05-20 16:42 UTC (permalink / raw)
  To: linux-bluetooth

From: Marcel Holtmann <marcel@holtmann.org>

The usage of __hci_cmd_sync() within the hdev->setup() callback allows for
a nice and simple serialized execution of HCI commands. More importantly
it allows for result processing before issueing the next command.

With the current usage of hci_req_run() it is possible to batch up
commands and execute them, but it is impossible to react to their
results or errors.

This is an attempt to generalize the hdev->setup() handling and provide
a simple way of running multiple HCI commands from a single function
context.

There are multiple struct work that are decdicated to certain tasks
already used right now. It is add a lot of bloat to hci_dev struct and
extra handling code. So it might be possible to put all of these behind
a common HCI command infrastructure and just execute the HCI commands
from the same work context in a serialized fashion.

For example updating the white list and resolving list can be done now
without having to know the list size ahead of time. Also preparing for
suspend or resume shouldn't require a state machine anymore. There are
other tasks that should be simplified as well.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci_core.h | 14 +++++++
 net/bluetooth/hci_core.c         | 68 ++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 43b08bebae74..aecbdf99c216 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -302,6 +302,14 @@ struct amp_assoc {
 
 #define HCI_MAX_PAGES	3
 
+typedef void (*cmd_sync_work_func_t)(struct hci_dev *hdev, void *data);
+
+struct cmd_sync_work_entry {
+	struct list_head list;
+	cmd_sync_work_func_t func;
+	void *data;
+};
+
 struct hci_dev {
 	struct list_head list;
 	struct mutex	lock;
@@ -463,6 +471,9 @@ struct hci_dev {
 	struct work_struct	power_on;
 	struct delayed_work	power_off;
 	struct work_struct	error_reset;
+	struct work_struct	cmd_sync_work;
+	struct list_head	cmd_sync_work_list;
+	struct mutex		cmd_sync_work_lock;
 
 	__u16			discov_timeout;
 	struct delayed_work	discov_off;
@@ -1701,6 +1712,9 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
 struct sk_buff *hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
 			     const void *param, u32 timeout);
 
+int hci_cmd_sync_queue(struct hci_dev *hdev, cmd_sync_work_func_t func,
+		       void *data);
+
 u32 hci_conn_get_phy(struct hci_conn *conn);
 
 /* ----- HCI Sockets ----- */
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 7baf93eda936..5fb0079f64c1 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2329,6 +2329,67 @@ static void hci_error_reset(struct work_struct *work)
 	hci_dev_do_open(hdev);
 }
 
+static void hci_cmd_sync_work(struct work_struct *work)
+{
+	struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_sync_work);
+	struct cmd_sync_work_entry *entry;
+	cmd_sync_work_func_t func;
+	void *data;
+
+	bt_dev_dbg(hdev, "");
+
+	mutex_lock(&hdev->cmd_sync_work_lock);
+	entry = list_first_entry(&hdev->cmd_sync_work_list,
+				 struct cmd_sync_work_entry, list);
+	if (entry) {
+		list_del(&entry->list);
+		func = entry->func;
+		data = entry->data;
+		kfree(entry);
+	} else {
+		func = NULL;
+		data = NULL;
+	}
+	mutex_unlock(&hdev->cmd_sync_work_lock);
+
+	if (func) {
+		hci_req_sync_lock(hdev);
+		func(hdev, data);
+		hci_req_sync_unlock(hdev);
+	}
+}
+
+int hci_cmd_sync_queue(struct hci_dev *hdev, cmd_sync_work_func_t func,
+		       void *data)
+{
+	struct cmd_sync_work_entry *entry;
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	entry->func = func;
+	entry->data = data;
+
+	mutex_lock(&hdev->cmd_sync_work_lock);
+	list_add_tail(&entry->list, &hdev->cmd_sync_work_list);
+	mutex_unlock(&hdev->cmd_sync_work_lock);
+
+	queue_work(hdev->req_workqueue, &hdev->cmd_sync_work);
+
+	return 0;
+}
+
+static void hci_cmd_sync_clear(struct hci_dev *hdev)
+{
+	struct cmd_sync_work_entry *entry, *tmp;
+
+	list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+}
+
 void hci_uuids_clear(struct hci_dev *hdev)
 {
 	struct bt_uuid *uuid, *tmp;
@@ -3845,6 +3906,10 @@ struct hci_dev *hci_alloc_dev(void)
 	INIT_WORK(&hdev->error_reset, hci_error_reset);
 	INIT_WORK(&hdev->suspend_prepare, hci_prepare_suspend);
 
+	INIT_WORK(&hdev->cmd_sync_work, hci_cmd_sync_work);
+	INIT_LIST_HEAD(&hdev->cmd_sync_work_list);
+	mutex_init(&hdev->cmd_sync_work_lock);
+
 	INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
 
 	skb_queue_head_init(&hdev->rx_q);
@@ -4005,6 +4070,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
 
 	cancel_work_sync(&hdev->power_on);
 
+	cancel_work_sync(&hdev->cmd_sync_work);
+	hci_cmd_sync_clear(hdev);
+
 	if (!test_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks)) {
 		hci_suspend_clear_tasks(hdev);
 		unregister_pm_notifier(&hdev->suspend_notifier);
-- 
2.31.1


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

* [PATCH 2/2] Bluetooth: hci_sync: Make use of hci_cmd_sync_queue
  2021-05-20 16:42 [PATCH 1/2] Bluetooth: Add helper for serialized HCI command execution Luiz Augusto von Dentz
@ 2021-05-20 16:42 ` Luiz Augusto von Dentz
  2021-05-20 20:17   ` Marcel Holtmann
  2021-05-20 17:49 ` [1/2] Bluetooth: Add helper for serialized HCI command execution bluez.test.bot
  1 sibling, 1 reply; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2021-05-20 16:42 UTC (permalink / raw)
  To: linux-bluetooth

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

This make use of hci_cmd_sync_queue for the following MGMT commands:

Set Device Class
Set Device ID
Add UUID
Remove UUID

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 include/net/bluetooth/hci_core.h |   2 +
 net/bluetooth/Makefile           |   2 +-
 net/bluetooth/hci_request.c      |  18 +++
 net/bluetooth/hci_sync.c         | 241 +++++++++++++++++++++++++++++++
 net/bluetooth/hci_sync.h         |   9 ++
 net/bluetooth/mgmt.c             | 123 ++++++++--------
 6 files changed, 328 insertions(+), 67 deletions(-)
 create mode 100644 net/bluetooth/hci_sync.c
 create mode 100644 net/bluetooth/hci_sync.h

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index aecbdf99c216..2494c547a622 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1699,6 +1699,8 @@ struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
 			       const void *param, u32 timeout);
 struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
 				  const void *param, u8 event, u32 timeout);
+int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen,
+			  const void *param, u32 timeout);
 int __hci_cmd_send(struct hci_dev *hdev, u16 opcode, u32 plen,
 		   const void *param);
 
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index cc0995301f93..ab46b2b4f3cb 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -14,7 +14,7 @@ bluetooth_6lowpan-y := 6lowpan.o
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
 	hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o lib.o \
-	ecdh_helper.o hci_request.o mgmt_util.o mgmt_config.o
+	ecdh_helper.o hci_request.o hci_sync.o mgmt_util.o mgmt_config.o
 
 bluetooth-$(CONFIG_BT_BREDR) += sco.o
 bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index fa9125b782f8..f390ac33ced9 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -189,6 +189,24 @@ struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
 }
 EXPORT_SYMBOL(__hci_cmd_sync);
 
+int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen,
+			  const void *param, u32 timeout)
+{
+	struct sk_buff *skb;
+	uint8_t status;
+
+	skb = __hci_cmd_sync(hdev, opcode, plen, param, timeout);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+	status = skb->data[0];
+
+	kfree_skb(skb);
+
+	return status;
+}
+EXPORT_SYMBOL(__hci_cmd_sync_status);
+
 /* Execute request and wait for completion. */
 int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req,
 						     unsigned long opt),
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
new file mode 100644
index 000000000000..5b73fcf09c18
--- /dev/null
+++ b/net/bluetooth/hci_sync.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2021 Intel Corporation
+ */
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include "hci_request.h"
+#include "hci_sync.h"
+
+#define PNP_INFO_SVCLASS_ID		0x1200
+
+static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
+{
+	u8 *ptr = data, *uuids_start = NULL;
+	struct bt_uuid *uuid;
+
+	if (len < 4)
+		return ptr;
+
+	list_for_each_entry(uuid, &hdev->uuids, list) {
+		u16 uuid16;
+
+		if (uuid->size != 16)
+			continue;
+
+		uuid16 = get_unaligned_le16(&uuid->uuid[12]);
+		if (uuid16 < 0x1100)
+			continue;
+
+		if (uuid16 == PNP_INFO_SVCLASS_ID)
+			continue;
+
+		if (!uuids_start) {
+			uuids_start = ptr;
+			uuids_start[0] = 1;
+			uuids_start[1] = EIR_UUID16_ALL;
+			ptr += 2;
+		}
+
+		/* Stop if not enough space to put next UUID */
+		if ((ptr - data) + sizeof(u16) > len) {
+			uuids_start[1] = EIR_UUID16_SOME;
+			break;
+		}
+
+		*ptr++ = (uuid16 & 0x00ff);
+		*ptr++ = (uuid16 & 0xff00) >> 8;
+		uuids_start[0] += sizeof(uuid16);
+	}
+
+	return ptr;
+}
+
+static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
+{
+	u8 *ptr = data, *uuids_start = NULL;
+	struct bt_uuid *uuid;
+
+	if (len < 6)
+		return ptr;
+
+	list_for_each_entry(uuid, &hdev->uuids, list) {
+		if (uuid->size != 32)
+			continue;
+
+		if (!uuids_start) {
+			uuids_start = ptr;
+			uuids_start[0] = 1;
+			uuids_start[1] = EIR_UUID32_ALL;
+			ptr += 2;
+		}
+
+		/* Stop if not enough space to put next UUID */
+		if ((ptr - data) + sizeof(u32) > len) {
+			uuids_start[1] = EIR_UUID32_SOME;
+			break;
+		}
+
+		memcpy(ptr, &uuid->uuid[12], sizeof(u32));
+		ptr += sizeof(u32);
+		uuids_start[0] += sizeof(u32);
+	}
+
+	return ptr;
+}
+
+static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
+{
+	u8 *ptr = data, *uuids_start = NULL;
+	struct bt_uuid *uuid;
+
+	if (len < 18)
+		return ptr;
+
+	list_for_each_entry(uuid, &hdev->uuids, list) {
+		if (uuid->size != 128)
+			continue;
+
+		if (!uuids_start) {
+			uuids_start = ptr;
+			uuids_start[0] = 1;
+			uuids_start[1] = EIR_UUID128_ALL;
+			ptr += 2;
+		}
+
+		/* Stop if not enough space to put next UUID */
+		if ((ptr - data) + 16 > len) {
+			uuids_start[1] = EIR_UUID128_SOME;
+			break;
+		}
+
+		memcpy(ptr, uuid->uuid, 16);
+		ptr += 16;
+		uuids_start[0] += 16;
+	}
+
+	return ptr;
+}
+
+static void create_eir(struct hci_dev *hdev, u8 *data)
+{
+	u8 *ptr = data;
+	size_t name_len;
+
+	name_len = strlen(hdev->dev_name);
+
+	if (name_len > 0) {
+		/* EIR Data type */
+		if (name_len > 48) {
+			name_len = 48;
+			ptr[1] = EIR_NAME_SHORT;
+		} else
+			ptr[1] = EIR_NAME_COMPLETE;
+
+		/* EIR Data length */
+		ptr[0] = name_len + 1;
+
+		memcpy(ptr + 2, hdev->dev_name, name_len);
+
+		ptr += (name_len + 2);
+	}
+
+	if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
+		ptr[0] = 2;
+		ptr[1] = EIR_TX_POWER;
+		ptr[2] = (u8) hdev->inq_tx_power;
+
+		ptr += 3;
+	}
+
+	if (hdev->devid_source > 0) {
+		ptr[0] = 9;
+		ptr[1] = EIR_DEVICE_ID;
+
+		put_unaligned_le16(hdev->devid_source, ptr + 2);
+		put_unaligned_le16(hdev->devid_vendor, ptr + 4);
+		put_unaligned_le16(hdev->devid_product, ptr + 6);
+		put_unaligned_le16(hdev->devid_version, ptr + 8);
+
+		ptr += 10;
+	}
+
+	ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
+	ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
+	ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
+}
+
+int __hci_update_eir_sync(struct hci_dev *hdev)
+{
+	struct hci_cp_write_eir cp;
+
+	bt_dev_dbg(hdev, "");
+
+	if (!hdev_is_powered(hdev))
+		return 0;
+
+	if (!lmp_ext_inq_capable(hdev))
+		return 0;
+
+	if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
+		return 0;
+
+	if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
+		return 0;
+
+	memset(&cp, 0, sizeof(cp));
+
+	create_eir(hdev, cp.data);
+
+	if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
+		return 0;
+
+	memcpy(hdev->eir, cp.data, sizeof(cp.data));
+
+	return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp,
+				     HCI_CMD_TIMEOUT);
+}
+
+static u8 get_service_classes(struct hci_dev *hdev)
+{
+	struct bt_uuid *uuid;
+	u8 val = 0;
+
+	list_for_each_entry(uuid, &hdev->uuids, list)
+		val |= uuid->svc_hint;
+
+	return val;
+}
+
+int __hci_update_class_sync(struct hci_dev *hdev)
+{
+	u8 cod[3];
+
+	bt_dev_dbg(hdev, "");
+
+	if (!hdev_is_powered(hdev))
+		return 0;
+
+	if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
+		return 0;
+
+	if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
+		return 0;
+
+	cod[0] = hdev->minor_class;
+	cod[1] = hdev->major_class;
+	cod[2] = get_service_classes(hdev);
+
+	if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
+		cod[1] |= 0x20;
+
+	if (memcmp(cod, hdev->dev_class, 3) == 0)
+		return 0;
+
+	return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_CLASS_OF_DEV,
+				     sizeof(cod), cod, HCI_CMD_TIMEOUT);
+}
diff --git a/net/bluetooth/hci_sync.h b/net/bluetooth/hci_sync.h
new file mode 100644
index 000000000000..735ff4b46e86
--- /dev/null
+++ b/net/bluetooth/hci_sync.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2021 Intel Corporation
+ */
+
+int __hci_update_eir_sync(struct hci_dev *hdev);
+int __hci_update_class_sync(struct hci_dev *hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index b44e19c69c44..96759c166678 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -34,6 +34,7 @@
 #include <net/bluetooth/mgmt.h>
 
 #include "hci_request.h"
+#include "hci_sync.h"
 #include "smp.h"
 #include "mgmt_util.h"
 #include "mgmt_config.h"
@@ -950,25 +951,21 @@ bool mgmt_get_connectable(struct hci_dev *hdev)
 	return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
 }
 
+static void __service_cache_sync(struct hci_dev *hdev, void *data)
+{
+	__hci_update_eir_sync(hdev);
+	__hci_update_class_sync(hdev);
+}
+
 static void service_cache_off(struct work_struct *work)
 {
 	struct hci_dev *hdev = container_of(work, struct hci_dev,
 					    service_cache.work);
-	struct hci_request req;
 
 	if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
 		return;
 
-	hci_req_init(&req, hdev);
-
-	hci_dev_lock(hdev);
-
-	__hci_req_update_eir(&req);
-	__hci_req_update_class(&req);
-
-	hci_dev_unlock(hdev);
-
-	hci_req_run(&req, NULL);
+	hci_cmd_sync_queue(hdev, __service_cache_sync, NULL);
 }
 
 static void rpa_expired(struct work_struct *work)
@@ -2093,8 +2090,17 @@ static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
 	hci_dev_unlock(hdev);
 }
 
-static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
+static void __add_uuid_sync(struct hci_dev *hdev, void *data)
 {
+	uint8_t status;
+
+	status = __hci_update_class_sync(hdev);
+	if (status)
+		goto done;
+
+	status = __hci_update_eir_sync(hdev);
+
+done:
 	bt_dev_dbg(hdev, "status 0x%02x", status);
 
 	mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
@@ -2104,7 +2110,6 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 {
 	struct mgmt_cp_add_uuid *cp = data;
 	struct mgmt_pending_cmd *cmd;
-	struct hci_request req;
 	struct bt_uuid *uuid;
 	int err;
 
@@ -2130,20 +2135,9 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
 	list_add_tail(&uuid->list, &hdev->uuids);
 
-	hci_req_init(&req, hdev);
-
-	__hci_req_update_class(&req);
-	__hci_req_update_eir(&req);
-
-	err = hci_req_run(&req, add_uuid_complete);
-	if (err < 0) {
-		if (err != -ENODATA)
-			goto failed;
-
-		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
-					hdev->dev_class, 3);
+	err = hci_cmd_sync_queue(hdev, __add_uuid_sync, NULL);
+	if (err < 0)
 		goto failed;
-	}
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
 	if (!cmd) {
@@ -2172,8 +2166,17 @@ static bool enable_service_cache(struct hci_dev *hdev)
 	return false;
 }
 
-static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
+static void __remove_uuid_sync(struct hci_dev *hdev, void *data)
 {
+	uint8_t status;
+
+	status = __hci_update_class_sync(hdev);
+	if (status)
+		goto done;
+
+	status = __hci_update_eir_sync(hdev);
+
+done:
 	bt_dev_dbg(hdev, "status 0x%02x", status);
 
 	mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
@@ -2186,7 +2189,6 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 	struct mgmt_pending_cmd *cmd;
 	struct bt_uuid *match, *tmp;
 	u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-	struct hci_request req;
 	int err, found;
 
 	bt_dev_dbg(hdev, "sock %p", sk);
@@ -2230,20 +2232,9 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 	}
 
 update_class:
-	hci_req_init(&req, hdev);
-
-	__hci_req_update_class(&req);
-	__hci_req_update_eir(&req);
-
-	err = hci_req_run(&req, remove_uuid_complete);
-	if (err < 0) {
-		if (err != -ENODATA)
-			goto unlock;
-
-		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
-					hdev->dev_class, 3);
+	err = hci_cmd_sync_queue(hdev, __remove_uuid_sync, NULL);
+	if (err < 0)
 		goto unlock;
-	}
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
 	if (!cmd) {
@@ -2258,8 +2249,24 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 	return err;
 }
 
-static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
+static void __set_class_sync(struct hci_dev *hdev, void *data)
 {
+	uint8_t status = 0;
+
+	hci_dev_lock(hdev);
+
+	if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
+		hci_dev_unlock(hdev);
+		cancel_delayed_work_sync(&hdev->service_cache);
+		hci_dev_lock(hdev);
+		status = __hci_update_eir_sync(hdev);
+	}
+
+	hci_dev_unlock(hdev);
+
+	if (!status)
+		status = __hci_update_class_sync(hdev);
+
 	bt_dev_dbg(hdev, "status 0x%02x", status);
 
 	mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
@@ -2270,7 +2277,6 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 {
 	struct mgmt_cp_set_dev_class *cp = data;
 	struct mgmt_pending_cmd *cmd;
-	struct hci_request req;
 	int err;
 
 	bt_dev_dbg(hdev, "sock %p", sk);
@@ -2302,26 +2308,9 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 		goto unlock;
 	}
 
-	hci_req_init(&req, hdev);
-
-	if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
-		hci_dev_unlock(hdev);
-		cancel_delayed_work_sync(&hdev->service_cache);
-		hci_dev_lock(hdev);
-		__hci_req_update_eir(&req);
-	}
-
-	__hci_req_update_class(&req);
-
-	err = hci_req_run(&req, set_class_complete);
-	if (err < 0) {
-		if (err != -ENODATA)
-			goto unlock;
-
-		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
-					hdev->dev_class, 3);
+	err = hci_cmd_sync_queue(hdev, __set_class_sync, NULL);
+	if (err < 0)
 		goto unlock;
-	}
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
 	if (!cmd) {
@@ -5263,11 +5252,15 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
 	return err;
 }
 
+static void __set_device_id_sync(struct hci_dev *hdev, void *data)
+{
+	__hci_update_eir_sync(hdev);
+}
+
 static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
 			 u16 len)
 {
 	struct mgmt_cp_set_device_id *cp = data;
-	struct hci_request req;
 	int err;
 	__u16 source;
 
@@ -5289,9 +5282,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
 	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
 				NULL, 0);
 
-	hci_req_init(&req, hdev);
-	__hci_req_update_eir(&req);
-	hci_req_run(&req, NULL);
+	hci_cmd_sync_queue(hdev, __set_device_id_sync, NULL);
 
 	hci_dev_unlock(hdev);
 
-- 
2.31.1


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

* RE: [1/2] Bluetooth: Add helper for serialized HCI command execution
  2021-05-20 16:42 [PATCH 1/2] Bluetooth: Add helper for serialized HCI command execution Luiz Augusto von Dentz
  2021-05-20 16:42 ` [PATCH 2/2] Bluetooth: hci_sync: Make use of hci_cmd_sync_queue Luiz Augusto von Dentz
@ 2021-05-20 17:49 ` bluez.test.bot
  1 sibling, 0 replies; 5+ messages in thread
From: bluez.test.bot @ 2021-05-20 17:49 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz

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

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=485957

---Test result---

Test Summary:
CheckPatch                    FAIL      2.33 seconds
GitLint                       PASS      0.21 seconds
BuildKernel                   PASS      554.04 seconds
TestRunner: Setup             PASS      377.70 seconds
TestRunner: l2cap-tester      PASS      2.85 seconds
TestRunner: bnep-tester       PASS      2.02 seconds
TestRunner: mgmt-tester       PASS      28.06 seconds
TestRunner: rfcomm-tester     PASS      2.16 seconds
TestRunner: sco-tester        PASS      2.08 seconds
TestRunner: smp-tester        PASS      2.27 seconds
TestRunner: userchan-tester   PASS      1.98 seconds

Details
##############################
Test: CheckPatch - FAIL - 2.33 seconds
Run checkpatch.pl script with rule in .checkpatch.conf
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue
CHECK: Prefer kernel type 'u8' over 'uint8_t'
#53: FILE: net/bluetooth/hci_request.c:196:
+	uint8_t status;

WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#71: 
new file mode 100644

CHECK: braces {} should be used on all arms of this statement
#208: FILE: net/bluetooth/hci_sync.c:133:
+		if (name_len > 48) {
[...]
+		} else
[...]

CHECK: Unbalanced braces around else statement
#211: FILE: net/bluetooth/hci_sync.c:136:
+		} else

CHECK: No space is necessary after a cast
#225: FILE: net/bluetooth/hci_sync.c:150:
+		ptr[2] = (u8) hdev->inq_tx_power;

CHECK: Prefer kernel type 'u8' over 'uint8_t'
#384: FILE: net/bluetooth/mgmt.c:2095:
+	uint8_t status;

CHECK: Prefer kernel type 'u8' over 'uint8_t'
#434: FILE: net/bluetooth/mgmt.c:2171:
+	uint8_t status;

CHECK: Prefer kernel type 'u8' over 'uint8_t'
#484: FILE: net/bluetooth/mgmt.c:2254:
+	uint8_t status = 0;

total: 0 errors, 1 warnings, 7 checks, 509 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

"[PATCH] Bluetooth: hci_sync: Make use of hci_cmd_sync_queue" has style problems, please review.

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: GitLint - PASS - 0.21 seconds
Run gitlint with rule in .gitlint


##############################
Test: BuildKernel - PASS - 554.04 seconds
Build Kernel with minimal configuration supports Bluetooth


##############################
Test: TestRunner: Setup - PASS - 377.70 seconds
Setup environment for running Test Runner


##############################
Test: TestRunner: l2cap-tester - PASS - 2.85 seconds
Run test-runner with l2cap-tester
Total: 40, Passed: 40 (100.0%), Failed: 0, Not Run: 0

##############################
Test: TestRunner: bnep-tester - PASS - 2.02 seconds
Run test-runner with bnep-tester
Total: 1, Passed: 1 (100.0%), Failed: 0, Not Run: 0

##############################
Test: TestRunner: mgmt-tester - PASS - 28.06 seconds
Run test-runner with mgmt-tester
Total: 416, Passed: 403 (96.9%), Failed: 0, Not Run: 13

##############################
Test: TestRunner: rfcomm-tester - PASS - 2.16 seconds
Run test-runner with rfcomm-tester
Total: 9, Passed: 9 (100.0%), Failed: 0, Not Run: 0

##############################
Test: TestRunner: sco-tester - PASS - 2.08 seconds
Run test-runner with sco-tester
Total: 8, Passed: 8 (100.0%), Failed: 0, Not Run: 0

##############################
Test: TestRunner: smp-tester - PASS - 2.27 seconds
Run test-runner with smp-tester
Total: 8, Passed: 8 (100.0%), Failed: 0, Not Run: 0

##############################
Test: TestRunner: userchan-tester - PASS - 1.98 seconds
Run test-runner with userchan-tester
Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0



---
Regards,
Linux Bluetooth


[-- Attachment #2: l2cap-tester.log --]
[-- Type: application/octet-stream, Size: 44350 bytes --]

[-- Attachment #3: bnep-tester.log --]
[-- Type: application/octet-stream, Size: 3557 bytes --]

[-- Attachment #4: mgmt-tester.log --]
[-- Type: application/octet-stream, Size: 546637 bytes --]

[-- Attachment #5: rfcomm-tester.log --]
[-- Type: application/octet-stream, Size: 11677 bytes --]

[-- Attachment #6: sco-tester.log --]
[-- Type: application/octet-stream, Size: 9912 bytes --]

[-- Attachment #7: smp-tester.log --]
[-- Type: application/octet-stream, Size: 11821 bytes --]

[-- Attachment #8: userchan-tester.log --]
[-- Type: application/octet-stream, Size: 5454 bytes --]

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

* Re: [PATCH 2/2] Bluetooth: hci_sync: Make use of hci_cmd_sync_queue
  2021-05-20 16:42 ` [PATCH 2/2] Bluetooth: hci_sync: Make use of hci_cmd_sync_queue Luiz Augusto von Dentz
@ 2021-05-20 20:17   ` Marcel Holtmann
  2021-05-20 23:57     ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 5+ messages in thread
From: Marcel Holtmann @ 2021-05-20 20:17 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

> This make use of hci_cmd_sync_queue for the following MGMT commands:
> 
> Set Device Class
> Set Device ID
> Add UUID
> Remove UUID
> 
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> ---
> include/net/bluetooth/hci_core.h |   2 +
> net/bluetooth/Makefile           |   2 +-
> net/bluetooth/hci_request.c      |  18 +++
> net/bluetooth/hci_sync.c         | 241 +++++++++++++++++++++++++++++++
> net/bluetooth/hci_sync.h         |   9 ++
> net/bluetooth/mgmt.c             | 123 ++++++++--------
> 6 files changed, 328 insertions(+), 67 deletions(-)
> create mode 100644 net/bluetooth/hci_sync.c
> create mode 100644 net/bluetooth/hci_sync.h

I was thinking to put things into hci_bredr.c and hci_le.c.

> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index aecbdf99c216..2494c547a622 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -1699,6 +1699,8 @@ struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
> 			       const void *param, u32 timeout);
> struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
> 				  const void *param, u8 event, u32 timeout);
> +int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen,
> +			  const void *param, u32 timeout);
> int __hci_cmd_send(struct hci_dev *hdev, u16 opcode, u32 plen,
> 		   const void *param);
> 
> diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
> index cc0995301f93..ab46b2b4f3cb 100644
> --- a/net/bluetooth/Makefile
> +++ b/net/bluetooth/Makefile
> @@ -14,7 +14,7 @@ bluetooth_6lowpan-y := 6lowpan.o
> 
> bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
> 	hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o lib.o \
> -	ecdh_helper.o hci_request.o mgmt_util.o mgmt_config.o
> +	ecdh_helper.o hci_request.o hci_sync.o mgmt_util.o mgmt_config.o
> 
> bluetooth-$(CONFIG_BT_BREDR) += sco.o
> bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
> diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
> index fa9125b782f8..f390ac33ced9 100644
> --- a/net/bluetooth/hci_request.c
> +++ b/net/bluetooth/hci_request.c
> @@ -189,6 +189,24 @@ struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
> }
> EXPORT_SYMBOL(__hci_cmd_sync);
> 
> +int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen,
> +			  const void *param, u32 timeout)
> +{
> +	struct sk_buff *skb;
> +	uint8_t status;

Use u8 here since that is not user space. And drop the timeout parameter. We always use the same anyway.

> +
> +	skb = __hci_cmd_sync(hdev, opcode, plen, param, timeout);
> +	if (IS_ERR(skb))
> +		return PTR_ERR(skb);
> +
> +	status = skb->data[0];
> +
> +	kfree_skb(skb);
> +
> +	return status;
> +}
> +EXPORT_SYMBOL(__hci_cmd_sync_status);

Either we use u8 as return value or we convert it to the matching errno value.

> +
> /* Execute request and wait for completion. */
> int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req,
> 						     unsigned long opt),
> diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> new file mode 100644
> index 000000000000..5b73fcf09c18
> --- /dev/null
> +++ b/net/bluetooth/hci_sync.c
> @@ -0,0 +1,241 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * BlueZ - Bluetooth protocol stack for Linux
> + *
> + * Copyright (C) 2021 Intel Corporation
> + */
> +
> +#include <net/bluetooth/bluetooth.h>
> +#include <net/bluetooth/hci_core.h>
> +
> +#include "hci_request.h"
> +#include "hci_sync.h"
> +
> +#define PNP_INFO_SVCLASS_ID		0x1200
> +
> +static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
> +{
> +	u8 *ptr = data, *uuids_start = NULL;
> +	struct bt_uuid *uuid;
> +
> +	if (len < 4)
> +		return ptr;
> +
> +	list_for_each_entry(uuid, &hdev->uuids, list) {
> +		u16 uuid16;
> +
> +		if (uuid->size != 16)
> +			continue;
> +
> +		uuid16 = get_unaligned_le16(&uuid->uuid[12]);
> +		if (uuid16 < 0x1100)
> +			continue;
> +
> +		if (uuid16 == PNP_INFO_SVCLASS_ID)
> +			continue;
> +
> +		if (!uuids_start) {
> +			uuids_start = ptr;
> +			uuids_start[0] = 1;
> +			uuids_start[1] = EIR_UUID16_ALL;
> +			ptr += 2;
> +		}
> +
> +		/* Stop if not enough space to put next UUID */
> +		if ((ptr - data) + sizeof(u16) > len) {
> +			uuids_start[1] = EIR_UUID16_SOME;
> +			break;
> +		}
> +
> +		*ptr++ = (uuid16 & 0x00ff);
> +		*ptr++ = (uuid16 & 0xff00) >> 8;
> +		uuids_start[0] += sizeof(uuid16);
> +	}
> +
> +	return ptr;
> +}
> +
> +static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
> +{
> +	u8 *ptr = data, *uuids_start = NULL;
> +	struct bt_uuid *uuid;
> +
> +	if (len < 6)
> +		return ptr;
> +
> +	list_for_each_entry(uuid, &hdev->uuids, list) {
> +		if (uuid->size != 32)
> +			continue;
> +
> +		if (!uuids_start) {
> +			uuids_start = ptr;
> +			uuids_start[0] = 1;
> +			uuids_start[1] = EIR_UUID32_ALL;
> +			ptr += 2;
> +		}
> +
> +		/* Stop if not enough space to put next UUID */
> +		if ((ptr - data) + sizeof(u32) > len) {
> +			uuids_start[1] = EIR_UUID32_SOME;
> +			break;
> +		}
> +
> +		memcpy(ptr, &uuid->uuid[12], sizeof(u32));
> +		ptr += sizeof(u32);
> +		uuids_start[0] += sizeof(u32);
> +	}
> +
> +	return ptr;
> +}
> +
> +static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
> +{
> +	u8 *ptr = data, *uuids_start = NULL;
> +	struct bt_uuid *uuid;
> +
> +	if (len < 18)
> +		return ptr;
> +
> +	list_for_each_entry(uuid, &hdev->uuids, list) {
> +		if (uuid->size != 128)
> +			continue;
> +
> +		if (!uuids_start) {
> +			uuids_start = ptr;
> +			uuids_start[0] = 1;
> +			uuids_start[1] = EIR_UUID128_ALL;
> +			ptr += 2;
> +		}
> +
> +		/* Stop if not enough space to put next UUID */
> +		if ((ptr - data) + 16 > len) {
> +			uuids_start[1] = EIR_UUID128_SOME;
> +			break;
> +		}
> +
> +		memcpy(ptr, uuid->uuid, 16);
> +		ptr += 16;
> +		uuids_start[0] += 16;
> +	}
> +
> +	return ptr;
> +}
> +
> +static void create_eir(struct hci_dev *hdev, u8 *data)
> +{
> +	u8 *ptr = data;
> +	size_t name_len;
> +
> +	name_len = strlen(hdev->dev_name);
> +
> +	if (name_len > 0) {
> +		/* EIR Data type */
> +		if (name_len > 48) {
> +			name_len = 48;
> +			ptr[1] = EIR_NAME_SHORT;
> +		} else
> +			ptr[1] = EIR_NAME_COMPLETE;
> +
> +		/* EIR Data length */
> +		ptr[0] = name_len + 1;
> +
> +		memcpy(ptr + 2, hdev->dev_name, name_len);
> +
> +		ptr += (name_len + 2);
> +	}
> +
> +	if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
> +		ptr[0] = 2;
> +		ptr[1] = EIR_TX_POWER;
> +		ptr[2] = (u8) hdev->inq_tx_power;
> +
> +		ptr += 3;
> +	}
> +
> +	if (hdev->devid_source > 0) {
> +		ptr[0] = 9;
> +		ptr[1] = EIR_DEVICE_ID;
> +
> +		put_unaligned_le16(hdev->devid_source, ptr + 2);
> +		put_unaligned_le16(hdev->devid_vendor, ptr + 4);
> +		put_unaligned_le16(hdev->devid_product, ptr + 6);
> +		put_unaligned_le16(hdev->devid_version, ptr + 8);
> +
> +		ptr += 10;
> +	}
> +
> +	ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
> +	ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
> +	ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
> +}
> +
> +int __hci_update_eir_sync(struct hci_dev *hdev)
> +{
> +	struct hci_cp_write_eir cp;
> +
> +	bt_dev_dbg(hdev, "");
> +
> +	if (!hdev_is_powered(hdev))
> +		return 0;
> +
> +	if (!lmp_ext_inq_capable(hdev))
> +		return 0;
> +
> +	if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
> +		return 0;
> +
> +	if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
> +		return 0;
> +
> +	memset(&cp, 0, sizeof(cp));
> +
> +	create_eir(hdev, cp.data);
> +
> +	if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
> +		return 0;
> +
> +	memcpy(hdev->eir, cp.data, sizeof(cp.data));
> +
> +	return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp,
> +				     HCI_CMD_TIMEOUT);
> +}
> +
> +static u8 get_service_classes(struct hci_dev *hdev)
> +{
> +	struct bt_uuid *uuid;
> +	u8 val = 0;
> +
> +	list_for_each_entry(uuid, &hdev->uuids, list)
> +		val |= uuid->svc_hint;
> +
> +	return val;
> +}
> +
> +int __hci_update_class_sync(struct hci_dev *hdev)
> +{
> +	u8 cod[3];
> +
> +	bt_dev_dbg(hdev, "");
> +
> +	if (!hdev_is_powered(hdev))
> +		return 0;
> +
> +	if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
> +		return 0;
> +
> +	if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
> +		return 0;
> +
> +	cod[0] = hdev->minor_class;
> +	cod[1] = hdev->major_class;
> +	cod[2] = get_service_classes(hdev);
> +
> +	if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
> +		cod[1] |= 0x20;
> +
> +	if (memcmp(cod, hdev->dev_class, 3) == 0)
> +		return 0;
> +
> +	return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_CLASS_OF_DEV,
> +				     sizeof(cod), cod, HCI_CMD_TIMEOUT);
> +}
> diff --git a/net/bluetooth/hci_sync.h b/net/bluetooth/hci_sync.h
> new file mode 100644
> index 000000000000..735ff4b46e86
> --- /dev/null
> +++ b/net/bluetooth/hci_sync.h
> @@ -0,0 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * BlueZ - Bluetooth protocol stack for Linux
> + *
> + * Copyright (C) 2021 Intel Corporation
> + */
> +
> +int __hci_update_eir_sync(struct hci_dev *hdev);
> +int __hci_update_class_sync(struct hci_dev *hdev);
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index b44e19c69c44..96759c166678 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -34,6 +34,7 @@
> #include <net/bluetooth/mgmt.h>
> 
> #include "hci_request.h"
> +#include "hci_sync.h"
> #include "smp.h"
> #include "mgmt_util.h"
> #include "mgmt_config.h"
> @@ -950,25 +951,21 @@ bool mgmt_get_connectable(struct hci_dev *hdev)
> 	return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
> }
> 
> +static void __service_cache_sync(struct hci_dev *hdev, void *data)
> +{
> +	__hci_update_eir_sync(hdev);
> +	__hci_update_class_sync(hdev);
> +}
> +
> static void service_cache_off(struct work_struct *work)
> {
> 	struct hci_dev *hdev = container_of(work, struct hci_dev,
> 					    service_cache.work);
> -	struct hci_request req;
> 
> 	if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
> 		return;
> 
> -	hci_req_init(&req, hdev);
> -
> -	hci_dev_lock(hdev);
> -
> -	__hci_req_update_eir(&req);
> -	__hci_req_update_class(&req);
> -
> -	hci_dev_unlock(hdev);
> -
> -	hci_req_run(&req, NULL);
> +	hci_cmd_sync_queue(hdev, __service_cache_sync, NULL);
> }
> 
> static void rpa_expired(struct work_struct *work)
> @@ -2093,8 +2090,17 @@ static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
> 	hci_dev_unlock(hdev);
> }
> 
> -static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
> +static void __add_uuid_sync(struct hci_dev *hdev, void *data)
> {
> +	uint8_t status;
> +
> +	status = __hci_update_class_sync(hdev);
> +	if (status)
> +		goto done;
> +
> +	status = __hci_update_eir_sync(hdev);
> +
> +done:
> 	bt_dev_dbg(hdev, "status 0x%02x", status);
> 
> 	mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
> @@ -2104,7 +2110,6 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
> {
> 	struct mgmt_cp_add_uuid *cp = data;
> 	struct mgmt_pending_cmd *cmd;
> -	struct hci_request req;
> 	struct bt_uuid *uuid;
> 	int err;
> 
> @@ -2130,20 +2135,9 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
> 
> 	list_add_tail(&uuid->list, &hdev->uuids);
> 
> -	hci_req_init(&req, hdev);
> -
> -	__hci_req_update_class(&req);
> -	__hci_req_update_eir(&req);
> -
> -	err = hci_req_run(&req, add_uuid_complete);
> -	if (err < 0) {
> -		if (err != -ENODATA)
> -			goto failed;
> -
> -		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
> -					hdev->dev_class, 3);
> +	err = hci_cmd_sync_queue(hdev, __add_uuid_sync, NULL);
> +	if (err < 0)
> 		goto failed;
> -	}
> 
> 	cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
> 	if (!cmd) {
> @@ -2172,8 +2166,17 @@ static bool enable_service_cache(struct hci_dev *hdev)
> 	return false;
> }
> 
> -static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
> +static void __remove_uuid_sync(struct hci_dev *hdev, void *data)
> {
> +	uint8_t status;
> +
> +	status = __hci_update_class_sync(hdev);
> +	if (status)
> +		goto done;
> +
> +	status = __hci_update_eir_sync(hdev);
> +
> +done:
> 	bt_dev_dbg(hdev, "status 0x%02x", status);
> 
> 	mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
> @@ -2186,7 +2189,6 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
> 	struct mgmt_pending_cmd *cmd;
> 	struct bt_uuid *match, *tmp;
> 	u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
> -	struct hci_request req;
> 	int err, found;
> 
> 	bt_dev_dbg(hdev, "sock %p", sk);
> @@ -2230,20 +2232,9 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
> 	}
> 
> update_class:
> -	hci_req_init(&req, hdev);
> -
> -	__hci_req_update_class(&req);
> -	__hci_req_update_eir(&req);
> -
> -	err = hci_req_run(&req, remove_uuid_complete);
> -	if (err < 0) {
> -		if (err != -ENODATA)
> -			goto unlock;
> -
> -		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
> -					hdev->dev_class, 3);
> +	err = hci_cmd_sync_queue(hdev, __remove_uuid_sync, NULL);
> +	if (err < 0)
> 		goto unlock;
> -	}
> 
> 	cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
> 	if (!cmd) {
> @@ -2258,8 +2249,24 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
> 	return err;
> }
> 
> -static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
> +static void __set_class_sync(struct hci_dev *hdev, void *data)
> {
> +	uint8_t status = 0;
> +
> +	hci_dev_lock(hdev);
> +
> +	if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
> +		hci_dev_unlock(hdev);
> +		cancel_delayed_work_sync(&hdev->service_cache);
> +		hci_dev_lock(hdev);
> +		status = __hci_update_eir_sync(hdev);
> +	}
> +
> +	hci_dev_unlock(hdev);
> +
> +	if (!status)
> +		status = __hci_update_class_sync(hdev);
> +
> 	bt_dev_dbg(hdev, "status 0x%02x", status);
> 
> 	mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
> @@ -2270,7 +2277,6 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
> {
> 	struct mgmt_cp_set_dev_class *cp = data;
> 	struct mgmt_pending_cmd *cmd;
> -	struct hci_request req;
> 	int err;
> 
> 	bt_dev_dbg(hdev, "sock %p", sk);
> @@ -2302,26 +2308,9 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
> 		goto unlock;
> 	}
> 
> -	hci_req_init(&req, hdev);
> -
> -	if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
> -		hci_dev_unlock(hdev);
> -		cancel_delayed_work_sync(&hdev->service_cache);
> -		hci_dev_lock(hdev);
> -		__hci_req_update_eir(&req);
> -	}
> -
> -	__hci_req_update_class(&req);
> -
> -	err = hci_req_run(&req, set_class_complete);
> -	if (err < 0) {
> -		if (err != -ENODATA)
> -			goto unlock;
> -
> -		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
> -					hdev->dev_class, 3);
> +	err = hci_cmd_sync_queue(hdev, __set_class_sync, NULL);
> +	if (err < 0)
> 		goto unlock;
> -	}
> 
> 	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
> 	if (!cmd) {
> @@ -5263,11 +5252,15 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
> 	return err;
> }
> 
> +static void __set_device_id_sync(struct hci_dev *hdev, void *data)
> +{
> +	__hci_update_eir_sync(hdev);
> +}
> +
> static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
> 			 u16 len)
> {
> 	struct mgmt_cp_set_device_id *cp = data;
> -	struct hci_request req;
> 	int err;
> 	__u16 source;
> 
> @@ -5289,9 +5282,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
> 	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
> 				NULL, 0);
> 
> -	hci_req_init(&req, hdev);
> -	__hci_req_update_eir(&req);
> -	hci_req_run(&req, NULL);
> +	hci_cmd_sync_queue(hdev, __set_device_id_sync, NULL);
> 
> 	hci_dev_unlock(hdev);

I dislike the prefix __sync. They are in a separate anyway. So keep is simple and also scrap the __ prefix.

Regards

Marcel


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

* Re: [PATCH 2/2] Bluetooth: hci_sync: Make use of hci_cmd_sync_queue
  2021-05-20 20:17   ` Marcel Holtmann
@ 2021-05-20 23:57     ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2021-05-20 23:57 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth

Hi Marcel,

On Thu, May 20, 2021 at 1:17 PM Marcel Holtmann <marcel@holtmann.org> wrote:
>
> Hi Luiz,
>
> > This make use of hci_cmd_sync_queue for the following MGMT commands:
> >
> > Set Device Class
> > Set Device ID
> > Add UUID
> > Remove UUID
> >
> > Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> > ---
> > include/net/bluetooth/hci_core.h |   2 +
> > net/bluetooth/Makefile           |   2 +-
> > net/bluetooth/hci_request.c      |  18 +++
> > net/bluetooth/hci_sync.c         | 241 +++++++++++++++++++++++++++++++
> > net/bluetooth/hci_sync.h         |   9 ++
> > net/bluetooth/mgmt.c             | 123 ++++++++--------
> > 6 files changed, 328 insertions(+), 67 deletions(-)
> > create mode 100644 net/bluetooth/hci_sync.c
> > create mode 100644 net/bluetooth/hci_sync.h
>
> I was thinking to put things into hci_bredr.c and hci_le.c.

Initially I thought about that but I was afraid of things that could
affect states in both bearers so I went with what I considered to be
simpler.

> >
> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > index aecbdf99c216..2494c547a622 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -1699,6 +1699,8 @@ struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
> >                              const void *param, u32 timeout);
> > struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
> >                                 const void *param, u8 event, u32 timeout);
> > +int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen,
> > +                       const void *param, u32 timeout);
> > int __hci_cmd_send(struct hci_dev *hdev, u16 opcode, u32 plen,
> >                  const void *param);
> >
> > diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
> > index cc0995301f93..ab46b2b4f3cb 100644
> > --- a/net/bluetooth/Makefile
> > +++ b/net/bluetooth/Makefile
> > @@ -14,7 +14,7 @@ bluetooth_6lowpan-y := 6lowpan.o
> >
> > bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
> >       hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o lib.o \
> > -     ecdh_helper.o hci_request.o mgmt_util.o mgmt_config.o
> > +     ecdh_helper.o hci_request.o hci_sync.o mgmt_util.o mgmt_config.o
> >
> > bluetooth-$(CONFIG_BT_BREDR) += sco.o
> > bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
> > diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
> > index fa9125b782f8..f390ac33ced9 100644
> > --- a/net/bluetooth/hci_request.c
> > +++ b/net/bluetooth/hci_request.c
> > @@ -189,6 +189,24 @@ struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
> > }
> > EXPORT_SYMBOL(__hci_cmd_sync);
> >
> > +int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen,
> > +                       const void *param, u32 timeout)
> > +{
> > +     struct sk_buff *skb;
> > +     uint8_t status;
>
> Use u8 here since that is not user space. And drop the timeout parameter. We always use the same anyway.

Yep, I fixed that already.

> > +
> > +     skb = __hci_cmd_sync(hdev, opcode, plen, param, timeout);
> > +     if (IS_ERR(skb))
> > +             return PTR_ERR(skb);
> > +
> > +     status = skb->data[0];
> > +
> > +     kfree_skb(skb);
> > +
> > +     return status;
> > +}
> > +EXPORT_SYMBOL(__hci_cmd_sync_status);
>
> Either we use u8 as return value or we convert it to the matching errno value.

Ok, I was thinking of converting but it looks like the mgmt can
actually report the status, that said we may need to convert the
PTR_ERR then.

> > +
> > /* Execute request and wait for completion. */
> > int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req,
> >                                                    unsigned long opt),
> > diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> > new file mode 100644
> > index 000000000000..5b73fcf09c18
> > --- /dev/null
> > +++ b/net/bluetooth/hci_sync.c
> > @@ -0,0 +1,241 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * BlueZ - Bluetooth protocol stack for Linux
> > + *
> > + * Copyright (C) 2021 Intel Corporation
> > + */
> > +
> > +#include <net/bluetooth/bluetooth.h>
> > +#include <net/bluetooth/hci_core.h>
> > +
> > +#include "hci_request.h"
> > +#include "hci_sync.h"
> > +
> > +#define PNP_INFO_SVCLASS_ID          0x1200
> > +
> > +static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
> > +{
> > +     u8 *ptr = data, *uuids_start = NULL;
> > +     struct bt_uuid *uuid;
> > +
> > +     if (len < 4)
> > +             return ptr;
> > +
> > +     list_for_each_entry(uuid, &hdev->uuids, list) {
> > +             u16 uuid16;
> > +
> > +             if (uuid->size != 16)
> > +                     continue;
> > +
> > +             uuid16 = get_unaligned_le16(&uuid->uuid[12]);
> > +             if (uuid16 < 0x1100)
> > +                     continue;
> > +
> > +             if (uuid16 == PNP_INFO_SVCLASS_ID)
> > +                     continue;
> > +
> > +             if (!uuids_start) {
> > +                     uuids_start = ptr;
> > +                     uuids_start[0] = 1;
> > +                     uuids_start[1] = EIR_UUID16_ALL;
> > +                     ptr += 2;
> > +             }
> > +
> > +             /* Stop if not enough space to put next UUID */
> > +             if ((ptr - data) + sizeof(u16) > len) {
> > +                     uuids_start[1] = EIR_UUID16_SOME;
> > +                     break;
> > +             }
> > +
> > +             *ptr++ = (uuid16 & 0x00ff);
> > +             *ptr++ = (uuid16 & 0xff00) >> 8;
> > +             uuids_start[0] += sizeof(uuid16);
> > +     }
> > +
> > +     return ptr;
> > +}
> > +
> > +static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
> > +{
> > +     u8 *ptr = data, *uuids_start = NULL;
> > +     struct bt_uuid *uuid;
> > +
> > +     if (len < 6)
> > +             return ptr;
> > +
> > +     list_for_each_entry(uuid, &hdev->uuids, list) {
> > +             if (uuid->size != 32)
> > +                     continue;
> > +
> > +             if (!uuids_start) {
> > +                     uuids_start = ptr;
> > +                     uuids_start[0] = 1;
> > +                     uuids_start[1] = EIR_UUID32_ALL;
> > +                     ptr += 2;
> > +             }
> > +
> > +             /* Stop if not enough space to put next UUID */
> > +             if ((ptr - data) + sizeof(u32) > len) {
> > +                     uuids_start[1] = EIR_UUID32_SOME;
> > +                     break;
> > +             }
> > +
> > +             memcpy(ptr, &uuid->uuid[12], sizeof(u32));
> > +             ptr += sizeof(u32);
> > +             uuids_start[0] += sizeof(u32);
> > +     }
> > +
> > +     return ptr;
> > +}
> > +
> > +static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
> > +{
> > +     u8 *ptr = data, *uuids_start = NULL;
> > +     struct bt_uuid *uuid;
> > +
> > +     if (len < 18)
> > +             return ptr;
> > +
> > +     list_for_each_entry(uuid, &hdev->uuids, list) {
> > +             if (uuid->size != 128)
> > +                     continue;
> > +
> > +             if (!uuids_start) {
> > +                     uuids_start = ptr;
> > +                     uuids_start[0] = 1;
> > +                     uuids_start[1] = EIR_UUID128_ALL;
> > +                     ptr += 2;
> > +             }
> > +
> > +             /* Stop if not enough space to put next UUID */
> > +             if ((ptr - data) + 16 > len) {
> > +                     uuids_start[1] = EIR_UUID128_SOME;
> > +                     break;
> > +             }
> > +
> > +             memcpy(ptr, uuid->uuid, 16);
> > +             ptr += 16;
> > +             uuids_start[0] += 16;
> > +     }
> > +
> > +     return ptr;
> > +}
> > +
> > +static void create_eir(struct hci_dev *hdev, u8 *data)
> > +{
> > +     u8 *ptr = data;
> > +     size_t name_len;
> > +
> > +     name_len = strlen(hdev->dev_name);
> > +
> > +     if (name_len > 0) {
> > +             /* EIR Data type */
> > +             if (name_len > 48) {
> > +                     name_len = 48;
> > +                     ptr[1] = EIR_NAME_SHORT;
> > +             } else
> > +                     ptr[1] = EIR_NAME_COMPLETE;
> > +
> > +             /* EIR Data length */
> > +             ptr[0] = name_len + 1;
> > +
> > +             memcpy(ptr + 2, hdev->dev_name, name_len);
> > +
> > +             ptr += (name_len + 2);
> > +     }
> > +
> > +     if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
> > +             ptr[0] = 2;
> > +             ptr[1] = EIR_TX_POWER;
> > +             ptr[2] = (u8) hdev->inq_tx_power;
> > +
> > +             ptr += 3;
> > +     }
> > +
> > +     if (hdev->devid_source > 0) {
> > +             ptr[0] = 9;
> > +             ptr[1] = EIR_DEVICE_ID;
> > +
> > +             put_unaligned_le16(hdev->devid_source, ptr + 2);
> > +             put_unaligned_le16(hdev->devid_vendor, ptr + 4);
> > +             put_unaligned_le16(hdev->devid_product, ptr + 6);
> > +             put_unaligned_le16(hdev->devid_version, ptr + 8);
> > +
> > +             ptr += 10;
> > +     }
> > +
> > +     ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
> > +     ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
> > +     ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
> > +}
> > +
> > +int __hci_update_eir_sync(struct hci_dev *hdev)
> > +{
> > +     struct hci_cp_write_eir cp;
> > +
> > +     bt_dev_dbg(hdev, "");
> > +
> > +     if (!hdev_is_powered(hdev))
> > +             return 0;
> > +
> > +     if (!lmp_ext_inq_capable(hdev))
> > +             return 0;
> > +
> > +     if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
> > +             return 0;
> > +
> > +     if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
> > +             return 0;
> > +
> > +     memset(&cp, 0, sizeof(cp));
> > +
> > +     create_eir(hdev, cp.data);
> > +
> > +     if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
> > +             return 0;
> > +
> > +     memcpy(hdev->eir, cp.data, sizeof(cp.data));
> > +
> > +     return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp,
> > +                                  HCI_CMD_TIMEOUT);
> > +}
> > +
> > +static u8 get_service_classes(struct hci_dev *hdev)
> > +{
> > +     struct bt_uuid *uuid;
> > +     u8 val = 0;
> > +
> > +     list_for_each_entry(uuid, &hdev->uuids, list)
> > +             val |= uuid->svc_hint;
> > +
> > +     return val;
> > +}
> > +
> > +int __hci_update_class_sync(struct hci_dev *hdev)
> > +{
> > +     u8 cod[3];
> > +
> > +     bt_dev_dbg(hdev, "");
> > +
> > +     if (!hdev_is_powered(hdev))
> > +             return 0;
> > +
> > +     if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
> > +             return 0;
> > +
> > +     if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
> > +             return 0;
> > +
> > +     cod[0] = hdev->minor_class;
> > +     cod[1] = hdev->major_class;
> > +     cod[2] = get_service_classes(hdev);
> > +
> > +     if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
> > +             cod[1] |= 0x20;
> > +
> > +     if (memcmp(cod, hdev->dev_class, 3) == 0)
> > +             return 0;
> > +
> > +     return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_CLASS_OF_DEV,
> > +                                  sizeof(cod), cod, HCI_CMD_TIMEOUT);
> > +}
> > diff --git a/net/bluetooth/hci_sync.h b/net/bluetooth/hci_sync.h
> > new file mode 100644
> > index 000000000000..735ff4b46e86
> > --- /dev/null
> > +++ b/net/bluetooth/hci_sync.h
> > @@ -0,0 +1,9 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * BlueZ - Bluetooth protocol stack for Linux
> > + *
> > + * Copyright (C) 2021 Intel Corporation
> > + */
> > +
> > +int __hci_update_eir_sync(struct hci_dev *hdev);
> > +int __hci_update_class_sync(struct hci_dev *hdev);
> > diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> > index b44e19c69c44..96759c166678 100644
> > --- a/net/bluetooth/mgmt.c
> > +++ b/net/bluetooth/mgmt.c
> > @@ -34,6 +34,7 @@
> > #include <net/bluetooth/mgmt.h>
> >
> > #include "hci_request.h"
> > +#include "hci_sync.h"
> > #include "smp.h"
> > #include "mgmt_util.h"
> > #include "mgmt_config.h"
> > @@ -950,25 +951,21 @@ bool mgmt_get_connectable(struct hci_dev *hdev)
> >       return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
> > }
> >
> > +static void __service_cache_sync(struct hci_dev *hdev, void *data)
> > +{
> > +     __hci_update_eir_sync(hdev);
> > +     __hci_update_class_sync(hdev);
> > +}
> > +
> > static void service_cache_off(struct work_struct *work)
> > {
> >       struct hci_dev *hdev = container_of(work, struct hci_dev,
> >                                           service_cache.work);
> > -     struct hci_request req;
> >
> >       if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
> >               return;
> >
> > -     hci_req_init(&req, hdev);
> > -
> > -     hci_dev_lock(hdev);
> > -
> > -     __hci_req_update_eir(&req);
> > -     __hci_req_update_class(&req);
> > -
> > -     hci_dev_unlock(hdev);
> > -
> > -     hci_req_run(&req, NULL);
> > +     hci_cmd_sync_queue(hdev, __service_cache_sync, NULL);
> > }
> >
> > static void rpa_expired(struct work_struct *work)
> > @@ -2093,8 +2090,17 @@ static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
> >       hci_dev_unlock(hdev);
> > }
> >
> > -static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
> > +static void __add_uuid_sync(struct hci_dev *hdev, void *data)
> > {
> > +     uint8_t status;
> > +
> > +     status = __hci_update_class_sync(hdev);
> > +     if (status)
> > +             goto done;
> > +
> > +     status = __hci_update_eir_sync(hdev);
> > +
> > +done:
> >       bt_dev_dbg(hdev, "status 0x%02x", status);
> >
> >       mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
> > @@ -2104,7 +2110,6 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
> > {
> >       struct mgmt_cp_add_uuid *cp = data;
> >       struct mgmt_pending_cmd *cmd;
> > -     struct hci_request req;
> >       struct bt_uuid *uuid;
> >       int err;
> >
> > @@ -2130,20 +2135,9 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
> >
> >       list_add_tail(&uuid->list, &hdev->uuids);
> >
> > -     hci_req_init(&req, hdev);
> > -
> > -     __hci_req_update_class(&req);
> > -     __hci_req_update_eir(&req);
> > -
> > -     err = hci_req_run(&req, add_uuid_complete);
> > -     if (err < 0) {
> > -             if (err != -ENODATA)
> > -                     goto failed;
> > -
> > -             err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
> > -                                     hdev->dev_class, 3);
> > +     err = hci_cmd_sync_queue(hdev, __add_uuid_sync, NULL);
> > +     if (err < 0)
> >               goto failed;
> > -     }
> >
> >       cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
> >       if (!cmd) {
> > @@ -2172,8 +2166,17 @@ static bool enable_service_cache(struct hci_dev *hdev)
> >       return false;
> > }
> >
> > -static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
> > +static void __remove_uuid_sync(struct hci_dev *hdev, void *data)
> > {
> > +     uint8_t status;
> > +
> > +     status = __hci_update_class_sync(hdev);
> > +     if (status)
> > +             goto done;
> > +
> > +     status = __hci_update_eir_sync(hdev);
> > +
> > +done:
> >       bt_dev_dbg(hdev, "status 0x%02x", status);
> >
> >       mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
> > @@ -2186,7 +2189,6 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
> >       struct mgmt_pending_cmd *cmd;
> >       struct bt_uuid *match, *tmp;
> >       u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
> > -     struct hci_request req;
> >       int err, found;
> >
> >       bt_dev_dbg(hdev, "sock %p", sk);
> > @@ -2230,20 +2232,9 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
> >       }
> >
> > update_class:
> > -     hci_req_init(&req, hdev);
> > -
> > -     __hci_req_update_class(&req);
> > -     __hci_req_update_eir(&req);
> > -
> > -     err = hci_req_run(&req, remove_uuid_complete);
> > -     if (err < 0) {
> > -             if (err != -ENODATA)
> > -                     goto unlock;
> > -
> > -             err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
> > -                                     hdev->dev_class, 3);
> > +     err = hci_cmd_sync_queue(hdev, __remove_uuid_sync, NULL);
> > +     if (err < 0)
> >               goto unlock;
> > -     }
> >
> >       cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
> >       if (!cmd) {
> > @@ -2258,8 +2249,24 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
> >       return err;
> > }
> >
> > -static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
> > +static void __set_class_sync(struct hci_dev *hdev, void *data)
> > {
> > +     uint8_t status = 0;
> > +
> > +     hci_dev_lock(hdev);
> > +
> > +     if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
> > +             hci_dev_unlock(hdev);
> > +             cancel_delayed_work_sync(&hdev->service_cache);
> > +             hci_dev_lock(hdev);
> > +             status = __hci_update_eir_sync(hdev);
> > +     }
> > +
> > +     hci_dev_unlock(hdev);
> > +
> > +     if (!status)
> > +             status = __hci_update_class_sync(hdev);
> > +
> >       bt_dev_dbg(hdev, "status 0x%02x", status);
> >
> >       mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
> > @@ -2270,7 +2277,6 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
> > {
> >       struct mgmt_cp_set_dev_class *cp = data;
> >       struct mgmt_pending_cmd *cmd;
> > -     struct hci_request req;
> >       int err;
> >
> >       bt_dev_dbg(hdev, "sock %p", sk);
> > @@ -2302,26 +2308,9 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
> >               goto unlock;
> >       }
> >
> > -     hci_req_init(&req, hdev);
> > -
> > -     if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
> > -             hci_dev_unlock(hdev);
> > -             cancel_delayed_work_sync(&hdev->service_cache);
> > -             hci_dev_lock(hdev);
> > -             __hci_req_update_eir(&req);
> > -     }
> > -
> > -     __hci_req_update_class(&req);
> > -
> > -     err = hci_req_run(&req, set_class_complete);
> > -     if (err < 0) {
> > -             if (err != -ENODATA)
> > -                     goto unlock;
> > -
> > -             err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
> > -                                     hdev->dev_class, 3);
> > +     err = hci_cmd_sync_queue(hdev, __set_class_sync, NULL);
> > +     if (err < 0)
> >               goto unlock;
> > -     }
> >
> >       cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
> >       if (!cmd) {
> > @@ -5263,11 +5252,15 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
> >       return err;
> > }
> >
> > +static void __set_device_id_sync(struct hci_dev *hdev, void *data)
> > +{
> > +     __hci_update_eir_sync(hdev);
> > +}
> > +
> > static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
> >                        u16 len)
> > {
> >       struct mgmt_cp_set_device_id *cp = data;
> > -     struct hci_request req;
> >       int err;
> >       __u16 source;
> >
> > @@ -5289,9 +5282,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
> >       err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
> >                               NULL, 0);
> >
> > -     hci_req_init(&req, hdev);
> > -     __hci_req_update_eir(&req);
> > -     hci_req_run(&req, NULL);
> > +     hci_cmd_sync_queue(hdev, __set_device_id_sync, NULL);
> >
> >       hci_dev_unlock(hdev);
>
> I dislike the prefix __sync. They are in a separate anyway. So keep is simple and also scrap the __ prefix.

Sure, do you want to perhaps have it as hci_sync given those should
indicate that they require hci_req_sync_lock to be held, or you think
that given the we will be converting everything to use the cmd_sync
work that is not really necessary? Btw, as part of the cleanup Im also
planning to send a patch moving eir/adv data related code to
eir.{c,h}, do you have anything against it?

>
> Regards
>
> Marcel
>


-- 
Luiz Augusto von Dentz

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

end of thread, other threads:[~2021-05-20 23:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-20 16:42 [PATCH 1/2] Bluetooth: Add helper for serialized HCI command execution Luiz Augusto von Dentz
2021-05-20 16:42 ` [PATCH 2/2] Bluetooth: hci_sync: Make use of hci_cmd_sync_queue Luiz Augusto von Dentz
2021-05-20 20:17   ` Marcel Holtmann
2021-05-20 23:57     ` Luiz Augusto von Dentz
2021-05-20 17:49 ` [1/2] Bluetooth: Add helper for serialized HCI command execution bluez.test.bot

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.