* [PATCH RFC 0/2] USB/Bluetooth: recover MT7925 after warm reboot
@ 2026-08-18 2:55 ` George Maraveyas
0 siblings, 0 replies; 11+ messages in thread
From: George Maraveyas via B4 Relay @ 2026-08-18 2:55 UTC (permalink / raw)
To: Greg Kroah-Hartman, Marcel Holtmann, Luiz Augusto von Dentz,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-usb, linux-kernel, linux-bluetooth, linux-arm-kernel,
linux-mediatek, George Maraveyas
While dual booting Windows 11 and Linux on an ASUS ROG Strix B850-I
Gaming WiFi, I found that the MediaTek MT7925 Bluetooth controller could
remain unusable after a warm reboot even though its USB function had
enumerated successfully.
This investigation originally began on Ubuntu 26.04 LTS, where the
failure was already present on the stock kernel, and remained
reproducible after the work was moved to linux-next for upstream testing.
The Bluetooth USB function on this system is 13d3:3602. The problem was
reproduced with ASUS motherboard BIOS versions 1644 and 1681. Updating
the BIOS did not change the failure.
A typical failure occurs after restarting directly from Windows 11 into
Linux without removing power. The MT7925 USB function enumerates, btusb
begins setting up the controller, and the WMT function-control command
eventually times out with -ETIMEDOUT (-110). The existing MediaTek reset
path then runs, but the subsequent MT7925 subsystem reset also times out
and resetting the existing usb_device does not recover the controller.
Powering the machine off and starting again was not a reliable workaround
in later testing, especially after booting Windows and then Linux.
Linux-to-Linux warm reboots after a failure were also inconsistent: on
some boots Bluetooth recovered, while on others the failed controller
state persisted.
When that state persisted across a reboot, the MT7925 could fail earlier
while USB core was reading its descriptors. USB core then handled the
failure through its normal enumeration retry path and could eventually
reach the existing port power-cycle.
The series was tested on top of Chia-Lin Kao's:
[PATCH v2] USB: hub: call ACPI _PRR reset during port power-cycle on
enumeration failure
Kao's patch adds the ACPI _PRR reset to that existing mid-retry
power-cycle. It is required for the port recovery used on this machine,
but it does not fix the original warm-reboot failure by itself. On the
first Linux boot after Windows, USB enumeration has already succeeded
before the WMT command times out, so USB core does not enter the
enumeration retry path where the power-cycle and _PRR reset occur.
Patch 1 adds usb_queue_reenumerate_device(). It allows a driver to ask
USB core to remove the current usb_device and enumerate the
still-connected physical device again through the normal hub path. It
does not itself request a port power-cycle or an ACPI _PRR reset.
Patch 2 changes one part of the existing MT7925 reset path. After
btmtk_usb_subsys_reset() returns, an MT7925 -ETIMEDOUT result causes the
driver to request re-enumeration through the helper from Patch 1. If
that request cannot be queued, the existing usb_queue_reset_device()
path remains as the fallback. Other MediaTek devices and other reset
results retain their existing behaviour.
On the test system the re-enumerated MT7925 continued to fail descriptor
reads. The normal hub retry logic therefore eventually reached its
existing port power-cycle, where Kao's prerequisite supplied the ACPI
_PRR reset. Enumeration then succeeded and Bluetooth setup completed.
Three controlled Windows 11-to-Linux warm restart tests recovered
successfully with the series. The observed average interval from the
initial WMT timeout to successful Bluetooth setup was about 70.9 seconds.
Bluetooth remained unavailable during most of that interval, so someone
testing the series should not expect the controller to return
immediately after re-enumeration is requested.
Since completing those controlled tests, I have continued to use the
patched kernel as my daily Linux system. On this machine it has been the
only reliable way I have found to switch between Windows and Linux
without repeated reboot or power-cycle attempts to recover Bluetooth.
The test kernel was based on next-20260812 and reported:
7.2.0-rc7-next-20260812-mt7925-rfc-v1
I am sending this as an RFC because Patch 1 adds a USB-core interface. I
would particularly appreciate feedback on whether returning an
already-enumerated device to the normal hub enumeration path through
hub_port_logical_disconnect() is the appropriate interface for this
recovery.
Signed-off-by: George Maraveyas <george.0xfff@gmail.com>
---
George Maraveyas (2):
USB: core: add helper to queue device re-enumeration
Bluetooth: mt7925: recover subsystem-reset timeout through USB re-enumeration
drivers/bluetooth/btmtk.c | 4 ++++
drivers/bluetooth/btusb.c | 16 ++++++++++++++
drivers/usb/core/hub.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/usb.h | 1 +
4 files changed, 75 insertions(+)
---
base-commit: 28d012efb4327f9c75d5e042a7c91e9a542efa98
change-id: 20260818-mt7925-rfc-edd34ef031d9
prerequisite-message-id: <20260706080117.3754550-1-acelan.kao@canonical.com>
prerequisite-patch-id: 47a2729fbc473534f8ba52052b00723c54a26c17
Best regards,
--
George Maraveyas <george.0xfff@gmail.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH RFC 0/2] USB/Bluetooth: recover MT7925 after warm reboot
@ 2026-08-18 2:55 ` George Maraveyas
0 siblings, 0 replies; 11+ messages in thread
From: George Maraveyas @ 2026-08-18 2:55 UTC (permalink / raw)
To: Greg Kroah-Hartman, Marcel Holtmann, Luiz Augusto von Dentz,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-usb, linux-kernel, linux-bluetooth, linux-arm-kernel,
linux-mediatek, George Maraveyas
While dual booting Windows 11 and Linux on an ASUS ROG Strix B850-I
Gaming WiFi, I found that the MediaTek MT7925 Bluetooth controller could
remain unusable after a warm reboot even though its USB function had
enumerated successfully.
This investigation originally began on Ubuntu 26.04 LTS, where the
failure was already present on the stock kernel, and remained
reproducible after the work was moved to linux-next for upstream testing.
The Bluetooth USB function on this system is 13d3:3602. The problem was
reproduced with ASUS motherboard BIOS versions 1644 and 1681. Updating
the BIOS did not change the failure.
A typical failure occurs after restarting directly from Windows 11 into
Linux without removing power. The MT7925 USB function enumerates, btusb
begins setting up the controller, and the WMT function-control command
eventually times out with -ETIMEDOUT (-110). The existing MediaTek reset
path then runs, but the subsequent MT7925 subsystem reset also times out
and resetting the existing usb_device does not recover the controller.
Powering the machine off and starting again was not a reliable workaround
in later testing, especially after booting Windows and then Linux.
Linux-to-Linux warm reboots after a failure were also inconsistent: on
some boots Bluetooth recovered, while on others the failed controller
state persisted.
When that state persisted across a reboot, the MT7925 could fail earlier
while USB core was reading its descriptors. USB core then handled the
failure through its normal enumeration retry path and could eventually
reach the existing port power-cycle.
The series was tested on top of Chia-Lin Kao's:
[PATCH v2] USB: hub: call ACPI _PRR reset during port power-cycle on
enumeration failure
Kao's patch adds the ACPI _PRR reset to that existing mid-retry
power-cycle. It is required for the port recovery used on this machine,
but it does not fix the original warm-reboot failure by itself. On the
first Linux boot after Windows, USB enumeration has already succeeded
before the WMT command times out, so USB core does not enter the
enumeration retry path where the power-cycle and _PRR reset occur.
Patch 1 adds usb_queue_reenumerate_device(). It allows a driver to ask
USB core to remove the current usb_device and enumerate the
still-connected physical device again through the normal hub path. It
does not itself request a port power-cycle or an ACPI _PRR reset.
Patch 2 changes one part of the existing MT7925 reset path. After
btmtk_usb_subsys_reset() returns, an MT7925 -ETIMEDOUT result causes the
driver to request re-enumeration through the helper from Patch 1. If
that request cannot be queued, the existing usb_queue_reset_device()
path remains as the fallback. Other MediaTek devices and other reset
results retain their existing behaviour.
On the test system the re-enumerated MT7925 continued to fail descriptor
reads. The normal hub retry logic therefore eventually reached its
existing port power-cycle, where Kao's prerequisite supplied the ACPI
_PRR reset. Enumeration then succeeded and Bluetooth setup completed.
Three controlled Windows 11-to-Linux warm restart tests recovered
successfully with the series. The observed average interval from the
initial WMT timeout to successful Bluetooth setup was about 70.9 seconds.
Bluetooth remained unavailable during most of that interval, so someone
testing the series should not expect the controller to return
immediately after re-enumeration is requested.
Since completing those controlled tests, I have continued to use the
patched kernel as my daily Linux system. On this machine it has been the
only reliable way I have found to switch between Windows and Linux
without repeated reboot or power-cycle attempts to recover Bluetooth.
The test kernel was based on next-20260812 and reported:
7.2.0-rc7-next-20260812-mt7925-rfc-v1
I am sending this as an RFC because Patch 1 adds a USB-core interface. I
would particularly appreciate feedback on whether returning an
already-enumerated device to the normal hub enumeration path through
hub_port_logical_disconnect() is the appropriate interface for this
recovery.
Signed-off-by: George Maraveyas <george.0xfff@gmail.com>
---
George Maraveyas (2):
USB: core: add helper to queue device re-enumeration
Bluetooth: mt7925: recover subsystem-reset timeout through USB re-enumeration
drivers/bluetooth/btmtk.c | 4 ++++
drivers/bluetooth/btusb.c | 16 ++++++++++++++
drivers/usb/core/hub.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/usb.h | 1 +
4 files changed, 75 insertions(+)
---
base-commit: 28d012efb4327f9c75d5e042a7c91e9a542efa98
change-id: 20260818-mt7925-rfc-edd34ef031d9
prerequisite-message-id: <20260706080117.3754550-1-acelan.kao@canonical.com>
prerequisite-patch-id: 47a2729fbc473534f8ba52052b00723c54a26c17
Best regards,
--
George Maraveyas <george.0xfff@gmail.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH RFC 1/2] USB: core: add helper to queue device re-enumeration
2026-08-18 2:55 ` George Maraveyas
@ 2026-08-18 2:55 ` George Maraveyas
-1 siblings, 0 replies; 11+ messages in thread
From: George Maraveyas via B4 Relay @ 2026-08-18 2:55 UTC (permalink / raw)
To: Greg Kroah-Hartman, Marcel Holtmann, Luiz Augusto von Dentz,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-usb, linux-kernel, linux-bluetooth, linux-arm-kernel,
linux-mediatek, George Maraveyas
From: George Maraveyas <george.0xfff@gmail.com>
USB drivers can use usb_queue_reset_device() when they need USB core to
reset an already enumerated device asynchronously.
There is currently no driver-facing helper corresponding to
usb_queue_reset_device() which allows an interface driver to ask USB core
to remove the current usb_device and enumerate the physical device on the
port again.
The difference between the two is that a device reset continues using the
existing usb_device and its current enumeration state while
re-enumeration removes the existing usb_device and returns the port to
the hub code, which then discovers the device again through the normal
USB enumeration path.
Add usb_queue_reenumerate_device() to provide this facility.
The helper queues a logical disconnect on the parent hub port.
hub_port_logical_disconnect() disables the port, records a logical
connect-change event and queues the hub work. The hub work later
disconnects the existing usb_device and, if the physical device remains
connected, attempts to enumerate it again through the normal hub path.
Any retries or port recovery required during the subsequent enumeration
remain the responsibility of the existing hub code.
usb_remove_device() cannot provide the same behaviour because it also
marks the port in removed_bits. The hub connection path does not
enumerate a device on a port while that bit remains set.
The helper takes the device lock required by usb_hub_to_struct_hub() and
holds a runtime-PM reference on the parent hub interface while the
logical disconnect is queued.
The helper does not decide when re-enumeration is needed. That decision
remains with the calling driver.
The following MT7925 Bluetooth patch is the first user of the helper. It
requests re-enumeration after the controller has already enumerated
successfully but later fails during Bluetooth setup and cannot be
recovered by its existing reset path.
Signed-off-by: George Maraveyas <george.0xfff@gmail.com>
---
drivers/usb/core/hub.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/usb.h | 1 +
2 files changed, 55 insertions(+)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index fcac92bd7..22279d438 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -6503,6 +6503,60 @@ void usb_queue_reset_device(struct usb_interface *iface)
}
EXPORT_SYMBOL_GPL(usb_queue_reset_device);
+/**
+ * usb_queue_reenumerate_device - queue logical disconnect and re-enumeration
+ * @iface: USB interface belonging to the device to re-enumerate
+ *
+ * Request that USB core logically disconnect the device and subsequently
+ * re-enumerate its parent hub port. The actual device teardown and
+ * re-enumeration are handled asynchronously by the hub workqueue.
+ *
+ * This is intended for failures where resetting the existing usb_device is
+ * insufficient and the driver needs USB core to perform a full logical
+ * disconnect/re-enumeration cycle.
+ *
+ * Return: 0 if re-enumeration was queued successfully, or a negative error
+ * code otherwise.
+ */
+int usb_queue_reenumerate_device(struct usb_interface *iface)
+{
+ struct usb_device *udev = interface_to_usbdev(iface);
+ struct usb_interface *hub_intf;
+ struct usb_hub *hub;
+ int ret;
+
+ usb_lock_device(udev);
+
+ if (!udev->parent || udev->state == USB_STATE_NOTATTACHED) {
+ ret = -ENODEV;
+ goto out_unlock;
+ }
+
+ /*
+ * usb_hub_to_struct_hub() requires either the hub or one of its
+ * children to be locked. @udev is locked above.
+ */
+ hub = usb_hub_to_struct_hub(udev->parent);
+ if (!hub) {
+ ret = -ENODEV;
+ goto out_unlock;
+ }
+
+ hub_intf = to_usb_interface(hub->intfdev);
+ ret = usb_autopm_get_interface(hub_intf);
+ if (ret < 0)
+ goto out_unlock;
+
+ hub_port_logical_disconnect(hub, udev->portnum);
+ usb_autopm_put_interface(hub_intf);
+ ret = 0;
+
+out_unlock:
+ usb_unlock_device(udev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usb_queue_reenumerate_device);
+
/**
* usb_hub_find_child - Get the pointer of child device
* attached to the port which is specified by @port1.
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 49ab8dbb8..9841029a2 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -789,6 +789,7 @@ extern int usb_lock_device_for_reset(struct usb_device *udev,
/* USB port reset for device reinitialization */
extern int usb_reset_device(struct usb_device *dev);
extern void usb_queue_reset_device(struct usb_interface *dev);
+int usb_queue_reenumerate_device(struct usb_interface *iface);
extern struct device *usb_intf_get_dma_device(struct usb_interface *intf);
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH RFC 1/2] USB: core: add helper to queue device re-enumeration
@ 2026-08-18 2:55 ` George Maraveyas
0 siblings, 0 replies; 11+ messages in thread
From: George Maraveyas @ 2026-08-18 2:55 UTC (permalink / raw)
To: Greg Kroah-Hartman, Marcel Holtmann, Luiz Augusto von Dentz,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-usb, linux-kernel, linux-bluetooth, linux-arm-kernel,
linux-mediatek, George Maraveyas
USB drivers can use usb_queue_reset_device() when they need USB core to
reset an already enumerated device asynchronously.
There is currently no driver-facing helper corresponding to
usb_queue_reset_device() which allows an interface driver to ask USB core
to remove the current usb_device and enumerate the physical device on the
port again.
The difference between the two is that a device reset continues using the
existing usb_device and its current enumeration state while
re-enumeration removes the existing usb_device and returns the port to
the hub code, which then discovers the device again through the normal
USB enumeration path.
Add usb_queue_reenumerate_device() to provide this facility.
The helper queues a logical disconnect on the parent hub port.
hub_port_logical_disconnect() disables the port, records a logical
connect-change event and queues the hub work. The hub work later
disconnects the existing usb_device and, if the physical device remains
connected, attempts to enumerate it again through the normal hub path.
Any retries or port recovery required during the subsequent enumeration
remain the responsibility of the existing hub code.
usb_remove_device() cannot provide the same behaviour because it also
marks the port in removed_bits. The hub connection path does not
enumerate a device on a port while that bit remains set.
The helper takes the device lock required by usb_hub_to_struct_hub() and
holds a runtime-PM reference on the parent hub interface while the
logical disconnect is queued.
The helper does not decide when re-enumeration is needed. That decision
remains with the calling driver.
The following MT7925 Bluetooth patch is the first user of the helper. It
requests re-enumeration after the controller has already enumerated
successfully but later fails during Bluetooth setup and cannot be
recovered by its existing reset path.
Signed-off-by: George Maraveyas <george.0xfff@gmail.com>
---
drivers/usb/core/hub.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/usb.h | 1 +
2 files changed, 55 insertions(+)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index fcac92bd7..22279d438 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -6503,6 +6503,60 @@ void usb_queue_reset_device(struct usb_interface *iface)
}
EXPORT_SYMBOL_GPL(usb_queue_reset_device);
+/**
+ * usb_queue_reenumerate_device - queue logical disconnect and re-enumeration
+ * @iface: USB interface belonging to the device to re-enumerate
+ *
+ * Request that USB core logically disconnect the device and subsequently
+ * re-enumerate its parent hub port. The actual device teardown and
+ * re-enumeration are handled asynchronously by the hub workqueue.
+ *
+ * This is intended for failures where resetting the existing usb_device is
+ * insufficient and the driver needs USB core to perform a full logical
+ * disconnect/re-enumeration cycle.
+ *
+ * Return: 0 if re-enumeration was queued successfully, or a negative error
+ * code otherwise.
+ */
+int usb_queue_reenumerate_device(struct usb_interface *iface)
+{
+ struct usb_device *udev = interface_to_usbdev(iface);
+ struct usb_interface *hub_intf;
+ struct usb_hub *hub;
+ int ret;
+
+ usb_lock_device(udev);
+
+ if (!udev->parent || udev->state == USB_STATE_NOTATTACHED) {
+ ret = -ENODEV;
+ goto out_unlock;
+ }
+
+ /*
+ * usb_hub_to_struct_hub() requires either the hub or one of its
+ * children to be locked. @udev is locked above.
+ */
+ hub = usb_hub_to_struct_hub(udev->parent);
+ if (!hub) {
+ ret = -ENODEV;
+ goto out_unlock;
+ }
+
+ hub_intf = to_usb_interface(hub->intfdev);
+ ret = usb_autopm_get_interface(hub_intf);
+ if (ret < 0)
+ goto out_unlock;
+
+ hub_port_logical_disconnect(hub, udev->portnum);
+ usb_autopm_put_interface(hub_intf);
+ ret = 0;
+
+out_unlock:
+ usb_unlock_device(udev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usb_queue_reenumerate_device);
+
/**
* usb_hub_find_child - Get the pointer of child device
* attached to the port which is specified by @port1.
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 49ab8dbb8..9841029a2 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -789,6 +789,7 @@ extern int usb_lock_device_for_reset(struct usb_device *udev,
/* USB port reset for device reinitialization */
extern int usb_reset_device(struct usb_device *dev);
extern void usb_queue_reset_device(struct usb_interface *dev);
+int usb_queue_reenumerate_device(struct usb_interface *iface);
extern struct device *usb_intf_get_dma_device(struct usb_interface *intf);
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH RFC 2/2] Bluetooth: mt7925: recover subsystem-reset timeout through USB re-enumeration
2026-08-18 2:55 ` George Maraveyas
@ 2026-08-18 2:55 ` George Maraveyas
-1 siblings, 0 replies; 11+ messages in thread
From: George Maraveyas via B4 Relay @ 2026-08-18 2:55 UTC (permalink / raw)
To: Greg Kroah-Hartman, Marcel Holtmann, Luiz Augusto von Dentz,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-usb, linux-kernel, linux-bluetooth, linux-arm-kernel,
linux-mediatek, George Maraveyas
From: George Maraveyas <george.0xfff@gmail.com>
The MT7925 Bluetooth controller on an ASUS ROG Strix B850-I Gaming WiFi
can remain unusable after a warm reboot even though its USB function
initially enumerates normally.
The Bluetooth USB function on the test system is:
idVendor=13d3, idProduct=3602
Manufacturer: MediaTek Inc.
Product: Wireless_Device
The problem was reproduced with ASUS motherboard BIOS versions 1644 and
1681. Updating from BIOS 1644 to 1681 did not change the failure.
The Bluetooth firmware reported during testing was:
HW/SW Version: 0x00000000
Build Time: 20260605184935
A typical Windows 11-to-Linux failure is:
1. The MT7925 USB function enumerates as 13d3:3602.
2. Bluetooth setup begins.
3. The WMT function-control command times out with -ETIMEDOUT (-110).
4. The existing MediaTek reset work runs.
5. btmtk_usb_subsys_reset() also times out.
6. Resetting the existing usb_device does not recover the controller.
The relevant log contains:
Bluetooth: hci0: Execution of wmt command timed out
Bluetooth: hci0: Failed to send wmt func ctrl (-110)
Bluetooth: hci0: MT7925 WMT func ctrl timed out (dev_id=0x7925), scheduling device reset
Bluetooth: hci0: Failed to read uhw reg(-110)
The WMT timeout handling and scheduling of the MediaTek reset already
exist before this change. This patch begins later, inside
btusb_mtk_reset(), after btmtk_usb_subsys_reset() has returned.
The existing path calls btmtk_usb_subsys_reset() and then queues
usb_queue_reset_device(). On the affected MT7925 the subsystem reset
returns -ETIMEDOUT, and resetting the existing usb_device does not recover
the controller.
After btmtk_usb_subsys_reset() returns, check for an MT7925 device and an
-ETIMEDOUT result. When both conditions are present, request
re-enumeration through usb_queue_reenumerate_device(), added by Patch 1.
If the re-enumeration request is queued successfully, clear
BTMTK_HW_RESET_ACTIVE and return the original subsystem-reset error. If
the request cannot be queued, report the error and continue into the
existing usb_queue_reset_device() path.
Other MediaTek devices and MT7925 reset results other than -ETIMEDOUT
continue to use the existing recovery path unchanged.
The re-enumeration request gives the MT7925 another chance to go through
normal USB enumeration via the helper in Patch 1, which does this. This
patch calls that helper when the MT7925 subsystem reset has timed out.
Chia-Lin Kao's preceding _PRR patch is required for the port recovery
used on this machine. Re-enumeration does not itself request a port
power-cycle or an ACPI _PRR reset. If the re-enumerated device continues
to fail during enumeration, the existing hub retry path can reach its
port power-cycle, where the _PRR prerequisite supplies the ACPI reset.
The _PRR prerequisite does not fix this failure by itself because the
first USB enumeration has already succeeded before the WMT timeout and
subsequent subsystem-reset timeout occur.
A representative successful recovery was:
Bluetooth: hci0: MT7925 subsystem reset timed out, requesting USB re-enumeration
usb 1-11: USB disconnect, device number 4
usb 1-11: device descriptor read/64, error -110
usb 1-11: device descriptor read/64, error -110
usb usb1-port11: attempt power cycle
usb 1-11: New USB device found, idVendor=13d3, idProduct=3602
Three Windows 11-to-Linux warm restart tests recovered successfully with
this series. The observed average interval from the initial WMT timeout
to successful Bluetooth setup was about 70.9 seconds.
Bluetooth remains unavailable during most of this interval, so recovery
should not be expected immediately after usb_queue_reenumerate_device()
is called.
Signed-off-by: George Maraveyas <george.0xfff@gmail.com>
---
drivers/bluetooth/btmtk.c | 4 ++++
drivers/bluetooth/btusb.c | 16 ++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 66b346761..e8f02f1e3 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -1413,6 +1413,10 @@ int btmtk_usb_setup(struct hci_dev *hdev)
err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
+
+ if (dev_id == 0x7925 && err == -ETIMEDOUT)
+ btmtk_reset_sync(hdev);
+
return err;
}
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 2bae85b00..5b56c26de 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2943,6 +2943,22 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
err = btmtk_usb_subsys_reset(hdev, btmtk_data->dev_id);
+ if (btmtk_data->dev_id == 0x7925 && err == -ETIMEDOUT) {
+ int reenum_err;
+
+ bt_dev_warn(hdev,
+ "MT7925 subsystem reset timed out, requesting USB re-enumeration");
+
+ reenum_err = usb_queue_reenumerate_device(data->intf);
+ if (!reenum_err) {
+ clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
+ return err;
+ }
+
+ bt_dev_err(hdev, "Failed to queue USB re-enumeration (%d)",
+ reenum_err);
+ }
+
usb_queue_reset_device(data->intf);
clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH RFC 2/2] Bluetooth: mt7925: recover subsystem-reset timeout through USB re-enumeration
@ 2026-08-18 2:55 ` George Maraveyas
0 siblings, 0 replies; 11+ messages in thread
From: George Maraveyas @ 2026-08-18 2:55 UTC (permalink / raw)
To: Greg Kroah-Hartman, Marcel Holtmann, Luiz Augusto von Dentz,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-usb, linux-kernel, linux-bluetooth, linux-arm-kernel,
linux-mediatek, George Maraveyas
The MT7925 Bluetooth controller on an ASUS ROG Strix B850-I Gaming WiFi
can remain unusable after a warm reboot even though its USB function
initially enumerates normally.
The Bluetooth USB function on the test system is:
idVendor=13d3, idProduct=3602
Manufacturer: MediaTek Inc.
Product: Wireless_Device
The problem was reproduced with ASUS motherboard BIOS versions 1644 and
1681. Updating from BIOS 1644 to 1681 did not change the failure.
The Bluetooth firmware reported during testing was:
HW/SW Version: 0x00000000
Build Time: 20260605184935
A typical Windows 11-to-Linux failure is:
1. The MT7925 USB function enumerates as 13d3:3602.
2. Bluetooth setup begins.
3. The WMT function-control command times out with -ETIMEDOUT (-110).
4. The existing MediaTek reset work runs.
5. btmtk_usb_subsys_reset() also times out.
6. Resetting the existing usb_device does not recover the controller.
The relevant log contains:
Bluetooth: hci0: Execution of wmt command timed out
Bluetooth: hci0: Failed to send wmt func ctrl (-110)
Bluetooth: hci0: MT7925 WMT func ctrl timed out (dev_id=0x7925), scheduling device reset
Bluetooth: hci0: Failed to read uhw reg(-110)
The WMT timeout handling and scheduling of the MediaTek reset already
exist before this change. This patch begins later, inside
btusb_mtk_reset(), after btmtk_usb_subsys_reset() has returned.
The existing path calls btmtk_usb_subsys_reset() and then queues
usb_queue_reset_device(). On the affected MT7925 the subsystem reset
returns -ETIMEDOUT, and resetting the existing usb_device does not recover
the controller.
After btmtk_usb_subsys_reset() returns, check for an MT7925 device and an
-ETIMEDOUT result. When both conditions are present, request
re-enumeration through usb_queue_reenumerate_device(), added by Patch 1.
If the re-enumeration request is queued successfully, clear
BTMTK_HW_RESET_ACTIVE and return the original subsystem-reset error. If
the request cannot be queued, report the error and continue into the
existing usb_queue_reset_device() path.
Other MediaTek devices and MT7925 reset results other than -ETIMEDOUT
continue to use the existing recovery path unchanged.
The re-enumeration request gives the MT7925 another chance to go through
normal USB enumeration via the helper in Patch 1, which does this. This
patch calls that helper when the MT7925 subsystem reset has timed out.
Chia-Lin Kao's preceding _PRR patch is required for the port recovery
used on this machine. Re-enumeration does not itself request a port
power-cycle or an ACPI _PRR reset. If the re-enumerated device continues
to fail during enumeration, the existing hub retry path can reach its
port power-cycle, where the _PRR prerequisite supplies the ACPI reset.
The _PRR prerequisite does not fix this failure by itself because the
first USB enumeration has already succeeded before the WMT timeout and
subsequent subsystem-reset timeout occur.
A representative successful recovery was:
Bluetooth: hci0: MT7925 subsystem reset timed out, requesting USB re-enumeration
usb 1-11: USB disconnect, device number 4
usb 1-11: device descriptor read/64, error -110
usb 1-11: device descriptor read/64, error -110
usb usb1-port11: attempt power cycle
usb 1-11: New USB device found, idVendor=13d3, idProduct=3602
Three Windows 11-to-Linux warm restart tests recovered successfully with
this series. The observed average interval from the initial WMT timeout
to successful Bluetooth setup was about 70.9 seconds.
Bluetooth remains unavailable during most of this interval, so recovery
should not be expected immediately after usb_queue_reenumerate_device()
is called.
Signed-off-by: George Maraveyas <george.0xfff@gmail.com>
---
drivers/bluetooth/btmtk.c | 4 ++++
drivers/bluetooth/btusb.c | 16 ++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 66b346761..e8f02f1e3 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -1413,6 +1413,10 @@ int btmtk_usb_setup(struct hci_dev *hdev)
err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
+
+ if (dev_id == 0x7925 && err == -ETIMEDOUT)
+ btmtk_reset_sync(hdev);
+
return err;
}
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 2bae85b00..5b56c26de 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2943,6 +2943,22 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
err = btmtk_usb_subsys_reset(hdev, btmtk_data->dev_id);
+ if (btmtk_data->dev_id == 0x7925 && err == -ETIMEDOUT) {
+ int reenum_err;
+
+ bt_dev_warn(hdev,
+ "MT7925 subsystem reset timed out, requesting USB re-enumeration");
+
+ reenum_err = usb_queue_reenumerate_device(data->intf);
+ if (!reenum_err) {
+ clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
+ return err;
+ }
+
+ bt_dev_err(hdev, "Failed to queue USB re-enumeration (%d)",
+ reenum_err);
+ }
+
usb_queue_reset_device(data->intf);
clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH RFC 1/2] USB: core: add helper to queue device re-enumeration
2026-08-18 2:55 ` George Maraveyas
(?)
@ 2026-08-18 3:20 ` Alan Stern
-1 siblings, 0 replies; 11+ messages in thread
From: Alan Stern @ 2026-08-18 3:20 UTC (permalink / raw)
To: george.0xfff
Cc: Greg Kroah-Hartman, Marcel Holtmann, Luiz Augusto von Dentz,
Matthias Brugger, AngeloGioacchino Del Regno, linux-usb,
linux-kernel, linux-bluetooth, linux-arm-kernel, linux-mediatek
On Tue, Aug 18, 2026 at 04:55:20AM +0200, George Maraveyas via B4 Relay wrote:
> From: George Maraveyas <george.0xfff@gmail.com>
>
> USB drivers can use usb_queue_reset_device() when they need USB core to
> reset an already enumerated device asynchronously.
>
> There is currently no driver-facing helper corresponding to
> usb_queue_reset_device() which allows an interface driver to ask USB core
> to remove the current usb_device and enumerate the physical device on the
> port again.
>
> The difference between the two is that a device reset continues using the
> existing usb_device and its current enumeration state while
> re-enumeration removes the existing usb_device and returns the port to
> the hub code, which then discovers the device again through the normal
> USB enumeration path.
A device reset continues to use the existing usb_device only when a new
partial enumeration yields the same descriptors as before. If the
descriptors have changed significantly then it goes through a logical
disconnect and re-enumeration, just like the function you want to add.
For this reason it's not clear why you can't just use
usb_queue_reset_device() here. From the device's point of view, the two
approaches do pretty much the same thing.
Alan Stern
> Add usb_queue_reenumerate_device() to provide this facility.
>
> The helper queues a logical disconnect on the parent hub port.
> hub_port_logical_disconnect() disables the port, records a logical
> connect-change event and queues the hub work. The hub work later
> disconnects the existing usb_device and, if the physical device remains
> connected, attempts to enumerate it again through the normal hub path.
>
> Any retries or port recovery required during the subsequent enumeration
> remain the responsibility of the existing hub code.
>
> usb_remove_device() cannot provide the same behaviour because it also
> marks the port in removed_bits. The hub connection path does not
> enumerate a device on a port while that bit remains set.
>
> The helper takes the device lock required by usb_hub_to_struct_hub() and
> holds a runtime-PM reference on the parent hub interface while the
> logical disconnect is queued.
>
> The helper does not decide when re-enumeration is needed. That decision
> remains with the calling driver.
>
> The following MT7925 Bluetooth patch is the first user of the helper. It
> requests re-enumeration after the controller has already enumerated
> successfully but later fails during Bluetooth setup and cannot be
> recovered by its existing reset path.
>
> Signed-off-by: George Maraveyas <george.0xfff@gmail.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: USB/Bluetooth: recover MT7925 after warm reboot
2026-08-18 2:55 ` George Maraveyas
(?)
(?)
@ 2026-08-18 4:15 ` bluez.test.bot
-1 siblings, 0 replies; 11+ messages in thread
From: bluez.test.bot @ 2026-08-18 4:15 UTC (permalink / raw)
To: linux-bluetooth, george.0xfff
[-- Attachment #1: Type: text/plain, Size: 3921 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1147517
---Test result---
Test Summary:
CheckPatch FAIL 1.94 seconds
VerifyFixes PASS 0.14 seconds
VerifySignedoff PASS 0.14 seconds
GitLint FAIL 0.66 seconds
SubjectPrefix FAIL 0.26 seconds
BuildKernel PASS 27.45 seconds
CheckAllWarning PASS 30.18 seconds
CheckSparse PASS 28.91 seconds
BuildKernel32 PASS 26.45 seconds
CheckKernelLLVM SKIP 0.00 seconds
TestRunnerSetup PASS 504.88 seconds
TestRunner_l2cap-tester PASS 66.18 seconds
TestRunner_iso-tester PASS 81.14 seconds
TestRunner_bnep-tester PASS 19.30 seconds
TestRunner_mgmt-tester FAIL 225.09 seconds
TestRunner_rfcomm-tester PASS 25.60 seconds
TestRunner_sco-tester PASS 32.45 seconds
TestRunner_ioctl-tester PASS 26.93 seconds
TestRunner_mesh-tester FAIL 25.95 seconds
TestRunner_smp-tester PASS 23.96 seconds
TestRunner_userchan-tester PASS 20.87 seconds
TestRunner_6lowpan-tester PASS 23.51 seconds
IncrementalBuild PASS 27.95 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[RFC,2/2] Bluetooth: mt7925: recover subsystem-reset timeout through USB re-enumeration
WARNING: Prefer a maximum 75 chars per line (possible unwrapped commit description?)
#114:
Bluetooth: hci0: MT7925 WMT func ctrl timed out (dev_id=0x7925), scheduling device reset
total: 0 errors, 1 warnings, 32 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14754479.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[RFC,2/2] Bluetooth: mt7925: recover subsystem-reset timeout through USB re-enumeration
1: T1 Title exceeds max length (87>80): "[RFC,2/2] Bluetooth: mt7925: recover subsystem-reset timeout through USB re-enumeration"
36: B1 Line exceeds max length (90>80): " Bluetooth: hci0: MT7925 WMT func ctrl timed out (dev_id=0x7925), scheduling device reset"
76: B1 Line exceeds max length (82>80): " Bluetooth: hci0: MT7925 subsystem reset timed out, requesting USB re-enumeration"
##############################
Test: SubjectPrefix - FAIL
Desc: Check subject contains "Bluetooth" prefix
Output:
"Bluetooth: " prefix is not specified in the subject
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 501, Passed: 496 (99.0%), Failed: 1, Not Run: 4
Failed Test Cases
Read Exp Feature - Success Failed 0.254 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0
Failed Test Cases
Mesh - Send cancel - 1 Timed out 1.995 seconds
Mesh - Send cancel - 2 Timed out 1.990 seconds
https://github.com/bluez/bluetooth-next/pull/604
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH RFC v2] Bluetooth: mt7925: trigger reset on WMT timeout
2026-08-18 2:55 ` George Maraveyas
@ 2026-08-21 23:37 ` George Maraveyas
-1 siblings, 0 replies; 11+ messages in thread
From: George Maraveyas via B4 Relay @ 2026-08-21 23:37 UTC (permalink / raw)
To: Alan Stern, Marcel Holtmann, Luiz Augusto von Dentz,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-bluetooth, linux-kernel, linux-arm-kernel, linux-mediatek,
Chia-Lin Kao, George Maraveyas
From: George Maraveyas <george.0xfff@gmail.com>
The MT7925 Bluetooth USB function can enumerate successfully after a warm
reboot while the WMT function-control command remains unresponsive.
When that command times out, btmtk_usb_setup() currently returns
-ETIMEDOUT without entering the existing MediaTek reset path. The existing
USB reset and recovery machinery is therefore never reached.
For MT7925, call btmtk_reset_sync() when the WMT function-control command
times out. This enters the existing reset path in btusb_mtk_reset(), which
performs the MediaTek subsystem reset and queues a USB device reset.
Runtime tracing on the affected hardware showed the resulting path through
usb_queue_reset_device(), usb_reset_device() and
usb_reset_and_verify_device(). When reset and verification could not
restore the device, the USB core escalated to a logical disconnect and
re-enumeration.
Recovery succeeded in three controlled Windows-to-Linux tests. Runtime
tracing showed the existing USB reset path escalating to logical disconnect
and re-enumeration. In two of those tests, tracing continued through the
subsequent enumeration failures and directly captured
usb_acpi_port_prr_reset(), after which the MT7925 re-enumerated and
Bluetooth recovered.
These tests were performed on top of Chia-Lin Kao's ACPI _PRR hub patch,
which remains a prerequisite for this patch.
A fourth Windows-to-Linux test was then performed with the diagnostic btusb
blacklist removed and btusb binding normally during boot. The WMT timeout
reproduced and Bluetooth recovered automatically without manual
intervention.
Signed-off-by: George Maraveyas <george.0xfff@gmail.com>
---
Dear Alan,
Thank you for taking the time to look into my patch and for pointing me
towards the existing reset path. I have now traced the failure on the
affected MT7925 hardware and tested the individual parts separately.
You were correct that a new USB re-enumeration helper is unnecessary.
Once the MT7925 failure is made to enter the existing reset path, I can
see:
btmtk_reset_sync()
-> btmtk_usb_subsys_reset()
-> usb_queue_reset_device()
-> usb_reset_device()
-> usb_reset_and_verify_device()
When reset and verification cannot restore the device,
usb_reset_and_verify_device() eventually reaches:
hub_port_logical_disconnect()
and normal hub re-enumeration follows. I have therefore dropped the
proposed USB helper from v1.
The problem I found is earlier in the Bluetooth path. When MT7925 WMT
FUNC_CTRL times out, btmtk_usb_setup() currently returns -ETIMEDOUT
without entering the existing MediaTek reset machinery. The revised patch
now consists only of the part of my original submission that makes this
timeout enter the existing reset path:
if (dev_id == 0x7925 && err == -ETIMEDOUT)
btmtk_reset_sync(hdev);
I tested this both with and without Chia-Lin Kao's _PRR hub patch. I want
to stress that this v2 is based on and dependent on Kao's patch; that
remains the configuration in which I have validated recovery.
Kao's patch alone does not recover this failure because the WMT timeout
never enters the reset path. With the WMT trigger but without Kao's patch,
the reset/disconnect/re-enumeration sequence started, but the device did
not recover in that test.
With Kao's patch plus the WMT trigger, I reproduced and recovered the
Windows-to-Linux failure in three controlled tests. Runtime tracing showed
the existing reset path escalating through usb_queue_reset_device(),
usb_reset_and_verify_device() and hub_port_logical_disconnect(). In two
of those runs, tracing continued through the subsequent enumeration
failures and directly captured:
usb_acpi_port_prr_reset() <- hub_event.cold
The MT7925 subsequently re-enumerated and Bluetooth recovered.
I then removed the diagnostic btusb blacklist and repeated the test as a
normal Windows-to-Linux restart, allowing btusb to bind automatically.
The WMT command again timed out with -110 and the adapter recovered
without any manual module loading or other intervention.
One behavioural difference is recovery time. The original RFC, which
requested logical disconnect/re-enumeration directly after the MT7925
subsystem reset timed out, recovered Bluetooth in about 71 seconds on
average. Using the existing usb_queue_reset_device() path takes about
133 seconds to complete Bluetooth setup in the current tests, with
successful USB re-enumeration at about 114-115 seconds.
The traces account for most of that difference:
usb_reset_and_verify_device() spends roughly 65 seconds attempting reset
and verification before escalating to hub_port_logical_disconnect(). In
practice this was long enough that, during the first test of the reduced
patch, I almost concluded that recovery had failed and rebooted to start
the test again before the device eventually returned.
I do not think that recovery-time difference justifies retaining the new
USB API, but it seemed worth mentioning because it is a noticeable
behavioural difference between v1 and the reduced approach.
Changes in v2:
- Drop the proposed USB re-enumeration helper.
- Drop the direct MT7925 re-enumeration handling which depended on it.
- Reduce the series from two patches to one Bluetooth patch.
- Retain only the part of the original Bluetooth patch that enters the
existing reset path on an MT7925 WMT -ETIMEDOUT.
- Keep Chia-Lin Kao's ACPI _PRR hub patch as a prerequisite.
- Add the new runtime trace and recovery results.
- Link to v1: https://patch.msgid.link/20260818-mt7925-rfc-v1-0-284d856ac572@gmail.com
Thanks again for the review.
Kind regards,
George
---
drivers/bluetooth/btmtk.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 66b346761..e8f02f1e3 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -1413,6 +1413,10 @@ int btmtk_usb_setup(struct hci_dev *hdev)
err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
+
+ if (dev_id == 0x7925 && err == -ETIMEDOUT)
+ btmtk_reset_sync(hdev);
+
return err;
}
---
base-commit: 28d012efb4327f9c75d5e042a7c91e9a542efa98
change-id: 20260818-mt7925-rfc-edd34ef031d9
prerequisite-message-id: <20260706080117.3754550-1-acelan.kao@canonical.com>
prerequisite-patch-id: 47a2729fbc473534f8ba52052b00723c54a26c17
Best regards,
--
George Maraveyas <george.0xfff@gmail.com>
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH RFC v2] Bluetooth: mt7925: trigger reset on WMT timeout
@ 2026-08-21 23:37 ` George Maraveyas
0 siblings, 0 replies; 11+ messages in thread
From: George Maraveyas @ 2026-08-21 23:37 UTC (permalink / raw)
To: Alan Stern, Marcel Holtmann, Luiz Augusto von Dentz,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-bluetooth, linux-kernel, linux-arm-kernel, linux-mediatek,
Chia-Lin Kao, George Maraveyas
The MT7925 Bluetooth USB function can enumerate successfully after a warm
reboot while the WMT function-control command remains unresponsive.
When that command times out, btmtk_usb_setup() currently returns
-ETIMEDOUT without entering the existing MediaTek reset path. The existing
USB reset and recovery machinery is therefore never reached.
For MT7925, call btmtk_reset_sync() when the WMT function-control command
times out. This enters the existing reset path in btusb_mtk_reset(), which
performs the MediaTek subsystem reset and queues a USB device reset.
Runtime tracing on the affected hardware showed the resulting path through
usb_queue_reset_device(), usb_reset_device() and
usb_reset_and_verify_device(). When reset and verification could not
restore the device, the USB core escalated to a logical disconnect and
re-enumeration.
Recovery succeeded in three controlled Windows-to-Linux tests. Runtime
tracing showed the existing USB reset path escalating to logical disconnect
and re-enumeration. In two of those tests, tracing continued through the
subsequent enumeration failures and directly captured
usb_acpi_port_prr_reset(), after which the MT7925 re-enumerated and
Bluetooth recovered.
These tests were performed on top of Chia-Lin Kao's ACPI _PRR hub patch,
which remains a prerequisite for this patch.
A fourth Windows-to-Linux test was then performed with the diagnostic btusb
blacklist removed and btusb binding normally during boot. The WMT timeout
reproduced and Bluetooth recovered automatically without manual
intervention.
Signed-off-by: George Maraveyas <george.0xfff@gmail.com>
---
Dear Alan,
Thank you for taking the time to look into my patch and for pointing me
towards the existing reset path. I have now traced the failure on the
affected MT7925 hardware and tested the individual parts separately.
You were correct that a new USB re-enumeration helper is unnecessary.
Once the MT7925 failure is made to enter the existing reset path, I can
see:
btmtk_reset_sync()
-> btmtk_usb_subsys_reset()
-> usb_queue_reset_device()
-> usb_reset_device()
-> usb_reset_and_verify_device()
When reset and verification cannot restore the device,
usb_reset_and_verify_device() eventually reaches:
hub_port_logical_disconnect()
and normal hub re-enumeration follows. I have therefore dropped the
proposed USB helper from v1.
The problem I found is earlier in the Bluetooth path. When MT7925 WMT
FUNC_CTRL times out, btmtk_usb_setup() currently returns -ETIMEDOUT
without entering the existing MediaTek reset machinery. The revised patch
now consists only of the part of my original submission that makes this
timeout enter the existing reset path:
if (dev_id == 0x7925 && err == -ETIMEDOUT)
btmtk_reset_sync(hdev);
I tested this both with and without Chia-Lin Kao's _PRR hub patch. I want
to stress that this v2 is based on and dependent on Kao's patch; that
remains the configuration in which I have validated recovery.
Kao's patch alone does not recover this failure because the WMT timeout
never enters the reset path. With the WMT trigger but without Kao's patch,
the reset/disconnect/re-enumeration sequence started, but the device did
not recover in that test.
With Kao's patch plus the WMT trigger, I reproduced and recovered the
Windows-to-Linux failure in three controlled tests. Runtime tracing showed
the existing reset path escalating through usb_queue_reset_device(),
usb_reset_and_verify_device() and hub_port_logical_disconnect(). In two
of those runs, tracing continued through the subsequent enumeration
failures and directly captured:
usb_acpi_port_prr_reset() <- hub_event.cold
The MT7925 subsequently re-enumerated and Bluetooth recovered.
I then removed the diagnostic btusb blacklist and repeated the test as a
normal Windows-to-Linux restart, allowing btusb to bind automatically.
The WMT command again timed out with -110 and the adapter recovered
without any manual module loading or other intervention.
One behavioural difference is recovery time. The original RFC, which
requested logical disconnect/re-enumeration directly after the MT7925
subsystem reset timed out, recovered Bluetooth in about 71 seconds on
average. Using the existing usb_queue_reset_device() path takes about
133 seconds to complete Bluetooth setup in the current tests, with
successful USB re-enumeration at about 114-115 seconds.
The traces account for most of that difference:
usb_reset_and_verify_device() spends roughly 65 seconds attempting reset
and verification before escalating to hub_port_logical_disconnect(). In
practice this was long enough that, during the first test of the reduced
patch, I almost concluded that recovery had failed and rebooted to start
the test again before the device eventually returned.
I do not think that recovery-time difference justifies retaining the new
USB API, but it seemed worth mentioning because it is a noticeable
behavioural difference between v1 and the reduced approach.
Changes in v2:
- Drop the proposed USB re-enumeration helper.
- Drop the direct MT7925 re-enumeration handling which depended on it.
- Reduce the series from two patches to one Bluetooth patch.
- Retain only the part of the original Bluetooth patch that enters the
existing reset path on an MT7925 WMT -ETIMEDOUT.
- Keep Chia-Lin Kao's ACPI _PRR hub patch as a prerequisite.
- Add the new runtime trace and recovery results.
- Link to v1: https://patch.msgid.link/20260818-mt7925-rfc-v1-0-284d856ac572@gmail.com
Thanks again for the review.
Kind regards,
George
---
drivers/bluetooth/btmtk.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 66b346761..e8f02f1e3 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -1413,6 +1413,10 @@ int btmtk_usb_setup(struct hci_dev *hdev)
err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
+
+ if (dev_id == 0x7925 && err == -ETIMEDOUT)
+ btmtk_reset_sync(hdev);
+
return err;
}
---
base-commit: 28d012efb4327f9c75d5e042a7c91e9a542efa98
change-id: 20260818-mt7925-rfc-edd34ef031d9
prerequisite-message-id: <20260706080117.3754550-1-acelan.kao@canonical.com>
prerequisite-patch-id: 47a2729fbc473534f8ba52052b00723c54a26c17
Best regards,
--
George Maraveyas <george.0xfff@gmail.com>
^ permalink raw reply related [flat|nested] 11+ messages in thread
* RE: [RFC,v2] Bluetooth: mt7925: trigger reset on WMT timeout
2026-08-21 23:37 ` George Maraveyas
(?)
@ 2026-08-22 0:07 ` bluez.test.bot
-1 siblings, 0 replies; 11+ messages in thread
From: bluez.test.bot @ 2026-08-22 0:07 UTC (permalink / raw)
To: linux-bluetooth, george.0xfff
[-- Attachment #1: Type: text/plain, Size: 1362 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1150044
---Test result---
Test Summary:
CheckPatch PASS 0.50 seconds
VerifyFixes PASS 0.10 seconds
VerifySignedoff PASS 0.10 seconds
GitLint FAIL 0.24 seconds
SubjectPrefix PASS 0.09 seconds
BuildKernel PASS 17.92 seconds
CheckAllWarning PASS 20.10 seconds
CheckSparse PASS 19.22 seconds
BuildKernel32 PASS 17.27 seconds
CheckKernelLLVM SKIP 0.00 seconds
TestRunnerSetup PASS 309.21 seconds
IncrementalBuild PASS 18.15 seconds
Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[RFC,v2] Bluetooth: mt7925: trigger reset on WMT timeout
140: B2 Line has trailing whitespace: "-- "
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
https://github.com/bluez/bluetooth-next/pull/633
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-08-22 0:07 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-18 2:55 [PATCH RFC 0/2] USB/Bluetooth: recover MT7925 after warm reboot George Maraveyas via B4 Relay
2026-08-18 2:55 ` George Maraveyas
2026-08-18 2:55 ` [PATCH RFC 1/2] USB: core: add helper to queue device re-enumeration George Maraveyas via B4 Relay
2026-08-18 2:55 ` George Maraveyas
2026-08-18 3:20 ` Alan Stern
2026-08-18 4:15 ` USB/Bluetooth: recover MT7925 after warm reboot bluez.test.bot
2026-08-18 2:55 ` [PATCH RFC 2/2] Bluetooth: mt7925: recover subsystem-reset timeout through USB re-enumeration George Maraveyas via B4 Relay
2026-08-18 2:55 ` George Maraveyas
2026-08-21 23:37 ` [PATCH RFC v2] Bluetooth: mt7925: trigger reset on WMT timeout George Maraveyas via B4 Relay
2026-08-21 23:37 ` George Maraveyas
2026-08-22 0:07 ` [RFC,v2] " bluez.test.bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.