mirror of
https://github.com/shenmintao/aic8800d80.git
synced 2026-09-26 17:44:16 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbc12c7bdb |
@@ -0,0 +1,2 @@
|
|||||||
|
tests/issue63-btusb-zlp/*.patch -whitespace
|
||||||
|
tests/issue63-btusb-zlp/*.sh text eol=lf
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Shen Mintao <cx330.shen@autocore.ai>
|
||||||
|
Date: Fri, 17 Jul 2026 21:00:00 +0800
|
||||||
|
Subject: [PATCH] Bluetooth: btusb: add bulk TX ZLP quirk for AIC 8800D80
|
||||||
|
|
||||||
|
The AIC 8800D80 controller can stop returning HCI Number Of Completed
|
||||||
|
Packets events during sustained AAC A2DP traffic when driven by the
|
||||||
|
generic btusb transport. Once the controller's ACL credits are
|
||||||
|
exhausted, the connection is terminated by the HCI ACL TX watchdog.
|
||||||
|
|
||||||
|
The vendor transport sets URB_ZERO_PACKET on every ACL bulk OUT URB.
|
||||||
|
Add an equivalent, device-specific quirk to btusb for the 368b:8d81
|
||||||
|
variant so that the standard kernel driver retains control of the
|
||||||
|
device.
|
||||||
|
|
||||||
|
This is intentionally limited to the USB ID from the reproducer while
|
||||||
|
the behaviour is validated on additional AIC variants.
|
||||||
|
|
||||||
|
Link: https://github.com/shenmintao/aic8800d80/issues/63
|
||||||
|
Signed-off-by: Shen Mintao <cx330.shen@autocore.ai>
|
||||||
|
---
|
||||||
|
drivers/bluetooth/btusb.c | 10 ++++++++++
|
||||||
|
1 file changed, 10 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
|
||||||
|
index 830fefb342c6..97118c095369 100644
|
||||||
|
--- a/drivers/bluetooth/btusb.c
|
||||||
|
+++ b/drivers/bluetooth/btusb.c
|
||||||
|
@@ -67,6 +67,7 @@ static bool reset = true;
|
||||||
|
#define BTUSB_INTEL_NO_WBS_SUPPORT BIT(26)
|
||||||
|
#define BTUSB_ACTIONS_SEMI BIT(27)
|
||||||
|
#define BTUSB_BARROT BIT(28)
|
||||||
|
+#define BTUSB_BULK_TX_ZLP BIT(29)
|
||||||
|
|
||||||
|
static const struct usb_device_id btusb_table[] = {
|
||||||
|
/* Generic Bluetooth USB device */
|
||||||
|
@@ -178,5 +179,9 @@ MODULE_DEVICE_TABLE(usb, btusb_table);
|
||||||
|
|
||||||
|
static const struct usb_device_id quirks_table[] = {
|
||||||
|
+ /* AIC Semiconductor AIC 8800D80 */
|
||||||
|
+ { USB_DEVICE(0x368b, 0x8d81),
|
||||||
|
+ .driver_info = BTUSB_BULK_TX_ZLP },
|
||||||
|
+
|
||||||
|
/* CSR BlueCore devices */
|
||||||
|
{ USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR },
|
||||||
|
|
||||||
|
@@ -949,6 +954,7 @@ struct btusb_data {
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
bool poll_sync;
|
||||||
|
+ bool bulk_tx_zlp;
|
||||||
|
int intr_interval;
|
||||||
|
struct work_struct work;
|
||||||
|
struct work_struct waker;
|
||||||
|
@@ -2138,6 +2144,9 @@ static struct urb *alloc_bulk_urb(struct hci_dev *hdev, struct sk_buff *skb)
|
||||||
|
usb_fill_bulk_urb(urb, data->udev, pipe,
|
||||||
|
skb->data, skb->len, btusb_tx_complete, skb);
|
||||||
|
|
||||||
|
+ if (data->bulk_tx_zlp)
|
||||||
|
+ urb->transfer_flags |= URB_ZERO_PACKET;
|
||||||
|
+
|
||||||
|
skb->dev = (void *)hdev;
|
||||||
|
|
||||||
|
return urb;
|
||||||
|
@@ -4100,6 +4109,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
|
|
||||||
|
data->udev = interface_to_usbdev(intf);
|
||||||
|
data->intf = intf;
|
||||||
|
+ data->bulk_tx_zlp = id->driver_info & BTUSB_BULK_TX_ZLP;
|
||||||
|
|
||||||
|
INIT_WORK(&data->work, btusb_work);
|
||||||
|
INIT_WORK(&data->waker, btusb_waker);
|
||||||
|
--
|
||||||
|
2.50.1
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Issue #63: system `btusb` ZLP test
|
||||||
|
|
||||||
|
This test keeps the normal `aic_load_fw + btusb` architecture. It does not
|
||||||
|
restore or install the vendor `aic_btusb` driver.
|
||||||
|
|
||||||
|
The patch adds one quirk to the standard Linux `btusb` source:
|
||||||
|
|
||||||
|
- match only AICSemi `368b:8d81`;
|
||||||
|
- set `URB_ZERO_PACKET` on Bluetooth ACL bulk OUT transfers;
|
||||||
|
- leave every other `btusb` device and code path unchanged.
|
||||||
|
|
||||||
|
The test installer downloads the standard `btusb` source matching the running
|
||||||
|
kernel's upstream version, applies the patch, and installs the resulting
|
||||||
|
`btusb.ko` through DKMS. The distribution module is not overwritten and can be
|
||||||
|
restored by removing the DKMS test package.
|
||||||
|
|
||||||
|
## Install the test module
|
||||||
|
|
||||||
|
On Fedora, make sure the test build dependencies are installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo dnf install dkms gcc make kernel-devel-$(uname -r) curl patch
|
||||||
|
```
|
||||||
|
|
||||||
|
Stop Bluetooth scanning and disconnect Bluetooth devices, then run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd tests/issue63-btusb-zlp
|
||||||
|
sudo ./btusb-zlp-test.sh install
|
||||||
|
./btusb-zlp-test.sh status
|
||||||
|
```
|
||||||
|
|
||||||
|
`modinfo -n btusb` should point to an `updates/dkms` path. Secure Boot systems
|
||||||
|
may require the DKMS module to be signed or enrolled before it can load.
|
||||||
|
|
||||||
|
Select AAC again and play audio for at least one hour:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bluetoothctl scan off
|
||||||
|
pactl set-card-profile bluez_card.28_6F_40_46_AB_B1 a2dp-sink-aac
|
||||||
|
```
|
||||||
|
|
||||||
|
Please capture `sudo btmon -w issue63-zlp.btsnoop` and relevant `dmesg` lines if
|
||||||
|
the connection still stalls.
|
||||||
|
|
||||||
|
## Restore the distribution module
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./btusb-zlp-test.sh remove
|
||||||
|
./btusb-zlp-test.sh status
|
||||||
|
```
|
||||||
|
|
||||||
|
After removal, `modinfo -n btusb` should point back to the distribution's
|
||||||
|
`kernel/drivers/bluetooth/btusb.ko` path.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This is an A/B diagnostic patch, not a production workaround. If AAC remains
|
||||||
|
stable, the small kernel patch can be submitted upstream. If it still fails,
|
||||||
|
the next isolated experiment should add an AIC-specific runtime-PM quirk rather
|
||||||
|
than replacing the standard Bluetooth driver.
|
||||||
Executable
+196
@@ -0,0 +1,196 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PACKAGE_NAME="btusb-aic-zlp"
|
||||||
|
PACKAGE_VERSION="0.1"
|
||||||
|
KERNEL_RELEASE="${KERNEL_RELEASE:-$(uname -r)}"
|
||||||
|
UPSTREAM_VERSION="${UPSTREAM_VERSION:-$(printf '%s' "$KERNEL_RELEASE" | sed -nE 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/p')}"
|
||||||
|
UPSTREAM_TAG="${UPSTREAM_TAG:-v${UPSTREAM_VERSION}}"
|
||||||
|
KERNEL_BUILD_DIR="/lib/modules/${KERNEL_RELEASE}/build"
|
||||||
|
SOURCE_DIR="/usr/src/${PACKAGE_NAME}-${PACKAGE_VERSION}"
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PATCH_FILE="${SCRIPT_DIR}/0001-Bluetooth-btusb-add-AIC-bulk-TX-ZLP-quirk.patch"
|
||||||
|
BASE_URL="https://raw.githubusercontent.com/gregkh/linux/${UPSTREAM_TAG}/drivers/bluetooth"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
printf '[btusb-zlp-test] %s\n' "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
printf '[btusb-zlp-test] ERROR: %s\n' "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
require_root() {
|
||||||
|
[ "$(id -u)" -eq 0 ] || die "run this command as root"
|
||||||
|
}
|
||||||
|
|
||||||
|
require_command() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_bluetooth() {
|
||||||
|
if command -v systemctl >/dev/null 2>&1; then
|
||||||
|
systemctl stop bluetooth.service 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
start_bluetooth() {
|
||||||
|
if command -v systemctl >/dev/null 2>&1; then
|
||||||
|
systemctl start bluetooth.service 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
rollback_test_install() {
|
||||||
|
log "rolling back to the distribution btusb module"
|
||||||
|
dkms remove -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" --all >/dev/null 2>&1 || true
|
||||||
|
rm -rf -- "${SOURCE_DIR}"
|
||||||
|
depmod -a "${KERNEL_RELEASE}" || true
|
||||||
|
modprobe btusb || true
|
||||||
|
start_bluetooth
|
||||||
|
}
|
||||||
|
|
||||||
|
activate_test_module() {
|
||||||
|
stop_bluetooth
|
||||||
|
|
||||||
|
if ! modprobe -r btusb; then
|
||||||
|
rollback_test_install
|
||||||
|
die "could not unload btusb; disconnect active Bluetooth devices and retry"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! modprobe btusb; then
|
||||||
|
rollback_test_install
|
||||||
|
die "the patched btusb could not load; the distribution module was restored"
|
||||||
|
fi
|
||||||
|
|
||||||
|
start_bluetooth
|
||||||
|
}
|
||||||
|
|
||||||
|
write_build_files() {
|
||||||
|
cat > "${SOURCE_DIR}/Makefile" <<'EOF'
|
||||||
|
KVER ?= $(shell uname -r)
|
||||||
|
KDIR ?= /lib/modules/$(KVER)/build
|
||||||
|
|
||||||
|
obj-m += btusb.o
|
||||||
|
btusb-y := drivers/bluetooth/btusb.o
|
||||||
|
ccflags-y += -I$(src)/drivers/bluetooth
|
||||||
|
|
||||||
|
all:
|
||||||
|
$(MAKE) -C $(KDIR) M=$(CURDIR) modules
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(MAKE) -C $(KDIR) M=$(CURDIR) clean
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > "${SOURCE_DIR}/dkms.conf" <<'EOF'
|
||||||
|
PACKAGE_NAME="btusb-aic-zlp"
|
||||||
|
PACKAGE_VERSION="0.1"
|
||||||
|
MAKE[0]="make KVER=${kernelver}"
|
||||||
|
CLEAN="make KVER=${kernelver} clean"
|
||||||
|
BUILT_MODULE_NAME[0]="btusb"
|
||||||
|
BUILT_MODULE_LOCATION[0]="."
|
||||||
|
DEST_MODULE_LOCATION[0]="/updates/dkms"
|
||||||
|
AUTOINSTALL="no"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
download_sources() {
|
||||||
|
local file
|
||||||
|
|
||||||
|
install -d "${SOURCE_DIR}/drivers/bluetooth"
|
||||||
|
|
||||||
|
for file in btusb.c btintel.h btbcm.h btrtl.h btmtk.h; do
|
||||||
|
log "downloading ${file} from Linux ${UPSTREAM_TAG}"
|
||||||
|
curl --fail --location --silent --show-error \
|
||||||
|
"${BASE_URL}/${file}" \
|
||||||
|
--output "${SOURCE_DIR}/drivers/bluetooth/${file}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
install_test_module() {
|
||||||
|
require_root
|
||||||
|
require_command curl
|
||||||
|
require_command dkms
|
||||||
|
require_command make
|
||||||
|
require_command modprobe
|
||||||
|
require_command patch
|
||||||
|
|
||||||
|
[ -n "${UPSTREAM_VERSION}" ] || die "could not derive an upstream version from ${KERNEL_RELEASE}"
|
||||||
|
[ -r "${KERNEL_BUILD_DIR}/Makefile" ] || die "kernel build tree not found: ${KERNEL_BUILD_DIR}"
|
||||||
|
[ -r "${PATCH_FILE}" ] || die "patch file not found: ${PATCH_FILE}"
|
||||||
|
|
||||||
|
if command -v lsusb >/dev/null 2>&1 && ! lsusb -d 368b:8d81 >/dev/null 2>&1; then
|
||||||
|
die "the test patch is restricted to USB device 368b:8d81, which is not connected"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if dkms status -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" 2>/dev/null | grep -q .; then
|
||||||
|
log "removing an earlier test build"
|
||||||
|
dkms remove -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" --all || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf -- "${SOURCE_DIR}"
|
||||||
|
download_sources
|
||||||
|
write_build_files
|
||||||
|
|
||||||
|
log "applying the AIC bulk TX ZLP quirk"
|
||||||
|
patch --directory "${SOURCE_DIR}" --strip 1 --input "${PATCH_FILE}"
|
||||||
|
|
||||||
|
log "building patched system btusb for ${KERNEL_RELEASE}"
|
||||||
|
dkms add -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}"
|
||||||
|
dkms build -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" -k "${KERNEL_RELEASE}"
|
||||||
|
dkms install -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" \
|
||||||
|
-k "${KERNEL_RELEASE}" --force
|
||||||
|
depmod -a "${KERNEL_RELEASE}"
|
||||||
|
|
||||||
|
activate_test_module
|
||||||
|
|
||||||
|
log "loaded module: $(modinfo -n btusb)"
|
||||||
|
log "test AAC playback for at least one hour; use '$0 remove' to restore the distribution module"
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_test_module() {
|
||||||
|
require_root
|
||||||
|
require_command dkms
|
||||||
|
require_command modprobe
|
||||||
|
|
||||||
|
stop_bluetooth
|
||||||
|
modprobe -r btusb || {
|
||||||
|
start_bluetooth
|
||||||
|
die "could not unload btusb; disconnect active Bluetooth devices and retry"
|
||||||
|
}
|
||||||
|
|
||||||
|
dkms remove -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" --all || true
|
||||||
|
rm -rf -- "${SOURCE_DIR}"
|
||||||
|
depmod -a "${KERNEL_RELEASE}"
|
||||||
|
|
||||||
|
modprobe btusb || {
|
||||||
|
start_bluetooth
|
||||||
|
die "the distribution btusb module could not be loaded"
|
||||||
|
}
|
||||||
|
start_bluetooth
|
||||||
|
|
||||||
|
log "restored module: $(modinfo -n btusb)"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_status() {
|
||||||
|
printf 'kernel: %s\n' "${KERNEL_RELEASE}"
|
||||||
|
printf 'upstream tag: %s\n' "${UPSTREAM_TAG}"
|
||||||
|
printf 'btusb module: %s\n' "$(modinfo -n btusb 2>/dev/null || printf 'not found')"
|
||||||
|
printf 'dkms status: %s\n' "$(dkms status -m "${PACKAGE_NAME}" -v "${PACKAGE_VERSION}" 2>/dev/null || printf 'not installed')"
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
install)
|
||||||
|
install_test_module
|
||||||
|
;;
|
||||||
|
remove)
|
||||||
|
remove_test_module
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
show_status
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf 'Usage: %s {install|remove|status}\n' "$0" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in New Issue
Block a user