mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v7 1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding
@ 2023-06-26 20:41 sean.wang
  2023-06-26 20:41 ` [PATCH v7 2/3] Bluetooth: btmtk: introduce btmtk reset work sean.wang
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: sean.wang @ 2023-06-26 20:41 UTC (permalink / raw)
  To: marcel, johan.hedberg, luiz.dentz
  Cc: sean.wang, chris.lu, Soul.Huang, Leon.Yen, Deren.Wu, km.lin,
	robin.chiu, Eddie.Chen, ch.yeh, jenhao.yang, Stella.Chang,
	Tom.Chou, steve.lee, jsiuda, frankgor, abhishekpandit,
	michaelfsun, abhishekpandit, mcchou, shawnku, linux-bluetooth,
	linux-mediatek, linux-kernel

From: Sean Wang <sean.wang@mediatek.com>

Use readx_poll_timeout instead of open coding to poll the hardware reset
status until it is done.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
v2: use 20ms as the unit to poll according to the requirement of
    readx_poll_timeout
v3: refine btusb_mtk_reset_done and drop the necessary error check
    in btusb_mtk_cmd_timeout
v4, v5, v6 and v7: rebase onto the latest codebase
---
 drivers/bluetooth/btusb.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 1c0879601735..71b119bcff29 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2654,8 +2654,6 @@ static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
 #define MTK_EP_RST_OPT		0x74011890
 #define MTK_EP_RST_IN_OUT_OPT	0x00010001
 #define MTK_BT_RST_DONE		0x00000100
-#define MTK_BT_RESET_WAIT_MS	100
-#define MTK_BT_RESET_NUM_TRIES	10
 #define MTK_BT_RESET_REG_CONNV3	0x70028610
 #define MTK_BT_READ_DEV_ID	0x70010200
 
@@ -3029,6 +3027,16 @@ 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_setup(struct hci_dev *hdev)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -3229,7 +3237,7 @@ static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
 	u32 val;
-	int err, retry = 0;
+	int err;
 	struct btmediatek_data *mediatek;
 
 	/* It's MediaTek specific bluetooth reset mechanism via USB */
@@ -3281,18 +3289,10 @@ static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
 		btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
 	}
 
-	/* Poll the register until reset is completed */
-	do {
-		btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val);
-		if (val & MTK_BT_RST_DONE) {
-			bt_dev_dbg(hdev, "Bluetooth Reset Successfully");
-			break;
-		}
-
-		bt_dev_dbg(hdev, "Polling Bluetooth Reset CR");
-		retry++;
-		msleep(MTK_BT_RESET_WAIT_MS);
-	} while (retry < MTK_BT_RESET_NUM_TRIES);
+	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");
 
 	btusb_mtk_id_get(data, 0x70010200, &val);
 	if (!val)
-- 
2.25.1


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

* [PATCH v7 2/3] Bluetooth: btmtk: introduce btmtk reset work
  2023-06-26 20:41 [PATCH v7 1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding sean.wang
@ 2023-06-26 20:41 ` sean.wang
  2023-06-26 20:49   ` Luiz Augusto von Dentz
  2023-06-26 20:41 ` [PATCH v7 3/3] Bluetooth: btusb: mediatek: add MediaTek devcoredump support sean.wang
  2023-06-29 19:24 ` [PATCH v7 1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding patchwork-bot+bluetooth
  2 siblings, 1 reply; 5+ messages in thread
From: sean.wang @ 2023-06-26 20:41 UTC (permalink / raw)
  To: marcel, johan.hedberg, luiz.dentz
  Cc: sean.wang, chris.lu, Soul.Huang, Leon.Yen, Deren.Wu, km.lin,
	robin.chiu, Eddie.Chen, ch.yeh, jenhao.yang, Stella.Chang,
	Tom.Chou, steve.lee, jsiuda, frankgor, abhishekpandit,
	michaelfsun, abhishekpandit, mcchou, shawnku, linux-bluetooth,
	linux-mediatek, linux-kernel, Jing Cai

From: Jing Cai <jing.cai@mediatek.com>

Introduce btmtk_reset_work which can be called whenever the firmware abort,
HCI command timeout, other fatal error happen.

Co-developed-by: Chris Lu <chris.lu@mediatek.com>
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
Co-developed-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Jing Cai <jing.cai@mediatek.com>
---
v2, v3, v4: rebase onto the latest codebase
v5: reset the device on hdev basis and use hci_cmd_sync_queue to
    schedule reset work
v6 and v7: rebase onto the latest codebase
---
 drivers/bluetooth/btmtk.c |  15 ++++
 drivers/bluetooth/btmtk.h |   8 +++
 drivers/bluetooth/btusb.c | 145 +++++++++++++++++++-------------------
 3 files changed, 97 insertions(+), 71 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 9482401d97fa..b8678b75276e 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -280,6 +280,21 @@ int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
 }
 EXPORT_SYMBOL_GPL(btmtk_set_bdaddr);
 
+void btmtk_reset_sync(struct hci_dev *hdev)
+{
+	struct btmediatek_data *reset_work = hci_get_priv(hdev);
+	int err;
+
+	hci_dev_lock(hdev);
+
+	err = hci_cmd_sync_queue(hdev, reset_work->reset_sync, NULL, NULL);
+	if (err)
+		bt_dev_err(hdev, "failed to reset (%d)", err);
+
+	hci_dev_unlock(hdev);
+}
+EXPORT_SYMBOL_GPL(btmtk_reset_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 fadc1a520652..75d8e71efcd3 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -120,8 +120,11 @@ struct btmtk_hci_wmt_params {
 	u32 *status;
 };
 
+typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);
+
 struct btmediatek_data {
 	u32 dev_id;
+	btmtk_reset_sync_func_t reset_sync;
 };
 
 typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
@@ -136,6 +139,8 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 
 int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
 			 wmt_cmd_sync_func_t wmt_cmd_sync);
+
+void btmtk_reset_sync(struct hci_dev *hdev);
 #else
 
 static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
@@ -156,4 +161,7 @@ static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
 	return -EOPNOTSUPP;
 }
 
+static void btmtk_reset_sync(struct hci_dev *hdev)
+{
+}
 #endif
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 71b119bcff29..4ebab61c288c 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -3037,6 +3037,78 @@ static u32 btusb_mtk_reset_done(struct hci_dev *hdev)
 	return val & MTK_BT_RST_DONE;
 }
 
+static int btusb_mtk_reset_work(struct hci_dev *hdev, void *rst_data)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+	struct btmediatek_data *mediatek;
+	u32 val;
+	int err;
+
+	/* It's MediaTek specific bluetooth reset mechanism via USB */
+	if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
+		bt_dev_err(hdev, "last reset failed? Not resetting again");
+		return -EBUSY;
+	}
+
+	err = usb_autopm_get_interface(data->intf);
+	if (err < 0)
+		return err;
+
+	btusb_stop_traffic(data);
+	usb_kill_anchored_urbs(&data->tx_anchor);
+	mediatek = hci_get_priv(hdev);
+
+	if (mediatek->dev_id == 0x7925) {
+		btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
+		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);
+		val &= 0xFFFF00FF;
+		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);
+		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);
+		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);
+
+		/* 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);
+		/* 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 = 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");
+
+	btusb_mtk_id_get(data, 0x70010200, &val);
+	if (!val)
+		bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
+
+	usb_queue_reset_device(data->intf);
+
+	clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags);
+
+	return err;
+}
+
 static int btusb_mtk_setup(struct hci_dev *hdev)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -3076,6 +3148,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 
 	mediatek = hci_get_priv(hdev);
 	mediatek->dev_id = dev_id;
+	mediatek->reset_sync = btusb_mtk_reset_work;
 
 	switch (dev_id) {
 	case 0x7663:
@@ -3233,76 +3306,6 @@ static int btusb_mtk_shutdown(struct hci_dev *hdev)
 	return 0;
 }
 
-static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
-{
-	struct btusb_data *data = hci_get_drvdata(hdev);
-	u32 val;
-	int err;
-	struct btmediatek_data *mediatek;
-
-	/* It's MediaTek specific bluetooth reset mechanism via USB */
-	if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
-		bt_dev_err(hdev, "last reset failed? Not resetting again");
-		return;
-	}
-
-	err = usb_autopm_get_interface(data->intf);
-	if (err < 0)
-		return;
-
-	btusb_stop_traffic(data);
-	usb_kill_anchored_urbs(&data->tx_anchor);
-	mediatek = hci_get_priv(hdev);
-
-	if (mediatek->dev_id == 0x7925) {
-		btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
-		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);
-		val &= 0xFFFF00FF;
-		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);
-		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);
-		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);
-
-		/* 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);
-		/* 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 = 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");
-
-	btusb_mtk_id_get(data, 0x70010200, &val);
-	if (!val)
-		bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
-
-	usb_queue_reset_device(data->intf);
-
-	clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags);
-}
-
 static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
@@ -4429,7 +4432,7 @@ static int btusb_probe(struct usb_interface *intf,
 		hdev->setup = btusb_mtk_setup;
 		hdev->shutdown = btusb_mtk_shutdown;
 		hdev->manufacturer = 70;
-		hdev->cmd_timeout = btusb_mtk_cmd_timeout;
+		hdev->cmd_timeout = btmtk_reset_sync;
 		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);
-- 
2.25.1


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

* [PATCH v7 3/3] Bluetooth: btusb: mediatek: add MediaTek devcoredump support
  2023-06-26 20:41 [PATCH v7 1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding sean.wang
  2023-06-26 20:41 ` [PATCH v7 2/3] Bluetooth: btmtk: introduce btmtk reset work sean.wang
@ 2023-06-26 20:41 ` sean.wang
  2023-06-29 19:24 ` [PATCH v7 1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding patchwork-bot+bluetooth
  2 siblings, 0 replies; 5+ messages in thread
From: sean.wang @ 2023-06-26 20:41 UTC (permalink / raw)
  To: marcel, johan.hedberg, luiz.dentz
  Cc: sean.wang, chris.lu, Soul.Huang, Leon.Yen, Deren.Wu, km.lin,
	robin.chiu, Eddie.Chen, ch.yeh, jenhao.yang, Stella.Chang,
	Tom.Chou, steve.lee, jsiuda, frankgor, abhishekpandit,
	michaelfsun, abhishekpandit, mcchou, shawnku, linux-bluetooth,
	linux-mediatek, linux-kernel, Jing Cai

From: Jing Cai <jing.cai@mediatek.com>

This patch implement function .coredump() and dmp_hdr() in btusb
driver for MediaTek controller.  FW core dump was triggered by FW
specific event to show something unexpected happened in the controller.

The driver would be responsible for collecting and uploading the device
core dump pieces in hci driver using core dump API. Once we finished
the whole process, the driver would reset the controller to recover the
kind of fatal error.

Co-developed-by: Chris Lu <chris.lu@mediatek.com>
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
Co-developed-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Jing Cai <jing.cai@mediatek.com>
---
v2, v3: rebase onto the latest codebase
v4: update the newest API usage for the coredump which was already
    into the upstream
v5: support devcoredump on hdev basis
v6: reuse the coredump state HCI_DEVCOREDUMP_* in driver
    and drop the driver name copying
v7: rebase ontto the latest codebase and refine the check if
    we are reaching the end of the coredump
---
 drivers/bluetooth/btmtk.c | 112 ++++++++++++++++++++++++++++++++++++++
 drivers/bluetooth/btmtk.h |  28 ++++++++++
 drivers/bluetooth/btusb.c |  14 +++++
 3 files changed, 154 insertions(+)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index b8678b75276e..8fe1b7e7255c 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -53,6 +53,56 @@ struct btmtk_section_map {
 	};
 } __packed;
 
+static void btmtk_coredump(struct hci_dev *hdev)
+{
+	int err;
+
+	err = __hci_cmd_send(hdev, 0xfd5b, 0, NULL);
+	if (err < 0)
+		bt_dev_err(hdev, "Coredump failed (%d)", err);
+}
+
+static void btmtk_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct btmediatek_data *data = hci_get_priv(hdev);
+	char buf[80];
+
+	snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
+		 data->dev_id);
+	skb_put_data(skb, buf, strlen(buf));
+
+	snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n",
+		 data->cd_info.fw_version);
+	skb_put_data(skb, buf, strlen(buf));
+
+	snprintf(buf, sizeof(buf), "Driver: %s\n",
+		 data->cd_info.driver_name);
+	skb_put_data(skb, buf, strlen(buf));
+
+	snprintf(buf, sizeof(buf), "Vendor: MediaTek\n");
+	skb_put_data(skb, buf, strlen(buf));
+}
+
+static void btmtk_coredump_notify(struct hci_dev *hdev, int state)
+{
+	struct btmediatek_data *data = hci_get_priv(hdev);
+
+	switch (state) {
+	case HCI_DEVCOREDUMP_IDLE:
+		data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
+		break;
+	case HCI_DEVCOREDUMP_ACTIVE:
+		data->cd_info.state = HCI_DEVCOREDUMP_ACTIVE;
+		break;
+	case HCI_DEVCOREDUMP_TIMEOUT:
+	case HCI_DEVCOREDUMP_ABORT:
+	case HCI_DEVCOREDUMP_DONE:
+		data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
+		btmtk_reset_sync(hdev);
+		break;
+	}
+}
+
 int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 			      wmt_cmd_sync_func_t wmt_cmd_sync)
 {
@@ -295,6 +345,68 @@ void btmtk_reset_sync(struct hci_dev *hdev)
 }
 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);
+
+	if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
+		return -EOPNOTSUPP;
+
+	data->cd_info.fw_version = fw_version;
+	data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
+	data->cd_info.driver_name = name;
+
+	return hci_devcd_register(hdev, btmtk_coredump, btmtk_coredump_hdr,
+				  btmtk_coredump_notify);
+}
+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);
+	int err;
+
+	if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
+		return 0;
+
+	switch (data->cd_info.state) {
+	case HCI_DEVCOREDUMP_IDLE:
+		err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
+		if (err < 0)
+			break;
+		data->cd_info.cnt = 0;
+
+		/* It is supposed coredump can be done within 5 seconds */
+		schedule_delayed_work(&hdev->dump.dump_timeout,
+				      msecs_to_jiffies(5000));
+		fallthrough;
+	case HCI_DEVCOREDUMP_ACTIVE:
+	default:
+		err = hci_devcd_append(hdev, skb);
+		if (err < 0)
+			break;
+		data->cd_info.cnt++;
+
+		/* Mediatek coredump data would be more than MTK_COREDUMP_NUM */
+		if (data->cd_info.cnt > MTK_COREDUMP_NUM &&
+		    skb->len > sizeof(MTK_COREDUMP_END) &&
+		    !memcmp((char *)&skb->data[skb->len - sizeof(MTK_COREDUMP_END)],
+			    MTK_COREDUMP_END, sizeof(MTK_COREDUMP_END) - 1)) {
+			bt_dev_info(hdev, "Mediatek coredump end");
+			hci_devcd_complete(hdev);
+		}
+
+		break;
+	}
+
+	if (err < 0)
+		kfree_skb(skb);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(btmtk_process_coredump);
+
 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 75d8e71efcd3..68309dfe076a 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -22,6 +22,10 @@
 #define MT7921_DLSTATUS 0x7c053c10
 #define BT_DL_STATE BIT(1)
 
+#define MTK_COREDUMP_SIZE		(1024 * 1000)
+#define MTK_COREDUMP_END		"coredump end"
+#define MTK_COREDUMP_NUM		255
+
 enum {
 	BTMTK_WMT_PATCH_DWNLD = 0x1,
 	BTMTK_WMT_TEST = 0x2,
@@ -122,9 +126,17 @@ struct btmtk_hci_wmt_params {
 
 typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);
 
+struct btmtk_coredump_info {
+	const char *driver_name;
+	u32 fw_version;
+	u16 cnt;
+	int state;
+};
+
 struct btmediatek_data {
 	u32 dev_id;
 	btmtk_reset_sync_func_t reset_sync;
+	struct btmtk_coredump_info cd_info;
 };
 
 typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
@@ -141,6 +153,11 @@ int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
 			 wmt_cmd_sync_func_t wmt_cmd_sync);
 
 void btmtk_reset_sync(struct hci_dev *hdev);
+
+int btmtk_register_coredump(struct hci_dev *hdev, const char *name,
+			    u32 fw_version);
+
+int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb);
 #else
 
 static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
@@ -164,4 +181,15 @@ static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
 static void btmtk_reset_sync(struct hci_dev *hdev)
 {
 }
+
+static int btmtk_register_coredump(struct hci_dev *hdev, const char *name,
+				   u32 fw_version)
+{
+	return -EOPNOTSUPP;
+}
+
+static int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	return -EOPNOTSUPP;
+}
 #endif
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 4ebab61c288c..729445ef3871 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -3150,6 +3150,10 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 	mediatek->dev_id = dev_id;
 	mediatek->reset_sync = btusb_mtk_reset_work;
 
+	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;
@@ -3310,6 +3314,7 @@ 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);
+	struct sk_buff *skb_cd;
 
 	switch (handle) {
 	case 0xfc6f:		/* Firmware dump from device */
@@ -3317,6 +3322,15 @@ static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
 		 * 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.
+		 */
+		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 */
-- 
2.25.1


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

* Re: [PATCH v7 2/3] Bluetooth: btmtk: introduce btmtk reset work
  2023-06-26 20:41 ` [PATCH v7 2/3] Bluetooth: btmtk: introduce btmtk reset work sean.wang
@ 2023-06-26 20:49   ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 5+ messages in thread
From: Luiz Augusto von Dentz @ 2023-06-26 20:49 UTC (permalink / raw)
  To: sean.wang
  Cc: marcel, johan.hedberg, chris.lu, Soul.Huang, Leon.Yen, Deren.Wu,
	km.lin, robin.chiu, Eddie.Chen, ch.yeh, jenhao.yang,
	Stella.Chang, Tom.Chou, steve.lee, jsiuda, frankgor,
	abhishekpandit, michaelfsun, abhishekpandit, mcchou, shawnku,
	linux-bluetooth, linux-mediatek, linux-kernel, Jing Cai

Hi Sean,

On Mon, Jun 26, 2023 at 1:41 PM <sean.wang@mediatek.com> wrote:
>
> From: Jing Cai <jing.cai@mediatek.com>
>
> Introduce btmtk_reset_work which can be called whenever the firmware abort,
> HCI command timeout, other fatal error happen.
>
> Co-developed-by: Chris Lu <chris.lu@mediatek.com>
> Signed-off-by: Chris Lu <chris.lu@mediatek.com>
> Co-developed-by: Sean Wang <sean.wang@mediatek.com>
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> Signed-off-by: Jing Cai <jing.cai@mediatek.com>
> ---
> v2, v3, v4: rebase onto the latest codebase
> v5: reset the device on hdev basis and use hci_cmd_sync_queue to
>     schedule reset work
> v6 and v7: rebase onto the latest codebase
> ---
>  drivers/bluetooth/btmtk.c |  15 ++++
>  drivers/bluetooth/btmtk.h |   8 +++
>  drivers/bluetooth/btusb.c | 145 +++++++++++++++++++-------------------
>  3 files changed, 97 insertions(+), 71 deletions(-)
>
> diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
> index 9482401d97fa..b8678b75276e 100644
> --- a/drivers/bluetooth/btmtk.c
> +++ b/drivers/bluetooth/btmtk.c
> @@ -280,6 +280,21 @@ int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
>  }
>  EXPORT_SYMBOL_GPL(btmtk_set_bdaddr);
>
> +void btmtk_reset_sync(struct hci_dev *hdev)
> +{
> +       struct btmediatek_data *reset_work = hci_get_priv(hdev);
> +       int err;
> +
> +       hci_dev_lock(hdev);
> +
> +       err = hci_cmd_sync_queue(hdev, reset_work->reset_sync, NULL, NULL);
> +       if (err)
> +               bt_dev_err(hdev, "failed to reset (%d)", err);
> +
> +       hci_dev_unlock(hdev);
> +}
> +EXPORT_SYMBOL_GPL(btmtk_reset_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 fadc1a520652..75d8e71efcd3 100644
> --- a/drivers/bluetooth/btmtk.h
> +++ b/drivers/bluetooth/btmtk.h
> @@ -120,8 +120,11 @@ struct btmtk_hci_wmt_params {
>         u32 *status;
>  };
>
> +typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);
> +
>  struct btmediatek_data {
>         u32 dev_id;
> +       btmtk_reset_sync_func_t reset_sync;
>  };
>
>  typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
> @@ -136,6 +139,8 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
>
>  int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
>                          wmt_cmd_sync_func_t wmt_cmd_sync);
> +
> +void btmtk_reset_sync(struct hci_dev *hdev);
>  #else
>
>  static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
> @@ -156,4 +161,7 @@ static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
>         return -EOPNOTSUPP;
>  }
>
> +static void btmtk_reset_sync(struct hci_dev *hdev)
> +{
> +}
>  #endif
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 71b119bcff29..4ebab61c288c 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -3037,6 +3037,78 @@ static u32 btusb_mtk_reset_done(struct hci_dev *hdev)
>         return val & MTK_BT_RST_DONE;
>  }
>
> +static int btusb_mtk_reset_work(struct hci_dev *hdev, void *rst_data)

You can probably drop _work suffix since it no longer runs on its own
dedicated work.

> +{
> +       struct btusb_data *data = hci_get_drvdata(hdev);
> +       struct btmediatek_data *mediatek;
> +       u32 val;
> +       int err;
> +
> +       /* It's MediaTek specific bluetooth reset mechanism via USB */
> +       if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
> +               bt_dev_err(hdev, "last reset failed? Not resetting again");
> +               return -EBUSY;
> +       }
> +
> +       err = usb_autopm_get_interface(data->intf);
> +       if (err < 0)
> +               return err;
> +
> +       btusb_stop_traffic(data);
> +       usb_kill_anchored_urbs(&data->tx_anchor);
> +       mediatek = hci_get_priv(hdev);
> +
> +       if (mediatek->dev_id == 0x7925) {
> +               btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
> +               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);
> +               val &= 0xFFFF00FF;
> +               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);
> +               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);
> +               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);
> +
> +               /* 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);
> +               /* 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 = 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");
> +
> +       btusb_mtk_id_get(data, 0x70010200, &val);
> +       if (!val)
> +               bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
> +
> +       usb_queue_reset_device(data->intf);
> +
> +       clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags);
> +
> +       return err;
> +}
> +
>  static int btusb_mtk_setup(struct hci_dev *hdev)
>  {
>         struct btusb_data *data = hci_get_drvdata(hdev);
> @@ -3076,6 +3148,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
>
>         mediatek = hci_get_priv(hdev);
>         mediatek->dev_id = dev_id;
> +       mediatek->reset_sync = btusb_mtk_reset_work;
>
>         switch (dev_id) {
>         case 0x7663:
> @@ -3233,76 +3306,6 @@ static int btusb_mtk_shutdown(struct hci_dev *hdev)
>         return 0;
>  }
>
> -static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
> -{
> -       struct btusb_data *data = hci_get_drvdata(hdev);
> -       u32 val;
> -       int err;
> -       struct btmediatek_data *mediatek;
> -
> -       /* It's MediaTek specific bluetooth reset mechanism via USB */
> -       if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
> -               bt_dev_err(hdev, "last reset failed? Not resetting again");
> -               return;
> -       }
> -
> -       err = usb_autopm_get_interface(data->intf);
> -       if (err < 0)
> -               return;
> -
> -       btusb_stop_traffic(data);
> -       usb_kill_anchored_urbs(&data->tx_anchor);
> -       mediatek = hci_get_priv(hdev);
> -
> -       if (mediatek->dev_id == 0x7925) {
> -               btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
> -               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);
> -               val &= 0xFFFF00FF;
> -               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);
> -               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);
> -               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);
> -
> -               /* 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);
> -               /* 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 = 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");
> -
> -       btusb_mtk_id_get(data, 0x70010200, &val);
> -       if (!val)
> -               bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
> -
> -       usb_queue_reset_device(data->intf);
> -
> -       clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags);
> -}
> -
>  static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
>  {
>         struct btusb_data *data = hci_get_drvdata(hdev);
> @@ -4429,7 +4432,7 @@ static int btusb_probe(struct usb_interface *intf,
>                 hdev->setup = btusb_mtk_setup;
>                 hdev->shutdown = btusb_mtk_shutdown;
>                 hdev->manufacturer = 70;
> -               hdev->cmd_timeout = btusb_mtk_cmd_timeout;
> +               hdev->cmd_timeout = btmtk_reset_sync;
>                 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);
> --
> 2.25.1
>


-- 
Luiz Augusto von Dentz

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

* Re: [PATCH v7 1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding
  2023-06-26 20:41 [PATCH v7 1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding sean.wang
  2023-06-26 20:41 ` [PATCH v7 2/3] Bluetooth: btmtk: introduce btmtk reset work sean.wang
  2023-06-26 20:41 ` [PATCH v7 3/3] Bluetooth: btusb: mediatek: add MediaTek devcoredump support sean.wang
@ 2023-06-29 19:24 ` patchwork-bot+bluetooth
  2 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+bluetooth @ 2023-06-29 19:24 UTC (permalink / raw)
  To: Sean Wang
  Cc: marcel, johan.hedberg, luiz.dentz, chris.lu, Soul.Huang,
	Leon.Yen, Deren.Wu, km.lin, robin.chiu, Eddie.Chen, ch.yeh,
	jenhao.yang, Stella.Chang, Tom.Chou, steve.lee, jsiuda, frankgor,
	abhishekpandit, michaelfsun, abhishekpandit, mcchou, shawnku,
	linux-bluetooth, linux-mediatek, linux-kernel

Hello:

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

On Tue, 27 Jun 2023 04:41:37 +0800 you wrote:
> From: Sean Wang <sean.wang@mediatek.com>
> 
> Use readx_poll_timeout instead of open coding to poll the hardware reset
> status until it is done.
> 
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> 
> [...]

Here is the summary with links:
  - [v7,1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding
    https://git.kernel.org/bluetooth/bluetooth-next/c/c56e5f834e13
  - [v7,2/3] Bluetooth: btmtk: introduce btmtk reset work
    (no matching commit)
  - [v7,3/3] Bluetooth: btusb: mediatek: add MediaTek devcoredump support
    (no matching commit)

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] 5+ messages in thread

end of thread, other threads:[~2023-06-29 19:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-26 20:41 [PATCH v7 1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding sean.wang
2023-06-26 20:41 ` [PATCH v7 2/3] Bluetooth: btmtk: introduce btmtk reset work sean.wang
2023-06-26 20:49   ` Luiz Augusto von Dentz
2023-06-26 20:41 ` [PATCH v7 3/3] Bluetooth: btusb: mediatek: add MediaTek devcoredump support sean.wang
2023-06-29 19:24 ` [PATCH v7 1/3] Bluetooth: btusb: mediatek: use readx_poll_timeout instead of open coding 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

all inboxes | Powered by JetHome®