diff options
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r-- | drivers/bluetooth/btusb.c | 1182 |
1 files changed, 367 insertions, 815 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d31edad7a056..a0fc465458b2 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -17,7 +17,7 @@ #include <linux/suspend.h> #include <linux/gpio/consumer.h> #include <linux/debugfs.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -34,6 +34,7 @@ static bool force_scofix; static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND); static bool enable_poll_sync = IS_ENABLED(CONFIG_BT_HCIBTUSB_POLL_SYNC); static bool reset = true; +static bool auto_isoc_alt = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTO_ISOC_ALT); static struct usb_driver btusb_driver; @@ -59,7 +60,7 @@ static struct usb_driver btusb_driver; #define BTUSB_CW6622 BIT(19) #define BTUSB_MEDIATEK BIT(20) #define BTUSB_WIDEBAND_SPEECH BIT(21) -#define BTUSB_VALID_LE_STATES BIT(22) +#define BTUSB_INVALID_LE_STATES BIT(22) #define BTUSB_QCA_WCN6855 BIT(23) #define BTUSB_INTEL_BROKEN_SHUTDOWN_LED BIT(24) #define BTUSB_INTEL_BROKEN_INITIAL_NCMD BIT(25) @@ -298,115 +299,87 @@ static const struct usb_device_id quirks_table[] = { /* QCA WCN6855 chipset */ { USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0cc), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0d6), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0e3), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9309), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9409), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0d0), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9108), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9109), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9208), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9209), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9308), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9408), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9508), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9509), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9608), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9609), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x10ab, 0x9f09), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3022), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0c7), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0c9), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0ca), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0cb), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0ce), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0de), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0df), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0e1), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0ea), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0ec), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3023), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3024), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3a22), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3a24), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3a26), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3a27), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, /* QCA WCN785x chipset */ { USB_DEVICE(0x0cf3, 0xe700), .driver_info = BTUSB_QCA_WCN6855 | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe0fc), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe0f3), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3623), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x2c7c, 0x0130), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH }, /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 }, @@ -477,7 +450,9 @@ static const struct usb_device_id quirks_table[] = { { USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED }, { USB_DEVICE(0x8087, 0x0035), .driver_info = BTUSB_INTEL_COMBINED }, { USB_DEVICE(0x8087, 0x0036), .driver_info = BTUSB_INTEL_COMBINED }, + { USB_DEVICE(0x8087, 0x0037), .driver_info = BTUSB_INTEL_COMBINED }, { USB_DEVICE(0x8087, 0x0038), .driver_info = BTUSB_INTEL_COMBINED }, + { USB_DEVICE(0x8087, 0x0039), .driver_info = BTUSB_INTEL_COMBINED }, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_INTEL_NO_WBS_SUPPORT | @@ -509,6 +484,9 @@ static const struct usb_device_id quirks_table[] = { { USB_DEVICE(0x13d3, 0x3549), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + /* Realtek 8851BE Bluetooth devices */ + { USB_DEVICE(0x13d3, 0x3600), .driver_info = BTUSB_REALTEK }, + /* Realtek 8852AE Bluetooth devices */ { USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, @@ -538,10 +516,14 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3592), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe122), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, /* Realtek 8852BE Bluetooth devices */ { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK | @@ -552,6 +534,26 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3572), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3591), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe123), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe125), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + + /* Realtek 8852BT/8852BE-VT Bluetooth devices */ + { USB_DEVICE(0x0bda, 0x8520), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + + /* Realtek 8922AE Bluetooth devices */ + { USB_DEVICE(0x0bda, 0x8922), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3617), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3616), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe130), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, /* Realtek Bluetooth devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01), @@ -560,100 +562,130 @@ static const struct usb_device_id quirks_table[] = { /* MediaTek Bluetooth devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x0e8d, 0xe0, 0x01, 0x01), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, /* Additional MediaTek MT7615E Bluetooth devices */ { USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK}, /* Additional MediaTek MT7663 Bluetooth devices */ { USB_DEVICE(0x043e, 0x310c), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3801), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, /* Additional MediaTek MT7668 Bluetooth devices */ { USB_DEVICE(0x043e, 0x3109), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, + + /* Additional MediaTek MT7920 Bluetooth devices */ + { USB_DEVICE(0x0489, 0xe134), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3620), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3621), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3622), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, /* Additional MediaTek MT7921 Bluetooth devices */ { USB_DEVICE(0x0489, 0xe0c8), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0e0), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0e8d, 0x0608), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3563), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3564), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3567), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3576), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3578), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3583), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, - { USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, - { USB_DEVICE(0x0e8d, 0x0608), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3606), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + + /* MediaTek MT7922 Bluetooth devices */ + { USB_DEVICE(0x13d3, 0x3585), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3610), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, /* MediaTek MT7922A Bluetooth devices */ { USB_DEVICE(0x0489, 0xe0d8), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, - { USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, - { USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0e2), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0e4), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0f1), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe0f6), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe102), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x04ca, 0x38e4), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3605), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3607), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3614), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3615), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x35f5, 0x7922), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH | - BTUSB_VALID_LE_STATES }, + BTUSB_WIDEBAND_SPEECH }, + + /* Additional MediaTek MT7925 Bluetooth devices */ + { USB_DEVICE(0x0489, 0xe111), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe113), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe118), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe11e), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe124), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe139), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe14f), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe150), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe151), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3602), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3603), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3604), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3608), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3628), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, /* Additional Realtek 8723AE Bluetooth devices */ { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK }, @@ -854,8 +886,11 @@ struct btusb_data { int (*setup_on_usb)(struct hci_dev *hdev); + int (*suspend)(struct hci_dev *hdev); + int (*resume)(struct hci_dev *hdev); + int (*disconnect)(struct hci_dev *hdev); + int oob_wake_irq; /* irq for out-of-band wake-on-bt */ - unsigned cmd_timeout_cnt; struct qca_dump_info qca_dump; }; @@ -865,11 +900,6 @@ static void btusb_reset(struct hci_dev *hdev) struct btusb_data *data; int err; - if (hdev->reset) { - hdev->reset(hdev); - return; - } - data = hci_get_drvdata(hdev); /* This is not an unbalanced PM reference since the device will reset */ err = usb_autopm_get_interface(data->intf); @@ -882,15 +912,12 @@ static void btusb_reset(struct hci_dev *hdev) usb_queue_reset_device(data->intf); } -static void btusb_intel_cmd_timeout(struct hci_dev *hdev) +static void btusb_intel_reset(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); struct gpio_desc *reset_gpio = data->reset_gpio; struct btintel_data *intel_data = hci_get_priv(hdev); - if (++data->cmd_timeout_cnt < 5) - return; - if (intel_data->acpi_reset_method) { if (test_and_set_bit(INTEL_ACPI_RESET_ACTIVE, intel_data->flags)) { bt_dev_err(hdev, "acpi: last reset failed ? Not resetting again"); @@ -963,7 +990,7 @@ static inline void btusb_rtl_alloc_devcoredump(struct hci_dev *hdev, } } -static void btusb_rtl_cmd_timeout(struct hci_dev *hdev) +static void btusb_rtl_reset(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); struct gpio_desc *reset_gpio = data->reset_gpio; @@ -973,9 +1000,6 @@ static void btusb_rtl_cmd_timeout(struct hci_dev *hdev) btusb_rtl_alloc_devcoredump(hdev, &hdr, NULL, 0); - if (++data->cmd_timeout_cnt < 5) - return; - if (!reset_gpio) { btusb_reset(hdev); return; @@ -1010,19 +1034,16 @@ static void btusb_rtl_hw_error(struct hci_dev *hdev, u8 code) btusb_rtl_alloc_devcoredump(hdev, &hdr, NULL, 0); } -static void btusb_qca_cmd_timeout(struct hci_dev *hdev) +static void btusb_qca_reset(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); struct gpio_desc *reset_gpio = data->reset_gpio; if (test_bit(BTUSB_HW_SSR_ACTIVE, &data->flags)) { - bt_dev_info(hdev, "Ramdump in progress, defer cmd_timeout"); + bt_dev_info(hdev, "Ramdump in progress, defer reset"); return; } - if (++data->cmd_timeout_cnt < 5) - return; - if (reset_gpio) { bt_dev_err(hdev, "Reset qca device via bt_en gpio"); @@ -1065,13 +1086,53 @@ static inline void btusb_free_frags(struct btusb_data *data) spin_unlock_irqrestore(&data->rxlock, flags); } +static void btusb_sco_connected(struct btusb_data *data, struct sk_buff *skb) +{ + struct hci_event_hdr *hdr = (void *) skb->data; + struct hci_ev_sync_conn_complete *ev = + (void *) skb->data + sizeof(*hdr); + struct hci_dev *hdev = data->hdev; + unsigned int notify_air_mode; + + if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT) + return; + + if (skb->len < sizeof(*hdr) || hdr->evt != HCI_EV_SYNC_CONN_COMPLETE) + return; + + if (skb->len != sizeof(*hdr) + sizeof(*ev) || ev->status) + return; + + switch (ev->air_mode) { + case BT_CODEC_CVSD: + notify_air_mode = HCI_NOTIFY_ENABLE_SCO_CVSD; + break; + + case BT_CODEC_TRANSPARENT: + notify_air_mode = HCI_NOTIFY_ENABLE_SCO_TRANSP; + break; + + default: + return; + } + + bt_dev_info(hdev, "enabling SCO with air mode %u", ev->air_mode); + data->sco_num = 1; + data->air_mode = notify_air_mode; + schedule_work(&data->work); +} + static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb) { if (data->intr_interval) { - /* Trigger dequeue immediatelly if an event is received */ + /* Trigger dequeue immediately if an event is received */ schedule_delayed_work(&data->rx_work, 0); } + /* Configure altsetting for HCI_USER_CHANNEL on SCO connected */ + if (auto_isoc_alt && hci_dev_test_flag(data->hdev, HCI_USER_CHANNEL)) + btusb_sco_connected(data, skb); + return data->recv_event(data->hdev, skb); } @@ -1352,7 +1413,15 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags) if (!urb) return -ENOMEM; - size = le16_to_cpu(data->intr_ep->wMaxPacketSize); + if (le16_to_cpu(data->udev->descriptor.idVendor) == 0x0a12 && + le16_to_cpu(data->udev->descriptor.idProduct) == 0x0001) + /* Fake CSR devices don't seem to support sort-transter */ + size = le16_to_cpu(data->intr_ep->wMaxPacketSize); + else + /* Use maximum HCI Event size so the USB stack handles + * ZPL/short-transfer automatically. + */ + size = HCI_MAX_EVENT_SIZE; buf = kmalloc(size, mem_flags); if (!buf) { @@ -2074,7 +2143,8 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) return submit_or_queue_tx_urb(hdev, urb); case HCI_SCODATA_PKT: - if (hci_conn_num(hdev, SCO_LINK) < 1) + if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && + hci_conn_num(hdev, SCO_LINK) < 1) return -ENODEV; urb = alloc_isoc_urb(hdev, skb); @@ -2548,7 +2618,8 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) return submit_or_queue_tx_urb(hdev, urb); case HCI_SCODATA_PKT: - if (hci_conn_num(hdev, SCO_LINK) < 1) + if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && + hci_conn_num(hdev, SCO_LINK) < 1) return -ENODEV; urb = alloc_isoc_urb(hdev, skb); @@ -2601,410 +2672,66 @@ static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb) return hci_recv_frame(hdev, skb); } -/* UHW CR mapping */ -#define MTK_BT_MISC 0x70002510 -#define MTK_BT_SUBSYS_RST 0x70002610 -#define MTK_UDMA_INT_STA_BT 0x74000024 -#define MTK_UDMA_INT_STA_BT1 0x74000308 -#define MTK_BT_WDT_STATUS 0x740003A0 -#define MTK_EP_RST_OPT 0x74011890 -#define MTK_EP_RST_IN_OUT_OPT 0x00010001 -#define MTK_BT_RST_DONE 0x00000100 -#define MTK_BT_RESET_REG_CONNV3 0x70028610 -#define MTK_BT_READ_DEV_ID 0x70010200 - - -static void btusb_mtk_wmt_recv(struct urb *urb) -{ - struct hci_dev *hdev = urb->context; - struct btusb_data *data = hci_get_drvdata(hdev); - struct sk_buff *skb; - int err; - - if (urb->status == 0 && urb->actual_length > 0) { - hdev->stat.byte_rx += urb->actual_length; - - /* WMT event shouldn't be fragmented and the size should be - * less than HCI_WMT_MAX_EVENT_SIZE. - */ - skb = bt_skb_alloc(HCI_WMT_MAX_EVENT_SIZE, GFP_ATOMIC); - if (!skb) { - hdev->stat.err_rx++; - kfree(urb->setup_packet); - return; - } - - hci_skb_pkt_type(skb) = HCI_EVENT_PKT; - skb_put_data(skb, urb->transfer_buffer, urb->actual_length); - - /* When someone waits for the WMT event, the skb is being cloned - * and being processed the events from there then. - */ - if (test_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags)) { - data->evt_skb = skb_clone(skb, GFP_ATOMIC); - if (!data->evt_skb) { - kfree_skb(skb); - kfree(urb->setup_packet); - return; - } - } - - err = hci_recv_frame(hdev, skb); - if (err < 0) { - kfree_skb(data->evt_skb); - data->evt_skb = NULL; - kfree(urb->setup_packet); - return; - } - - if (test_and_clear_bit(BTUSB_TX_WAIT_VND_EVT, - &data->flags)) { - /* Barrier to sync with other CPUs */ - smp_mb__after_atomic(); - wake_up_bit(&data->flags, - BTUSB_TX_WAIT_VND_EVT); - } - kfree(urb->setup_packet); - return; - } else if (urb->status == -ENOENT) { - /* Avoid suspend failed when usb_kill_urb */ - return; - } - - usb_mark_last_busy(data->udev); - - /* The URB complete handler is still called with urb->actual_length = 0 - * when the event is not available, so we should keep re-submitting - * URB until WMT event returns, Also, It's necessary to wait some time - * between the two consecutive control URBs to relax the target device - * to generate the event. Otherwise, the WMT event cannot return from - * the device successfully. - */ - udelay(500); - - usb_anchor_urb(urb, &data->ctrl_anchor); - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0) { - kfree(urb->setup_packet); - /* -EPERM: urb is being killed; - * -ENODEV: device got disconnected - */ - if (err != -EPERM && err != -ENODEV) - bt_dev_err(hdev, "urb %p failed to resubmit (%d)", - urb, -err); - usb_unanchor_urb(urb); - } -} - -static int btusb_mtk_submit_wmt_recv_urb(struct hci_dev *hdev) -{ - struct btusb_data *data = hci_get_drvdata(hdev); - struct usb_ctrlrequest *dr; - unsigned char *buf; - int err, size = 64; - unsigned int pipe; - struct urb *urb; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - return -ENOMEM; - - dr = kmalloc(sizeof(*dr), GFP_KERNEL); - if (!dr) { - usb_free_urb(urb); - return -ENOMEM; - } - - dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_IN; - dr->bRequest = 1; - dr->wIndex = cpu_to_le16(0); - dr->wValue = cpu_to_le16(48); - dr->wLength = cpu_to_le16(size); - - buf = kmalloc(size, GFP_KERNEL); - if (!buf) { - kfree(dr); - usb_free_urb(urb); - return -ENOMEM; - } - - pipe = usb_rcvctrlpipe(data->udev, 0); - - usb_fill_control_urb(urb, data->udev, pipe, (void *)dr, - buf, size, btusb_mtk_wmt_recv, hdev); - - urb->transfer_flags |= URB_FREE_BUFFER; - - usb_anchor_urb(urb, &data->ctrl_anchor); - err = usb_submit_urb(urb, GFP_KERNEL); - if (err < 0) { - if (err != -EPERM && err != -ENODEV) - bt_dev_err(hdev, "urb %p submission failed (%d)", - urb, -err); - usb_unanchor_urb(urb); - } - - usb_free_urb(urb); - - return err; -} - -static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev, - struct btmtk_hci_wmt_params *wmt_params) +static void btusb_mtk_claim_iso_intf(struct btusb_data *data) { - struct btusb_data *data = hci_get_drvdata(hdev); - struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc; - u32 hlen, status = BTMTK_WMT_INVALID; - struct btmtk_hci_wmt_evt *wmt_evt; - struct btmtk_hci_wmt_cmd *wc; - struct btmtk_wmt_hdr *hdr; + struct btmtk_data *btmtk_data = hci_get_priv(data->hdev); int err; - /* Send the WMT command and wait until the WMT event returns */ - hlen = sizeof(*hdr) + wmt_params->dlen; - if (hlen > 255) - return -EINVAL; - - wc = kzalloc(hlen, GFP_KERNEL); - if (!wc) - return -ENOMEM; - - hdr = &wc->hdr; - hdr->dir = 1; - hdr->op = wmt_params->op; - hdr->dlen = cpu_to_le16(wmt_params->dlen + 1); - hdr->flag = wmt_params->flag; - memcpy(wc->data, wmt_params->data, wmt_params->dlen); - - set_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags); - - /* WMT cmd/event doesn't follow up the generic HCI cmd/event handling, - * it needs constantly polling control pipe until the host received the - * WMT event, thus, we should require to specifically acquire PM counter - * on the USB to prevent the interface from entering auto suspended - * while WMT cmd/event in progress. - */ - err = usb_autopm_get_interface(data->intf); - if (err < 0) - goto err_free_wc; - - err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc); - - if (err < 0) { - clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags); - usb_autopm_put_interface(data->intf); - goto err_free_wc; - } - - /* Submit control IN URB on demand to process the WMT event */ - err = btusb_mtk_submit_wmt_recv_urb(hdev); - - usb_autopm_put_interface(data->intf); - - if (err < 0) - goto err_free_wc; - - /* The vendor specific WMT commands are all answered by a vendor - * specific event and will have the Command Status or Command - * Complete as with usual HCI command flow control. - * - * After sending the command, wait for BTUSB_TX_WAIT_VND_EVT - * state to be cleared. The driver specific event receive routine - * will clear that state and with that indicate completion of the - * WMT command. + /* + * The function usb_driver_claim_interface() is documented to need + * locks held if it's not called from a probe routine. The code here + * is called from the hci_power_on workqueue, so grab the lock. */ - err = wait_on_bit_timeout(&data->flags, BTUSB_TX_WAIT_VND_EVT, - TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT); - if (err == -EINTR) { - bt_dev_err(hdev, "Execution of wmt command interrupted"); - clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags); - goto err_free_wc; - } - - if (err) { - bt_dev_err(hdev, "Execution of wmt command timed out"); - clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags); - err = -ETIMEDOUT; - goto err_free_wc; - } - - if (data->evt_skb == NULL) - goto err_free_wc; - - /* Parse and handle the return WMT event */ - wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data; - if (wmt_evt->whdr.op != hdr->op) { - bt_dev_err(hdev, "Wrong op received %d expected %d", - wmt_evt->whdr.op, hdr->op); - err = -EIO; - goto err_free_skb; - } - - switch (wmt_evt->whdr.op) { - case BTMTK_WMT_SEMAPHORE: - if (wmt_evt->whdr.flag == 2) - status = BTMTK_WMT_PATCH_UNDONE; - else - status = BTMTK_WMT_PATCH_DONE; - break; - case BTMTK_WMT_FUNC_CTRL: - wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt; - if (be16_to_cpu(wmt_evt_funcc->status) == 0x404) - status = BTMTK_WMT_ON_DONE; - else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420) - status = BTMTK_WMT_ON_PROGRESS; - else - status = BTMTK_WMT_ON_UNDONE; - break; - case BTMTK_WMT_PATCH_DWNLD: - if (wmt_evt->whdr.flag == 2) - status = BTMTK_WMT_PATCH_DONE; - else if (wmt_evt->whdr.flag == 1) - status = BTMTK_WMT_PATCH_PROGRESS; - else - status = BTMTK_WMT_PATCH_UNDONE; - break; - } - - if (wmt_params->status) - *wmt_params->status = status; - -err_free_skb: - kfree_skb(data->evt_skb); - data->evt_skb = NULL; -err_free_wc: - kfree(wc); - return err; -} - -static int btusb_mtk_func_query(struct hci_dev *hdev) -{ - struct btmtk_hci_wmt_params wmt_params; - int status, err; - u8 param = 0; - - /* Query whether the function is enabled */ - wmt_params.op = BTMTK_WMT_FUNC_CTRL; - wmt_params.flag = 4; - wmt_params.dlen = sizeof(param); - wmt_params.data = ¶m; - wmt_params.status = &status; - - err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); + device_lock(&btmtk_data->isopkt_intf->dev); + err = usb_driver_claim_interface(&btusb_driver, + btmtk_data->isopkt_intf, data); + device_unlock(&btmtk_data->isopkt_intf->dev); if (err < 0) { - bt_dev_err(hdev, "Failed to query function status (%d)", err); - return err; + btmtk_data->isopkt_intf = NULL; + bt_dev_err(data->hdev, "Failed to claim iso interface"); + return; } - return status; + set_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags); + init_usb_anchor(&btmtk_data->isopkt_anchor); } -static int btusb_mtk_uhw_reg_write(struct btusb_data *data, u32 reg, u32 val) +static void btusb_mtk_release_iso_intf(struct hci_dev *hdev) { - struct hci_dev *hdev = data->hdev; - int pipe, err; - void *buf; + struct btmtk_data *btmtk_data = hci_get_priv(hdev); - buf = kzalloc(4, GFP_KERNEL); - if (!buf) - return -ENOMEM; + if (test_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags)) { + usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor); + clear_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags); - put_unaligned_le32(val, buf); - - pipe = usb_sndctrlpipe(data->udev, 0); - err = usb_control_msg(data->udev, pipe, 0x02, - 0x5E, - reg >> 16, reg & 0xffff, - buf, 4, USB_CTRL_SET_TIMEOUT); - if (err < 0) { - bt_dev_err(hdev, "Failed to write uhw reg(%d)", err); - goto err_free_buf; + dev_kfree_skb_irq(btmtk_data->isopkt_skb); + btmtk_data->isopkt_skb = NULL; + usb_set_intfdata(btmtk_data->isopkt_intf, NULL); + usb_driver_release_interface(&btusb_driver, + btmtk_data->isopkt_intf); } -err_free_buf: - kfree(buf); - - return err; -} - -static int btusb_mtk_uhw_reg_read(struct btusb_data *data, u32 reg, u32 *val) -{ - struct hci_dev *hdev = data->hdev; - int pipe, err; - void *buf; - - buf = kzalloc(4, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - pipe = usb_rcvctrlpipe(data->udev, 0); - err = usb_control_msg(data->udev, pipe, 0x01, - 0xDE, - reg >> 16, reg & 0xffff, - buf, 4, USB_CTRL_SET_TIMEOUT); - if (err < 0) { - bt_dev_err(hdev, "Failed to read uhw reg(%d)", err); - goto err_free_buf; - } - - *val = get_unaligned_le32(buf); - bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val); - -err_free_buf: - kfree(buf); - - return err; -} - -static int btusb_mtk_reg_read(struct btusb_data *data, u32 reg, u32 *val) -{ - int pipe, err, size = sizeof(u32); - void *buf; - - buf = kzalloc(size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - pipe = usb_rcvctrlpipe(data->udev, 0); - err = usb_control_msg(data->udev, pipe, 0x63, - USB_TYPE_VENDOR | USB_DIR_IN, - reg >> 16, reg & 0xffff, - buf, size, USB_CTRL_SET_TIMEOUT); - if (err < 0) - goto err_free_buf; - - *val = get_unaligned_le32(buf); - -err_free_buf: - kfree(buf); - - return err; + clear_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags); } -static int btusb_mtk_id_get(struct btusb_data *data, u32 reg, u32 *id) +static int btusb_mtk_disconnect(struct hci_dev *hdev) { - 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); + /* This function describes the specific additional steps taken by MediaTek + * when Bluetooth usb driver's resume function is called. + */ + btusb_mtk_release_iso_intf(hdev); - return val & MTK_BT_RST_DONE; + return 0; } static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data) { struct btusb_data *data = hci_get_drvdata(hdev); - struct btmediatek_data *mediatek; - u32 val; + struct btmtk_data *btmtk_data = hci_get_priv(hdev); int err; /* It's MediaTek specific bluetooth reset mechanism via USB */ - if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) { + if (test_and_set_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags)) { bt_dev_err(hdev, "last reset failed? Not resetting again"); return -EBUSY; } @@ -3013,290 +2740,70 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data) if (err < 0) return err; + /* Release MediaTek ISO data interface */ + btusb_mtk_release_iso_intf(hdev); + 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."); + err = btmtk_usb_subsys_reset(hdev, btmtk_data->dev_id); usb_queue_reset_device(data->intf); - - clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags); + clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags); return err; } -static int btusb_mtk_setup(struct hci_dev *hdev) +static int btusb_send_frame_mtk(struct hci_dev *hdev, struct sk_buff *skb) { - struct btusb_data *data = hci_get_drvdata(hdev); - struct btmtk_hci_wmt_params wmt_params; - ktime_t calltime, delta, rettime; - struct btmtk_tci_sleep tci_sleep; - unsigned long long duration; - struct sk_buff *skb; - const char *fwname; - int err, status; - u32 dev_id = 0; - char fw_bin_name[64]; - u32 fw_version = 0; - u8 param; - struct btmediatek_data *mediatek; - - calltime = ktime_get(); - - err = btusb_mtk_id_get(data, 0x80000008, &dev_id); - if (err < 0) { - bt_dev_err(hdev, "Failed to get device id (%d)", err); - return err; - } - - if (!dev_id || dev_id != 0x7663) { - err = btusb_mtk_id_get(data, 0x70010200, &dev_id); - if (err < 0) { - bt_dev_err(hdev, "Failed to get device id (%d)", err); - return err; - } - err = btusb_mtk_id_get(data, 0x80021004, &fw_version); - if (err < 0) { - bt_dev_err(hdev, "Failed to get fw version (%d)", err); - return err; - } - } - - mediatek = hci_get_priv(hdev); - mediatek->dev_id = dev_id; - mediatek->reset_sync = btusb_mtk_reset; - - err = btmtk_register_coredump(hdev, btusb_driver.name, fw_version); - if (err < 0) - bt_dev_err(hdev, "Failed to register coredump (%d)", err); - - switch (dev_id) { - case 0x7663: - fwname = FIRMWARE_MT7663; - break; - case 0x7668: - fwname = FIRMWARE_MT7668; - break; - case 0x7922: - case 0x7961: - case 0x7925: - if (dev_id == 0x7925) - snprintf(fw_bin_name, sizeof(fw_bin_name), - "mediatek/mt%04x/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", - dev_id & 0xffff, dev_id & 0xffff, (fw_version & 0xff) + 1); - else - snprintf(fw_bin_name, sizeof(fw_bin_name), - "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", - dev_id & 0xffff, (fw_version & 0xff) + 1); - - err = btmtk_setup_firmware_79xx(hdev, fw_bin_name, - btusb_mtk_hci_wmt_sync); - if (err < 0) { - bt_dev_err(hdev, "Failed to set up firmware (%d)", err); - return err; - } - - /* It's Device EndPoint Reset Option Register */ - btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); - - /* Enable Bluetooth protocol */ - param = 1; - wmt_params.op = BTMTK_WMT_FUNC_CTRL; - wmt_params.flag = 0; - wmt_params.dlen = sizeof(param); - wmt_params.data = ¶m; - wmt_params.status = NULL; - - err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); - return err; - } - - hci_set_msft_opcode(hdev, 0xFD30); - hci_set_aosp_capable(hdev); - goto done; - default: - bt_dev_err(hdev, "Unsupported hardware variant (%08x)", - dev_id); - return -ENODEV; - } - - /* Query whether the firmware is already download */ - wmt_params.op = BTMTK_WMT_SEMAPHORE; - wmt_params.flag = 1; - wmt_params.dlen = 0; - wmt_params.data = NULL; - wmt_params.status = &status; - - err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to query firmware status (%d)", err); - return err; - } - - if (status == BTMTK_WMT_PATCH_DONE) { - bt_dev_info(hdev, "firmware already downloaded"); - goto ignore_setup_fw; - } - - /* Setup a firmware which the device definitely requires */ - err = btmtk_setup_firmware(hdev, fwname, - btusb_mtk_hci_wmt_sync); - if (err < 0) - return err; - -ignore_setup_fw: - err = readx_poll_timeout(btusb_mtk_func_query, hdev, status, - status < 0 || status != BTMTK_WMT_ON_PROGRESS, - 2000, 5000000); - /* -ETIMEDOUT happens */ - if (err < 0) - return err; - - /* The other errors happen in btusb_mtk_func_query */ - if (status < 0) - return status; - - if (status == BTMTK_WMT_ON_DONE) { - bt_dev_info(hdev, "function already on"); - goto ignore_func_on; - } - - /* Enable Bluetooth protocol */ - param = 1; - wmt_params.op = BTMTK_WMT_FUNC_CTRL; - wmt_params.flag = 0; - wmt_params.dlen = sizeof(param); - wmt_params.data = ¶m; - wmt_params.status = NULL; + struct urb *urb; - err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); - return err; - } + BT_DBG("%s", hdev->name); -ignore_func_on: - /* Apply the low power environment setup */ - tci_sleep.mode = 0x5; - tci_sleep.duration = cpu_to_le16(0x640); - tci_sleep.host_duration = cpu_to_le16(0x640); - tci_sleep.host_wakeup_pin = 0; - tci_sleep.time_compensation = 0; + if (hci_skb_pkt_type(skb) == HCI_ISODATA_PKT) { + urb = alloc_mtk_intr_urb(hdev, skb, btusb_tx_complete); + if (IS_ERR(urb)) + return PTR_ERR(urb); - skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep, - HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - err = PTR_ERR(skb); - bt_dev_err(hdev, "Failed to apply low power setting (%d)", err); - return err; + return submit_or_queue_tx_urb(hdev, urb); + } else { + return btusb_send_frame(hdev, skb); } - kfree_skb(skb); - -done: - rettime = ktime_get(); - delta = ktime_sub(rettime, calltime); - duration = (unsigned long long)ktime_to_ns(delta) >> 10; - - bt_dev_info(hdev, "Device setup in %llu usecs", duration); - - return 0; } -static int btusb_mtk_shutdown(struct hci_dev *hdev) +static int btusb_mtk_setup(struct hci_dev *hdev) { - struct btmtk_hci_wmt_params wmt_params; - u8 param = 0; - int err; + struct btusb_data *data = hci_get_drvdata(hdev); + struct btmtk_data *btmtk_data = hci_get_priv(hdev); - /* Disable the device */ - wmt_params.op = BTMTK_WMT_FUNC_CTRL; - wmt_params.flag = 0; - wmt_params.dlen = sizeof(param); - wmt_params.data = ¶m; - wmt_params.status = NULL; + /* MediaTek WMT vendor cmd requiring below USB resources to + * complete the handshake. + */ + btmtk_data->drv_name = btusb_driver.name; + btmtk_data->intf = data->intf; + btmtk_data->udev = data->udev; + btmtk_data->ctrl_anchor = &data->ctrl_anchor; + btmtk_data->reset_sync = btusb_mtk_reset; - err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); - if (err < 0) { - bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); - return err; + /* Claim ISO data interface and endpoint */ + if (!test_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags)) { + btmtk_data->isopkt_intf = usb_ifnum_to_if(data->udev, MTK_ISO_IFNUM); + btusb_mtk_claim_iso_intf(data); } - return 0; + return btmtk_usb_setup(hdev); } -static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb) +static int btusb_mtk_shutdown(struct hci_dev *hdev) { - 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 */ - /* When the firmware hangs, the device can no longer - * suspend and thus disable auto-suspend. - */ - usb_disable_autosuspend(data->udev); + int ret; - /* 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); + ret = btmtk_usb_shutdown(hdev); - fallthrough; - case 0x05ff: /* Firmware debug logging 1 */ - case 0x05fe: /* Firmware debug logging 2 */ - return hci_recv_diag(hdev, skb); - } + /* Release MediaTek iso interface after shutdown */ + btusb_mtk_release_iso_intf(hdev); - return hci_recv_frame(hdev, skb); + return ret; } #ifdef CONFIG_PM @@ -3461,13 +2968,12 @@ static void btusb_dump_hdr_qca(struct hci_dev *hdev, struct sk_buff *skb) static void btusb_coredump_qca(struct hci_dev *hdev) { + int err; static const u8 param[] = { 0x26 }; - struct sk_buff *skb; - skb = __hci_cmd_sync(hdev, 0xfc0c, 1, param, HCI_CMD_TIMEOUT); - if (IS_ERR(skb)) - bt_dev_err(hdev, "%s: triggle crash failed (%ld)", __func__, PTR_ERR(skb)); - kfree_skb(skb); + err = __hci_cmd_send(hdev, 0xfc0c, 1, param); + if (err < 0) + bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err); } /* @@ -3673,7 +3179,7 @@ static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request, */ pipe = usb_rcvctrlpipe(udev, 0); err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN, - 0, 0, buf, size, USB_CTRL_SET_TIMEOUT); + 0, 0, buf, size, USB_CTRL_GET_TIMEOUT); if (err < 0) { dev_err(&udev->dev, "Failed to access otp area (%d)", err); goto done; @@ -4179,12 +3685,39 @@ static ssize_t force_poll_sync_write(struct file *file, } static const struct file_operations force_poll_sync_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = force_poll_sync_read, .write = force_poll_sync_write, .llseek = default_llseek, }; +static ssize_t isoc_alt_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct btusb_data *data = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%d\n", data->isoc_altsetting); +} + +static ssize_t isoc_alt_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct btusb_data *data = dev_get_drvdata(dev); + int alt; + int ret; + + if (kstrtoint(buf, 10, &alt)) + return -EINVAL; + + ret = btusb_switch_alt_setting(data->hdev, alt); + return ret < 0 ? ret : count; +} + +static DEVICE_ATTR_RW(isoc_alt); + static int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -4299,7 +3832,7 @@ static int btusb_probe(struct usb_interface *intf, data->recv_event = btusb_recv_event_realtek; } else if (id->driver_info & BTUSB_MEDIATEK) { /* Allocate extra space for Mediatek device */ - priv_size += sizeof(struct btmediatek_data); + priv_size += sizeof(struct btmtk_data); } data->recv_acl = hci_recv_frame; @@ -4311,11 +3844,6 @@ static int btusb_probe(struct usb_interface *intf, hdev->bus = HCI_USB; hci_set_drvdata(hdev, data); - if (id->driver_info & BTUSB_AMP) - hdev->dev_type = HCI_AMP; - else - hdev->dev_type = HCI_PRIMARY; - data->hdev = hdev; SET_HCIDEV_DEV(hdev, &intf->dev); @@ -4386,7 +3914,7 @@ static int btusb_probe(struct usb_interface *intf, /* Transport specific configuration */ hdev->send = btusb_send_frame_intel; - hdev->cmd_timeout = btusb_intel_cmd_timeout; + hdev->reset = btusb_intel_reset; if (id->driver_info & BTUSB_INTEL_NO_WBS_SUPPORT) btintel_set_flag(hdev, INTEL_ROM_LEGACY_NO_WBS_SUPPORT); @@ -4406,11 +3934,15 @@ static int btusb_probe(struct usb_interface *intf, hdev->setup = btusb_mtk_setup; hdev->shutdown = btusb_mtk_shutdown; hdev->manufacturer = 70; - hdev->cmd_timeout = btmtk_reset_sync; + hdev->reset = btmtk_reset_sync; hdev->set_bdaddr = btmtk_set_bdaddr; + hdev->send = btusb_send_frame_mtk; set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); - data->recv_acl = btusb_recv_acl_mtk; + data->recv_acl = btmtk_usb_recv_acl; + data->suspend = btmtk_usb_suspend; + data->resume = btmtk_usb_resume; + data->disconnect = btusb_mtk_disconnect; } if (id->driver_info & BTUSB_SWAVE) { @@ -4434,7 +3966,7 @@ static int btusb_probe(struct usb_interface *intf, data->setup_on_usb = btusb_setup_qca; hdev->shutdown = btusb_shutdown_qca; hdev->set_bdaddr = btusb_set_bdaddr_ath3012; - hdev->cmd_timeout = btusb_qca_cmd_timeout; + hdev->reset = btusb_qca_reset; set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); btusb_check_needs_reset_resume(intf); } @@ -4448,7 +3980,7 @@ static int btusb_probe(struct usb_interface *intf, data->setup_on_usb = btusb_setup_qca; hdev->shutdown = btusb_shutdown_qca; hdev->set_bdaddr = btusb_set_bdaddr_wcn6855; - hdev->cmd_timeout = btusb_qca_cmd_timeout; + hdev->reset = btusb_qca_reset; set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); hci_set_msft_opcode(hdev, 0xFD70); } @@ -4467,7 +3999,7 @@ static int btusb_probe(struct usb_interface *intf, btrtl_set_driver_name(hdev, btusb_driver.name); hdev->setup = btusb_setup_realtek; hdev->shutdown = btrtl_shutdown_realtek; - hdev->cmd_timeout = btusb_rtl_cmd_timeout; + hdev->reset = btusb_rtl_reset; hdev->hw_error = btusb_rtl_hw_error; /* Realtek devices need to set remote wakeup on auto-suspend */ @@ -4481,6 +4013,9 @@ static int btusb_probe(struct usb_interface *intf, set_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks); set_bit(HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT, &hdev->quirks); set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks); + set_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks); + set_bit(HCI_QUIRK_BROKEN_EXT_CREATE_CONN, &hdev->quirks); + set_bit(HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT, &hdev->quirks); } if (!reset) @@ -4497,8 +4032,8 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_WIDEBAND_SPEECH) set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); - if (id->driver_info & BTUSB_VALID_LE_STATES) - set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); + if (id->driver_info & BTUSB_INVALID_LE_STATES) + set_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks); if (id->driver_info & BTUSB_DIGIANSWER) { data->cmdreq_type = USB_TYPE_VENDOR; @@ -4546,6 +4081,10 @@ static int btusb_probe(struct usb_interface *intf, data->isoc, data); if (err < 0) goto out_free_dev; + + err = device_create_file(&intf->dev, &dev_attr_isoc_alt); + if (err) + goto out_free_dev; } if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) && data->diag) { @@ -4592,12 +4131,17 @@ static void btusb_disconnect(struct usb_interface *intf) hdev = data->hdev; usb_set_intfdata(data->intf, NULL); - if (data->isoc) + if (data->isoc) { + device_remove_file(&intf->dev, &dev_attr_isoc_alt); usb_set_intfdata(data->isoc, NULL); + } if (data->diag) usb_set_intfdata(data->diag, NULL); + if (data->disconnect) + data->disconnect(hdev); + hci_unregister_dev(hdev); if (intf == data->intf) { @@ -4631,8 +4175,10 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) BT_DBG("intf %p", intf); - /* Don't suspend if there are connections */ - if (hci_conn_count(data->hdev)) + /* Don't auto-suspend if there are connections; external suspend calls + * shall never fail. + */ + if (PMSG_IS_AUTO(message) && hci_conn_count(data->hdev)) return -EBUSY; if (data->suspend_count++) @@ -4650,6 +4196,9 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) cancel_work_sync(&data->work); + if (data->suspend) + data->suspend(data->hdev); + btusb_stop_traffic(data); usb_kill_anchored_urbs(&data->tx_anchor); @@ -4753,6 +4302,9 @@ static int btusb_resume(struct usb_interface *intf) btusb_submit_isoc_urb(hdev, GFP_NOIO); } + if (data->resume) + data->resume(hdev); + spin_lock_irq(&data->txlock); play_deferred(data); clear_bit(BTUSB_SUSPENDING, &data->flags); |