linux-mediatek.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support
@ 2024-07-04  6:01 Chris Lu
  2024-07-04  6:01 ` [PATCH v7 1/8] Bluetooth: btusb: mediatek: remove the unnecessary goto tag Chris Lu
                   ` (8 more replies)
  0 siblings, 9 replies; 17+ messages in thread
From: Chris Lu @ 2024-07-04  6:01 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth, linux-kernel,
	linux-mediatek, Chris Lu

Since SIG has not yet clearly defined the specification for ISO data
transmission over USB, MediaTek has adopted a method of adding an
additional interrupt endpoint for ISO data transmission. This approach
differs from the current method used in the Bluetooth upstream driver,
which utilizes existing bulk endpoints. The interrupt endpoint provides
guaranteed bandwidth, sufficient maximum data length for ISO packets
and error checking.

Driver sets up ISO interface and endpoints in btusb_mtk_setup and clears
the setup in btusb_mtk_shutdown. These flow can't move to btmtk.c due to
btusb_driver is only defined in btusb.c when claiming/relaesing interface.
Once ISO interface is claimed, driver can use specific interrupt endpoint
to send and receive iso data. ISO packet anchor stops when driver
suspending and resubmit interrupt urb for ISO data when driver resuming.

---
Change from v6 to v7:
-Change MediaTek's specific suspend/resume function naming to
btmtk_usb_suspend/resume and add comment to explain the purpose of function.
---

Chris Lu (8):
  Bluetooth: btusb: mediatek: remove the unnecessary goto tag
  Bluetooth: btusb: mediatek: return error for failed reg access
  Bluetooth: btmtk: rename btmediatek_data
  Bluetooth: btusb: add callback function in btusb suspend/resume
  Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c
  Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c
  Bluetooth: btmtk: move btusb_recv_acl_mtk to btmtk.c
  Bluetooth: btusb: mediatek: add ISO data transmission functions

 drivers/bluetooth/btmtk.c     | 1067 ++++++++++++++++++++++++++++++++-
 drivers/bluetooth/btmtk.h     |   91 ++-
 drivers/bluetooth/btmtksdio.c |    1 +
 drivers/bluetooth/btmtkuart.c |    1 +
 drivers/bluetooth/btusb.c     |  751 +++--------------------
 5 files changed, 1227 insertions(+), 684 deletions(-)

-- 
2.18.0



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

* [PATCH v7 1/8] Bluetooth: btusb: mediatek: remove the unnecessary goto tag
  2024-07-04  6:01 [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support Chris Lu
@ 2024-07-04  6:01 ` Chris Lu
  2024-07-04  6:01 ` [PATCH v7 2/8] Bluetooth: btusb: mediatek: return error for failed reg access Chris Lu
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Chris Lu @ 2024-07-04  6:01 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth, linux-kernel,
	linux-mediatek, Chris Lu

Remove the unnecessary goto tag whether there is an error or not, we have
to free the buffer at the end of the function.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
 drivers/bluetooth/btusb.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 79aefdb3324d..fcdd660add19 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2953,12 +2953,9 @@ static int btusb_mtk_uhw_reg_write(struct btusb_data *data, u32 reg, u32 val)
 			      0x5E,
 			      reg >> 16, reg & 0xffff,
 			      buf, 4, USB_CTRL_SET_TIMEOUT);
-	if (err < 0) {
+	if (err < 0)
 		bt_dev_err(hdev, "Failed to write uhw reg(%d)", err);
-		goto err_free_buf;
-	}
 
-err_free_buf:
 	kfree(buf);
 
 	return err;
-- 
2.18.0



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

* [PATCH v7 2/8] Bluetooth: btusb: mediatek: return error for failed reg access
  2024-07-04  6:01 [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support Chris Lu
  2024-07-04  6:01 ` [PATCH v7 1/8] Bluetooth: btusb: mediatek: remove the unnecessary goto tag Chris Lu
@ 2024-07-04  6:01 ` Chris Lu
  2024-07-04  6:01 ` [PATCH v7 3/8] Bluetooth: btmtk: rename btmediatek_data Chris Lu
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Chris Lu @ 2024-07-04  6:01 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth, linux-kernel,
	linux-mediatek, Chris Lu

Update the code to immediately return an error code if accessing a
related register fails. This ensures that our desired logic for
subsequent register operations is maintained and allows us to promptly
catch any unexpected errors.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
 drivers/bluetooth/btusb.c | 114 ++++++++++++++++++++++++++++----------
 1 file changed, 84 insertions(+), 30 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index fcdd660add19..8239d9c891e6 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -3037,47 +3037,98 @@ static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id)
 	int err;
 
 	if (dev_id == 0x7922) {
-		btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
+		err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
+		if (err < 0)
+			return err;
 		val |= 0x00002020;
-		btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val);
-		btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001);
-		btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
+		err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
+		if (err < 0)
+			return err;
 		val |= BIT(0);
-		btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val);
+		err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val);
+		if (err < 0)
+			return err;
 		msleep(100);
 	} else if (dev_id == 0x7925) {
-		btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
+		err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
+		if (err < 0)
+			return err;
 		val |= (1 << 5);
-		btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
-		btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
+		err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
+		if (err < 0)
+			return err;
 		val &= 0xFFFF00FF;
+		if (err < 0)
+			return err;
 		val |= (1 << 13);
-		btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
-		btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001);
-		btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
+		err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
+		if (err < 0)
+			return err;
 		val |= (1 << 0);
-		btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
-		btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
-		btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
-		btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
-		btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
+		err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
+		if (err < 0)
+			return err;
 		msleep(100);
 	} else {
 		/* It's Device EndPoint Reset Option Register */
 		bt_dev_dbg(hdev, "Initiating reset mechanism via uhw");
-		btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
-		btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val);
-
+		err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val);
+		if (err < 0)
+			return err;
 		/* Reset the bluetooth chip via USB interface. */
-		btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1);
-		btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
-		btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
-		btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
-		btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
+		err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
+		if (err < 0)
+			return err;
 		/* MT7921 need to delay 20ms between toggle reset bit */
 		msleep(20);
-		btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
-		btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
+		err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
+		if (err < 0)
+			return err;
+		err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
+		if (err < 0)
+			return err;
 	}
 
 	err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val,
@@ -3085,11 +3136,14 @@ static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id)
 	if (err < 0)
 		bt_dev_err(hdev, "Reset timeout");
 
-	if (dev_id == 0x7922)
-		btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
+	if (dev_id == 0x7922) {
+		err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
+		if (err < 0)
+			return err;
+	}
 
-	btusb_mtk_id_get(data, 0x70010200, &val);
-	if (!val)
+	err = btusb_mtk_id_get(data, 0x70010200, &val);
+	if (err < 0 || !val)
 		bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
 
 	return err;
-- 
2.18.0



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

* [PATCH v7 3/8] Bluetooth: btmtk: rename btmediatek_data
  2024-07-04  6:01 [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support Chris Lu
  2024-07-04  6:01 ` [PATCH v7 1/8] Bluetooth: btusb: mediatek: remove the unnecessary goto tag Chris Lu
  2024-07-04  6:01 ` [PATCH v7 2/8] Bluetooth: btusb: mediatek: return error for failed reg access Chris Lu
@ 2024-07-04  6:01 ` Chris Lu
  2024-07-04  6:01 ` [PATCH v7 4/8] Bluetooth: btusb: add callback function in btusb suspend/resume Chris Lu
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Chris Lu @ 2024-07-04  6:01 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth, linux-kernel,
	linux-mediatek, Chris Lu

Rename btmediatek_data to have a consistent prefix throughout the driver.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
 drivers/bluetooth/btmtk.c | 10 +++++-----
 drivers/bluetooth/btmtk.h |  2 +-
 drivers/bluetooth/btusb.c |  9 ++++-----
 3 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index a27c251bf56e..6489e4a63fb6 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -64,7 +64,7 @@ static void btmtk_coredump(struct hci_dev *hdev)
 
 static void btmtk_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct btmediatek_data *data = hci_get_priv(hdev);
+	struct btmtk_data *data = hci_get_priv(hdev);
 	char buf[80];
 
 	snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
@@ -85,7 +85,7 @@ static void btmtk_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void btmtk_coredump_notify(struct hci_dev *hdev, int state)
 {
-	struct btmediatek_data *data = hci_get_priv(hdev);
+	struct btmtk_data *data = hci_get_priv(hdev);
 
 	switch (state) {
 	case HCI_DEVCOREDUMP_IDLE:
@@ -355,7 +355,7 @@ EXPORT_SYMBOL_GPL(btmtk_set_bdaddr);
 
 void btmtk_reset_sync(struct hci_dev *hdev)
 {
-	struct btmediatek_data *reset_work = hci_get_priv(hdev);
+	struct btmtk_data *reset_work = hci_get_priv(hdev);
 	int err;
 
 	hci_dev_lock(hdev);
@@ -371,7 +371,7 @@ EXPORT_SYMBOL_GPL(btmtk_reset_sync);
 int btmtk_register_coredump(struct hci_dev *hdev, const char *name,
 			    u32 fw_version)
 {
-	struct btmediatek_data *data = hci_get_priv(hdev);
+	struct btmtk_data *data = hci_get_priv(hdev);
 
 	if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
 		return -EOPNOTSUPP;
@@ -387,7 +387,7 @@ EXPORT_SYMBOL_GPL(btmtk_register_coredump);
 
 int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	struct btmediatek_data *data = hci_get_priv(hdev);
+	struct btmtk_data *data = hci_get_priv(hdev);
 	int err;
 
 	if (!IS_ENABLED(CONFIG_DEV_COREDUMP)) {
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index e76b8a358be8..dde6fbdeb2b3 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -135,7 +135,7 @@ struct btmtk_coredump_info {
 	int state;
 };
 
-struct btmediatek_data {
+struct btmtk_data {
 	u32 dev_id;
 	btmtk_reset_sync_func_t reset_sync;
 	struct btmtk_coredump_info cd_info;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8239d9c891e6..7612f10f9d39 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -3152,7 +3152,7 @@ static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id)
 static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
-	struct btmediatek_data *mtk_data;
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
 	int err;
 
 	/* It's MediaTek specific bluetooth reset mechanism via USB */
@@ -3167,9 +3167,8 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
 
 	btusb_stop_traffic(data);
 	usb_kill_anchored_urbs(&data->tx_anchor);
-	mtk_data = hci_get_priv(hdev);
 
-	err = btusb_mtk_subsys_reset(hdev, mtk_data->dev_id);
+	err = btusb_mtk_subsys_reset(hdev, btmtk_data->dev_id);
 
 	usb_queue_reset_device(data->intf);
 	clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags);
@@ -3191,7 +3190,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 	char fw_bin_name[64];
 	u32 fw_version = 0, fw_flavor = 0;
 	u8 param;
-	struct btmediatek_data *mediatek;
+	struct btmtk_data *mediatek;
 
 	calltime = ktime_get();
 
@@ -4419,7 +4418,7 @@ static int btusb_probe(struct usb_interface *intf,
 		data->recv_event = btusb_recv_event_realtek;
 	} else if (id->driver_info & BTUSB_MEDIATEK) {
 		/* Allocate extra space for Mediatek device */
-		priv_size += sizeof(struct btmediatek_data);
+		priv_size += sizeof(struct btmtk_data);
 	}
 
 	data->recv_acl = hci_recv_frame;
-- 
2.18.0



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

* [PATCH v7 4/8] Bluetooth: btusb: add callback function in btusb suspend/resume
  2024-07-04  6:01 [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support Chris Lu
                   ` (2 preceding siblings ...)
  2024-07-04  6:01 ` [PATCH v7 3/8] Bluetooth: btmtk: rename btmediatek_data Chris Lu
@ 2024-07-04  6:01 ` Chris Lu
  2024-07-04  6:01 ` [PATCH v7 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c Chris Lu
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Chris Lu @ 2024-07-04  6:01 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth, linux-kernel,
	linux-mediatek, Chris Lu

Add suspend/resum callback function in btusb_data which are reserved
for vendor specific usage during suspend/resume. hdev->suspend will be
added before stop traffic in btusb_suspend and hdev-> resume will be
added after resubmit urb in btusb_resume.

Signed-off-by: Chris Lu <chris.lu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/bluetooth/btusb.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 7612f10f9d39..4ec18b58dc68 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -891,6 +891,9 @@ struct btusb_data {
 
 	int (*setup_on_usb)(struct hci_dev *hdev);
 
+	int (*suspend)(struct hci_dev *hdev);
+	int (*resume)(struct hci_dev *hdev);
+
 	int oob_wake_irq;   /* irq for out-of-band wake-on-bt */
 	unsigned cmd_timeout_cnt;
 
@@ -4765,6 +4768,9 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
 
 	cancel_work_sync(&data->work);
 
+	if (data->suspend)
+		data->suspend(data->hdev);
+
 	btusb_stop_traffic(data);
 	usb_kill_anchored_urbs(&data->tx_anchor);
 
@@ -4868,6 +4874,9 @@ static int btusb_resume(struct usb_interface *intf)
 			btusb_submit_isoc_urb(hdev, GFP_NOIO);
 	}
 
+	if (data->resume)
+		data->resume(hdev);
+
 	spin_lock_irq(&data->txlock);
 	play_deferred(data);
 	clear_bit(BTUSB_SUSPENDING, &data->flags);
-- 
2.18.0



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

* [PATCH v7 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c
  2024-07-04  6:01 [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support Chris Lu
                   ` (3 preceding siblings ...)
  2024-07-04  6:01 ` [PATCH v7 4/8] Bluetooth: btusb: add callback function in btusb suspend/resume Chris Lu
@ 2024-07-04  6:01 ` Chris Lu
  2024-07-05  6:09   ` kernel test robot
  2024-07-05  9:33   ` kernel test robot
  2024-07-04  6:01 ` [PATCH v7 6/8] Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] " Chris Lu
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 17+ messages in thread
From: Chris Lu @ 2024-07-04  6:01 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth, linux-kernel,
	linux-mediatek, Chris Lu

Move btusb_mtk_hci_wmt_sync from btusb.c to btmtk.c which holds
vendor specific stuff and would make btusb.c clean.

Add usb.h header to btmtksdio.c/btmtkuart.c for usb related element
defined in btmtk.h

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
 drivers/bluetooth/btmtk.c     | 265 +++++++++++++++++++++++++++++++
 drivers/bluetooth/btmtk.h     |  31 ++++
 drivers/bluetooth/btmtksdio.c |   1 +
 drivers/bluetooth/btmtkuart.c |   1 +
 drivers/bluetooth/btusb.c     | 290 +---------------------------------
 5 files changed, 305 insertions(+), 283 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 6489e4a63fb6..3443a0837a86 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -4,6 +4,7 @@
  */
 #include <linux/module.h>
 #include <linux/firmware.h>
+#include <linux/usb.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -431,6 +432,270 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(btmtk_process_coredump);
 
+static void btmtk_usb_wmt_recv(struct urb *urb)
+{
+	struct hci_dev *hdev = urb->context;
+	struct btmtk_data *data = hci_get_priv(hdev);
+	struct sk_buff *skb;
+	int err;
+
+	if (urb->status == 0 && urb->actual_length > 0) {
+		hdev->stat.byte_rx += urb->actual_length;
+
+		/* WMT event shouldn't be fragmented and the size should be
+		 * less than HCI_WMT_MAX_EVENT_SIZE.
+		 */
+		skb = bt_skb_alloc(HCI_WMT_MAX_EVENT_SIZE, GFP_ATOMIC);
+		if (!skb) {
+			hdev->stat.err_rx++;
+			kfree(urb->setup_packet);
+			return;
+		}
+
+		hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
+		skb_put_data(skb, urb->transfer_buffer, urb->actual_length);
+
+		/* When someone waits for the WMT event, the skb is being cloned
+		 * and being processed the events from there then.
+		 */
+		if (test_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags)) {
+			data->evt_skb = skb_clone(skb, GFP_ATOMIC);
+			if (!data->evt_skb) {
+				kfree_skb(skb);
+				kfree(urb->setup_packet);
+				return;
+			}
+		}
+
+		err = hci_recv_frame(hdev, skb);
+		if (err < 0) {
+			kfree_skb(data->evt_skb);
+			data->evt_skb = NULL;
+			kfree(urb->setup_packet);
+			return;
+		}
+
+		if (test_and_clear_bit(BTMTK_TX_WAIT_VND_EVT,
+				       &data->flags)) {
+			/* Barrier to sync with other CPUs */
+			smp_mb__after_atomic();
+			wake_up_bit(&data->flags,
+				    BTMTK_TX_WAIT_VND_EVT);
+		}
+		kfree(urb->setup_packet);
+		return;
+	} else if (urb->status == -ENOENT) {
+		/* Avoid suspend failed when usb_kill_urb */
+		return;
+	}
+
+	usb_mark_last_busy(data->udev);
+
+	/* The URB complete handler is still called with urb->actual_length = 0
+	 * when the event is not available, so we should keep re-submitting
+	 * URB until WMT event returns, Also, It's necessary to wait some time
+	 * between the two consecutive control URBs to relax the target device
+	 * to generate the event. Otherwise, the WMT event cannot return from
+	 * the device successfully.
+	 */
+	udelay(500);
+
+	usb_anchor_urb(urb, data->ctrl_anchor);
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err < 0) {
+		kfree(urb->setup_packet);
+		/* -EPERM: urb is being killed;
+		 * -ENODEV: device got disconnected
+		 */
+		if (err != -EPERM && err != -ENODEV)
+			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
+				   urb, -err);
+		usb_unanchor_urb(urb);
+	}
+}
+
+static int btmtk_usb_submit_wmt_recv_urb(struct hci_dev *hdev)
+{
+	struct btmtk_data *data = hci_get_priv(hdev);
+	struct usb_ctrlrequest *dr;
+	unsigned char *buf;
+	int err, size = 64;
+	unsigned int pipe;
+	struct urb *urb;
+
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb)
+		return -ENOMEM;
+
+	dr = kmalloc(sizeof(*dr), GFP_KERNEL);
+	if (!dr) {
+		usb_free_urb(urb);
+		return -ENOMEM;
+	}
+
+	dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_IN;
+	dr->bRequest     = 1;
+	dr->wIndex       = cpu_to_le16(0);
+	dr->wValue       = cpu_to_le16(48);
+	dr->wLength      = cpu_to_le16(size);
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (!buf) {
+		kfree(dr);
+		usb_free_urb(urb);
+		return -ENOMEM;
+	}
+
+	pipe = usb_rcvctrlpipe(data->udev, 0);
+
+	usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
+			     buf, size, btmtk_usb_wmt_recv, hdev);
+
+	urb->transfer_flags |= URB_FREE_BUFFER;
+
+	usb_anchor_urb(urb, data->ctrl_anchor);
+	err = usb_submit_urb(urb, GFP_KERNEL);
+	if (err < 0) {
+		if (err != -EPERM && err != -ENODEV)
+			bt_dev_err(hdev, "urb %p submission failed (%d)",
+				   urb, -err);
+		usb_unanchor_urb(urb);
+	}
+
+	usb_free_urb(urb);
+
+	return err;
+}
+
+int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
+			   struct btmtk_hci_wmt_params *wmt_params)
+{
+	struct btmtk_data *data = hci_get_priv(hdev);
+	struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
+	u32 hlen, status = BTMTK_WMT_INVALID;
+	struct btmtk_hci_wmt_evt *wmt_evt;
+	struct btmtk_hci_wmt_cmd *wc;
+	struct btmtk_wmt_hdr *hdr;
+	int err;
+
+	/* Send the WMT command and wait until the WMT event returns */
+	hlen = sizeof(*hdr) + wmt_params->dlen;
+	if (hlen > 255)
+		return -EINVAL;
+
+	wc = kzalloc(hlen, GFP_KERNEL);
+	if (!wc)
+		return -ENOMEM;
+
+	hdr = &wc->hdr;
+	hdr->dir = 1;
+	hdr->op = wmt_params->op;
+	hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
+	hdr->flag = wmt_params->flag;
+	memcpy(wc->data, wmt_params->data, wmt_params->dlen);
+
+	set_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags);
+
+	/* WMT cmd/event doesn't follow up the generic HCI cmd/event handling,
+	 * it needs constantly polling control pipe until the host received the
+	 * WMT event, thus, we should require to specifically acquire PM counter
+	 * on the USB to prevent the interface from entering auto suspended
+	 * while WMT cmd/event in progress.
+	 */
+	err = usb_autopm_get_interface(data->intf);
+	if (err < 0)
+		goto err_free_wc;
+
+	err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
+
+	if (err < 0) {
+		clear_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags);
+		usb_autopm_put_interface(data->intf);
+		goto err_free_wc;
+	}
+
+	/* Submit control IN URB on demand to process the WMT event */
+	err = btmtk_usb_submit_wmt_recv_urb(hdev);
+
+	usb_autopm_put_interface(data->intf);
+
+	if (err < 0)
+		goto err_free_wc;
+
+	/* The vendor specific WMT commands are all answered by a vendor
+	 * specific event and will have the Command Status or Command
+	 * Complete as with usual HCI command flow control.
+	 *
+	 * After sending the command, wait for BTUSB_TX_WAIT_VND_EVT
+	 * state to be cleared. The driver specific event receive routine
+	 * will clear that state and with that indicate completion of the
+	 * WMT command.
+	 */
+	err = wait_on_bit_timeout(&data->flags, BTMTK_TX_WAIT_VND_EVT,
+				  TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT);
+	if (err == -EINTR) {
+		bt_dev_err(hdev, "Execution of wmt command interrupted");
+		clear_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags);
+		goto err_free_wc;
+	}
+
+	if (err) {
+		bt_dev_err(hdev, "Execution of wmt command timed out");
+		clear_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags);
+		err = -ETIMEDOUT;
+		goto err_free_wc;
+	}
+
+	if (data->evt_skb == NULL)
+		goto err_free_wc;
+
+	/* Parse and handle the return WMT event */
+	wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
+	if (wmt_evt->whdr.op != hdr->op) {
+		bt_dev_err(hdev, "Wrong op received %d expected %d",
+			   wmt_evt->whdr.op, hdr->op);
+		err = -EIO;
+		goto err_free_skb;
+	}
+
+	switch (wmt_evt->whdr.op) {
+	case BTMTK_WMT_SEMAPHORE:
+		if (wmt_evt->whdr.flag == 2)
+			status = BTMTK_WMT_PATCH_UNDONE;
+		else
+			status = BTMTK_WMT_PATCH_DONE;
+		break;
+	case BTMTK_WMT_FUNC_CTRL:
+		wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
+		if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
+			status = BTMTK_WMT_ON_DONE;
+		else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
+			status = BTMTK_WMT_ON_PROGRESS;
+		else
+			status = BTMTK_WMT_ON_UNDONE;
+		break;
+	case BTMTK_WMT_PATCH_DWNLD:
+		if (wmt_evt->whdr.flag == 2)
+			status = BTMTK_WMT_PATCH_DONE;
+		else if (wmt_evt->whdr.flag == 1)
+			status = BTMTK_WMT_PATCH_PROGRESS;
+		else
+			status = BTMTK_WMT_PATCH_UNDONE;
+		break;
+	}
+
+	if (wmt_params->status)
+		*wmt_params->status = status;
+
+err_free_skb:
+	kfree_skb(data->evt_skb);
+	data->evt_skb = NULL;
+err_free_wc:
+	kfree(wc);
+	return err;
+}
+EXPORT_SYMBOL_GPL(btmtk_usb_hci_wmt_sync);
+
 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
 MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>");
 MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index dde6fbdeb2b3..3055b9728ae2 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -28,6 +28,18 @@
 #define MTK_COREDUMP_END_LEN		(sizeof(MTK_COREDUMP_END))
 #define MTK_COREDUMP_NUM		255
 
+/* UHW CR mapping */
+#define MTK_BT_MISC		0x70002510
+#define MTK_BT_SUBSYS_RST	0x70002610
+#define MTK_UDMA_INT_STA_BT	0x74000024
+#define MTK_UDMA_INT_STA_BT1	0x74000308
+#define MTK_BT_WDT_STATUS	0x740003A0
+#define MTK_EP_RST_OPT		0x74011890
+#define MTK_EP_RST_IN_OUT_OPT	0x00010001
+#define MTK_BT_RST_DONE		0x00000100
+#define MTK_BT_RESET_REG_CONNV3	0x70028610
+#define MTK_BT_READ_DEV_ID	0x70010200
+
 enum {
 	BTMTK_WMT_PATCH_DWNLD = 0x1,
 	BTMTK_WMT_TEST = 0x2,
@@ -126,6 +138,10 @@ struct btmtk_hci_wmt_params {
 	u32 *status;
 };
 
+enum {
+	BTMTK_TX_WAIT_VND_EVT,
+};
+
 typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);
 
 struct btmtk_coredump_info {
@@ -136,9 +152,15 @@ struct btmtk_coredump_info {
 };
 
 struct btmtk_data {
+	unsigned long flags;
 	u32 dev_id;
 	btmtk_reset_sync_func_t reset_sync;
 	struct btmtk_coredump_info cd_info;
+
+	struct usb_device *udev;
+	struct usb_interface *intf;
+	struct usb_anchor *ctrl_anchor;
+	struct sk_buff *evt_skb;
 };
 
 typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
@@ -163,6 +185,9 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb);
 
 void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver,
 			   u32 fw_flavor);
+
+int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
+			   struct btmtk_hci_wmt_params *wmt_params);
 #else
 
 static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
@@ -202,4 +227,10 @@ static void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id,
 				  u32 fw_ver, u32 fw_flavor)
 {
 }
+
+static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
+				  struct btmtk_hci_wmt_params *wmt_params)
+{
+	return -EOPNOTSUPP;
+}
 #endif
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index b4e560a17aa6..39d6898497a4 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -20,6 +20,7 @@
 #include <linux/of.h>
 #include <linux/pm_runtime.h>
 #include <linux/skbuff.h>
+#include <linux/usb.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdio_ids.h>
diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c
index e6bc4a73c9fc..aa87c3e78871 100644
--- a/drivers/bluetooth/btmtkuart.c
+++ b/drivers/bluetooth/btmtkuart.c
@@ -22,6 +22,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/serdev.h>
 #include <linux/skbuff.h>
+#include <linux/usb.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 4ec18b58dc68..660e528fdd94 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2641,282 +2641,6 @@ static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
 	return hci_recv_frame(hdev, skb);
 }
 
-/* UHW CR mapping */
-#define MTK_BT_MISC		0x70002510
-#define MTK_BT_SUBSYS_RST	0x70002610
-#define MTK_UDMA_INT_STA_BT	0x74000024
-#define MTK_UDMA_INT_STA_BT1	0x74000308
-#define MTK_BT_WDT_STATUS	0x740003A0
-#define MTK_EP_RST_OPT		0x74011890
-#define MTK_EP_RST_IN_OUT_OPT	0x00010001
-#define MTK_BT_RST_DONE		0x00000100
-#define MTK_BT_RESET_REG_CONNV3	0x70028610
-#define MTK_BT_READ_DEV_ID	0x70010200
-
-
-static void btusb_mtk_wmt_recv(struct urb *urb)
-{
-	struct hci_dev *hdev = urb->context;
-	struct btusb_data *data = hci_get_drvdata(hdev);
-	struct sk_buff *skb;
-	int err;
-
-	if (urb->status == 0 && urb->actual_length > 0) {
-		hdev->stat.byte_rx += urb->actual_length;
-
-		/* WMT event shouldn't be fragmented and the size should be
-		 * less than HCI_WMT_MAX_EVENT_SIZE.
-		 */
-		skb = bt_skb_alloc(HCI_WMT_MAX_EVENT_SIZE, GFP_ATOMIC);
-		if (!skb) {
-			hdev->stat.err_rx++;
-			kfree(urb->setup_packet);
-			return;
-		}
-
-		hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
-		skb_put_data(skb, urb->transfer_buffer, urb->actual_length);
-
-		/* When someone waits for the WMT event, the skb is being cloned
-		 * and being processed the events from there then.
-		 */
-		if (test_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags)) {
-			data->evt_skb = skb_clone(skb, GFP_ATOMIC);
-			if (!data->evt_skb) {
-				kfree_skb(skb);
-				kfree(urb->setup_packet);
-				return;
-			}
-		}
-
-		err = hci_recv_frame(hdev, skb);
-		if (err < 0) {
-			kfree_skb(data->evt_skb);
-			data->evt_skb = NULL;
-			kfree(urb->setup_packet);
-			return;
-		}
-
-		if (test_and_clear_bit(BTUSB_TX_WAIT_VND_EVT,
-				       &data->flags)) {
-			/* Barrier to sync with other CPUs */
-			smp_mb__after_atomic();
-			wake_up_bit(&data->flags,
-				    BTUSB_TX_WAIT_VND_EVT);
-		}
-		kfree(urb->setup_packet);
-		return;
-	} else if (urb->status == -ENOENT) {
-		/* Avoid suspend failed when usb_kill_urb */
-		return;
-	}
-
-	usb_mark_last_busy(data->udev);
-
-	/* The URB complete handler is still called with urb->actual_length = 0
-	 * when the event is not available, so we should keep re-submitting
-	 * URB until WMT event returns, Also, It's necessary to wait some time
-	 * between the two consecutive control URBs to relax the target device
-	 * to generate the event. Otherwise, the WMT event cannot return from
-	 * the device successfully.
-	 */
-	udelay(500);
-
-	usb_anchor_urb(urb, &data->ctrl_anchor);
-	err = usb_submit_urb(urb, GFP_ATOMIC);
-	if (err < 0) {
-		kfree(urb->setup_packet);
-		/* -EPERM: urb is being killed;
-		 * -ENODEV: device got disconnected
-		 */
-		if (err != -EPERM && err != -ENODEV)
-			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
-				   urb, -err);
-		usb_unanchor_urb(urb);
-	}
-}
-
-static int btusb_mtk_submit_wmt_recv_urb(struct hci_dev *hdev)
-{
-	struct btusb_data *data = hci_get_drvdata(hdev);
-	struct usb_ctrlrequest *dr;
-	unsigned char *buf;
-	int err, size = 64;
-	unsigned int pipe;
-	struct urb *urb;
-
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb)
-		return -ENOMEM;
-
-	dr = kmalloc(sizeof(*dr), GFP_KERNEL);
-	if (!dr) {
-		usb_free_urb(urb);
-		return -ENOMEM;
-	}
-
-	dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_IN;
-	dr->bRequest     = 1;
-	dr->wIndex       = cpu_to_le16(0);
-	dr->wValue       = cpu_to_le16(48);
-	dr->wLength      = cpu_to_le16(size);
-
-	buf = kmalloc(size, GFP_KERNEL);
-	if (!buf) {
-		kfree(dr);
-		usb_free_urb(urb);
-		return -ENOMEM;
-	}
-
-	pipe = usb_rcvctrlpipe(data->udev, 0);
-
-	usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
-			     buf, size, btusb_mtk_wmt_recv, hdev);
-
-	urb->transfer_flags |= URB_FREE_BUFFER;
-
-	usb_anchor_urb(urb, &data->ctrl_anchor);
-	err = usb_submit_urb(urb, GFP_KERNEL);
-	if (err < 0) {
-		if (err != -EPERM && err != -ENODEV)
-			bt_dev_err(hdev, "urb %p submission failed (%d)",
-				   urb, -err);
-		usb_unanchor_urb(urb);
-	}
-
-	usb_free_urb(urb);
-
-	return err;
-}
-
-static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
-				  struct btmtk_hci_wmt_params *wmt_params)
-{
-	struct btusb_data *data = hci_get_drvdata(hdev);
-	struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
-	u32 hlen, status = BTMTK_WMT_INVALID;
-	struct btmtk_hci_wmt_evt *wmt_evt;
-	struct btmtk_hci_wmt_cmd *wc;
-	struct btmtk_wmt_hdr *hdr;
-	int err;
-
-	/* Send the WMT command and wait until the WMT event returns */
-	hlen = sizeof(*hdr) + wmt_params->dlen;
-	if (hlen > 255)
-		return -EINVAL;
-
-	wc = kzalloc(hlen, GFP_KERNEL);
-	if (!wc)
-		return -ENOMEM;
-
-	hdr = &wc->hdr;
-	hdr->dir = 1;
-	hdr->op = wmt_params->op;
-	hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
-	hdr->flag = wmt_params->flag;
-	memcpy(wc->data, wmt_params->data, wmt_params->dlen);
-
-	set_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
-
-	/* WMT cmd/event doesn't follow up the generic HCI cmd/event handling,
-	 * it needs constantly polling control pipe until the host received the
-	 * WMT event, thus, we should require to specifically acquire PM counter
-	 * on the USB to prevent the interface from entering auto suspended
-	 * while WMT cmd/event in progress.
-	 */
-	err = usb_autopm_get_interface(data->intf);
-	if (err < 0)
-		goto err_free_wc;
-
-	err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
-
-	if (err < 0) {
-		clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
-		usb_autopm_put_interface(data->intf);
-		goto err_free_wc;
-	}
-
-	/* Submit control IN URB on demand to process the WMT event */
-	err = btusb_mtk_submit_wmt_recv_urb(hdev);
-
-	usb_autopm_put_interface(data->intf);
-
-	if (err < 0)
-		goto err_free_wc;
-
-	/* The vendor specific WMT commands are all answered by a vendor
-	 * specific event and will have the Command Status or Command
-	 * Complete as with usual HCI command flow control.
-	 *
-	 * After sending the command, wait for BTUSB_TX_WAIT_VND_EVT
-	 * state to be cleared. The driver specific event receive routine
-	 * will clear that state and with that indicate completion of the
-	 * WMT command.
-	 */
-	err = wait_on_bit_timeout(&data->flags, BTUSB_TX_WAIT_VND_EVT,
-				  TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT);
-	if (err == -EINTR) {
-		bt_dev_err(hdev, "Execution of wmt command interrupted");
-		clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
-		goto err_free_wc;
-	}
-
-	if (err) {
-		bt_dev_err(hdev, "Execution of wmt command timed out");
-		clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
-		err = -ETIMEDOUT;
-		goto err_free_wc;
-	}
-
-	if (data->evt_skb == NULL)
-		goto err_free_wc;
-
-	/* Parse and handle the return WMT event */
-	wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
-	if (wmt_evt->whdr.op != hdr->op) {
-		bt_dev_err(hdev, "Wrong op received %d expected %d",
-			   wmt_evt->whdr.op, hdr->op);
-		err = -EIO;
-		goto err_free_skb;
-	}
-
-	switch (wmt_evt->whdr.op) {
-	case BTMTK_WMT_SEMAPHORE:
-		if (wmt_evt->whdr.flag == 2)
-			status = BTMTK_WMT_PATCH_UNDONE;
-		else
-			status = BTMTK_WMT_PATCH_DONE;
-		break;
-	case BTMTK_WMT_FUNC_CTRL:
-		wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
-		if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
-			status = BTMTK_WMT_ON_DONE;
-		else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
-			status = BTMTK_WMT_ON_PROGRESS;
-		else
-			status = BTMTK_WMT_ON_UNDONE;
-		break;
-	case BTMTK_WMT_PATCH_DWNLD:
-		if (wmt_evt->whdr.flag == 2)
-			status = BTMTK_WMT_PATCH_DONE;
-		else if (wmt_evt->whdr.flag == 1)
-			status = BTMTK_WMT_PATCH_PROGRESS;
-		else
-			status = BTMTK_WMT_PATCH_UNDONE;
-		break;
-	}
-
-	if (wmt_params->status)
-		*wmt_params->status = status;
-
-err_free_skb:
-	kfree_skb(data->evt_skb);
-	data->evt_skb = NULL;
-err_free_wc:
-	kfree(wc);
-	return err;
-}
-
 static int btusb_mtk_func_query(struct hci_dev *hdev)
 {
 	struct btmtk_hci_wmt_params wmt_params;
@@ -2930,7 +2654,7 @@ static int btusb_mtk_func_query(struct hci_dev *hdev)
 	wmt_params.data = &param;
 	wmt_params.status = &status;
 
-	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
+	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
 	if (err < 0) {
 		bt_dev_err(hdev, "Failed to query function status (%d)", err);
 		return err;
@@ -3251,7 +2975,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 				      fw_version, fw_flavor);
 
 		err = btmtk_setup_firmware_79xx(hdev, fw_bin_name,
-						btusb_mtk_hci_wmt_sync);
+						btmtk_usb_hci_wmt_sync);
 		if (err < 0) {
 			bt_dev_err(hdev, "Failed to set up firmware (%d)", err);
 			clear_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
@@ -3271,7 +2995,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 		wmt_params.data = &param;
 		wmt_params.status = NULL;
 
-		err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
+		err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
 		if (err < 0) {
 			bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
 			return err;
@@ -3293,7 +3017,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 	wmt_params.data = NULL;
 	wmt_params.status = &status;
 
-	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
+	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
 	if (err < 0) {
 		bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
 		return err;
@@ -3306,7 +3030,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 
 	/* Setup a firmware which the device definitely requires */
 	err = btmtk_setup_firmware(hdev, fwname,
-				   btusb_mtk_hci_wmt_sync);
+				   btmtk_usb_hci_wmt_sync);
 	if (err < 0)
 		return err;
 
@@ -3335,7 +3059,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 	wmt_params.data = &param;
 	wmt_params.status = NULL;
 
-	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
+	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
 	if (err < 0) {
 		bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
 		return err;
@@ -3381,7 +3105,7 @@ static int btusb_mtk_shutdown(struct hci_dev *hdev)
 	wmt_params.data = &param;
 	wmt_params.status = NULL;
 
-	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
+	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
 	if (err < 0) {
 		bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
 		return err;
-- 
2.18.0



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

* [PATCH v7 6/8] Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c
  2024-07-04  6:01 [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support Chris Lu
                   ` (4 preceding siblings ...)
  2024-07-04  6:01 ` [PATCH v7 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c Chris Lu
@ 2024-07-04  6:01 ` Chris Lu
  2024-07-04  6:01 ` [PATCH v7 7/8] Bluetooth: btmtk: move btusb_recv_acl_mtk " Chris Lu
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Chris Lu @ 2024-07-04  6:01 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth, linux-kernel,
	linux-mediatek, Chris Lu

Move btusb_mtk_[setup, shutdown] and related function from
btusb.c to btmtk.c which holds vendor specific stuff and
would make btusb.c clean.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
 drivers/bluetooth/btmtk.c | 454 +++++++++++++++++++++++++++++++++++++-
 drivers/bluetooth/btmtk.h |  23 +-
 drivers/bluetooth/btusb.c | 452 ++-----------------------------------
 3 files changed, 484 insertions(+), 445 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 3443a0837a86..f5ecb8227d3b 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -5,6 +5,8 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/usb.h>
+#include <linux/iopoll.h>
+#include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -567,8 +569,8 @@ static int btmtk_usb_submit_wmt_recv_urb(struct hci_dev *hdev)
 	return err;
 }
 
-int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
-			   struct btmtk_hci_wmt_params *wmt_params)
+static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
+				  struct btmtk_hci_wmt_params *wmt_params)
 {
 	struct btmtk_data *data = hci_get_priv(hdev);
 	struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
@@ -694,7 +696,453 @@ int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
 	kfree(wc);
 	return err;
 }
-EXPORT_SYMBOL_GPL(btmtk_usb_hci_wmt_sync);
+
+static int btmtk_usb_func_query(struct hci_dev *hdev)
+{
+	struct btmtk_hci_wmt_params wmt_params;
+	int status, err;
+	u8 param = 0;
+
+	/* Query whether the function is enabled */
+	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
+	wmt_params.flag = 4;
+	wmt_params.dlen = sizeof(param);
+	wmt_params.data = &param;
+	wmt_params.status = &status;
+
+	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
+	if (err < 0) {
+		bt_dev_err(hdev, "Failed to query function status (%d)", err);
+		return err;
+	}
+
+	return status;
+}
+
+static int btmtk_usb_uhw_reg_write(struct hci_dev *hdev, u32 reg, u32 val)
+{
+	struct btmtk_data *data = hci_get_priv(hdev);
+	int pipe, err;
+	void *buf;
+
+	buf = kzalloc(4, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	put_unaligned_le32(val, buf);
+
+	pipe = usb_sndctrlpipe(data->udev, 0);
+	err = usb_control_msg(data->udev, pipe, 0x02,
+			      0x5E,
+			      reg >> 16, reg & 0xffff,
+			      buf, 4, USB_CTRL_SET_TIMEOUT);
+	if (err < 0)
+		bt_dev_err(hdev, "Failed to write uhw reg(%d)", err);
+
+	kfree(buf);
+
+	return err;
+}
+
+static int btmtk_usb_uhw_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
+{
+	struct btmtk_data *data = hci_get_priv(hdev);
+	int pipe, err;
+	void *buf;
+
+	buf = kzalloc(4, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	pipe = usb_rcvctrlpipe(data->udev, 0);
+	err = usb_control_msg(data->udev, pipe, 0x01,
+			      0xDE,
+			      reg >> 16, reg & 0xffff,
+			      buf, 4, USB_CTRL_GET_TIMEOUT);
+	if (err < 0) {
+		bt_dev_err(hdev, "Failed to read uhw reg(%d)", err);
+		goto err_free_buf;
+	}
+
+	*val = get_unaligned_le32(buf);
+	bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val);
+
+err_free_buf:
+	kfree(buf);
+
+	return err;
+}
+
+static int btmtk_usb_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
+{
+	struct btmtk_data *data = hci_get_priv(hdev);
+	int pipe, err, size = sizeof(u32);
+	void *buf;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	pipe = usb_rcvctrlpipe(data->udev, 0);
+	err = usb_control_msg(data->udev, pipe, 0x63,
+			      USB_TYPE_VENDOR | USB_DIR_IN,
+			      reg >> 16, reg & 0xffff,
+			      buf, size, USB_CTRL_GET_TIMEOUT);
+	if (err < 0)
+		goto err_free_buf;
+
+	*val = get_unaligned_le32(buf);
+
+err_free_buf:
+	kfree(buf);
+
+	return err;
+}
+
+static int btmtk_usb_id_get(struct hci_dev *hdev, u32 reg, u32 *id)
+{
+	return btmtk_usb_reg_read(hdev, reg, id);
+}
+
+static u32 btmtk_usb_reset_done(struct hci_dev *hdev)
+{
+	u32 val = 0;
+
+	btmtk_usb_uhw_reg_read(hdev, MTK_BT_MISC, &val);
+
+	return val & MTK_BT_RST_DONE;
+}
+
+int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
+{
+	u32 val;
+	int err;
+
+	if (dev_id == 0x7922) {
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
+		if (err < 0)
+			return err;
+		val |= 0x00002020;
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, val);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT, 0x00010001);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
+		if (err < 0)
+			return err;
+		val |= BIT(0);
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, val);
+		if (err < 0)
+			return err;
+		msleep(100);
+	} else if (dev_id == 0x7925) {
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
+		if (err < 0)
+			return err;
+		val |= (1 << 5);
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
+		if (err < 0)
+			return err;
+		val &= 0xFFFF00FF;
+		val |= (1 << 13);
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT, 0x00010001);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
+		if (err < 0)
+			return err;
+		val |= (1 << 0);
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT, 0x000000FF);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT, &val);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT1, 0x000000FF);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT1, &val);
+		if (err < 0)
+			return err;
+		msleep(100);
+	} else {
+		/* It's Device EndPoint Reset Option Register */
+		bt_dev_dbg(hdev, "Initiating reset mechanism via uhw");
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_WDT_STATUS, &val);
+		if (err < 0)
+			return err;
+		/* Reset the bluetooth chip via USB interface. */
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, 1);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT, 0x000000FF);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT, &val);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT1, 0x000000FF);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT1, &val);
+		if (err < 0)
+			return err;
+		/* MT7921 need to delay 20ms between toggle reset bit */
+		msleep(20);
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, 0);
+		if (err < 0)
+			return err;
+		err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
+		if (err < 0)
+			return err;
+	}
+
+	err = readx_poll_timeout(btmtk_usb_reset_done, hdev, val,
+				 val & MTK_BT_RST_DONE, 20000, 1000000);
+	if (err < 0)
+		bt_dev_err(hdev, "Reset timeout");
+
+	if (dev_id == 0x7922) {
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT, 0x000000FF);
+		if (err < 0)
+			return err;
+	}
+
+	err = btmtk_usb_id_get(hdev, 0x70010200, &val);
+	if (err < 0 || !val)
+		bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(btmtk_usb_subsys_reset);
+
+int btmtk_usb_setup(struct hci_dev *hdev)
+{
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+	struct btmtk_hci_wmt_params wmt_params;
+	ktime_t calltime, delta, rettime;
+	struct btmtk_tci_sleep tci_sleep;
+	unsigned long long duration;
+	struct sk_buff *skb;
+	const char *fwname;
+	int err, status;
+	u32 dev_id = 0;
+	char fw_bin_name[64];
+	u32 fw_version = 0, fw_flavor = 0;
+	u8 param;
+
+	calltime = ktime_get();
+
+	err = btmtk_usb_id_get(hdev, 0x80000008, &dev_id);
+	if (err < 0) {
+		bt_dev_err(hdev, "Failed to get device id (%d)", err);
+		return err;
+	}
+
+	if (!dev_id || dev_id != 0x7663) {
+		err = btmtk_usb_id_get(hdev, 0x70010200, &dev_id);
+		if (err < 0) {
+			bt_dev_err(hdev, "Failed to get device id (%d)", err);
+			return err;
+		}
+		err = btmtk_usb_id_get(hdev, 0x80021004, &fw_version);
+		if (err < 0) {
+			bt_dev_err(hdev, "Failed to get fw version (%d)", err);
+			return err;
+		}
+		err = btmtk_usb_id_get(hdev, 0x70010020, &fw_flavor);
+		if (err < 0) {
+			bt_dev_err(hdev, "Failed to get fw flavor (%d)", err);
+			return err;
+		}
+		fw_flavor = (fw_flavor & 0x00000080) >> 7;
+	}
+
+	btmtk_data->dev_id = dev_id;
+
+	err = btmtk_register_coredump(hdev, btmtk_data->drv_name, fw_version);
+	if (err < 0)
+		bt_dev_err(hdev, "Failed to register coredump (%d)", err);
+
+	switch (dev_id) {
+	case 0x7663:
+		fwname = FIRMWARE_MT7663;
+		break;
+	case 0x7668:
+		fwname = FIRMWARE_MT7668;
+		break;
+	case 0x7922:
+	case 0x7961:
+	case 0x7925:
+		/* Reset the device to ensure it's in the initial state before
+		 * downloading the firmware to ensure.
+		 */
+
+		if (!test_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags))
+			btmtk_usb_subsys_reset(hdev, dev_id);
+
+		btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id,
+				      fw_version, fw_flavor);
+
+		err = btmtk_setup_firmware_79xx(hdev, fw_bin_name,
+						btmtk_usb_hci_wmt_sync);
+		if (err < 0) {
+			bt_dev_err(hdev, "Failed to set up firmware (%d)", err);
+			clear_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags);
+			return err;
+		}
+
+		set_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags);
+
+		/* It's Device EndPoint Reset Option Register */
+		err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT,
+					      MTK_EP_RST_IN_OUT_OPT);
+		if (err < 0)
+			return err;
+
+		/* Enable Bluetooth protocol */
+		param = 1;
+		wmt_params.op = BTMTK_WMT_FUNC_CTRL;
+		wmt_params.flag = 0;
+		wmt_params.dlen = sizeof(param);
+		wmt_params.data = &param;
+		wmt_params.status = NULL;
+
+		err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
+		if (err < 0) {
+			bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
+			return err;
+		}
+
+		hci_set_msft_opcode(hdev, 0xFD30);
+		hci_set_aosp_capable(hdev);
+
+		goto done;
+	default:
+		bt_dev_err(hdev, "Unsupported hardware variant (%08x)",
+			   dev_id);
+		return -ENODEV;
+	}
+
+	/* Query whether the firmware is already download */
+	wmt_params.op = BTMTK_WMT_SEMAPHORE;
+	wmt_params.flag = 1;
+	wmt_params.dlen = 0;
+	wmt_params.data = NULL;
+	wmt_params.status = &status;
+
+	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
+	if (err < 0) {
+		bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
+		return err;
+	}
+
+	if (status == BTMTK_WMT_PATCH_DONE) {
+		bt_dev_info(hdev, "firmware already downloaded");
+		goto ignore_setup_fw;
+	}
+
+	/* Setup a firmware which the device definitely requires */
+	err = btmtk_setup_firmware(hdev, fwname,
+				   btmtk_usb_hci_wmt_sync);
+	if (err < 0)
+		return err;
+
+ignore_setup_fw:
+	err = readx_poll_timeout(btmtk_usb_func_query, hdev, status,
+				 status < 0 || status != BTMTK_WMT_ON_PROGRESS,
+				 2000, 5000000);
+	/* -ETIMEDOUT happens */
+	if (err < 0)
+		return err;
+
+	/* The other errors happen in btmtk_usb_func_query */
+	if (status < 0)
+		return status;
+
+	if (status == BTMTK_WMT_ON_DONE) {
+		bt_dev_info(hdev, "function already on");
+		goto ignore_func_on;
+	}
+
+	/* Enable Bluetooth protocol */
+	param = 1;
+	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
+	wmt_params.flag = 0;
+	wmt_params.dlen = sizeof(param);
+	wmt_params.data = &param;
+	wmt_params.status = NULL;
+
+	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
+	if (err < 0) {
+		bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
+		return err;
+	}
+
+ignore_func_on:
+	/* Apply the low power environment setup */
+	tci_sleep.mode = 0x5;
+	tci_sleep.duration = cpu_to_le16(0x640);
+	tci_sleep.host_duration = cpu_to_le16(0x640);
+	tci_sleep.host_wakeup_pin = 0;
+	tci_sleep.time_compensation = 0;
+
+	skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep,
+			     HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		err = PTR_ERR(skb);
+		bt_dev_err(hdev, "Failed to apply low power setting (%d)", err);
+		return err;
+	}
+	kfree_skb(skb);
+
+done:
+	rettime = ktime_get();
+	delta = ktime_sub(rettime, calltime);
+	duration = (unsigned long long)ktime_to_ns(delta) >> 10;
+
+	bt_dev_info(hdev, "Device setup in %llu usecs", duration);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btmtk_usb_setup);
+
+int btmtk_usb_shutdown(struct hci_dev *hdev)
+{
+	struct btmtk_hci_wmt_params wmt_params;
+	u8 param = 0;
+	int err;
+
+	/* Disable the device */
+	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
+	wmt_params.flag = 0;
+	wmt_params.dlen = sizeof(param);
+	wmt_params.data = &param;
+	wmt_params.status = NULL;
+
+	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
+	if (err < 0) {
+		bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
+		return err;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btmtk_usb_shutdown);
 
 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
 MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>");
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index 3055b9728ae2..fe41528ae509 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -140,6 +140,8 @@ struct btmtk_hci_wmt_params {
 
 enum {
 	BTMTK_TX_WAIT_VND_EVT,
+	BTMTK_FIRMWARE_LOADED,
+	BTMTK_HW_RESET_ACTIVE,
 };
 
 typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);
@@ -152,6 +154,7 @@ struct btmtk_coredump_info {
 };
 
 struct btmtk_data {
+	const char *drv_name;
 	unsigned long flags;
 	u32 dev_id;
 	btmtk_reset_sync_func_t reset_sync;
@@ -186,8 +189,11 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb);
 void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver,
 			   u32 fw_flavor);
 
-int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
-			   struct btmtk_hci_wmt_params *wmt_params);
+int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id);
+
+int btmtk_usb_setup(struct hci_dev *hdev);
+
+int btmtk_usb_shutdown(struct hci_dev *hdev);
 #else
 
 static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
@@ -228,8 +234,17 @@ static void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id,
 {
 }
 
-static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
-				  struct btmtk_hci_wmt_params *wmt_params)
+static int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
+{
+	return -EOPNOTSUPP;
+}
+
+static int btmtk_usb_setup(struct hci_dev *hdev)
+{
+	return -EOPNOTSUPP;
+}
+
+static int btmtk_usb_shutdown(struct hci_dev *hdev)
 {
 	return -EOPNOTSUPP;
 }
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 660e528fdd94..d61a1d02e3e3 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2641,241 +2641,6 @@ static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
 	return hci_recv_frame(hdev, skb);
 }
 
-static int btusb_mtk_func_query(struct hci_dev *hdev)
-{
-	struct btmtk_hci_wmt_params wmt_params;
-	int status, err;
-	u8 param = 0;
-
-	/* Query whether the function is enabled */
-	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
-	wmt_params.flag = 4;
-	wmt_params.dlen = sizeof(param);
-	wmt_params.data = &param;
-	wmt_params.status = &status;
-
-	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
-	if (err < 0) {
-		bt_dev_err(hdev, "Failed to query function status (%d)", err);
-		return err;
-	}
-
-	return status;
-}
-
-static int btusb_mtk_uhw_reg_write(struct btusb_data *data, u32 reg, u32 val)
-{
-	struct hci_dev *hdev = data->hdev;
-	int pipe, err;
-	void *buf;
-
-	buf = kzalloc(4, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	put_unaligned_le32(val, buf);
-
-	pipe = usb_sndctrlpipe(data->udev, 0);
-	err = usb_control_msg(data->udev, pipe, 0x02,
-			      0x5E,
-			      reg >> 16, reg & 0xffff,
-			      buf, 4, USB_CTRL_SET_TIMEOUT);
-	if (err < 0)
-		bt_dev_err(hdev, "Failed to write uhw reg(%d)", err);
-
-	kfree(buf);
-
-	return err;
-}
-
-static int btusb_mtk_uhw_reg_read(struct btusb_data *data, u32 reg, u32 *val)
-{
-	struct hci_dev *hdev = data->hdev;
-	int pipe, err;
-	void *buf;
-
-	buf = kzalloc(4, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	pipe = usb_rcvctrlpipe(data->udev, 0);
-	err = usb_control_msg(data->udev, pipe, 0x01,
-			      0xDE,
-			      reg >> 16, reg & 0xffff,
-			      buf, 4, USB_CTRL_GET_TIMEOUT);
-	if (err < 0) {
-		bt_dev_err(hdev, "Failed to read uhw reg(%d)", err);
-		goto err_free_buf;
-	}
-
-	*val = get_unaligned_le32(buf);
-	bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val);
-
-err_free_buf:
-	kfree(buf);
-
-	return err;
-}
-
-static int btusb_mtk_reg_read(struct btusb_data *data, u32 reg, u32 *val)
-{
-	int pipe, err, size = sizeof(u32);
-	void *buf;
-
-	buf = kzalloc(size, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	pipe = usb_rcvctrlpipe(data->udev, 0);
-	err = usb_control_msg(data->udev, pipe, 0x63,
-			      USB_TYPE_VENDOR | USB_DIR_IN,
-			      reg >> 16, reg & 0xffff,
-			      buf, size, USB_CTRL_GET_TIMEOUT);
-	if (err < 0)
-		goto err_free_buf;
-
-	*val = get_unaligned_le32(buf);
-
-err_free_buf:
-	kfree(buf);
-
-	return err;
-}
-
-static int btusb_mtk_id_get(struct btusb_data *data, u32 reg, u32 *id)
-{
-	return btusb_mtk_reg_read(data, reg, id);
-}
-
-static u32 btusb_mtk_reset_done(struct hci_dev *hdev)
-{
-	struct btusb_data *data = hci_get_drvdata(hdev);
-	u32 val = 0;
-
-	btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val);
-
-	return val & MTK_BT_RST_DONE;
-}
-
-static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id)
-{
-	struct btusb_data *data = hci_get_drvdata(hdev);
-	u32 val;
-	int err;
-
-	if (dev_id == 0x7922) {
-		err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
-		if (err < 0)
-			return err;
-		val |= 0x00002020;
-		err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
-		if (err < 0)
-			return err;
-		val |= BIT(0);
-		err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val);
-		if (err < 0)
-			return err;
-		msleep(100);
-	} else if (dev_id == 0x7925) {
-		err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
-		if (err < 0)
-			return err;
-		val |= (1 << 5);
-		err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
-		if (err < 0)
-			return err;
-		val &= 0xFFFF00FF;
-		if (err < 0)
-			return err;
-		val |= (1 << 13);
-		err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
-		if (err < 0)
-			return err;
-		val |= (1 << 0);
-		err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
-		if (err < 0)
-			return err;
-		msleep(100);
-	} else {
-		/* It's Device EndPoint Reset Option Register */
-		bt_dev_dbg(hdev, "Initiating reset mechanism via uhw");
-		err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val);
-		if (err < 0)
-			return err;
-		/* Reset the bluetooth chip via USB interface. */
-		err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
-		if (err < 0)
-			return err;
-		/* MT7921 need to delay 20ms between toggle reset bit */
-		msleep(20);
-		err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
-		if (err < 0)
-			return err;
-		err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
-		if (err < 0)
-			return err;
-	}
-
-	err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val,
-				 val & MTK_BT_RST_DONE, 20000, 1000000);
-	if (err < 0)
-		bt_dev_err(hdev, "Reset timeout");
-
-	if (dev_id == 0x7922) {
-		err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
-		if (err < 0)
-			return err;
-	}
-
-	err = btusb_mtk_id_get(data, 0x70010200, &val);
-	if (err < 0 || !val)
-		bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
-
-	return err;
-}
-
 static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -2883,7 +2648,7 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
 	int err;
 
 	/* It's MediaTek specific bluetooth reset mechanism via USB */
-	if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
+	if (test_and_set_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags)) {
 		bt_dev_err(hdev, "last reset failed? Not resetting again");
 		return -EBUSY;
 	}
@@ -2895,10 +2660,10 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
 	btusb_stop_traffic(data);
 	usb_kill_anchored_urbs(&data->tx_anchor);
 
-	err = btusb_mtk_subsys_reset(hdev, btmtk_data->dev_id);
+	err = btmtk_usb_subsys_reset(hdev, btmtk_data->dev_id);
 
 	usb_queue_reset_device(data->intf);
-	clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags);
+	clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
 
 	return err;
 }
@@ -2906,212 +2671,23 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
 static int btusb_mtk_setup(struct hci_dev *hdev)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
-	struct btmtk_hci_wmt_params wmt_params;
-	ktime_t calltime, delta, rettime;
-	struct btmtk_tci_sleep tci_sleep;
-	unsigned long long duration;
-	struct sk_buff *skb;
-	const char *fwname;
-	int err, status;
-	u32 dev_id = 0;
-	char fw_bin_name[64];
-	u32 fw_version = 0, fw_flavor = 0;
-	u8 param;
-	struct btmtk_data *mediatek;
-
-	calltime = ktime_get();
-
-	err = btusb_mtk_id_get(data, 0x80000008, &dev_id);
-	if (err < 0) {
-		bt_dev_err(hdev, "Failed to get device id (%d)", err);
-		return err;
-	}
-
-	if (!dev_id || dev_id != 0x7663) {
-		err = btusb_mtk_id_get(data, 0x70010200, &dev_id);
-		if (err < 0) {
-			bt_dev_err(hdev, "Failed to get device id (%d)", err);
-			return err;
-		}
-		err = btusb_mtk_id_get(data, 0x80021004, &fw_version);
-		if (err < 0) {
-			bt_dev_err(hdev, "Failed to get fw version (%d)", err);
-			return err;
-		}
-		err = btusb_mtk_id_get(data, 0x70010020, &fw_flavor);
-		if (err < 0) {
-			bt_dev_err(hdev, "Failed to get fw flavor (%d)", err);
-			return err;
-		}
-		fw_flavor = (fw_flavor & 0x00000080) >> 7;
-	}
-
-	mediatek = hci_get_priv(hdev);
-	mediatek->dev_id = dev_id;
-	mediatek->reset_sync = btusb_mtk_reset;
-
-	err = btmtk_register_coredump(hdev, btusb_driver.name, fw_version);
-	if (err < 0)
-		bt_dev_err(hdev, "Failed to register coredump (%d)", err);
-
-	switch (dev_id) {
-	case 0x7663:
-		fwname = FIRMWARE_MT7663;
-		break;
-	case 0x7668:
-		fwname = FIRMWARE_MT7668;
-		break;
-	case 0x7922:
-	case 0x7961:
-	case 0x7925:
-		/* Reset the device to ensure it's in the initial state before
-		 * downloading the firmware to ensure.
-		 */
-
-		if (!test_bit(BTUSB_FIRMWARE_LOADED, &data->flags))
-			btusb_mtk_subsys_reset(hdev, dev_id);
-
-		btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id,
-				      fw_version, fw_flavor);
-
-		err = btmtk_setup_firmware_79xx(hdev, fw_bin_name,
-						btmtk_usb_hci_wmt_sync);
-		if (err < 0) {
-			bt_dev_err(hdev, "Failed to set up firmware (%d)", err);
-			clear_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
-			return err;
-		}
-
-		set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
-
-		/* It's Device EndPoint Reset Option Register */
-		btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
-
-		/* Enable Bluetooth protocol */
-		param = 1;
-		wmt_params.op = BTMTK_WMT_FUNC_CTRL;
-		wmt_params.flag = 0;
-		wmt_params.dlen = sizeof(param);
-		wmt_params.data = &param;
-		wmt_params.status = NULL;
-
-		err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
-		if (err < 0) {
-			bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
-			return err;
-		}
-
-		hci_set_msft_opcode(hdev, 0xFD30);
-		hci_set_aosp_capable(hdev);
-		goto done;
-	default:
-		bt_dev_err(hdev, "Unsupported hardware variant (%08x)",
-			   dev_id);
-		return -ENODEV;
-	}
-
-	/* Query whether the firmware is already download */
-	wmt_params.op = BTMTK_WMT_SEMAPHORE;
-	wmt_params.flag = 1;
-	wmt_params.dlen = 0;
-	wmt_params.data = NULL;
-	wmt_params.status = &status;
-
-	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
-	if (err < 0) {
-		bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
-		return err;
-	}
-
-	if (status == BTMTK_WMT_PATCH_DONE) {
-		bt_dev_info(hdev, "firmware already downloaded");
-		goto ignore_setup_fw;
-	}
-
-	/* Setup a firmware which the device definitely requires */
-	err = btmtk_setup_firmware(hdev, fwname,
-				   btmtk_usb_hci_wmt_sync);
-	if (err < 0)
-		return err;
-
-ignore_setup_fw:
-	err = readx_poll_timeout(btusb_mtk_func_query, hdev, status,
-				 status < 0 || status != BTMTK_WMT_ON_PROGRESS,
-				 2000, 5000000);
-	/* -ETIMEDOUT happens */
-	if (err < 0)
-		return err;
-
-	/* The other errors happen in btusb_mtk_func_query */
-	if (status < 0)
-		return status;
-
-	if (status == BTMTK_WMT_ON_DONE) {
-		bt_dev_info(hdev, "function already on");
-		goto ignore_func_on;
-	}
-
-	/* Enable Bluetooth protocol */
-	param = 1;
-	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
-	wmt_params.flag = 0;
-	wmt_params.dlen = sizeof(param);
-	wmt_params.data = &param;
-	wmt_params.status = NULL;
-
-	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
-	if (err < 0) {
-		bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
-		return err;
-	}
-
-ignore_func_on:
-	/* Apply the low power environment setup */
-	tci_sleep.mode = 0x5;
-	tci_sleep.duration = cpu_to_le16(0x640);
-	tci_sleep.host_duration = cpu_to_le16(0x640);
-	tci_sleep.host_wakeup_pin = 0;
-	tci_sleep.time_compensation = 0;
-
-	skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep,
-			     HCI_INIT_TIMEOUT);
-	if (IS_ERR(skb)) {
-		err = PTR_ERR(skb);
-		bt_dev_err(hdev, "Failed to apply low power setting (%d)", err);
-		return err;
-	}
-	kfree_skb(skb);
-
-done:
-	rettime = ktime_get();
-	delta = ktime_sub(rettime, calltime);
-	duration = (unsigned long long)ktime_to_ns(delta) >> 10;
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
 
-	bt_dev_info(hdev, "Device setup in %llu usecs", duration);
+	/* MediaTek WMT vendor cmd requiring below USB resources to
+	 * complete the handshake.
+	 */
+	btmtk_data->drv_name = btusb_driver.name;
+	btmtk_data->intf = data->intf;
+	btmtk_data->udev = data->udev;
+	btmtk_data->ctrl_anchor = &data->ctrl_anchor;
+	btmtk_data->reset_sync = btusb_mtk_reset;
 
-	return 0;
+	return btmtk_usb_setup(hdev);
 }
 
 static int btusb_mtk_shutdown(struct hci_dev *hdev)
 {
-	struct btmtk_hci_wmt_params wmt_params;
-	u8 param = 0;
-	int err;
-
-	/* Disable the device */
-	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
-	wmt_params.flag = 0;
-	wmt_params.dlen = sizeof(param);
-	wmt_params.data = &param;
-	wmt_params.status = NULL;
-
-	err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
-	if (err < 0) {
-		bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
-		return err;
-	}
-
-	return 0;
+	return btmtk_usb_shutdown(hdev);
 }
 
 static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
-- 
2.18.0



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

* [PATCH v7 7/8] Bluetooth: btmtk: move btusb_recv_acl_mtk to btmtk.c
  2024-07-04  6:01 [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support Chris Lu
                   ` (5 preceding siblings ...)
  2024-07-04  6:01 ` [PATCH v7 6/8] Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] " Chris Lu
@ 2024-07-04  6:01 ` Chris Lu
  2024-07-04  6:01 ` [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions Chris Lu
  2024-07-08 21:20 ` [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support patchwork-bot+bluetooth
  8 siblings, 0 replies; 17+ messages in thread
From: Chris Lu @ 2024-07-04  6:01 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth, linux-kernel,
	linux-mediatek, Chris Lu

Move btusb_recv_acl_mtk from btusb.c to btmtk.c which holds
vendor specific stuff and would make btusb.c clean.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
 drivers/bluetooth/btmtk.c | 33 +++++++++++++++++++++++++++++++++
 drivers/bluetooth/btmtk.h |  7 +++++++
 drivers/bluetooth/btusb.c | 34 +---------------------------------
 3 files changed, 41 insertions(+), 33 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index f5ecb8227d3b..fe3b892f6c6e 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -930,6 +930,39 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
 }
 EXPORT_SYMBOL_GPL(btmtk_usb_subsys_reset);
 
+int btmtk_usb_recv_acl(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct btmtk_data *data = hci_get_priv(hdev);
+	u16 handle = le16_to_cpu(hci_acl_hdr(skb)->handle);
+
+	switch (handle) {
+	case 0xfc6f:		/* Firmware dump from device */
+		/* When the firmware hangs, the device can no longer
+		 * suspend and thus disable auto-suspend.
+		 */
+		usb_disable_autosuspend(data->udev);
+
+		/* We need to forward the diagnostic packet to userspace daemon
+		 * for backward compatibility, so we have to clone the packet
+		 * extraly for the in-kernel coredump support.
+		 */
+		if (IS_ENABLED(CONFIG_DEV_COREDUMP)) {
+			struct sk_buff *skb_cd = skb_clone(skb, GFP_ATOMIC);
+
+			if (skb_cd)
+				btmtk_process_coredump(hdev, skb_cd);
+		}
+
+		fallthrough;
+	case 0x05ff:		/* Firmware debug logging 1 */
+	case 0x05fe:		/* Firmware debug logging 2 */
+		return hci_recv_diag(hdev, skb);
+	}
+
+	return hci_recv_frame(hdev, skb);
+}
+EXPORT_SYMBOL_GPL(btmtk_usb_recv_acl);
+
 int btmtk_usb_setup(struct hci_dev *hdev)
 {
 	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index fe41528ae509..47193b867b9f 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -191,6 +191,8 @@ void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver,
 
 int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id);
 
+int btmtk_usb_recv_acl(struct hci_dev *hdev, struct sk_buff *skb);
+
 int btmtk_usb_setup(struct hci_dev *hdev);
 
 int btmtk_usb_shutdown(struct hci_dev *hdev);
@@ -239,6 +241,11 @@ static int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
 	return -EOPNOTSUPP;
 }
 
+static int btmtk_usb_recv_acl(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	return -EOPNOTSUPP;
+}
+
 static int btmtk_usb_setup(struct hci_dev *hdev)
 {
 	return -EOPNOTSUPP;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index d61a1d02e3e3..5de50c835964 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2690,38 +2690,6 @@ static int btusb_mtk_shutdown(struct hci_dev *hdev)
 	return btmtk_usb_shutdown(hdev);
 }
 
-static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
-{
-	struct btusb_data *data = hci_get_drvdata(hdev);
-	u16 handle = le16_to_cpu(hci_acl_hdr(skb)->handle);
-
-	switch (handle) {
-	case 0xfc6f:		/* Firmware dump from device */
-		/* When the firmware hangs, the device can no longer
-		 * suspend and thus disable auto-suspend.
-		 */
-		usb_disable_autosuspend(data->udev);
-
-		/* We need to forward the diagnostic packet to userspace daemon
-		 * for backward compatibility, so we have to clone the packet
-		 * extraly for the in-kernel coredump support.
-		 */
-		if (IS_ENABLED(CONFIG_DEV_COREDUMP)) {
-			struct sk_buff *skb_cd = skb_clone(skb, GFP_ATOMIC);
-
-			if (skb_cd)
-				btmtk_process_coredump(hdev, skb_cd);
-		}
-
-		fallthrough;
-	case 0x05ff:		/* Firmware debug logging 1 */
-	case 0x05fe:		/* Firmware debug logging 2 */
-		return hci_recv_diag(hdev, skb);
-	}
-
-	return hci_recv_frame(hdev, skb);
-}
-
 #ifdef CONFIG_PM
 /* Configure an out-of-band gpio as wake-up pin, if specified in device tree */
 static int marvell_config_oob_wake(struct hci_dev *hdev)
@@ -3827,7 +3795,7 @@ static int btusb_probe(struct usb_interface *intf,
 		hdev->set_bdaddr = btmtk_set_bdaddr;
 		set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
 		set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
-		data->recv_acl = btusb_recv_acl_mtk;
+		data->recv_acl = btmtk_usb_recv_acl;
 	}
 
 	if (id->driver_info & BTUSB_SWAVE) {
-- 
2.18.0



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

* [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions
  2024-07-04  6:01 [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support Chris Lu
                   ` (6 preceding siblings ...)
  2024-07-04  6:01 ` [PATCH v7 7/8] Bluetooth: btmtk: move btusb_recv_acl_mtk " Chris Lu
@ 2024-07-04  6:01 ` Chris Lu
  2024-07-05  9:11   ` kernel test robot
  2024-07-15 22:36   ` Nícolas F. R. A. Prado
  2024-07-08 21:20 ` [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support patchwork-bot+bluetooth
  8 siblings, 2 replies; 17+ messages in thread
From: Chris Lu @ 2024-07-04  6:01 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth, linux-kernel,
	linux-mediatek, Chris Lu

This patch implements functions for ISO data send and receive in btusb
driver for MediaTek's controller.

MediaTek defines a specific interrupt endpoint for ISO data transmissin
because the characteristics of interrupt endpoint are similar to the
application of ISO data which can support guaranteed transmissin
bandwidth, enough maximum data length and error checking mechanism.

Driver sets up ISO interface and endpoints in btusb_mtk_setup and clears
the setup in btusb_mtk_shutdown. These flow can't move to btmtk.c due to
btusb_driver is only defined in btusb.c when claiming/relaesing interface.
ISO packet anchor stops when driver suspending and resubmit interrupt urb
for ISO data when driver resuming.

Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
 drivers/bluetooth/btmtk.c | 311 ++++++++++++++++++++++++++++++++++++++
 drivers/bluetooth/btmtk.h |  36 +++++
 drivers/bluetooth/btusb.c |  68 +++++++++
 3 files changed, 415 insertions(+)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index fe3b892f6c6e..b7c348687a77 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -22,6 +22,9 @@
 #define MTK_SEC_MAP_COMMON_SIZE	12
 #define MTK_SEC_MAP_NEED_SEND_SIZE	52
 
+/* It is for mt79xx iso data transmission setting */
+#define MTK_ISO_THRESHOLD	264
+
 struct btmtk_patch_header {
 	u8 datetime[16];
 	u8 platform[4];
@@ -963,6 +966,308 @@ int btmtk_usb_recv_acl(struct hci_dev *hdev, struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(btmtk_usb_recv_acl);
 
+static int btmtk_isopkt_pad(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	if (skb->len > MTK_ISO_THRESHOLD)
+		return -EINVAL;
+
+	if (skb_pad(skb, MTK_ISO_THRESHOLD - skb->len))
+		return -ENOMEM;
+
+	__skb_put(skb, MTK_ISO_THRESHOLD - skb->len);
+
+	return 0;
+}
+
+static int __set_mtk_intr_interface(struct hci_dev *hdev)
+{
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+	struct usb_interface *intf = btmtk_data->isopkt_intf;
+	int i, err;
+
+	if (!btmtk_data->isopkt_intf)
+		return -ENODEV;
+
+	err = usb_set_interface(btmtk_data->udev, MTK_ISO_IFNUM, 1);
+	if (err < 0) {
+		bt_dev_err(hdev, "setting interface failed (%d)", -err);
+		return err;
+	}
+
+	btmtk_data->isopkt_tx_ep = NULL;
+	btmtk_data->isopkt_rx_ep = NULL;
+
+	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+		struct usb_endpoint_descriptor *ep_desc;
+
+		ep_desc = &intf->cur_altsetting->endpoint[i].desc;
+
+		if (!btmtk_data->isopkt_tx_ep &&
+		    usb_endpoint_is_int_out(ep_desc)) {
+			btmtk_data->isopkt_tx_ep = ep_desc;
+			continue;
+		}
+
+		if (!btmtk_data->isopkt_rx_ep &&
+		    usb_endpoint_is_int_in(ep_desc)) {
+			btmtk_data->isopkt_rx_ep = ep_desc;
+			continue;
+		}
+	}
+
+	if (!btmtk_data->isopkt_tx_ep ||
+	    !btmtk_data->isopkt_rx_ep) {
+		bt_dev_err(hdev, "invalid interrupt descriptors");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+struct urb *alloc_mtk_intr_urb(struct hci_dev *hdev, struct sk_buff *skb,
+			       usb_complete_t tx_complete)
+{
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+	struct urb *urb;
+	unsigned int pipe;
+
+	if (!btmtk_data->isopkt_tx_ep)
+		return ERR_PTR(-ENODEV);
+
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb)
+		return ERR_PTR(-ENOMEM);
+
+	if (btmtk_isopkt_pad(hdev, skb))
+		return ERR_PTR(-EINVAL);
+
+	pipe = usb_sndintpipe(btmtk_data->udev,
+			      btmtk_data->isopkt_tx_ep->bEndpointAddress);
+
+	usb_fill_int_urb(urb, btmtk_data->udev, pipe,
+			 skb->data, skb->len, tx_complete,
+			 skb, btmtk_data->isopkt_tx_ep->bInterval);
+
+	skb->dev = (void *)hdev;
+
+	return urb;
+}
+EXPORT_SYMBOL_GPL(alloc_mtk_intr_urb);
+
+static int btmtk_recv_isopkt(struct hci_dev *hdev, void *buffer, int count)
+{
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+	struct sk_buff *skb;
+	unsigned long flags;
+	int err = 0;
+
+	spin_lock_irqsave(&btmtk_data->isorxlock, flags);
+	skb = btmtk_data->isopkt_skb;
+
+	while (count) {
+		int len;
+
+		if (!skb) {
+			skb = bt_skb_alloc(HCI_MAX_ISO_SIZE, GFP_ATOMIC);
+			if (!skb) {
+				err = -ENOMEM;
+				break;
+			}
+
+			hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
+			hci_skb_expect(skb) = HCI_ISO_HDR_SIZE;
+		}
+
+		len = min_t(uint, hci_skb_expect(skb), count);
+		skb_put_data(skb, buffer, len);
+
+		count -= len;
+		buffer += len;
+		hci_skb_expect(skb) -= len;
+
+		if (skb->len == HCI_ISO_HDR_SIZE) {
+			__le16 dlen = ((struct hci_iso_hdr *)skb->data)->dlen;
+
+			/* Complete ISO header */
+			hci_skb_expect(skb) = __le16_to_cpu(dlen);
+
+			if (skb_tailroom(skb) < hci_skb_expect(skb)) {
+				kfree_skb(skb);
+				skb = NULL;
+
+				err = -EILSEQ;
+				break;
+			}
+		}
+
+		if (!hci_skb_expect(skb)) {
+			/* Complete frame */
+			hci_recv_frame(hdev, skb);
+			skb = NULL;
+		}
+	}
+
+	btmtk_data->isopkt_skb = skb;
+	spin_unlock_irqrestore(&btmtk_data->isorxlock, flags);
+
+	return err;
+}
+
+static void btmtk_intr_complete(struct urb *urb)
+{
+	struct hci_dev *hdev = urb->context;
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+	int err;
+
+	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
+	       urb->actual_length);
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		return;
+
+	if (hdev->suspended)
+		return;
+
+	if (urb->status == 0) {
+		hdev->stat.byte_rx += urb->actual_length;
+
+		if (btmtk_recv_isopkt(hdev, urb->transfer_buffer,
+				      urb->actual_length) < 0) {
+			bt_dev_err(hdev, "corrupted iso packet");
+			hdev->stat.err_rx++;
+		}
+	} else if (urb->status == -ENOENT) {
+		/* Avoid suspend failed when usb_kill_urb */
+		return;
+	}
+
+	usb_mark_last_busy(btmtk_data->udev);
+	usb_anchor_urb(urb, &btmtk_data->isopkt_anchor);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err < 0) {
+		/* -EPERM: urb is being killed;
+		 * -ENODEV: device got disconnected
+		 */
+		if (err != -EPERM && err != -ENODEV)
+			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
+				   urb, -err);
+		if (err != -EPERM)
+			hci_cmd_sync_cancel(hdev, -err);
+		usb_unanchor_urb(urb);
+	}
+}
+
+static int btmtk_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
+{
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+	unsigned char *buf;
+	unsigned int pipe;
+	struct urb *urb;
+	int err, size;
+
+	BT_DBG("%s", hdev->name);
+
+	if (!btmtk_data->isopkt_rx_ep)
+		return -ENODEV;
+
+	urb = usb_alloc_urb(0, mem_flags);
+	if (!urb)
+		return -ENOMEM;
+	size = le16_to_cpu(btmtk_data->isopkt_rx_ep->wMaxPacketSize);
+
+	buf = kmalloc(size, mem_flags);
+	if (!buf) {
+		usb_free_urb(urb);
+		return -ENOMEM;
+	}
+
+	pipe = usb_rcvintpipe(btmtk_data->udev,
+			      btmtk_data->isopkt_rx_ep->bEndpointAddress);
+
+	usb_fill_int_urb(urb, btmtk_data->udev, pipe, buf, size,
+			 btmtk_intr_complete, hdev,
+			 btmtk_data->isopkt_rx_ep->bInterval);
+
+	urb->transfer_flags |= URB_FREE_BUFFER;
+
+	usb_mark_last_busy(btmtk_data->udev);
+	usb_anchor_urb(urb, &btmtk_data->isopkt_anchor);
+
+	err = usb_submit_urb(urb, mem_flags);
+	if (err < 0) {
+		if (err != -EPERM && err != -ENODEV)
+			bt_dev_err(hdev, "urb %p submission failed (%d)",
+				   urb, -err);
+		usb_unanchor_urb(urb);
+	}
+
+	usb_free_urb(urb);
+
+	return err;
+}
+
+static int btmtk_usb_isointf_init(struct hci_dev *hdev)
+{
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+	u8 iso_param[2] = { 0x08, 0x01 };
+	struct sk_buff *skb;
+	int err;
+
+	init_usb_anchor(&btmtk_data->isopkt_anchor);
+	spin_lock_init(&btmtk_data->isorxlock);
+
+	__set_mtk_intr_interface(hdev);
+
+	err = btmtk_submit_intr_urb(hdev, GFP_KERNEL);
+	if (err < 0) {
+		usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor);
+		bt_dev_err(hdev, "ISO intf not support (%d)", err);
+		return err;
+	}
+
+	skb = __hci_cmd_sync(hdev, 0xfd98, sizeof(iso_param), iso_param,
+			     HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		bt_dev_err(hdev, "Failed to apply iso setting (%ld)", PTR_ERR(skb));
+		return PTR_ERR(skb);
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
+int btmtk_usb_resume(struct hci_dev *hdev)
+{
+	/* This function describes the specific additional steps taken by MediaTek
+	 * when Bluetooth usb driver's resume function is called.
+	 */
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+
+	/* Resubmit urb for iso data transmission */
+	if (test_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags)) {
+		if (btmtk_submit_intr_urb(hdev, GFP_NOIO) < 0)
+			clear_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btmtk_usb_resume);
+
+int btmtk_usb_suspend(struct hci_dev *hdev)
+{
+	/* This function describes the specific additional steps taken by MediaTek
+	 * when Bluetooth usb driver's suspend function is called.
+	 */
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+
+	/* Stop urb anchor for iso data transmission */
+	usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btmtk_usb_suspend);
+
 int btmtk_usb_setup(struct hci_dev *hdev)
 {
 	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
@@ -1064,6 +1369,12 @@ int btmtk_usb_setup(struct hci_dev *hdev)
 		hci_set_msft_opcode(hdev, 0xFD30);
 		hci_set_aosp_capable(hdev);
 
+		/* Set up ISO interface after protocol enabled */
+		if (test_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags)) {
+			if (!btmtk_usb_isointf_init(hdev))
+				set_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags);
+		}
+
 		goto done;
 	default:
 		bt_dev_err(hdev, "Unsupported hardware variant (%08x)",
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index 47193b867b9f..453ed5131a37 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -40,6 +40,9 @@
 #define MTK_BT_RESET_REG_CONNV3	0x70028610
 #define MTK_BT_READ_DEV_ID	0x70010200
 
+/* MediaTek ISO Interface */
+#define MTK_ISO_IFNUM		2
+
 enum {
 	BTMTK_WMT_PATCH_DWNLD = 0x1,
 	BTMTK_WMT_TEST = 0x2,
@@ -142,6 +145,8 @@ enum {
 	BTMTK_TX_WAIT_VND_EVT,
 	BTMTK_FIRMWARE_LOADED,
 	BTMTK_HW_RESET_ACTIVE,
+	BTMTK_ISOPKT_OVER_INTR,
+	BTMTK_ISOPKT_RUNNING,
 };
 
 typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);
@@ -164,6 +169,14 @@ struct btmtk_data {
 	struct usb_interface *intf;
 	struct usb_anchor *ctrl_anchor;
 	struct sk_buff *evt_skb;
+	struct usb_endpoint_descriptor *isopkt_tx_ep;
+	struct usb_endpoint_descriptor *isopkt_rx_ep;
+	struct usb_interface *isopkt_intf;
+	struct usb_anchor isopkt_anchor;
+	struct sk_buff *isopkt_skb;
+
+	/* spinlock for ISO data transmission */
+	spinlock_t isorxlock;
 };
 
 typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
@@ -193,6 +206,13 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id);
 
 int btmtk_usb_recv_acl(struct hci_dev *hdev, struct sk_buff *skb);
 
+struct urb *alloc_mtk_intr_urb(struct hci_dev *hdev, struct sk_buff *skb,
+			       usb_complete_t tx_complete);
+
+int btmtk_usb_resume(struct hci_dev *hdev);
+
+int btmtk_usb_suspend(struct hci_dev *hdev);
+
 int btmtk_usb_setup(struct hci_dev *hdev);
 
 int btmtk_usb_shutdown(struct hci_dev *hdev);
@@ -246,6 +266,22 @@ static int btmtk_usb_recv_acl(struct hci_dev *hdev, struct sk_buff *skb)
 	return -EOPNOTSUPP;
 }
 
+static struct urb *alloc_mtk_intr_urb(struct hci_dev *hdev, struct sk_buff *skb,
+				      usb_complete_t tx_complete)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static int btmtk_usb_resume(struct hci_dev *hdev)
+{
+	return -EOPNOTSUPP;
+}
+
+static int btmtk_usb_suspend(struct hci_dev *hdev)
+{
+	return -EOPNOTSUPP;
+}
+
 static int btmtk_usb_setup(struct hci_dev *hdev)
 {
 	return -EOPNOTSUPP;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 5de50c835964..1a4ab5619ab5 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2641,6 +2641,40 @@ static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
 	return hci_recv_frame(hdev, skb);
 }
 
+static void btusb_mtk_claim_iso_intf(struct btusb_data *data)
+{
+	struct btmtk_data *btmtk_data = hci_get_priv(data->hdev);
+	int err;
+
+	err = usb_driver_claim_interface(&btusb_driver,
+					 btmtk_data->isopkt_intf, data);
+	if (err < 0) {
+		btmtk_data->isopkt_intf = NULL;
+		bt_dev_err(data->hdev, "Failed to claim iso interface");
+		return;
+	}
+
+	set_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);
+}
+
+static void btusb_mtk_release_iso_intf(struct btusb_data *data)
+{
+	struct btmtk_data *btmtk_data = hci_get_priv(data->hdev);
+
+	if (btmtk_data->isopkt_intf) {
+		usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor);
+		clear_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags);
+
+		dev_kfree_skb_irq(btmtk_data->isopkt_skb);
+		btmtk_data->isopkt_skb = NULL;
+		usb_set_intfdata(btmtk_data->isopkt_intf, NULL);
+		usb_driver_release_interface(&btusb_driver,
+					     btmtk_data->isopkt_intf);
+	}
+
+	clear_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);
+}
+
 static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -2657,6 +2691,9 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
 	if (err < 0)
 		return err;
 
+	if (test_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags))
+		btusb_mtk_release_iso_intf(data);
+
 	btusb_stop_traffic(data);
 	usb_kill_anchored_urbs(&data->tx_anchor);
 
@@ -2668,6 +2705,23 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
 	return err;
 }
 
+static int btusb_send_frame_mtk(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct urb *urb;
+
+	BT_DBG("%s", hdev->name);
+
+	if (hci_skb_pkt_type(skb) == HCI_ISODATA_PKT) {
+		urb = alloc_mtk_intr_urb(hdev, skb, btusb_tx_complete);
+		if (IS_ERR(urb))
+			return PTR_ERR(urb);
+
+		return submit_or_queue_tx_urb(hdev, urb);
+	} else {
+		return btusb_send_frame(hdev, skb);
+	}
+}
+
 static int btusb_mtk_setup(struct hci_dev *hdev)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -2682,11 +2736,22 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 	btmtk_data->ctrl_anchor = &data->ctrl_anchor;
 	btmtk_data->reset_sync = btusb_mtk_reset;
 
+	/* Claim ISO data interface and endpoint */
+	btmtk_data->isopkt_intf = usb_ifnum_to_if(data->udev, MTK_ISO_IFNUM);
+	if (btmtk_data->isopkt_intf)
+		btusb_mtk_claim_iso_intf(data);
+
 	return btmtk_usb_setup(hdev);
 }
 
 static int btusb_mtk_shutdown(struct hci_dev *hdev)
 {
+	struct btusb_data *data = hci_get_drvdata(hdev);
+	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+
+	if (test_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags))
+		btusb_mtk_release_iso_intf(data);
+
 	return btmtk_usb_shutdown(hdev);
 }
 
@@ -3793,9 +3858,12 @@ static int btusb_probe(struct usb_interface *intf,
 		hdev->manufacturer = 70;
 		hdev->cmd_timeout = btmtk_reset_sync;
 		hdev->set_bdaddr = btmtk_set_bdaddr;
+		hdev->send = btusb_send_frame_mtk;
 		set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
 		set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
 		data->recv_acl = btmtk_usb_recv_acl;
+		data->suspend = btmtk_usb_suspend;
+		data->resume = btmtk_usb_resume;
 	}
 
 	if (id->driver_info & BTUSB_SWAVE) {
-- 
2.18.0



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

* Re: [PATCH v7 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c
  2024-07-04  6:01 ` [PATCH v7 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c Chris Lu
@ 2024-07-05  6:09   ` kernel test robot
  2024-07-05  9:33   ` kernel test robot
  1 sibling, 0 replies; 17+ messages in thread
From: kernel test robot @ 2024-07-05  6:09 UTC (permalink / raw)
  To: Chris Lu, Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: oe-kbuild-all, Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth,
	linux-kernel, linux-mediatek, Chris Lu

Hi Chris,

kernel test robot noticed the following build errors:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20240703]
[cannot apply to bluetooth/master linus/master v6.10-rc6]
[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#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Chris-Lu/Bluetooth-btusb-mediatek-remove-the-unnecessary-goto-tag/20240705-043833
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
patch link:    https://lore.kernel.org/r/20240704060116.16600-6-chris.lu%40mediatek.com
patch subject: [PATCH v7 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c
config: i386-buildonly-randconfig-001-20240705 (https://download.01.org/0day-ci/archive/20240705/202407051325.i8Ac4Nz9-lkp@intel.com/config)
compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240705/202407051325.i8Ac4Nz9-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202407051325.i8Ac4Nz9-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_submit_wmt_recv_urb':
   btmtk.c:(.text+0x731): undefined reference to `usb_alloc_urb'
>> ld: btmtk.c:(.text+0x7c5): undefined reference to `usb_anchor_urb'
>> ld: btmtk.c:(.text+0x7d1): undefined reference to `usb_submit_urb'
>> ld: btmtk.c:(.text+0x7de): undefined reference to `usb_free_urb'
>> ld: btmtk.c:(.text+0x820): undefined reference to `usb_unanchor_urb'
   ld: btmtk.c:(.text+0x829): undefined reference to `usb_free_urb'
   ld: btmtk.c:(.text+0x83e): undefined reference to `usb_free_urb'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_hci_wmt_sync':
   btmtk.c:(.text+0x8bd): undefined reference to `usb_autopm_get_interface'
>> ld: btmtk.c:(.text+0x8f9): undefined reference to `usb_autopm_put_interface'
   ld: btmtk.c:(.text+0x9bf): undefined reference to `usb_autopm_put_interface'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_wmt_recv':
   btmtk.c:(.text+0xb67): undefined reference to `usb_anchor_urb'
   ld: btmtk.c:(.text+0xb73): undefined reference to `usb_submit_urb'
   ld: btmtk.c:(.text+0xc8e): undefined reference to `usb_unanchor_urb'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


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

* Re: [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions
  2024-07-04  6:01 ` [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions Chris Lu
@ 2024-07-05  9:11   ` kernel test robot
  2024-07-15 22:36   ` Nícolas F. R. A. Prado
  1 sibling, 0 replies; 17+ messages in thread
From: kernel test robot @ 2024-07-05  9:11 UTC (permalink / raw)
  To: Chris Lu, Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: oe-kbuild-all, Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth,
	linux-kernel, linux-mediatek, Chris Lu

Hi Chris,

kernel test robot noticed the following build errors:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20240703]
[cannot apply to bluetooth/master linus/master v6.10-rc6]
[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#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Chris-Lu/Bluetooth-btusb-mediatek-remove-the-unnecessary-goto-tag/20240705-043833
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
patch link:    https://lore.kernel.org/r/20240704060116.16600-9-chris.lu%40mediatek.com
patch subject: [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions
config: i386-buildonly-randconfig-001-20240705 (https://download.01.org/0day-ci/archive/20240705/202407051652.C743BIjp-lkp@intel.com/config)
compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240705/202407051652.C743BIjp-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202407051652.C743BIjp-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_recv_acl':
   btmtk.c:(.text+0x749): undefined reference to `usb_disable_autosuspend'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_submit_wmt_recv_urb':
   btmtk.c:(.text+0x789): undefined reference to `usb_alloc_urb'
   ld: btmtk.c:(.text+0x81d): undefined reference to `usb_anchor_urb'
   ld: btmtk.c:(.text+0x829): undefined reference to `usb_submit_urb'
   ld: btmtk.c:(.text+0x836): undefined reference to `usb_free_urb'
   ld: btmtk.c:(.text+0x880): undefined reference to `usb_unanchor_urb'
   ld: btmtk.c:(.text+0x889): undefined reference to `usb_free_urb'
   ld: btmtk.c:(.text+0x89e): undefined reference to `usb_free_urb'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_submit_intr_urb':
   btmtk.c:(.text+0x8db): undefined reference to `usb_alloc_urb'
   ld: btmtk.c:(.text+0x991): undefined reference to `usb_anchor_urb'
   ld: btmtk.c:(.text+0x99a): undefined reference to `usb_submit_urb'
   ld: btmtk.c:(.text+0x9a7): undefined reference to `usb_free_urb'
   ld: btmtk.c:(.text+0xa18): undefined reference to `usb_unanchor_urb'
   ld: btmtk.c:(.text+0xa28): undefined reference to `usb_free_urb'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_suspend':
   btmtk.c:(.text+0xa92): undefined reference to `usb_kill_anchored_urbs'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_hci_wmt_sync':
   btmtk.c:(.text+0xb15): undefined reference to `usb_autopm_get_interface'
   ld: btmtk.c:(.text+0xb51): undefined reference to `usb_autopm_put_interface'
   ld: btmtk.c:(.text+0xc0f): undefined reference to `usb_autopm_put_interface'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_isointf_init.constprop.0':
   btmtk.c:(.text+0xefc): undefined reference to `usb_set_interface'
>> ld: btmtk.c:(.text+0x1063): undefined reference to `usb_kill_anchored_urbs'
   ld: drivers/bluetooth/btmtk.o: in function `alloc_mtk_intr_urb':
   btmtk.c:(.text+0x113c): undefined reference to `usb_alloc_urb'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_wmt_recv':
   btmtk.c:(.text+0x12bb): undefined reference to `usb_anchor_urb'
   ld: btmtk.c:(.text+0x12c7): undefined reference to `usb_submit_urb'
   ld: btmtk.c:(.text+0x13e6): undefined reference to `usb_unanchor_urb'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_reg_read':
   btmtk.c:(.text+0x14cb): undefined reference to `usb_control_msg'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_uhw_reg_write':
   btmtk.c:(.text+0x1559): undefined reference to `usb_control_msg'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_uhw_reg_read':
   btmtk.c:(.text+0x1609): undefined reference to `usb_control_msg'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_intr_complete':
   btmtk.c:(.text+0x170f): undefined reference to `usb_anchor_urb'
   ld: btmtk.c:(.text+0x171b): undefined reference to `usb_submit_urb'
   ld: btmtk.c:(.text+0x1779): undefined reference to `usb_unanchor_urb'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


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

* Re: [PATCH v7 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c
  2024-07-04  6:01 ` [PATCH v7 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c Chris Lu
  2024-07-05  6:09   ` kernel test robot
@ 2024-07-05  9:33   ` kernel test robot
  1 sibling, 0 replies; 17+ messages in thread
From: kernel test robot @ 2024-07-05  9:33 UTC (permalink / raw)
  To: Chris Lu, Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: oe-kbuild-all, Sean Wang, Aaron Hou, Steve Lee, linux-bluetooth,
	linux-kernel, linux-mediatek, Chris Lu

Hi Chris,

kernel test robot noticed the following build errors:

[auto build test ERROR on bluetooth-next/master]
[also build test ERROR on next-20240703]
[cannot apply to bluetooth/master linus/master v6.10-rc6]
[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#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Chris-Lu/Bluetooth-btusb-mediatek-remove-the-unnecessary-goto-tag/20240705-043833
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
patch link:    https://lore.kernel.org/r/20240704060116.16600-6-chris.lu%40mediatek.com
patch subject: [PATCH v7 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c
config: x86_64-randconfig-161-20240705 (https://download.01.org/0day-ci/archive/20240705/202407051720.d1FTJg6H-lkp@intel.com/config)
compiler: gcc-7 (Ubuntu 7.5.0-6ubuntu2) 7.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240705/202407051720.d1FTJg6H-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202407051720.d1FTJg6H-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_wmt_recv':
   drivers/bluetooth/btmtk.c:503:(.text+0xacf): undefined reference to `usb_anchor_urb'
   ld: drivers/bluetooth/btmtk.c:504:(.text+0xadc): undefined reference to `usb_submit_urb'
   ld: drivers/bluetooth/btmtk.c:513:(.text+0xc61): undefined reference to `usb_unanchor_urb'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_hci_wmt_sync':
   drivers/bluetooth/btmtk.c:605:(.text+0xda5): undefined reference to `usb_autopm_get_interface'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_submit_wmt_recv_urb':
   drivers/bluetooth/btmtk.c:526:(.text+0xe04): undefined reference to `usb_alloc_urb'
   ld: drivers/bluetooth/btmtk.c:556:(.text+0xefe): undefined reference to `usb_anchor_urb'
   ld: drivers/bluetooth/btmtk.c:557:(.text+0xf0b): undefined reference to `usb_submit_urb'
   ld: drivers/bluetooth/btmtk.c:565:(.text+0xf23): undefined reference to `usb_free_urb'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_hci_wmt_sync':
>> drivers/bluetooth/btmtk.c:620:(.text+0xf2f): undefined reference to `usb_autopm_put_interface'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_submit_wmt_recv_urb':
>> drivers/bluetooth/btmtk.c:562:(.text+0x1030): undefined reference to `usb_unanchor_urb'
   ld: drivers/bluetooth/btmtk.c:565:(.text+0x1038): undefined reference to `usb_free_urb'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_hci_wmt_sync':
   drivers/bluetooth/btmtk.c:620:(.text+0x1044): undefined reference to `usb_autopm_put_interface'
   ld: drivers/bluetooth/btmtk.c:613:(.text+0x1062): undefined reference to `usb_autopm_put_interface'
   ld: drivers/bluetooth/btmtk.c:620:(.text+0x11c6): undefined reference to `usb_autopm_put_interface'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_submit_wmt_recv_urb':
>> drivers/bluetooth/btmtk.c:545:(.text+0x1288): undefined reference to `usb_free_urb'
   ld: drivers/bluetooth/btmtk.o: in function `btmtk_usb_hci_wmt_sync':
   drivers/bluetooth/btmtk.c:620:(.text+0x1294): undefined reference to `usb_autopm_put_interface'


vim +620 drivers/bluetooth/btmtk.c

   516	
   517	static int btmtk_usb_submit_wmt_recv_urb(struct hci_dev *hdev)
   518	{
   519		struct btmtk_data *data = hci_get_priv(hdev);
   520		struct usb_ctrlrequest *dr;
   521		unsigned char *buf;
   522		int err, size = 64;
   523		unsigned int pipe;
   524		struct urb *urb;
   525	
   526		urb = usb_alloc_urb(0, GFP_KERNEL);
   527		if (!urb)
   528			return -ENOMEM;
   529	
   530		dr = kmalloc(sizeof(*dr), GFP_KERNEL);
   531		if (!dr) {
   532			usb_free_urb(urb);
   533			return -ENOMEM;
   534		}
   535	
   536		dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_IN;
   537		dr->bRequest     = 1;
   538		dr->wIndex       = cpu_to_le16(0);
   539		dr->wValue       = cpu_to_le16(48);
   540		dr->wLength      = cpu_to_le16(size);
   541	
   542		buf = kmalloc(size, GFP_KERNEL);
   543		if (!buf) {
   544			kfree(dr);
 > 545			usb_free_urb(urb);
   546			return -ENOMEM;
   547		}
   548	
   549		pipe = usb_rcvctrlpipe(data->udev, 0);
   550	
   551		usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
   552				     buf, size, btmtk_usb_wmt_recv, hdev);
   553	
   554		urb->transfer_flags |= URB_FREE_BUFFER;
   555	
   556		usb_anchor_urb(urb, data->ctrl_anchor);
   557		err = usb_submit_urb(urb, GFP_KERNEL);
   558		if (err < 0) {
   559			if (err != -EPERM && err != -ENODEV)
   560				bt_dev_err(hdev, "urb %p submission failed (%d)",
   561					   urb, -err);
 > 562			usb_unanchor_urb(urb);
   563		}
   564	
   565		usb_free_urb(urb);
   566	
   567		return err;
   568	}
   569	
   570	int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
   571				   struct btmtk_hci_wmt_params *wmt_params)
   572	{
   573		struct btmtk_data *data = hci_get_priv(hdev);
   574		struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
   575		u32 hlen, status = BTMTK_WMT_INVALID;
   576		struct btmtk_hci_wmt_evt *wmt_evt;
   577		struct btmtk_hci_wmt_cmd *wc;
   578		struct btmtk_wmt_hdr *hdr;
   579		int err;
   580	
   581		/* Send the WMT command and wait until the WMT event returns */
   582		hlen = sizeof(*hdr) + wmt_params->dlen;
   583		if (hlen > 255)
   584			return -EINVAL;
   585	
   586		wc = kzalloc(hlen, GFP_KERNEL);
   587		if (!wc)
   588			return -ENOMEM;
   589	
   590		hdr = &wc->hdr;
   591		hdr->dir = 1;
   592		hdr->op = wmt_params->op;
   593		hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
   594		hdr->flag = wmt_params->flag;
   595		memcpy(wc->data, wmt_params->data, wmt_params->dlen);
   596	
   597		set_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags);
   598	
   599		/* WMT cmd/event doesn't follow up the generic HCI cmd/event handling,
   600		 * it needs constantly polling control pipe until the host received the
   601		 * WMT event, thus, we should require to specifically acquire PM counter
   602		 * on the USB to prevent the interface from entering auto suspended
   603		 * while WMT cmd/event in progress.
   604		 */
   605		err = usb_autopm_get_interface(data->intf);
   606		if (err < 0)
   607			goto err_free_wc;
   608	
   609		err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
   610	
   611		if (err < 0) {
   612			clear_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags);
   613			usb_autopm_put_interface(data->intf);
   614			goto err_free_wc;
   615		}
   616	
   617		/* Submit control IN URB on demand to process the WMT event */
   618		err = btmtk_usb_submit_wmt_recv_urb(hdev);
   619	
 > 620		usb_autopm_put_interface(data->intf);
   621	
   622		if (err < 0)
   623			goto err_free_wc;
   624	
   625		/* The vendor specific WMT commands are all answered by a vendor
   626		 * specific event and will have the Command Status or Command
   627		 * Complete as with usual HCI command flow control.
   628		 *
   629		 * After sending the command, wait for BTUSB_TX_WAIT_VND_EVT
   630		 * state to be cleared. The driver specific event receive routine
   631		 * will clear that state and with that indicate completion of the
   632		 * WMT command.
   633		 */
   634		err = wait_on_bit_timeout(&data->flags, BTMTK_TX_WAIT_VND_EVT,
   635					  TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT);
   636		if (err == -EINTR) {
   637			bt_dev_err(hdev, "Execution of wmt command interrupted");
   638			clear_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags);
   639			goto err_free_wc;
   640		}
   641	
   642		if (err) {
   643			bt_dev_err(hdev, "Execution of wmt command timed out");
   644			clear_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags);
   645			err = -ETIMEDOUT;
   646			goto err_free_wc;
   647		}
   648	
   649		if (data->evt_skb == NULL)
   650			goto err_free_wc;
   651	
   652		/* Parse and handle the return WMT event */
   653		wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
   654		if (wmt_evt->whdr.op != hdr->op) {
   655			bt_dev_err(hdev, "Wrong op received %d expected %d",
   656				   wmt_evt->whdr.op, hdr->op);
   657			err = -EIO;
   658			goto err_free_skb;
   659		}
   660	
   661		switch (wmt_evt->whdr.op) {
   662		case BTMTK_WMT_SEMAPHORE:
   663			if (wmt_evt->whdr.flag == 2)
   664				status = BTMTK_WMT_PATCH_UNDONE;
   665			else
   666				status = BTMTK_WMT_PATCH_DONE;
   667			break;
   668		case BTMTK_WMT_FUNC_CTRL:
   669			wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
   670			if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
   671				status = BTMTK_WMT_ON_DONE;
   672			else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
   673				status = BTMTK_WMT_ON_PROGRESS;
   674			else
   675				status = BTMTK_WMT_ON_UNDONE;
   676			break;
   677		case BTMTK_WMT_PATCH_DWNLD:
   678			if (wmt_evt->whdr.flag == 2)
   679				status = BTMTK_WMT_PATCH_DONE;
   680			else if (wmt_evt->whdr.flag == 1)
   681				status = BTMTK_WMT_PATCH_PROGRESS;
   682			else
   683				status = BTMTK_WMT_PATCH_UNDONE;
   684			break;
   685		}
   686	
   687		if (wmt_params->status)
   688			*wmt_params->status = status;
   689	
   690	err_free_skb:
   691		kfree_skb(data->evt_skb);
   692		data->evt_skb = NULL;
   693	err_free_wc:
   694		kfree(wc);
   695		return err;
   696	}
   697	EXPORT_SYMBOL_GPL(btmtk_usb_hci_wmt_sync);
   698	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


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

* Re: [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support
  2024-07-04  6:01 [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support Chris Lu
                   ` (7 preceding siblings ...)
  2024-07-04  6:01 ` [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions Chris Lu
@ 2024-07-08 21:20 ` patchwork-bot+bluetooth
  8 siblings, 0 replies; 17+ messages in thread
From: patchwork-bot+bluetooth @ 2024-07-08 21:20 UTC (permalink / raw)
  To: Chris Lu
  Cc: marcel, johan.hedberg, luiz.dentz, sean.wang, aaron.hou,
	steve.lee, linux-bluetooth, linux-kernel, linux-mediatek

Hello:

This series was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Thu, 4 Jul 2024 14:01:08 +0800 you wrote:
> Since SIG has not yet clearly defined the specification for ISO data
> transmission over USB, MediaTek has adopted a method of adding an
> additional interrupt endpoint for ISO data transmission. This approach
> differs from the current method used in the Bluetooth upstream driver,
> which utilizes existing bulk endpoints. The interrupt endpoint provides
> guaranteed bandwidth, sufficient maximum data length for ISO packets
> and error checking.
> 
> [...]

Here is the summary with links:
  - [v7,1/8] Bluetooth: btusb: mediatek: remove the unnecessary goto tag
    https://git.kernel.org/bluetooth/bluetooth-next/c/a06a1458192e
  - [v7,2/8] Bluetooth: btusb: mediatek: return error for failed reg access
    https://git.kernel.org/bluetooth/bluetooth-next/c/ac7daf0f197c
  - [v7,3/8] Bluetooth: btmtk: rename btmediatek_data
    https://git.kernel.org/bluetooth/bluetooth-next/c/dfad4030dcc4
  - [v7,4/8] Bluetooth: btusb: add callback function in btusb suspend/resume
    https://git.kernel.org/bluetooth/bluetooth-next/c/cacda8ed6753
  - [v7,5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c
    https://git.kernel.org/bluetooth/bluetooth-next/c/39a9e1c69e74
  - [v7,6/8] Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c
    https://git.kernel.org/bluetooth/bluetooth-next/c/314f1c00d267
  - [v7,7/8] Bluetooth: btmtk: move btusb_recv_acl_mtk to btmtk.c
    https://git.kernel.org/bluetooth/bluetooth-next/c/91d0ac304edf
  - [v7,8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions
    https://git.kernel.org/bluetooth/bluetooth-next/c/7eac027d1b20

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




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

* Re: [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions
  2024-07-04  6:01 ` [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions Chris Lu
  2024-07-05  9:11   ` kernel test robot
@ 2024-07-15 22:36   ` Nícolas F. R. A. Prado
  2024-07-16  7:59     ` Chris Lu (陸稚泓)
  1 sibling, 1 reply; 17+ messages in thread
From: Nícolas F. R. A. Prado @ 2024-07-15 22:36 UTC (permalink / raw)
  To: Chris Lu
  Cc: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz, Sean Wang,
	Aaron Hou, Steve Lee, linux-bluetooth, linux-kernel,
	linux-mediatek, regressions, kernelci, kernel

On Thu, Jul 04, 2024 at 02:01:16PM +0800, Chris Lu wrote:
> This patch implements functions for ISO data send and receive in btusb
> driver for MediaTek's controller.
> 
> MediaTek defines a specific interrupt endpoint for ISO data transmissin
> because the characteristics of interrupt endpoint are similar to the
> application of ISO data which can support guaranteed transmissin
> bandwidth, enough maximum data length and error checking mechanism.
> 
> Driver sets up ISO interface and endpoints in btusb_mtk_setup and clears
> the setup in btusb_mtk_shutdown. These flow can't move to btmtk.c due to
> btusb_driver is only defined in btusb.c when claiming/relaesing interface.
> ISO packet anchor stops when driver suspending and resubmit interrupt urb
> for ISO data when driver resuming.
> 
> Signed-off-by: Chris Lu <chris.lu@mediatek.com>
> ---

Hi,

KernelCI has identified a boot regression originating from this patch. It
affects the mt8195-cherry-tomato-r2 platform.

Through additional runs I've determined that it only happens when the bluetooth
firmware (BT_RAM_CODE_MT7961_1_2_hdr.bin) isn't present. I realize the firmware
should be present to make proper use of the bluetooth driver, and I'll add it to
our testing images. Still, a panic shouldn't happen when it's missing, hence
this report.

Reverting this patch fixes the issue.

This is the traceback:

[    6.734214] BUG: spinlock bad magic on CPU#3, kworker/3:1/104
[    6.740002]  lock: 0xffff2c7b8655f660, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0
[    6.748207] CPU: 3 UID: 0 PID: 104 Comm: kworker/3:1 Not tainted 6.10.0-next-20240715 #1 35893202ca8f99b37129997821441a29d2b23f0a
[    6.759874] Hardware name: Acer Tomato (rev2) board (DT)
[    6.765195] Workqueue: pm pm_runtime_work
[    6.769235] Call trace:
[    6.771689]  dump_backtrace+0x9c/0x100
[    6.775456]  show_stack+0x20/0x38
[    6.778786]  dump_stack_lvl+0x80/0xf8
[    6.782463]  dump_stack+0x18/0x28
[    6.785791]  spin_bug+0x90/0xd8
[    6.788950]  do_raw_spin_lock+0xf4/0x128
[    6.792890]  _raw_spin_lock_irq+0x30/0x70
[    6.796915]  usb_kill_anchored_urbs+0x48/0x1e0
[    6.801378]  btmtk_usb_suspend+0x20/0x38 [btmtk 5f200a97badbdfda4266773fee49acfc8e0224d5]
[    6.809578]  btusb_suspend+0xd0/0x210 [btusb 0bfbf19a87ff406c83b87268b87ce1e80e9a829b]
[    6.817527]  usb_suspend_both+0x90/0x288
[    6.821469]  usb_runtime_suspend+0x3c/0xa8
[    6.825585]  __rpm_callback+0x50/0x1f0
[    6.829351]  rpm_callback+0x70/0x88
[    6.832856]  rpm_suspend+0xe4/0x5a0
[    6.836361]  pm_runtime_work+0xd4/0xe0
[    6.840126]  process_one_work+0x18c/0x440
[    6.844156]  worker_thread+0x314/0x428
[    6.847923]  kthread+0x128/0x138
[    6.851167]  ret_from_fork+0x10/0x20
[    6.854769] Unable to handle kernel paging request at virtual address ffffffffffffffd8
[    6.862694] Mem abort info:
[    6.865494]   ESR = 0x0000000096000006
[    6.869249]   EC = 0x25: DABT (current EL), IL = 32 bits
[    6.874571]   SET = 0, FnV = 0
[    6.877632]   EA = 0, S1PTW = 0
[    6.880780]   FSC = 0x06: level 2 translation fault
[    6.885665] Data abort info:
[    6.888553]   ISV = 0, ISS = 0x00000006, ISS2 = 0x00000000
[    6.894044]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[    6.899103]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[    6.904423] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000042533000
[    6.911134] [ffffffffffffffd8] pgd=0000000000000000, p4d=0000000042e94003, pud=0000000042e95003, pmd=0000000000000000
lav[    6.921781] Internal error: Oops: 0000000096000006 [#1] PREEMPT SMP
[    6.921794] Modules linked in: mt7921e mt7921_common mt792x_lib mt76_connac_lib mt76 mtk_vcodec_dec_hw mac80211 cros_ec_lid_angle cros_ec_sensors cros_ec_sensors_core industrialio_triggered_buffer cfg80211 kfifo_buf mtk_vcodec_dec mtk_jpeg v4l2_vp9 cros_ec_rpmsg mtk_vcodec_enc v4l2_h264 mtk_jpeg_enc_hw btusb mtk_vcodec_dbgfs mtk_jpeg_dec_hw mtk_dp mtk_vcodec_common btintel btbcm uvcvideo btmtk mtk_mdp3 videobuf2_vmalloc v4l2_mem2mem btrtl uvc joydev videobuf2_v4l2 videobuf2_dma_contig bluetooth elan_i2c videobuf2_memops ecdh_generic ecc videobuf2_common cros_ec_sensorhub cros_kbd_led_backlight mtk_scp snd_sof_mt8195 pcie_mediatek_gen3 mtk_rpmsg mtk_svs mtk_adsp_common snd_sof_xtensa_dsp rpmsg_core lvts_thermal snd_sof_of mtk_scp_ipi snd_soc_mt8195_afe snd_sof snd_sof_utils mtk_wdt mt6577_auxadc mt8195_mt6359
[    6.922087] CPU: 3 UID: 0 PID: 104 Comm: kworker/3:1 Not tainted 6.10.0-next-20240715 #1 35893202ca8f99b37129997821441a29d2b23f0a
[    6.922106] Hardware name: Acer Tomato (rev2) board (DT)
[    6.922114] Workqueue: pm pm_runtime_work
[    6.922132] pstate: 804000c9 (Nzcv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[    6.922147] pc : usb_kill_anchored_urbs+0x6c/0x1e0
[    6.922164] lr : usb_kill_anchored_urbs+0x48/0x1e0
[    6.922181] sp : ffff800080903b60
[    6.922187] x29: ffff800080903b60 x28: ffff2c7b85c32b80 x27: ffff2c7bbb370930
[    6.922211] x26: 00000000000f4240 x25: 00000000ffffffff x24: ffffd49ece2dcb48
[    6.922233] x23: 0000000000000001 x22: ffff2c7b8655f660 x21: ffff2c7b8655f628
[    6.922255] x20: ffffffffffffffd8 x19: 0000000000000000 x18: 0000000000000006
[    6.922276] x17: 6531656337386238 x16: 3632373862333863 x15: ffff800080903480
[    6.922297] x14: 0000000000000000 x13: 303278302f303178 x12: ffffd49ecf090e30
[    6.922318] x11: 0000000000000001 x10: 0000000000000001 x9 : ffffd49ecd2c5bb4
[    6.922339] x8 : c0000000ffffdfff x7 : ffffd49ecefe0db8 x6 : 00000000000affa8
[    6.922360] x5 : ffff2c7bbb35dd48 x4 : 0000000000000000 x3 : 0000000000000000
[    6.922379] x2 : 0000000000000000 x1 : 0000000000000003 x0 : ffffffffffffffd8
[    6.922400] Call trace:
[    6.922405]  usb_kill_anchored_urbs+0x6c/0x1e0
[    6.922422]  btmtk_usb_suspend+0x20/0x38 [btmtk 5f200a97badbdfda4266773fee49acfc8e0224d5]
[    6.922444]  btusb_suspend+0xd0/0x210 [btusb 0bfbf19a87ff406c83b87268b87ce1e80e9a829b]
[    6.922469]  usb_suspend_both+0x90/0x288
[    6.922487]  usb_runtime_suspend+0x3c/0xa8
[    6.922507]  __rpm_callback+0x50/0x1f0
[    6.922523]  rpm_callback+0x70/0x88
[    6.922538]  rpm_suspend+0xe4/0x5a0
[    6.922553]  pm_runtime_work+0xd4/0xe0
[    6.922569]  process_one_work+0x18c/0x440
[    6.922588]  worker_thread+0x314/0x428
[    6.922606]  kthread+0x128/0x138
[    6.922621]  ret_from_fork+0x10/0x20
[    6.922644] Code: f100a274 54000520 d503201f d100a260 (b8370000)
[    6.922654] ---[ end trace 0000000000000000 ]---
a-148[    7.203910] Kernel panic - not syncing: Oops: Fatal exception
[    7.209649] SMP: stopping secondary CPUs
[    7.213713] Kernel Offset: 0x549e4c400000 from 0xffff800080000000
[    7.219796] PHYS_OFFSET: 0xfff0d38580000000
[    7.223969] CPU features: 0x04,0000000b,80140528,4200720b
[    7.229360] Memory Limit: none

Full kernel log: http://0x0.st/X9rx.txt
Config: http://0x0.st/X9r2.txt

#regzbot introduced: ee6bd4b95c66
#regzbot title: usb_kill_anchored_urbs panic during boot on mt8195-cherry-tomato-r2

Thanks,
Nícolas


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

* Re: [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions
  2024-07-15 22:36   ` Nícolas F. R. A. Prado
@ 2024-07-16  7:59     ` Chris Lu (陸稚泓)
  2024-07-16 12:20       ` Nícolas F. R. A. Prado
  0 siblings, 1 reply; 17+ messages in thread
From: Chris Lu (陸稚泓) @ 2024-07-16  7:59 UTC (permalink / raw)
  To: luiz.dentz@gmail.com, nfraprado@collabora.com
  Cc: marcel@holtmann.org, linux-mediatek@lists.infradead.org,
	linux-kernel@vger.kernel.org, kernelci@lists.linux.dev,
	linux-bluetooth@vger.kernel.org, regressions@lists.linux.dev,
	johan.hedberg@gmail.com, Steve Lee (李視誠),
	kernel@collabora.com, Sean Wang,
	Aaron Hou (侯俊仰)

Hi Nicolas,

Thanks for reporting the crash issue, I've sent another patc to avoid
this crash issue happened. kill anchor function wasn't protect well if
MediaTek Bluetooth failed to setup. Add a flag check when running into
btmtk_usb_suspend function.

Thanks a lot,
Chris

On Mon, 2024-07-15 at 18:36 -0400, Nícolas F. R. A. Prado wrote:
> On Thu, Jul 04, 2024 at 02:01:16PM +0800, Chris Lu wrote:
> > This patch implements functions for ISO data send and receive in
> > btusb
> > driver for MediaTek's controller.
> > 
> > MediaTek defines a specific interrupt endpoint for ISO data
> > transmissin
> > because the characteristics of interrupt endpoint are similar to
> > the
> > application of ISO data which can support guaranteed transmissin
> > bandwidth, enough maximum data length and error checking mechanism.
> > 
> > Driver sets up ISO interface and endpoints in btusb_mtk_setup and
> > clears
> > the setup in btusb_mtk_shutdown. These flow can't move to btmtk.c
> > due to
> > btusb_driver is only defined in btusb.c when claiming/relaesing
> > interface.
> > ISO packet anchor stops when driver suspending and resubmit
> > interrupt urb
> > for ISO data when driver resuming.
> > 
> > Signed-off-by: Chris Lu <chris.lu@mediatek.com>
> > ---
> 
> Hi,
> 
> KernelCI has identified a boot regression originating from this
> patch. It
> affects the mt8195-cherry-tomato-r2 platform.
> 
> Through additional runs I've determined that it only happens when the
> bluetooth
> firmware (BT_RAM_CODE_MT7961_1_2_hdr.bin) isn't present. I realize
> the firmware
> should be present to make proper use of the bluetooth driver, and
> I'll add it to
> our testing images. Still, a panic shouldn't happen when it's
> missing, hence
> this report.
> 
> Reverting this patch fixes the issue.
> 
> This is the traceback:
> 
> [    6.734214] BUG: spinlock bad magic on CPU#3, kworker/3:1/104
> [    6.740002]  lock: 0xffff2c7b8655f660, .magic: 00000000, .owner:
> <none>/-1, .owner_cpu: 0
> [    6.748207] CPU: 3 UID: 0 PID: 104 Comm: kworker/3:1 Not tainted
> 6.10.0-next-20240715 #1 35893202ca8f99b37129997821441a29d2b23f0a
> [    6.759874] Hardware name: Acer Tomato (rev2) board (DT)
> [    6.765195] Workqueue: pm pm_runtime_work
> [    6.769235] Call trace:
> [    6.771689]  dump_backtrace+0x9c/0x100
> [    6.775456]  show_stack+0x20/0x38
> [    6.778786]  dump_stack_lvl+0x80/0xf8
> [    6.782463]  dump_stack+0x18/0x28
> [    6.785791]  spin_bug+0x90/0xd8
> [    6.788950]  do_raw_spin_lock+0xf4/0x128
> [    6.792890]  _raw_spin_lock_irq+0x30/0x70
> [    6.796915]  usb_kill_anchored_urbs+0x48/0x1e0
> [    6.801378]  btmtk_usb_suspend+0x20/0x38 [btmtk
> 5f200a97badbdfda4266773fee49acfc8e0224d5]
> [    6.809578]  btusb_suspend+0xd0/0x210 [btusb
> 0bfbf19a87ff406c83b87268b87ce1e80e9a829b]
> [    6.817527]  usb_suspend_both+0x90/0x288
> [    6.821469]  usb_runtime_suspend+0x3c/0xa8
> [    6.825585]  __rpm_callback+0x50/0x1f0
> [    6.829351]  rpm_callback+0x70/0x88
> [    6.832856]  rpm_suspend+0xe4/0x5a0
> [    6.836361]  pm_runtime_work+0xd4/0xe0
> [    6.840126]  process_one_work+0x18c/0x440
> [    6.844156]  worker_thread+0x314/0x428
> [    6.847923]  kthread+0x128/0x138
> [    6.851167]  ret_from_fork+0x10/0x20
> [    6.854769] Unable to handle kernel paging request at virtual
> address ffffffffffffffd8
> [    6.862694] Mem abort info:
> [    6.865494]   ESR = 0x0000000096000006
> [    6.869249]   EC = 0x25: DABT (current EL), IL = 32 bits
> [    6.874571]   SET = 0, FnV = 0
> [    6.877632]   EA = 0, S1PTW = 0
> [    6.880780]   FSC = 0x06: level 2 translation fault
> [    6.885665] Data abort info:
> [    6.888553]   ISV = 0, ISS = 0x00000006, ISS2 = 0x00000000
> [    6.894044]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> [    6.899103]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> [    6.904423] swapper pgtable: 4k pages, 48-bit VAs,
> pgdp=0000000042533000
> [    6.911134] [ffffffffffffffd8] pgd=0000000000000000,
> p4d=0000000042e94003, pud=0000000042e95003, pmd=0000000000000000
> lav[    6.921781] Internal error: Oops: 0000000096000006 [#1] PREEMPT
> SMP
> [    6.921794] Modules linked in: mt7921e mt7921_common mt792x_lib
> mt76_connac_lib mt76 mtk_vcodec_dec_hw mac80211 cros_ec_lid_angle
> cros_ec_sensors cros_ec_sensors_core industrialio_triggered_buffer
> cfg80211 kfifo_buf mtk_vcodec_dec mtk_jpeg v4l2_vp9 cros_ec_rpmsg
> mtk_vcodec_enc v4l2_h264 mtk_jpeg_enc_hw btusb mtk_vcodec_dbgfs
> mtk_jpeg_dec_hw mtk_dp mtk_vcodec_common btintel btbcm uvcvideo btmtk
> mtk_mdp3 videobuf2_vmalloc v4l2_mem2mem btrtl uvc joydev
> videobuf2_v4l2 videobuf2_dma_contig bluetooth elan_i2c
> videobuf2_memops ecdh_generic ecc videobuf2_common cros_ec_sensorhub
> cros_kbd_led_backlight mtk_scp snd_sof_mt8195 pcie_mediatek_gen3
> mtk_rpmsg mtk_svs mtk_adsp_common snd_sof_xtensa_dsp rpmsg_core
> lvts_thermal snd_sof_of mtk_scp_ipi snd_soc_mt8195_afe snd_sof
> snd_sof_utils mtk_wdt mt6577_auxadc mt8195_mt6359
> [    6.922087] CPU: 3 UID: 0 PID: 104 Comm: kworker/3:1 Not tainted
> 6.10.0-next-20240715 #1 35893202ca8f99b37129997821441a29d2b23f0a
> [    6.922106] Hardware name: Acer Tomato (rev2) board (DT)
> [    6.922114] Workqueue: pm pm_runtime_work
> [    6.922132] pstate: 804000c9 (Nzcv daIF +PAN -UAO -TCO -DIT -SSBS
> BTYPE=--)
> [    6.922147] pc : usb_kill_anchored_urbs+0x6c/0x1e0
> [    6.922164] lr : usb_kill_anchored_urbs+0x48/0x1e0
> [    6.922181] sp : ffff800080903b60
> [    6.922187] x29: ffff800080903b60 x28: ffff2c7b85c32b80 x27:
> ffff2c7bbb370930
> [    6.922211] x26: 00000000000f4240 x25: 00000000ffffffff x24:
> ffffd49ece2dcb48
> [    6.922233] x23: 0000000000000001 x22: ffff2c7b8655f660 x21:
> ffff2c7b8655f628
> [    6.922255] x20: ffffffffffffffd8 x19: 0000000000000000 x18:
> 0000000000000006
> [    6.922276] x17: 6531656337386238 x16: 3632373862333863 x15:
> ffff800080903480
> [    6.922297] x14: 0000000000000000 x13: 303278302f303178 x12:
> ffffd49ecf090e30
> [    6.922318] x11: 0000000000000001 x10: 0000000000000001 x9 :
> ffffd49ecd2c5bb4
> [    6.922339] x8 : c0000000ffffdfff x7 : ffffd49ecefe0db8 x6 :
> 00000000000affa8
> [    6.922360] x5 : ffff2c7bbb35dd48 x4 : 0000000000000000 x3 :
> 0000000000000000
> [    6.922379] x2 : 0000000000000000 x1 : 0000000000000003 x0 :
> ffffffffffffffd8
> [    6.922400] Call trace:
> [    6.922405]  usb_kill_anchored_urbs+0x6c/0x1e0
> [    6.922422]  btmtk_usb_suspend+0x20/0x38 [btmtk
> 5f200a97badbdfda4266773fee49acfc8e0224d5]
> [    6.922444]  btusb_suspend+0xd0/0x210 [btusb
> 0bfbf19a87ff406c83b87268b87ce1e80e9a829b]
> [    6.922469]  usb_suspend_both+0x90/0x288
> [    6.922487]  usb_runtime_suspend+0x3c/0xa8
> [    6.922507]  __rpm_callback+0x50/0x1f0
> [    6.922523]  rpm_callback+0x70/0x88
> [    6.922538]  rpm_suspend+0xe4/0x5a0
> [    6.922553]  pm_runtime_work+0xd4/0xe0
> [    6.922569]  process_one_work+0x18c/0x440
> [    6.922588]  worker_thread+0x314/0x428
> [    6.922606]  kthread+0x128/0x138
> [    6.922621]  ret_from_fork+0x10/0x20
> [    6.922644] Code: f100a274 54000520 d503201f d100a260 (b8370000)
> [    6.922654] ---[ end trace 0000000000000000 ]---
> a-148[    7.203910] Kernel panic - not syncing: Oops: Fatal exception
> [    7.209649] SMP: stopping secondary CPUs
> [    7.213713] Kernel Offset: 0x549e4c400000 from 0xffff800080000000
> [    7.219796] PHYS_OFFSET: 0xfff0d38580000000
> [    7.223969] CPU features: 0x04,0000000b,80140528,4200720b
> [    7.229360] Memory Limit: none
> 
> Full kernel log: 
> https://urldefense.com/v3/__http://0x0.st/X9rx.txt__;!!CTRNKA9wMg0ARbw!g_UleOH6C5AdZoKEVoko3ewb6zKCcWfDGfw3u6LV_x3JCST7WnvMrAzM7wP0A4WkiW4v0EM53wjf8el1gXWfqA$
>  
> Config: 
> https://urldefense.com/v3/__http://0x0.st/X9r2.txt__;!!CTRNKA9wMg0ARbw!g_UleOH6C5AdZoKEVoko3ewb6zKCcWfDGfw3u6LV_x3JCST7WnvMrAzM7wP0A4WkiW4v0EM53wjf8enPGJN1sg$
>  
> 
> #regzbot introduced: ee6bd4b95c66
> #regzbot title: usb_kill_anchored_urbs panic during boot on mt8195-
> cherry-tomato-r2
> 
> Thanks,
> Nícolas

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

* Re: [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions
  2024-07-16  7:59     ` Chris Lu (陸稚泓)
@ 2024-07-16 12:20       ` Nícolas F. R. A. Prado
  2024-07-30 15:38         ` Nícolas F. R. A. Prado
  0 siblings, 1 reply; 17+ messages in thread
From: Nícolas F. R. A. Prado @ 2024-07-16 12:20 UTC (permalink / raw)
  To: Chris Lu (陸稚泓)
  Cc: luiz.dentz@gmail.com, marcel@holtmann.org,
	linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	kernelci@lists.linux.dev, linux-bluetooth@vger.kernel.org,
	regressions@lists.linux.dev, johan.hedberg@gmail.com,
	Steve Lee (李視誠), kernel@collabora.com,
	Sean Wang, Aaron Hou (侯俊仰)

On Tue, Jul 16, 2024 at 07:59:53AM +0000, Chris Lu (陸稚泓) wrote:
> Hi Nicolas,
> 
> Thanks for reporting the crash issue, I've sent another patc to avoid
> this crash issue happened. kill anchor function wasn't protect well if
> MediaTek Bluetooth failed to setup. Add a flag check when running into
> btmtk_usb_suspend function.

Hi Chris,

thanks for the quick follow up! I see the patch at
https://lore.kernel.org/all/20240716074947.23073-1-chris.lu@mediatek.com/

I'll try it and reply there with my results.

Thanks,
Nícolas

> 
> Thanks a lot,
> Chris
> 
> On Mon, 2024-07-15 at 18:36 -0400, Nícolas F. R. A. Prado wrote:
> > On Thu, Jul 04, 2024 at 02:01:16PM +0800, Chris Lu wrote:
> > > This patch implements functions for ISO data send and receive in
> > > btusb
> > > driver for MediaTek's controller.
> > > 
> > > MediaTek defines a specific interrupt endpoint for ISO data
> > > transmissin
> > > because the characteristics of interrupt endpoint are similar to
> > > the
> > > application of ISO data which can support guaranteed transmissin
> > > bandwidth, enough maximum data length and error checking mechanism.
> > > 
> > > Driver sets up ISO interface and endpoints in btusb_mtk_setup and
> > > clears
> > > the setup in btusb_mtk_shutdown. These flow can't move to btmtk.c
> > > due to
> > > btusb_driver is only defined in btusb.c when claiming/relaesing
> > > interface.
> > > ISO packet anchor stops when driver suspending and resubmit
> > > interrupt urb
> > > for ISO data when driver resuming.
> > > 
> > > Signed-off-by: Chris Lu <chris.lu@mediatek.com>
> > > ---
> > 
> > Hi,
> > 
> > KernelCI has identified a boot regression originating from this
> > patch. It
> > affects the mt8195-cherry-tomato-r2 platform.
> > 
> > Through additional runs I've determined that it only happens when the
> > bluetooth
> > firmware (BT_RAM_CODE_MT7961_1_2_hdr.bin) isn't present. I realize
> > the firmware
> > should be present to make proper use of the bluetooth driver, and
> > I'll add it to
> > our testing images. Still, a panic shouldn't happen when it's
> > missing, hence
> > this report.
> > 
> > Reverting this patch fixes the issue.
> > 
> > This is the traceback:
> > 
> > [    6.734214] BUG: spinlock bad magic on CPU#3, kworker/3:1/104
> > [    6.740002]  lock: 0xffff2c7b8655f660, .magic: 00000000, .owner:
> > <none>/-1, .owner_cpu: 0
> > [    6.748207] CPU: 3 UID: 0 PID: 104 Comm: kworker/3:1 Not tainted
> > 6.10.0-next-20240715 #1 35893202ca8f99b37129997821441a29d2b23f0a
> > [    6.759874] Hardware name: Acer Tomato (rev2) board (DT)
> > [    6.765195] Workqueue: pm pm_runtime_work
> > [    6.769235] Call trace:
> > [    6.771689]  dump_backtrace+0x9c/0x100
> > [    6.775456]  show_stack+0x20/0x38
> > [    6.778786]  dump_stack_lvl+0x80/0xf8
> > [    6.782463]  dump_stack+0x18/0x28
> > [    6.785791]  spin_bug+0x90/0xd8
> > [    6.788950]  do_raw_spin_lock+0xf4/0x128
> > [    6.792890]  _raw_spin_lock_irq+0x30/0x70
> > [    6.796915]  usb_kill_anchored_urbs+0x48/0x1e0
> > [    6.801378]  btmtk_usb_suspend+0x20/0x38 [btmtk
> > 5f200a97badbdfda4266773fee49acfc8e0224d5]
> > [    6.809578]  btusb_suspend+0xd0/0x210 [btusb
> > 0bfbf19a87ff406c83b87268b87ce1e80e9a829b]
> > [    6.817527]  usb_suspend_both+0x90/0x288
> > [    6.821469]  usb_runtime_suspend+0x3c/0xa8
> > [    6.825585]  __rpm_callback+0x50/0x1f0
> > [    6.829351]  rpm_callback+0x70/0x88
> > [    6.832856]  rpm_suspend+0xe4/0x5a0
> > [    6.836361]  pm_runtime_work+0xd4/0xe0
> > [    6.840126]  process_one_work+0x18c/0x440
> > [    6.844156]  worker_thread+0x314/0x428
> > [    6.847923]  kthread+0x128/0x138
> > [    6.851167]  ret_from_fork+0x10/0x20
> > [    6.854769] Unable to handle kernel paging request at virtual
> > address ffffffffffffffd8
> > [    6.862694] Mem abort info:
> > [    6.865494]   ESR = 0x0000000096000006
> > [    6.869249]   EC = 0x25: DABT (current EL), IL = 32 bits
> > [    6.874571]   SET = 0, FnV = 0
> > [    6.877632]   EA = 0, S1PTW = 0
> > [    6.880780]   FSC = 0x06: level 2 translation fault
> > [    6.885665] Data abort info:
> > [    6.888553]   ISV = 0, ISS = 0x00000006, ISS2 = 0x00000000
> > [    6.894044]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> > [    6.899103]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> > [    6.904423] swapper pgtable: 4k pages, 48-bit VAs,
> > pgdp=0000000042533000
> > [    6.911134] [ffffffffffffffd8] pgd=0000000000000000,
> > p4d=0000000042e94003, pud=0000000042e95003, pmd=0000000000000000
> > lav[    6.921781] Internal error: Oops: 0000000096000006 [#1] PREEMPT
> > SMP
> > [    6.921794] Modules linked in: mt7921e mt7921_common mt792x_lib
> > mt76_connac_lib mt76 mtk_vcodec_dec_hw mac80211 cros_ec_lid_angle
> > cros_ec_sensors cros_ec_sensors_core industrialio_triggered_buffer
> > cfg80211 kfifo_buf mtk_vcodec_dec mtk_jpeg v4l2_vp9 cros_ec_rpmsg
> > mtk_vcodec_enc v4l2_h264 mtk_jpeg_enc_hw btusb mtk_vcodec_dbgfs
> > mtk_jpeg_dec_hw mtk_dp mtk_vcodec_common btintel btbcm uvcvideo btmtk
> > mtk_mdp3 videobuf2_vmalloc v4l2_mem2mem btrtl uvc joydev
> > videobuf2_v4l2 videobuf2_dma_contig bluetooth elan_i2c
> > videobuf2_memops ecdh_generic ecc videobuf2_common cros_ec_sensorhub
> > cros_kbd_led_backlight mtk_scp snd_sof_mt8195 pcie_mediatek_gen3
> > mtk_rpmsg mtk_svs mtk_adsp_common snd_sof_xtensa_dsp rpmsg_core
> > lvts_thermal snd_sof_of mtk_scp_ipi snd_soc_mt8195_afe snd_sof
> > snd_sof_utils mtk_wdt mt6577_auxadc mt8195_mt6359
> > [    6.922087] CPU: 3 UID: 0 PID: 104 Comm: kworker/3:1 Not tainted
> > 6.10.0-next-20240715 #1 35893202ca8f99b37129997821441a29d2b23f0a
> > [    6.922106] Hardware name: Acer Tomato (rev2) board (DT)
> > [    6.922114] Workqueue: pm pm_runtime_work
> > [    6.922132] pstate: 804000c9 (Nzcv daIF +PAN -UAO -TCO -DIT -SSBS
> > BTYPE=--)
> > [    6.922147] pc : usb_kill_anchored_urbs+0x6c/0x1e0
> > [    6.922164] lr : usb_kill_anchored_urbs+0x48/0x1e0
> > [    6.922181] sp : ffff800080903b60
> > [    6.922187] x29: ffff800080903b60 x28: ffff2c7b85c32b80 x27:
> > ffff2c7bbb370930
> > [    6.922211] x26: 00000000000f4240 x25: 00000000ffffffff x24:
> > ffffd49ece2dcb48
> > [    6.922233] x23: 0000000000000001 x22: ffff2c7b8655f660 x21:
> > ffff2c7b8655f628
> > [    6.922255] x20: ffffffffffffffd8 x19: 0000000000000000 x18:
> > 0000000000000006
> > [    6.922276] x17: 6531656337386238 x16: 3632373862333863 x15:
> > ffff800080903480
> > [    6.922297] x14: 0000000000000000 x13: 303278302f303178 x12:
> > ffffd49ecf090e30
> > [    6.922318] x11: 0000000000000001 x10: 0000000000000001 x9 :
> > ffffd49ecd2c5bb4
> > [    6.922339] x8 : c0000000ffffdfff x7 : ffffd49ecefe0db8 x6 :
> > 00000000000affa8
> > [    6.922360] x5 : ffff2c7bbb35dd48 x4 : 0000000000000000 x3 :
> > 0000000000000000
> > [    6.922379] x2 : 0000000000000000 x1 : 0000000000000003 x0 :
> > ffffffffffffffd8
> > [    6.922400] Call trace:
> > [    6.922405]  usb_kill_anchored_urbs+0x6c/0x1e0
> > [    6.922422]  btmtk_usb_suspend+0x20/0x38 [btmtk
> > 5f200a97badbdfda4266773fee49acfc8e0224d5]
> > [    6.922444]  btusb_suspend+0xd0/0x210 [btusb
> > 0bfbf19a87ff406c83b87268b87ce1e80e9a829b]
> > [    6.922469]  usb_suspend_both+0x90/0x288
> > [    6.922487]  usb_runtime_suspend+0x3c/0xa8
> > [    6.922507]  __rpm_callback+0x50/0x1f0
> > [    6.922523]  rpm_callback+0x70/0x88
> > [    6.922538]  rpm_suspend+0xe4/0x5a0
> > [    6.922553]  pm_runtime_work+0xd4/0xe0
> > [    6.922569]  process_one_work+0x18c/0x440
> > [    6.922588]  worker_thread+0x314/0x428
> > [    6.922606]  kthread+0x128/0x138
> > [    6.922621]  ret_from_fork+0x10/0x20
> > [    6.922644] Code: f100a274 54000520 d503201f d100a260 (b8370000)
> > [    6.922654] ---[ end trace 0000000000000000 ]---
> > a-148[    7.203910] Kernel panic - not syncing: Oops: Fatal exception
> > [    7.209649] SMP: stopping secondary CPUs
> > [    7.213713] Kernel Offset: 0x549e4c400000 from 0xffff800080000000
> > [    7.219796] PHYS_OFFSET: 0xfff0d38580000000
> > [    7.223969] CPU features: 0x04,0000000b,80140528,4200720b
> > [    7.229360] Memory Limit: none
> > 
> > Full kernel log: 
> > https://urldefense.com/v3/__http://0x0.st/X9rx.txt__;!!CTRNKA9wMg0ARbw!g_UleOH6C5AdZoKEVoko3ewb6zKCcWfDGfw3u6LV_x3JCST7WnvMrAzM7wP0A4WkiW4v0EM53wjf8el1gXWfqA$
> >  
> > Config: 
> > https://urldefense.com/v3/__http://0x0.st/X9r2.txt__;!!CTRNKA9wMg0ARbw!g_UleOH6C5AdZoKEVoko3ewb6zKCcWfDGfw3u6LV_x3JCST7WnvMrAzM7wP0A4WkiW4v0EM53wjf8enPGJN1sg$
> >  
> > 
> > #regzbot introduced: ee6bd4b95c66
> > #regzbot title: usb_kill_anchored_urbs panic during boot on mt8195-
> > cherry-tomato-r2
> > 
> > Thanks,
> > Nícolas


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

* Re: [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions
  2024-07-16 12:20       ` Nícolas F. R. A. Prado
@ 2024-07-30 15:38         ` Nícolas F. R. A. Prado
  0 siblings, 0 replies; 17+ messages in thread
From: Nícolas F. R. A. Prado @ 2024-07-30 15:38 UTC (permalink / raw)
  To: Chris Lu (陸稚泓)
  Cc: luiz.dentz@gmail.com, marcel@holtmann.org,
	linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
	kernelci@lists.linux.dev, linux-bluetooth@vger.kernel.org,
	regressions@lists.linux.dev, johan.hedberg@gmail.com,
	Steve Lee (李視誠), kernel@collabora.com,
	Sean Wang, Aaron Hou (侯俊仰)

On Tue, Jul 16, 2024 at 08:20:46AM -0400, Nícolas F. R. A. Prado wrote:
> On Tue, Jul 16, 2024 at 07:59:53AM +0000, Chris Lu (陸稚泓) wrote:
> > Hi Nicolas,
> > 
> > Thanks for reporting the crash issue, I've sent another patc to avoid
> > this crash issue happened. kill anchor function wasn't protect well if
> > MediaTek Bluetooth failed to setup. Add a flag check when running into
> > btmtk_usb_suspend function.
> 
> Hi Chris,
> 
> thanks for the quick follow up! I see the patch at
> https://lore.kernel.org/all/20240716074947.23073-1-chris.lu@mediatek.com/

That patch was merged without the Closes tag, so manually closing the
regression:

#regzbot fix: 'Bluetooth: btmtk: Fix kernel crash when entering btmtk_usb_suspend'

Thanks,
Nícolas


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

end of thread, other threads:[~2024-07-30 15:38 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-04  6:01 [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support Chris Lu
2024-07-04  6:01 ` [PATCH v7 1/8] Bluetooth: btusb: mediatek: remove the unnecessary goto tag Chris Lu
2024-07-04  6:01 ` [PATCH v7 2/8] Bluetooth: btusb: mediatek: return error for failed reg access Chris Lu
2024-07-04  6:01 ` [PATCH v7 3/8] Bluetooth: btmtk: rename btmediatek_data Chris Lu
2024-07-04  6:01 ` [PATCH v7 4/8] Bluetooth: btusb: add callback function in btusb suspend/resume Chris Lu
2024-07-04  6:01 ` [PATCH v7 5/8] Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c Chris Lu
2024-07-05  6:09   ` kernel test robot
2024-07-05  9:33   ` kernel test robot
2024-07-04  6:01 ` [PATCH v7 6/8] Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] " Chris Lu
2024-07-04  6:01 ` [PATCH v7 7/8] Bluetooth: btmtk: move btusb_recv_acl_mtk " Chris Lu
2024-07-04  6:01 ` [PATCH v7 8/8] Bluetooth: btusb: mediatek: add ISO data transmission functions Chris Lu
2024-07-05  9:11   ` kernel test robot
2024-07-15 22:36   ` Nícolas F. R. A. Prado
2024-07-16  7:59     ` Chris Lu (陸稚泓)
2024-07-16 12:20       ` Nícolas F. R. A. Prado
2024-07-30 15:38         ` Nícolas F. R. A. Prado
2024-07-08 21:20 ` [PATCH v7 0/8] Bluetooth: btmtk: MediaTek ISO data transmission support patchwork-bot+bluetooth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).