xref: /openbmc/linux/drivers/bluetooth/btusb.c (revision 8ebc80a25f9d9bf7a8e368b266d5b740c485c362)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
25e23b923SMarcel Holtmann /*
35e23b923SMarcel Holtmann  *
45e23b923SMarcel Holtmann  *  Generic Bluetooth USB driver
55e23b923SMarcel Holtmann  *
69bfa35feSMarcel Holtmann  *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
75e23b923SMarcel Holtmann  */
85e23b923SMarcel Holtmann 
91fdb9269SHans de Goede #include <linux/dmi.h>
105e23b923SMarcel Holtmann #include <linux/module.h>
115e23b923SMarcel Holtmann #include <linux/usb.h>
1261f5aceaSHans de Goede #include <linux/usb/quirks.h>
13dffd30eeSTedd Ho-Jeong An #include <linux/firmware.h>
14a1c49c43SSean Wang #include <linux/iopoll.h>
15fd913ef7SRajat Jain #include <linux/of_device.h>
16fd913ef7SRajat Jain #include <linux/of_irq.h>
17017789f3SJeffy Chen #include <linux/suspend.h>
18dc786b2cSRajat Jain #include <linux/gpio/consumer.h>
19800fe5ecSLuiz Augusto von Dentz #include <linux/debugfs.h>
20a2698a9bSDaniel Drake #include <asm/unaligned.h>
215e23b923SMarcel Holtmann 
225e23b923SMarcel Holtmann #include <net/bluetooth/bluetooth.h>
235e23b923SMarcel Holtmann #include <net/bluetooth/hci_core.h>
245e23b923SMarcel Holtmann 
254185a0f5SMarcel Holtmann #include "btintel.h"
261df1f591SMarcel Holtmann #include "btbcm.h"
27db33c77dSCarlo Caione #include "btrtl.h"
288c0d17b6SSean Wang #include "btmtk.h"
291df1f591SMarcel Holtmann 
3034dced9bSMarcel Holtmann #define VERSION "0.8"
31cfeb4145SMarcel Holtmann 
3290ab5ee9SRusty Russell static bool disable_scofix;
3390ab5ee9SRusty Russell static bool force_scofix;
34eff2d68cSHans de Goede static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
35bb1afb29SLuiz Augusto von Dentz static bool enable_poll_sync = IS_ENABLED(CONFIG_BT_HCIBTUSB_POLL_SYNC);
36917a3337SShailendra Verma static bool reset = true;
37cfeb4145SMarcel Holtmann 
38cfeb4145SMarcel Holtmann static struct usb_driver btusb_driver;
39cfeb4145SMarcel Holtmann 
40f95fd5f3SLuiz Augusto von Dentz #define BTUSB_IGNORE			BIT(0)
41f95fd5f3SLuiz Augusto von Dentz #define BTUSB_DIGIANSWER		BIT(1)
42f95fd5f3SLuiz Augusto von Dentz #define BTUSB_CSR			BIT(2)
43f95fd5f3SLuiz Augusto von Dentz #define BTUSB_SNIFFER			BIT(3)
44f95fd5f3SLuiz Augusto von Dentz #define BTUSB_BCM92035			BIT(4)
45f95fd5f3SLuiz Augusto von Dentz #define BTUSB_BROKEN_ISOC		BIT(5)
46f95fd5f3SLuiz Augusto von Dentz #define BTUSB_WRONG_SCO_MTU		BIT(6)
47f95fd5f3SLuiz Augusto von Dentz #define BTUSB_ATH3012			BIT(7)
48f95fd5f3SLuiz Augusto von Dentz #define BTUSB_INTEL_COMBINED		BIT(8)
49f95fd5f3SLuiz Augusto von Dentz #define BTUSB_INTEL_BOOT		BIT(9)
50f95fd5f3SLuiz Augusto von Dentz #define BTUSB_BCM_PATCHRAM		BIT(10)
51f95fd5f3SLuiz Augusto von Dentz #define BTUSB_MARVELL			BIT(11)
52f95fd5f3SLuiz Augusto von Dentz #define BTUSB_SWAVE			BIT(12)
53f95fd5f3SLuiz Augusto von Dentz #define BTUSB_AMP			BIT(13)
54f95fd5f3SLuiz Augusto von Dentz #define BTUSB_QCA_ROME			BIT(14)
55f95fd5f3SLuiz Augusto von Dentz #define BTUSB_BCM_APPLE			BIT(15)
56f95fd5f3SLuiz Augusto von Dentz #define BTUSB_REALTEK			BIT(16)
57f95fd5f3SLuiz Augusto von Dentz #define BTUSB_BCM2045			BIT(17)
58f95fd5f3SLuiz Augusto von Dentz #define BTUSB_IFNUM_2			BIT(18)
59f95fd5f3SLuiz Augusto von Dentz #define BTUSB_CW6622			BIT(19)
60f95fd5f3SLuiz Augusto von Dentz #define BTUSB_MEDIATEK			BIT(20)
61f95fd5f3SLuiz Augusto von Dentz #define BTUSB_WIDEBAND_SPEECH		BIT(21)
62f95fd5f3SLuiz Augusto von Dentz #define BTUSB_VALID_LE_STATES		BIT(22)
63f95fd5f3SLuiz Augusto von Dentz #define BTUSB_QCA_WCN6855		BIT(23)
64f95fd5f3SLuiz Augusto von Dentz #define BTUSB_INTEL_BROKEN_SHUTDOWN_LED	BIT(24)
65f95fd5f3SLuiz Augusto von Dentz #define BTUSB_INTEL_BROKEN_INITIAL_NCMD BIT(25)
66f95fd5f3SLuiz Augusto von Dentz #define BTUSB_INTEL_NO_WBS_SUPPORT	BIT(26)
675d44f76fSMarcel Holtmann #define BTUSB_ACTIONS_SEMI		BIT(27)
685e23b923SMarcel Holtmann 
6954265202SMarcel Holtmann static const struct usb_device_id btusb_table[] = {
705e23b923SMarcel Holtmann 	/* Generic Bluetooth USB device */
715e23b923SMarcel Holtmann 	{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
725e23b923SMarcel Holtmann 
73893ba544SMarcel Holtmann 	/* Generic Bluetooth AMP device */
74893ba544SMarcel Holtmann 	{ USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP },
75893ba544SMarcel Holtmann 
76d63b2826SDaniel Drake 	/* Generic Bluetooth USB interface */
77d63b2826SDaniel Drake 	{ USB_INTERFACE_INFO(0xe0, 0x01, 0x01) },
78d63b2826SDaniel Drake 
791fa6535fSHenrik Rydberg 	/* Apple-specific (Broadcom) devices */
8017b2772bSMarcel Holtmann 	{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01),
8122f8e9dbSMarcel Holtmann 	  .driver_info = BTUSB_BCM_APPLE | BTUSB_IFNUM_2 },
821fa6535fSHenrik Rydberg 
83178c059eSCho, Yu-Chen 	/* MediaTek MT76x0E */
84178c059eSCho, Yu-Chen 	{ USB_DEVICE(0x0e8d, 0x763f) },
85178c059eSCho, Yu-Chen 
86c510eae3SOliver Neukum 	/* Broadcom SoftSailing reporting vendor specific */
872e8b5063SDon Zickus 	{ USB_DEVICE(0x0a5c, 0x21e1) },
88c510eae3SOliver Neukum 
893cd01976SNobuhiro Iwamatsu 	/* Apple MacBookPro 7,1 */
903cd01976SNobuhiro Iwamatsu 	{ USB_DEVICE(0x05ac, 0x8213) },
913cd01976SNobuhiro Iwamatsu 
920a79f674SCyril Lacoux 	/* Apple iMac11,1 */
930a79f674SCyril Lacoux 	{ USB_DEVICE(0x05ac, 0x8215) },
940a79f674SCyril Lacoux 
959c047157SNobuhiro Iwamatsu 	/* Apple MacBookPro6,2 */
969c047157SNobuhiro Iwamatsu 	{ USB_DEVICE(0x05ac, 0x8218) },
979c047157SNobuhiro Iwamatsu 
983e3ede7dSEdgar (gimli) Hucek 	/* Apple MacBookAir3,1, MacBookAir3,2 */
993e3ede7dSEdgar (gimli) Hucek 	{ USB_DEVICE(0x05ac, 0x821b) },
1003e3ede7dSEdgar (gimli) Hucek 
101a63b723dSPieter-Augustijn Van Malleghem 	/* Apple MacBookAir4,1 */
102a63b723dSPieter-Augustijn Van Malleghem 	{ USB_DEVICE(0x05ac, 0x821f) },
103a63b723dSPieter-Augustijn Van Malleghem 
10488d377b6SMarc-Antoine Perennou 	/* Apple MacBookPro8,2 */
10588d377b6SMarc-Antoine Perennou 	{ USB_DEVICE(0x05ac, 0x821a) },
10688d377b6SMarc-Antoine Perennou 
107f78b6826SJurgen Kramer 	/* Apple MacMini5,1 */
108f78b6826SJurgen Kramer 	{ USB_DEVICE(0x05ac, 0x8281) },
109f78b6826SJurgen Kramer 
110cfeb4145SMarcel Holtmann 	/* AVM BlueFRITZ! USB v2.0 */
1114fcef8edSMarcel Holtmann 	{ USB_DEVICE(0x057c, 0x3800), .driver_info = BTUSB_SWAVE },
112cfeb4145SMarcel Holtmann 
113cfeb4145SMarcel Holtmann 	/* Bluetooth Ultraport Module from IBM */
114cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x04bf, 0x030a) },
115cfeb4145SMarcel Holtmann 
116cfeb4145SMarcel Holtmann 	/* ALPS Modules with non-standard id */
117cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x044e, 0x3001) },
118cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x044e, 0x3002) },
119cfeb4145SMarcel Holtmann 
120cfeb4145SMarcel Holtmann 	/* Ericsson with non-standard id */
121cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x0bdb, 0x1002) },
122cfeb4145SMarcel Holtmann 
123cfeb4145SMarcel Holtmann 	/* Canyon CN-BTU1 with HID interfaces */
1247a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0c10, 0x0000) },
125cfeb4145SMarcel Holtmann 
126d049f4e5SMarcel Holtmann 	/* Broadcom BCM20702B0 (Dynex/Insignia) */
127d049f4e5SMarcel Holtmann 	{ USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM },
128d049f4e5SMarcel Holtmann 
1292faf71ceSSanttu Rekilä 	/* Broadcom BCM43142A0 (Foxconn/Lenovo) */
130628c26b4SDmitry Tunin 	{ USB_VENDOR_AND_INTERFACE_INFO(0x105b, 0xff, 0x01, 0x01),
131628c26b4SDmitry Tunin 	  .driver_info = BTUSB_BCM_PATCHRAM },
1322faf71ceSSanttu Rekilä 
133a57bac43SChristoph Haag 	/* Broadcom BCM920703 (HTC Vive) */
134a57bac43SChristoph Haag 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0bb4, 0xff, 0x01, 0x01),
135a57bac43SChristoph Haag 	  .driver_info = BTUSB_BCM_PATCHRAM },
136a57bac43SChristoph Haag 
13798514036SSteven Harms 	/* Foxconn - Hon Hai */
1386029ddc2SHeinrich Siebmanns 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
1396029ddc2SHeinrich Siebmanns 	  .driver_info = BTUSB_BCM_PATCHRAM },
14098514036SSteven Harms 
1418f0c304cSMatej Dubovy 	/* Lite-On Technology - Broadcom based */
1428f0c304cSMatej Dubovy 	{ USB_VENDOR_AND_INTERFACE_INFO(0x04ca, 0xff, 0x01, 0x01),
1438f0c304cSMatej Dubovy 	  .driver_info = BTUSB_BCM_PATCHRAM },
1448f0c304cSMatej Dubovy 
14592c385f4SGustavo Padovan 	/* Broadcom devices with vendor specific id */
14610d4c673SPetri Gynther 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
14710d4c673SPetri Gynther 	  .driver_info = BTUSB_BCM_PATCHRAM },
14892c385f4SGustavo Padovan 
149c2aef6e8SMarcel Holtmann 	/* ASUSTek Computer - Broadcom based */
1509a5abdaaSRick Dunn 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01),
1519a5abdaaSRick Dunn 	  .driver_info = BTUSB_BCM_PATCHRAM },
152c2aef6e8SMarcel Holtmann 
1535bcecf32SKen O'Brien 	/* Belkin F8065bf - Broadcom based */
1546331c686SMarcel Holtmann 	{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01),
1556331c686SMarcel Holtmann 	  .driver_info = BTUSB_BCM_PATCHRAM },
1565bcecf32SKen O'Brien 
1579113bfd8SJurgen Kramer 	/* IMC Networks - Broadcom based */
1586331c686SMarcel Holtmann 	{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),
1596331c686SMarcel Holtmann 	  .driver_info = BTUSB_BCM_PATCHRAM },
1609113bfd8SJurgen Kramer 
161fdfddc60SWen-chien Jesse Sung 	/* Dell Computer - Broadcom based  */
162fdfddc60SWen-chien Jesse Sung 	{ USB_VENDOR_AND_INTERFACE_INFO(0x413c, 0xff, 0x01, 0x01),
163fdfddc60SWen-chien Jesse Sung 	  .driver_info = BTUSB_BCM_PATCHRAM },
164fdfddc60SWen-chien Jesse Sung 
1651623d0bfSDmitry Tunin 	/* Toshiba Corp - Broadcom based */
1661623d0bfSDmitry Tunin 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
1671623d0bfSDmitry Tunin 	  .driver_info = BTUSB_BCM_PATCHRAM },
1681623d0bfSDmitry Tunin 
16940df783dSMarcel Holtmann 	/* Intel Bluetooth USB Bootloader (RAM module) */
170d92f2df0SMarcel Holtmann 	{ USB_DEVICE(0x8087, 0x0a5a),
171d92f2df0SMarcel Holtmann 	  .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
17240df783dSMarcel Holtmann 
1735e23b923SMarcel Holtmann 	{ }	/* Terminating entry */
1745e23b923SMarcel Holtmann };
1755e23b923SMarcel Holtmann 
1765e23b923SMarcel Holtmann MODULE_DEVICE_TABLE(usb, btusb_table);
1775e23b923SMarcel Holtmann 
178d831e361SBastien Nocera static const struct usb_device_id quirks_table[] = {
179cfeb4145SMarcel Holtmann 	/* CSR BlueCore devices */
180cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR },
181cfeb4145SMarcel Holtmann 
182cfeb4145SMarcel Holtmann 	/* Broadcom BCM2033 without firmware */
183cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
184cfeb4145SMarcel Holtmann 
1856c9d435dSMarcel Holtmann 	/* Broadcom BCM2045 devices */
1866c9d435dSMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2045), .driver_info = BTUSB_BCM2045 },
1876c9d435dSMarcel Holtmann 
188be93112aSBala Shanmugam 	/* Atheros 3011 with sflash firmware */
1890b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
1900b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
1912eeff0b4SAlexander Ploumistos 	{ USB_DEVICE(0x04f2, 0xaff1), .driver_info = BTUSB_IGNORE },
1920b880062SAndy Shevchenko 	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
193be93112aSBala Shanmugam 	{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
1946eda541dSMarek Vasut 	{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
1952a7bccccSAndy Ross 	{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
196be93112aSBala Shanmugam 
197509e7861SCho, Yu-Chen 	/* Atheros AR9285 Malbec with sflash firmware */
198509e7861SCho, Yu-Chen 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
199509e7861SCho, Yu-Chen 
200d9f51b51SBala Shanmugam 	/* Atheros 3012 with sflash firmware */
2010b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
2020b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
2030b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
2040b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
2050b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
206692c062eSDmitry Tunin 	{ USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
2074b552bc9SAnantha Krishnan 	{ USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
20828c971d8SDmitry Tunin 	{ USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 },
2090b880062SAndy Shevchenko 	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
2100b880062SAndy Shevchenko 	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
2110b880062SAndy Shevchenko 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
2120b880062SAndy Shevchenko 	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
2131fb4e09aSMohammed Habibulla 	{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
2140b880062SAndy Shevchenko 	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
2150b880062SAndy Shevchenko 	{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
2167e730c7fSDmitry Tunin 	{ USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 },
217ec0810d2SDmitry Tunin 	{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
218134d3b35SJanne Heikkinen 	{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
21981d90442SDmitry Tunin 	{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
220441ad62dSDmitry Tunin 	{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
2210b880062SAndy Shevchenko 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
222cd355ff0SDmitry Tunin 	{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
2230b880062SAndy Shevchenko 	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
22489d2975fSVincent Zwanenburg 	{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
225a735f9e2SAndy Shevchenko 	{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
226d66629c1SMing Lei 	{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
227544a5916SHans de Goede 	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
22894a32d10SSunguk Lee 	{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
22907c0ea87SCho, Yu-Chen 	{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
230b131237cSOliver Neukum 	{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
2311e56f1ebSOliver Neukum 	{ USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
2320b880062SAndy Shevchenko 	{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
233ebaf5795SMing Lei 	{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
23418e0afabSDmitry Tunin 	{ USB_DEVICE(0x0cf3, 0x817b), .driver_info = BTUSB_ATH3012 },
2350b880062SAndy Shevchenko 	{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
236ac71311eSAceLan Kao 	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
2370a3658ccSPeng Chen 	{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
238ca79f232SWen-chien Jesse Sung 	{ USB_DEVICE(0x0cf3, 0xe006), .driver_info = BTUSB_ATH3012 },
2390b880062SAndy Shevchenko 	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
2400b880062SAndy Shevchenko 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
241eed307e2SAceLan Kao 	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
242609574ebSDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 },
2435b77a1f3SSujith Manoharan 	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
2443bb30a7cSDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
245033efa92SDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
246fa2f1394SAnantha Krishnan 	{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
24775c6aca4SDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
2480d0cef61SDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
24972f9f8b5SLauro Costa 	{ USB_DEVICE(0x13d3, 0x3487), .driver_info = BTUSB_ATH3012 },
25012d86896SDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3490), .driver_info = BTUSB_ATH3012 },
251d9f51b51SBala Shanmugam 
252e9036e33SCho, Yu-Chen 	/* Atheros AR5BBU12 with sflash firmware */
253e9036e33SCho, Yu-Chen 	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
254e9036e33SCho, Yu-Chen 
25585d59726SMichael Gruetzner 	/* Atheros AR5BBU12 with sflash firmware */
256bc21fde2SYevgeniy Melnichuk 	{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
2570b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
25885d59726SMichael Gruetzner 
2593267c884SKim, Ben Young Tae 	/* QCA ROME chipset */
260e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0x535b), .driver_info = BTUSB_QCA_ROME |
261e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
262e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME |
263e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
264e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME |
265e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
266e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe010), .driver_info = BTUSB_QCA_ROME |
267e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
268e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME |
269e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
270e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME |
271e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
272e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME |
273e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
2740324d19cSDaniel Lenski 	{ USB_DEVICE(0x0cf3, 0xe500), .driver_info = BTUSB_QCA_ROME |
2750324d19cSDaniel Lenski 						     BTUSB_WIDEBAND_SPEECH },
276e99f38b8SRocky Liao 	{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME |
277e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
278e99f38b8SRocky Liao 	{ USB_DEVICE(0x0489, 0xe09f), .driver_info = BTUSB_QCA_ROME |
279e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
280e99f38b8SRocky Liao 	{ USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME |
281e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
282e99f38b8SRocky Liao 	{ USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME |
283e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
284e99f38b8SRocky Liao 	{ USB_DEVICE(0x04ca, 0x3015), .driver_info = BTUSB_QCA_ROME |
285e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
286e99f38b8SRocky Liao 	{ USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME |
287e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
288e99f38b8SRocky Liao 	{ USB_DEVICE(0x04ca, 0x301a), .driver_info = BTUSB_QCA_ROME |
289e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
290e99f38b8SRocky Liao 	{ USB_DEVICE(0x04ca, 0x3021), .driver_info = BTUSB_QCA_ROME |
291e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
292e99f38b8SRocky Liao 	{ USB_DEVICE(0x13d3, 0x3491), .driver_info = BTUSB_QCA_ROME |
293e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
294e99f38b8SRocky Liao 	{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME |
295e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
296e99f38b8SRocky Liao 	{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME |
297e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
2983267c884SKim, Ben Young Tae 
299b40f58b9SRocky Liao 	/* QCA WCN6855 chipset */
300b40f58b9SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
301acd5aea4SMichael Sun 						     BTUSB_WIDEBAND_SPEECH |
302acd5aea4SMichael Sun 						     BTUSB_VALID_LE_STATES },
30321a241b3Stjiang@codeaurora.org 	{ USB_DEVICE(0x0489, 0xe0cc), .driver_info = BTUSB_QCA_WCN6855 |
30421a241b3Stjiang@codeaurora.org 						     BTUSB_WIDEBAND_SPEECH |
30521a241b3Stjiang@codeaurora.org 						     BTUSB_VALID_LE_STATES },
30621a241b3Stjiang@codeaurora.org 	{ USB_DEVICE(0x0489, 0xe0d6), .driver_info = BTUSB_QCA_WCN6855 |
30721a241b3Stjiang@codeaurora.org 						     BTUSB_WIDEBAND_SPEECH |
30821a241b3Stjiang@codeaurora.org 						     BTUSB_VALID_LE_STATES },
309e8c42585SZijun Hu 	{ USB_DEVICE(0x0489, 0xe0e3), .driver_info = BTUSB_QCA_WCN6855 |
310e8c42585SZijun Hu 						     BTUSB_WIDEBAND_SPEECH |
311e8c42585SZijun Hu 						     BTUSB_VALID_LE_STATES },
312d2666be5SZijun Hu 	{ USB_DEVICE(0x10ab, 0x9309), .driver_info = BTUSB_QCA_WCN6855 |
313d2666be5SZijun Hu 						     BTUSB_WIDEBAND_SPEECH |
314d2666be5SZijun Hu 						     BTUSB_VALID_LE_STATES },
315d2666be5SZijun Hu 	{ USB_DEVICE(0x10ab, 0x9409), .driver_info = BTUSB_QCA_WCN6855 |
316d2666be5SZijun Hu 						     BTUSB_WIDEBAND_SPEECH |
317d2666be5SZijun Hu 						     BTUSB_VALID_LE_STATES },
3181cd563ebSAaron Ma 	{ USB_DEVICE(0x0489, 0xe0d0), .driver_info = BTUSB_QCA_WCN6855 |
3191cd563ebSAaron Ma 						     BTUSB_WIDEBAND_SPEECH |
3201cd563ebSAaron Ma 						     BTUSB_VALID_LE_STATES },
321ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9108), .driver_info = BTUSB_QCA_WCN6855 |
322ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
323ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
324ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9109), .driver_info = BTUSB_QCA_WCN6855 |
325ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
326ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
327ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9208), .driver_info = BTUSB_QCA_WCN6855 |
328ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
329ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
330ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9209), .driver_info = BTUSB_QCA_WCN6855 |
331ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
332ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
333ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9308), .driver_info = BTUSB_QCA_WCN6855 |
334ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
335ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
336ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9408), .driver_info = BTUSB_QCA_WCN6855 |
337ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
338ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
339ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9508), .driver_info = BTUSB_QCA_WCN6855 |
340ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
341ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
342ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9509), .driver_info = BTUSB_QCA_WCN6855 |
343ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
344ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
345ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9608), .driver_info = BTUSB_QCA_WCN6855 |
346ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
347ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
348ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9609), .driver_info = BTUSB_QCA_WCN6855 |
349ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
350ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
351ca2a9944SShengyu Qu 	{ USB_DEVICE(0x10ab, 0x9f09), .driver_info = BTUSB_QCA_WCN6855 |
352ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
353ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
354ca2a9944SShengyu Qu 	{ USB_DEVICE(0x04ca, 0x3022), .driver_info = BTUSB_QCA_WCN6855 |
355ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
356ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
357ca2a9944SShengyu Qu 	{ USB_DEVICE(0x0489, 0xe0c7), .driver_info = BTUSB_QCA_WCN6855 |
358ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
359ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
360ca2a9944SShengyu Qu 	{ USB_DEVICE(0x0489, 0xe0c9), .driver_info = BTUSB_QCA_WCN6855 |
361ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
362ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
363ca2a9944SShengyu Qu 	{ USB_DEVICE(0x0489, 0xe0ca), .driver_info = BTUSB_QCA_WCN6855 |
364ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
365ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
366ca2a9944SShengyu Qu 	{ USB_DEVICE(0x0489, 0xe0cb), .driver_info = BTUSB_QCA_WCN6855 |
367ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
368ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
369ca2a9944SShengyu Qu 	{ USB_DEVICE(0x0489, 0xe0ce), .driver_info = BTUSB_QCA_WCN6855 |
370ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
371ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
372ca2a9944SShengyu Qu 	{ USB_DEVICE(0x0489, 0xe0de), .driver_info = BTUSB_QCA_WCN6855 |
373ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
374ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
375ca2a9944SShengyu Qu 	{ USB_DEVICE(0x0489, 0xe0df), .driver_info = BTUSB_QCA_WCN6855 |
376ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
377ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
378ca2a9944SShengyu Qu 	{ USB_DEVICE(0x0489, 0xe0e1), .driver_info = BTUSB_QCA_WCN6855 |
379ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
380ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
381ca2a9944SShengyu Qu 	{ USB_DEVICE(0x0489, 0xe0ea), .driver_info = BTUSB_QCA_WCN6855 |
382ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
383ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
384ca2a9944SShengyu Qu 	{ USB_DEVICE(0x0489, 0xe0ec), .driver_info = BTUSB_QCA_WCN6855 |
385ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
386ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
387ca2a9944SShengyu Qu 	{ USB_DEVICE(0x04ca, 0x3023), .driver_info = BTUSB_QCA_WCN6855 |
388ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
389ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
390ca2a9944SShengyu Qu 	{ USB_DEVICE(0x04ca, 0x3024), .driver_info = BTUSB_QCA_WCN6855 |
391ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
392ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
393ca2a9944SShengyu Qu 	{ USB_DEVICE(0x04ca, 0x3a22), .driver_info = BTUSB_QCA_WCN6855 |
394ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
395ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
396ca2a9944SShengyu Qu 	{ USB_DEVICE(0x04ca, 0x3a24), .driver_info = BTUSB_QCA_WCN6855 |
397ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
398ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
399ca2a9944SShengyu Qu 	{ USB_DEVICE(0x04ca, 0x3a26), .driver_info = BTUSB_QCA_WCN6855 |
400ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
401ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
402ca2a9944SShengyu Qu 	{ USB_DEVICE(0x04ca, 0x3a27), .driver_info = BTUSB_QCA_WCN6855 |
403ca2a9944SShengyu Qu 						     BTUSB_WIDEBAND_SPEECH |
404ca2a9944SShengyu Qu 						     BTUSB_VALID_LE_STATES },
405b40f58b9SRocky Liao 
40646225947SZijun Hu 	/* QCA WCN785x chipset */
40746225947SZijun Hu 	{ USB_DEVICE(0x0cf3, 0xe700), .driver_info = BTUSB_QCA_WCN6855 |
40846225947SZijun Hu 						     BTUSB_WIDEBAND_SPEECH |
40946225947SZijun Hu 						     BTUSB_VALID_LE_STATES },
41046225947SZijun Hu 
411cfeb4145SMarcel Holtmann 	/* Broadcom BCM2035 */
4127a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
4130b880062SAndy Shevchenko 	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
4140b880062SAndy Shevchenko 	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
415cfeb4145SMarcel Holtmann 
416cfeb4145SMarcel Holtmann 	/* Broadcom BCM2045 */
4177a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
4187a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_WRONG_SCO_MTU },
419bdbef3d6SMarcel Holtmann 
420cfeb4145SMarcel Holtmann 	/* IBM/Lenovo ThinkPad with Broadcom chip */
4217a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_WRONG_SCO_MTU },
4227a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_WRONG_SCO_MTU },
423cfeb4145SMarcel Holtmann 
424cfeb4145SMarcel Holtmann 	/* HP laptop with Broadcom chip */
4257a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x03f0, 0x171d), .driver_info = BTUSB_WRONG_SCO_MTU },
426cfeb4145SMarcel Holtmann 
427cfeb4145SMarcel Holtmann 	/* Dell laptop with Broadcom chip */
4287a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x413c, 0x8126), .driver_info = BTUSB_WRONG_SCO_MTU },
429cfeb4145SMarcel Holtmann 
4305ddd4a60SMarcel Holtmann 	/* Dell Wireless 370 and 410 devices */
4317a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x413c, 0x8152), .driver_info = BTUSB_WRONG_SCO_MTU },
4325ddd4a60SMarcel Holtmann 	{ USB_DEVICE(0x413c, 0x8156), .driver_info = BTUSB_WRONG_SCO_MTU },
433cfeb4145SMarcel Holtmann 
4347a9d4020SMarcel Holtmann 	/* Belkin F8T012 and F8T013 devices */
4357a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_WRONG_SCO_MTU },
4367a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_WRONG_SCO_MTU },
437cfeb4145SMarcel Holtmann 
4385ddd4a60SMarcel Holtmann 	/* Asus WL-BTD202 device */
4395ddd4a60SMarcel Holtmann 	{ USB_DEVICE(0x0b05, 0x1715), .driver_info = BTUSB_WRONG_SCO_MTU },
4405ddd4a60SMarcel Holtmann 
4415ddd4a60SMarcel Holtmann 	/* Kensington Bluetooth USB adapter */
4425ddd4a60SMarcel Holtmann 	{ USB_DEVICE(0x047d, 0x105e), .driver_info = BTUSB_WRONG_SCO_MTU },
4435ddd4a60SMarcel Holtmann 
444cfeb4145SMarcel Holtmann 	/* RTX Telecom based adapters with buggy SCO support */
445cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x0400, 0x0807), .driver_info = BTUSB_BROKEN_ISOC },
446cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x0400, 0x080a), .driver_info = BTUSB_BROKEN_ISOC },
447cfeb4145SMarcel Holtmann 
448cfeb4145SMarcel Holtmann 	/* CONWISE Technology based adapters with buggy SCO support */
449418678b0SSzymon Janc 	{ USB_DEVICE(0x0e5e, 0x6622),
450418678b0SSzymon Janc 	  .driver_info = BTUSB_BROKEN_ISOC | BTUSB_CW6622},
451cfeb4145SMarcel Holtmann 
4524fcef8edSMarcel Holtmann 	/* Roper Class 1 Bluetooth Dongle (Silicon Wave based) */
4532eeac871SAleksei Volkov 	{ USB_DEVICE(0x1310, 0x0001), .driver_info = BTUSB_SWAVE },
4544fcef8edSMarcel Holtmann 
455cfeb4145SMarcel Holtmann 	/* Digianswer devices */
456cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
457cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
458cfeb4145SMarcel Holtmann 
459cfeb4145SMarcel Holtmann 	/* CSR BlueCore Bluetooth Sniffer */
4604f64fa80SMarcel Holtmann 	{ USB_DEVICE(0x0a12, 0x0002),
4614f64fa80SMarcel Holtmann 	  .driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
462cfeb4145SMarcel Holtmann 
463cfeb4145SMarcel Holtmann 	/* Frontline ComProbe Bluetooth Sniffer */
4644f64fa80SMarcel Holtmann 	{ USB_DEVICE(0x16d3, 0x0002),
4654f64fa80SMarcel Holtmann 	  .driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
466cfeb4145SMarcel Holtmann 
467cb1ee89fSMarcel Holtmann 	/* Marvell Bluetooth devices */
468cb1ee89fSMarcel Holtmann 	{ USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL },
469cb1ee89fSMarcel Holtmann 	{ USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
4701165df0eSAmitkumar Karwar 	{ USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL },
471cb1ee89fSMarcel Holtmann 
472d0ac9eb7SMarcel Holtmann 	/* Intel Bluetooth devices */
4733df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_COMBINED },
4743df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_COMBINED },
4753df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_COMBINED },
4763df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_COMBINED },
4773df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED },
4782ca57c80SKiran K 	{ USB_DEVICE(0x8087, 0x0035), .driver_info = BTUSB_INTEL_COMBINED },
479999a8a6bSKiran K 	{ USB_DEVICE(0x8087, 0x0036), .driver_info = BTUSB_INTEL_COMBINED },
480407550feSMarcel Holtmann 	{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
481ea7c4c0eSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
48255235304STedd Ho-Jeong An 						     BTUSB_INTEL_NO_WBS_SUPPORT |
48395655456STedd Ho-Jeong An 						     BTUSB_INTEL_BROKEN_INITIAL_NCMD |
48495655456STedd Ho-Jeong An 						     BTUSB_INTEL_BROKEN_SHUTDOWN_LED },
48595655456STedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED |
48655235304STedd Ho-Jeong An 						     BTUSB_INTEL_NO_WBS_SUPPORT |
48795655456STedd Ho-Jeong An 						     BTUSB_INTEL_BROKEN_SHUTDOWN_LED },
4883df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_COMBINED },
48995655456STedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED |
49095655456STedd Ho-Jeong An 						     BTUSB_INTEL_BROKEN_SHUTDOWN_LED },
4913df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_COMBINED },
492dffd30eeSTedd Ho-Jeong An 
493d0ac9eb7SMarcel Holtmann 	/* Other Intel Bluetooth devices */
494d0ac9eb7SMarcel Holtmann 	{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
495d0ac9eb7SMarcel Holtmann 	  .driver_info = BTUSB_IGNORE },
496ae8df494SAmitkumar Karwar 
4971eec3b95SMoises Cardona 	/* Realtek 8821CE Bluetooth devices */
4981eec3b95SMoises Cardona 	{ USB_DEVICE(0x13d3, 0x3529), .driver_info = BTUSB_REALTEK |
4991eec3b95SMoises Cardona 						     BTUSB_WIDEBAND_SPEECH },
5001eec3b95SMoises Cardona 
50133bfd94aSJoseph Hwang 	/* Realtek 8822CE Bluetooth devices */
50233bfd94aSJoseph Hwang 	{ USB_DEVICE(0x0bda, 0xb00c), .driver_info = BTUSB_REALTEK |
50333bfd94aSJoseph Hwang 						     BTUSB_WIDEBAND_SPEECH },
5044d96d3b0SLarry Finger 	{ USB_DEVICE(0x0bda, 0xc822), .driver_info = BTUSB_REALTEK |
5054d96d3b0SLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
50633bfd94aSJoseph Hwang 
5076d0a4fe2SGongwei Li 	/* Realtek 8822CU Bluetooth devices */
5086d0a4fe2SGongwei Li 	{ USB_DEVICE(0x13d3, 0x3549), .driver_info = BTUSB_REALTEK |
5096d0a4fe2SGongwei Li 						     BTUSB_WIDEBAND_SPEECH },
5106d0a4fe2SGongwei Li 
5110d484db6SMax Chou 	/* Realtek 8852AE Bluetooth devices */
5122e7b4a32SLarry Finger 	{ USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK |
5132e7b4a32SLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
5140d484db6SMax Chou 	{ USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK |
5150d484db6SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
51627fe097bSLarry Finger 	{ USB_DEVICE(0x0bda, 0x385a), .driver_info = BTUSB_REALTEK |
51727fe097bSLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
518d1dcbf61SLarry Finger 	{ USB_DEVICE(0x0bda, 0x4852), .driver_info = BTUSB_REALTEK |
519d1dcbf61SLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
5209bba1286SMax Chou 	{ USB_DEVICE(0x04c5, 0x165c), .driver_info = BTUSB_REALTEK |
5219bba1286SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
522d1dcbf61SLarry Finger 	{ USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK |
523d1dcbf61SLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
524a0476f6aSLarry Finger 	{ USB_DEVICE(0x0cb8, 0xc549), .driver_info = BTUSB_REALTEK |
525a0476f6aSLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
5260d484db6SMax Chou 
527c379c96cSHilda Wu 	/* Realtek 8852CE Bluetooth devices */
528c379c96cSHilda Wu 	{ USB_DEVICE(0x04ca, 0x4007), .driver_info = BTUSB_REALTEK |
529c379c96cSHilda Wu 						     BTUSB_WIDEBAND_SPEECH },
530893fa8bcSHilda Wu 	{ USB_DEVICE(0x04c5, 0x1675), .driver_info = BTUSB_REALTEK |
531893fa8bcSHilda Wu 						     BTUSB_WIDEBAND_SPEECH },
5325b75ee37SHilda Wu 	{ USB_DEVICE(0x0cb8, 0xc558), .driver_info = BTUSB_REALTEK |
5335b75ee37SHilda Wu 						     BTUSB_WIDEBAND_SPEECH },
5348f0054ddSHilda Wu 	{ USB_DEVICE(0x13d3, 0x3587), .driver_info = BTUSB_REALTEK |
5358f0054ddSHilda Wu 						     BTUSB_WIDEBAND_SPEECH },
5366ad353dfSHilda Wu 	{ USB_DEVICE(0x13d3, 0x3586), .driver_info = BTUSB_REALTEK |
5376ad353dfSHilda Wu 						     BTUSB_WIDEBAND_SPEECH },
538c4ba5800SMax Chou 	{ USB_DEVICE(0x13d3, 0x3592), .driver_info = BTUSB_REALTEK |
539c4ba5800SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
54018ed567aSHilda Wu 	{ USB_DEVICE(0x0489, 0xe122), .driver_info = BTUSB_REALTEK |
54118ed567aSHilda Wu 						     BTUSB_WIDEBAND_SPEECH },
542c379c96cSHilda Wu 
543393b4916SArtem Lukyanov 	/* Realtek 8852BE Bluetooth devices */
544393b4916SArtem Lukyanov 	{ USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
545393b4916SArtem Lukyanov 						     BTUSB_WIDEBAND_SPEECH },
546e0813f22SWangYuli 	{ USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK |
547e0813f22SWangYuli 						     BTUSB_WIDEBAND_SPEECH },
548730a1d1aSLarry Finger 	{ USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
549730a1d1aSLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
550ac6d4cd9SGuan Wentao 	{ USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
551ac6d4cd9SGuan Wentao 						     BTUSB_WIDEBAND_SPEECH },
55203ec9c28SMasum Reza 	{ USB_DEVICE(0x13d3, 0x3570), .driver_info = BTUSB_REALTEK |
55303ec9c28SMasum Reza 						     BTUSB_WIDEBAND_SPEECH },
554069f5342SLarry Finger 	{ USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK |
555069f5342SLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
55634e4dfe8SWangYuli 	{ USB_DEVICE(0x13d3, 0x3591), .driver_info = BTUSB_REALTEK |
55734e4dfe8SWangYuli 						     BTUSB_WIDEBAND_SPEECH },
55836af5758SHilda Wu 	{ USB_DEVICE(0x0489, 0xe123), .driver_info = BTUSB_REALTEK |
55936af5758SHilda Wu 						     BTUSB_WIDEBAND_SPEECH },
560499ca9ddSHilda Wu 	{ USB_DEVICE(0x0489, 0xe125), .driver_info = BTUSB_REALTEK |
561499ca9ddSHilda Wu 						     BTUSB_WIDEBAND_SPEECH },
562393b4916SArtem Lukyanov 
563a2698a9bSDaniel Drake 	/* Realtek Bluetooth devices */
564a2698a9bSDaniel Drake 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
565a2698a9bSDaniel Drake 	  .driver_info = BTUSB_REALTEK },
566a2698a9bSDaniel Drake 
567a1c49c43SSean Wang 	/* MediaTek Bluetooth devices */
568a1c49c43SSean Wang 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0e8d, 0xe0, 0x01, 0x01),
56927e554a4Smark-yw.chen 	  .driver_info = BTUSB_MEDIATEK |
57027e554a4Smark-yw.chen 			 BTUSB_WIDEBAND_SPEECH |
57127e554a4Smark-yw.chen 			 BTUSB_VALID_LE_STATES },
572a1c49c43SSean Wang 
5733a567b95SChris Chiu 	/* Additional MediaTek MT7615E Bluetooth devices */
5743a567b95SChris Chiu 	{ USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK},
5753a567b95SChris Chiu 
576467e98cdSPiotr Dymacz 	/* Additional MediaTek MT7663 Bluetooth devices */
577467e98cdSPiotr Dymacz 	{ USB_DEVICE(0x043e, 0x310c), .driver_info = BTUSB_MEDIATEK |
578467e98cdSPiotr Dymacz 						     BTUSB_WIDEBAND_SPEECH |
579467e98cdSPiotr Dymacz 						     BTUSB_VALID_LE_STATES },
58013209415SMeng Tang 	{ USB_DEVICE(0x04ca, 0x3801), .driver_info = BTUSB_MEDIATEK |
58113209415SMeng Tang 						     BTUSB_WIDEBAND_SPEECH |
58213209415SMeng Tang 						     BTUSB_VALID_LE_STATES },
583467e98cdSPiotr Dymacz 
58437356827SForest Crossman 	/* Additional MediaTek MT7668 Bluetooth devices */
58537356827SForest Crossman 	{ USB_DEVICE(0x043e, 0x3109), .driver_info = BTUSB_MEDIATEK |
58637356827SForest Crossman 						     BTUSB_WIDEBAND_SPEECH |
58737356827SForest Crossman 						     BTUSB_VALID_LE_STATES },
58837356827SForest Crossman 
589393dc5d1Smark-yw.chen 	/* Additional MediaTek MT7921 Bluetooth devices */
59023fcb27bSSean Wang 	{ USB_DEVICE(0x0489, 0xe0c8), .driver_info = BTUSB_MEDIATEK |
59123fcb27bSSean Wang 						     BTUSB_WIDEBAND_SPEECH |
59223fcb27bSSean Wang 						     BTUSB_VALID_LE_STATES },
5937ac7267fSFae 	{ USB_DEVICE(0x0489, 0xe0e0), .driver_info = BTUSB_MEDIATEK |
5947ac7267fSFae 						     BTUSB_WIDEBAND_SPEECH |
5957ac7267fSFae 						     BTUSB_VALID_LE_STATES },
59683458a5fSMario Limonciello 	{ USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK |
59783458a5fSMario Limonciello 						     BTUSB_WIDEBAND_SPEECH |
59883458a5fSMario Limonciello 						     BTUSB_VALID_LE_STATES },
599393dc5d1Smark-yw.chen 	{ USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK |
600393dc5d1Smark-yw.chen 						     BTUSB_WIDEBAND_SPEECH |
601393dc5d1Smark-yw.chen 						     BTUSB_VALID_LE_STATES },
6022cdff8caSWai Paulo Valerio Wang 	{ USB_DEVICE(0x13d3, 0x3563), .driver_info = BTUSB_MEDIATEK |
6032cdff8caSWai Paulo Valerio Wang 						     BTUSB_WIDEBAND_SPEECH |
6042cdff8caSWai Paulo Valerio Wang 						     BTUSB_VALID_LE_STATES },
60515957cabSmark-yw.chen 	{ USB_DEVICE(0x13d3, 0x3564), .driver_info = BTUSB_MEDIATEK |
60615957cabSmark-yw.chen 						     BTUSB_WIDEBAND_SPEECH |
60715957cabSmark-yw.chen 						     BTUSB_VALID_LE_STATES },
608c5e25bb5SYake Yang 	{ USB_DEVICE(0x13d3, 0x3567), .driver_info = BTUSB_MEDIATEK |
609c5e25bb5SYake Yang 						     BTUSB_WIDEBAND_SPEECH |
610c5e25bb5SYake Yang 						     BTUSB_VALID_LE_STATES },
611a614ee94SChris Lu 	{ USB_DEVICE(0x13d3, 0x3578), .driver_info = BTUSB_MEDIATEK |
612a614ee94SChris Lu 						     BTUSB_WIDEBAND_SPEECH |
613a614ee94SChris Lu 						     BTUSB_VALID_LE_STATES },
614f0ad26eeSSean Wang 	{ USB_DEVICE(0x13d3, 0x3583), .driver_info = BTUSB_MEDIATEK |
615f0ad26eeSSean Wang 						     BTUSB_WIDEBAND_SPEECH |
616f0ad26eeSSean Wang 						     BTUSB_VALID_LE_STATES },
61764832df2SAaron Ma 	{ USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK |
61864832df2SAaron Ma 						     BTUSB_WIDEBAND_SPEECH |
61964832df2SAaron Ma 						     BTUSB_VALID_LE_STATES },
620be55622cSDaniel Golle 	{ USB_DEVICE(0x0e8d, 0x0608), .driver_info = BTUSB_MEDIATEK |
621be55622cSDaniel Golle 						     BTUSB_WIDEBAND_SPEECH |
622be55622cSDaniel Golle 						     BTUSB_VALID_LE_STATES },
623f8a67ffbSJiande Lu 	{ USB_DEVICE(0x13d3, 0x3606), .driver_info = BTUSB_MEDIATEK |
624f8a67ffbSJiande Lu 						     BTUSB_WIDEBAND_SPEECH |
625f8a67ffbSJiande Lu 						     BTUSB_VALID_LE_STATES },
626393dc5d1Smark-yw.chen 
62769326274SAaron Ma 	/* MediaTek MT7922A Bluetooth devices */
62869326274SAaron Ma 	{ USB_DEVICE(0x0489, 0xe0d8), .driver_info = BTUSB_MEDIATEK |
62969326274SAaron Ma 						     BTUSB_WIDEBAND_SPEECH |
63069326274SAaron Ma 						     BTUSB_VALID_LE_STATES },
63169326274SAaron Ma 	{ USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK |
63269326274SAaron Ma 						     BTUSB_WIDEBAND_SPEECH |
63369326274SAaron Ma 						     BTUSB_VALID_LE_STATES },
634fa01eba1SMatthew Anderson 	{ USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK |
635fa01eba1SMatthew Anderson 						     BTUSB_WIDEBAND_SPEECH |
636fa01eba1SMatthew Anderson 						     BTUSB_VALID_LE_STATES },
637c69ecb0eSAaron Ma 	{ USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK |
638c69ecb0eSAaron Ma 						     BTUSB_WIDEBAND_SPEECH |
639c69ecb0eSAaron Ma 						     BTUSB_VALID_LE_STATES },
64057117d72SHe Wang 	{ USB_DEVICE(0x0489, 0xe0e2), .driver_info = BTUSB_MEDIATEK |
64157117d72SHe Wang 						     BTUSB_WIDEBAND_SPEECH |
64257117d72SHe Wang 						     BTUSB_VALID_LE_STATES },
643125ede3aSMeng Tang 	{ USB_DEVICE(0x0489, 0xe0e4), .driver_info = BTUSB_MEDIATEK |
644125ede3aSMeng Tang 						     BTUSB_WIDEBAND_SPEECH |
645125ede3aSMeng Tang 						     BTUSB_VALID_LE_STATES },
6460cefdaedSRoger Gammans 	{ USB_DEVICE(0x0489, 0xe0f1), .driver_info = BTUSB_MEDIATEK |
6470cefdaedSRoger Gammans 						     BTUSB_WIDEBAND_SPEECH |
6480cefdaedSRoger Gammans 						     BTUSB_VALID_LE_STATES },
64913fcc94dSAndy Chi 	{ USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK |
65013fcc94dSAndy Chi 						     BTUSB_WIDEBAND_SPEECH |
65113fcc94dSAndy Chi 						     BTUSB_VALID_LE_STATES },
652e160a8f4SValentin David 	{ USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK |
653e160a8f4SValentin David 						     BTUSB_WIDEBAND_SPEECH |
654e160a8f4SValentin David 						     BTUSB_VALID_LE_STATES },
655b6cfa1c2SChris Lu 	{ USB_DEVICE(0x0489, 0xe0f6), .driver_info = BTUSB_MEDIATEK |
656b6cfa1c2SChris Lu 						     BTUSB_WIDEBAND_SPEECH |
657b6cfa1c2SChris Lu 						     BTUSB_VALID_LE_STATES },
658bf809efdSChris Lu 	{ USB_DEVICE(0x0489, 0xe102), .driver_info = BTUSB_MEDIATEK |
659bf809efdSChris Lu 						     BTUSB_WIDEBAND_SPEECH |
660bf809efdSChris Lu 						     BTUSB_VALID_LE_STATES },
66159be4be8SChris Lu 	{ USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
66259be4be8SChris Lu 						     BTUSB_WIDEBAND_SPEECH |
66359be4be8SChris Lu 						     BTUSB_VALID_LE_STATES },
664e612c16eSJingyang Wang 	{ USB_DEVICE(0x35f5, 0x7922), .driver_info = BTUSB_MEDIATEK |
665e612c16eSJingyang Wang 						     BTUSB_WIDEBAND_SPEECH |
666e612c16eSJingyang Wang 						     BTUSB_VALID_LE_STATES },
667f8a67ffbSJiande Lu 	{ USB_DEVICE(0x13d3, 0x3614), .driver_info = BTUSB_MEDIATEK |
668f8a67ffbSJiande Lu 						     BTUSB_WIDEBAND_SPEECH |
669f8a67ffbSJiande Lu 						     BTUSB_VALID_LE_STATES },
670f8a67ffbSJiande Lu 	{ USB_DEVICE(0x13d3, 0x3615), .driver_info = BTUSB_MEDIATEK |
671f8a67ffbSJiande Lu 						     BTUSB_WIDEBAND_SPEECH |
672f8a67ffbSJiande Lu 						     BTUSB_VALID_LE_STATES },
673f8a67ffbSJiande Lu 	{ USB_DEVICE(0x04ca, 0x38e4), .driver_info = BTUSB_MEDIATEK |
674f8a67ffbSJiande Lu 						     BTUSB_WIDEBAND_SPEECH |
675f8a67ffbSJiande Lu 						     BTUSB_VALID_LE_STATES },
676f8a67ffbSJiande Lu 	{ USB_DEVICE(0x13d3, 0x3605), .driver_info = BTUSB_MEDIATEK |
677f8a67ffbSJiande Lu 						     BTUSB_WIDEBAND_SPEECH |
678f8a67ffbSJiande Lu 						     BTUSB_VALID_LE_STATES },
679f8a67ffbSJiande Lu 	{ USB_DEVICE(0x13d3, 0x3607), .driver_info = BTUSB_MEDIATEK |
680f8a67ffbSJiande Lu 						     BTUSB_WIDEBAND_SPEECH |
681f8a67ffbSJiande Lu 						     BTUSB_VALID_LE_STATES },
68269326274SAaron Ma 
6831e7b1a8eSUlrik Strid 	/* Additional MediaTek MT7925 Bluetooth devices */
6844f4fe3dbSHao Qin 	{ USB_DEVICE(0x0489, 0xe111), .driver_info = BTUSB_MEDIATEK |
6854f4fe3dbSHao Qin 						     BTUSB_WIDEBAND_SPEECH },
686f8a67ffbSJiande Lu 	{ USB_DEVICE(0x0489, 0xe113), .driver_info = BTUSB_MEDIATEK |
687f8a67ffbSJiande Lu 						     BTUSB_WIDEBAND_SPEECH |
688f8a67ffbSJiande Lu 						     BTUSB_VALID_LE_STATES },
6891e7b1a8eSUlrik Strid 	{ USB_DEVICE(0x13d3, 0x3602), .driver_info = BTUSB_MEDIATEK |
6901e7b1a8eSUlrik Strid 						     BTUSB_WIDEBAND_SPEECH |
6911e7b1a8eSUlrik Strid 						     BTUSB_VALID_LE_STATES },
692f8a67ffbSJiande Lu 	{ USB_DEVICE(0x13d3, 0x3603), .driver_info = BTUSB_MEDIATEK |
693f8a67ffbSJiande Lu 						     BTUSB_WIDEBAND_SPEECH |
694f8a67ffbSJiande Lu 						     BTUSB_VALID_LE_STATES },
6951e7b1a8eSUlrik Strid 
696a2698a9bSDaniel Drake 	/* Additional Realtek 8723AE Bluetooth devices */
697a2698a9bSDaniel Drake 	{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
698a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3394), .driver_info = BTUSB_REALTEK },
699a2698a9bSDaniel Drake 
700a2698a9bSDaniel Drake 	/* Additional Realtek 8723BE Bluetooth devices */
701a2698a9bSDaniel Drake 	{ USB_DEVICE(0x0489, 0xe085), .driver_info = BTUSB_REALTEK },
702a2698a9bSDaniel Drake 	{ USB_DEVICE(0x0489, 0xe08b), .driver_info = BTUSB_REALTEK },
703cc68a041STakashi Iwai 	{ USB_DEVICE(0x04f2, 0xb49f), .driver_info = BTUSB_REALTEK },
704a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
705a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
706a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
707a81d72d2SDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK },
708a2698a9bSDaniel Drake 
709a41e0796SVicente Bergas 	/* Additional Realtek 8723BU Bluetooth devices */
710a41e0796SVicente Bergas 	{ USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
711a41e0796SVicente Bergas 
71266d9975cSJian-Hong Pan 	/* Additional Realtek 8723DE Bluetooth devices */
71345ae68b8SJian-Hong Pan 	{ USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK },
71466d9975cSJian-Hong Pan 	{ USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK },
71566d9975cSJian-Hong Pan 
716d8daa399SSzabolcs Sipos 	/* Additional Realtek 8761BUV Bluetooth devices */
7174fd6d490SNicholas Flintham 	{ USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK |
7184fd6d490SNicholas Flintham 						     BTUSB_WIDEBAND_SPEECH },
71933404381SJoakim Tjernlund 	{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
72033404381SJoakim Tjernlund 	  					     BTUSB_WIDEBAND_SPEECH },
7216dfbe29fSHelmut Grohne 	{ USB_DEVICE(0x2550, 0x8761), .driver_info = BTUSB_REALTEK |
7226dfbe29fSHelmut Grohne 						     BTUSB_WIDEBAND_SPEECH },
723c77a592bSIsmael Luceno 	{ USB_DEVICE(0x0bda, 0x8771), .driver_info = BTUSB_REALTEK |
724c77a592bSIsmael Luceno 						     BTUSB_WIDEBAND_SPEECH },
725022b6101SDan Gora 	{ USB_DEVICE(0x6655, 0x8771), .driver_info = BTUSB_REALTEK |
726022b6101SDan Gora 						     BTUSB_WIDEBAND_SPEECH },
727c7577014SSzabolcs Sipos 	{ USB_DEVICE(0x7392, 0xc611), .driver_info = BTUSB_REALTEK |
728c7577014SSzabolcs Sipos 						     BTUSB_WIDEBAND_SPEECH },
729ac09bb3fSRaman Varabets 	{ USB_DEVICE(0x2b89, 0x8761), .driver_info = BTUSB_REALTEK |
730ac09bb3fSRaman Varabets 						     BTUSB_WIDEBAND_SPEECH },
731c77a592bSIsmael Luceno 
732a2698a9bSDaniel Drake 	/* Additional Realtek 8821AE Bluetooth devices */
733a2698a9bSDaniel Drake 	{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
734a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
735a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3458), .driver_info = BTUSB_REALTEK },
736a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK },
737a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
738a2698a9bSDaniel Drake 
739fed03fe7SLarry Finger 	/* Additional Realtek 8822BE Bluetooth devices */
7401cd2fabfSArtiom Vaskov 	{ USB_DEVICE(0x13d3, 0x3526), .driver_info = BTUSB_REALTEK },
741fed03fe7SLarry Finger 	{ USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK },
742fed03fe7SLarry Finger 
7436d0762b1SJian-Hong Pan 	/* Additional Realtek 8822CE Bluetooth devices */
74473280f13SMax Chou 	{ USB_DEVICE(0x04ca, 0x4005), .driver_info = BTUSB_REALTEK |
74573280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
74673280f13SMax Chou 	{ USB_DEVICE(0x04c5, 0x161f), .driver_info = BTUSB_REALTEK |
74773280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
74873280f13SMax Chou 	{ USB_DEVICE(0x0b05, 0x18ef), .driver_info = BTUSB_REALTEK |
74973280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
75073280f13SMax Chou 	{ USB_DEVICE(0x13d3, 0x3548), .driver_info = BTUSB_REALTEK |
75173280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
75273280f13SMax Chou 	{ USB_DEVICE(0x13d3, 0x3549), .driver_info = BTUSB_REALTEK |
75373280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
75473280f13SMax Chou 	{ USB_DEVICE(0x13d3, 0x3553), .driver_info = BTUSB_REALTEK |
75573280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
75673280f13SMax Chou 	{ USB_DEVICE(0x13d3, 0x3555), .driver_info = BTUSB_REALTEK |
75773280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
75873280f13SMax Chou 	{ USB_DEVICE(0x2ff8, 0x3051), .driver_info = BTUSB_REALTEK |
75973280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
760f496297eSJulian Pidancet 	{ USB_DEVICE(0x1358, 0xc123), .driver_info = BTUSB_REALTEK |
761f496297eSJulian Pidancet 						     BTUSB_WIDEBAND_SPEECH },
76224d6a6d2SCadel Watson 	{ USB_DEVICE(0x0bda, 0xc123), .driver_info = BTUSB_REALTEK |
76324d6a6d2SCadel Watson 						     BTUSB_WIDEBAND_SPEECH },
7643edc5782SRasmus Moorats 	{ USB_DEVICE(0x0cb5, 0xc547), .driver_info = BTUSB_REALTEK |
7653edc5782SRasmus Moorats 						     BTUSB_WIDEBAND_SPEECH },
7666d0762b1SJian-Hong Pan 
7675d44f76fSMarcel Holtmann 	/* Actions Semiconductor ATS2851 based devices */
7685d44f76fSMarcel Holtmann 	{ USB_DEVICE(0x10d7, 0xb012), .driver_info = BTUSB_ACTIONS_SEMI },
7695d44f76fSMarcel Holtmann 
7704481c076SPeter Poklop 	/* Silicon Wave based devices */
7714481c076SPeter Poklop 	{ USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
7724481c076SPeter Poklop 
7735e23b923SMarcel Holtmann 	{ }	/* Terminating entry */
7745e23b923SMarcel Holtmann };
7755e23b923SMarcel Holtmann 
7761fdb9269SHans de Goede /* The Bluetooth USB module build into some devices needs to be reset on resume,
7771fdb9269SHans de Goede  * this is a problem with the platform (likely shutting off all power) not with
7781fdb9269SHans de Goede  * the module itself. So we use a DMI list to match known broken platforms.
7791fdb9269SHans de Goede  */
7801fdb9269SHans de Goede static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
7811fdb9269SHans de Goede 	{
7820c6e5266SKai-Heng Feng 		/* Dell OptiPlex 3060 (QCA ROME device 0cf3:e007) */
7831fdb9269SHans de Goede 		.matches = {
7840c6e5266SKai-Heng Feng 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
7850c6e5266SKai-Heng Feng 			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 3060"),
7861fdb9269SHans de Goede 		},
7871fdb9269SHans de Goede 	},
788596b07a9SHans de Goede 	{
789596b07a9SHans de Goede 		/* Dell XPS 9360 (QCA ROME device 0cf3:e300) */
790596b07a9SHans de Goede 		.matches = {
791596b07a9SHans de Goede 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
792596b07a9SHans de Goede 			DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"),
793596b07a9SHans de Goede 		},
794596b07a9SHans de Goede 	},
795939bc6c5SHans de Goede 	{
796939bc6c5SHans de Goede 		/* Dell Inspiron 5565 (QCA ROME device 0cf3:e009) */
797939bc6c5SHans de Goede 		.matches = {
798939bc6c5SHans de Goede 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
799939bc6c5SHans de Goede 			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5565"),
800939bc6c5SHans de Goede 		},
801939bc6c5SHans de Goede 	},
8021fdb9269SHans de Goede 	{}
8031fdb9269SHans de Goede };
8041fdb9269SHans de Goede 
80520981ce2STim Jiang struct qca_dump_info {
80620981ce2STim Jiang 	/* fields for dump collection */
80720981ce2STim Jiang 	u16 id_vendor;
80820981ce2STim Jiang 	u16 id_product;
80920981ce2STim Jiang 	u32 fw_version;
81020981ce2STim Jiang 	u32 controller_id;
81120981ce2STim Jiang 	u32 ram_dump_size;
81220981ce2STim Jiang 	u16 ram_dump_seqno;
81320981ce2STim Jiang };
81420981ce2STim Jiang 
8159bfa35feSMarcel Holtmann #define BTUSB_MAX_ISOC_FRAMES	10
8169bfa35feSMarcel Holtmann 
8175e23b923SMarcel Holtmann #define BTUSB_INTR_RUNNING	0
8185e23b923SMarcel Holtmann #define BTUSB_BULK_RUNNING	1
8199bfa35feSMarcel Holtmann #define BTUSB_ISOC_RUNNING	2
8207bee549eSOliver Neukum #define BTUSB_SUSPENDING	3
82108b8b6c4SGustavo F. Padovan #define BTUSB_DID_ISO_RESUME	4
822cda0dd78SMarcel Holtmann #define BTUSB_BOOTLOADER	5
823cda0dd78SMarcel Holtmann #define BTUSB_DOWNLOADING	6
824ce6bb929SMarcel Holtmann #define BTUSB_FIRMWARE_LOADED	7
825cda0dd78SMarcel Holtmann #define BTUSB_FIRMWARE_FAILED	8
826ce6bb929SMarcel Holtmann #define BTUSB_BOOTING		9
82761f5aceaSHans de Goede #define BTUSB_DIAG_RUNNING	10
82861f5aceaSHans de Goede #define BTUSB_OOB_WAKE_ENABLED	11
829dc786b2cSRajat Jain #define BTUSB_HW_RESET_ACTIVE	12
830a1c49c43SSean Wang #define BTUSB_TX_WAIT_VND_EVT	13
8318274db07SMax Chou #define BTUSB_WAKEUP_AUTOSUSPEND	14
83255981d35SPauli Virtanen #define BTUSB_USE_ALT3_FOR_WBS	15
833a479e713SHilda Wu #define BTUSB_ALT6_CONTINUOUS_TX	16
83420981ce2STim Jiang #define BTUSB_HW_SSR_ACTIVE	17
8355e23b923SMarcel Holtmann 
8365e23b923SMarcel Holtmann struct btusb_data {
8375e23b923SMarcel Holtmann 	struct hci_dev       *hdev;
8385e23b923SMarcel Holtmann 	struct usb_device    *udev;
8395fbcd260SMarcel Holtmann 	struct usb_interface *intf;
8409bfa35feSMarcel Holtmann 	struct usb_interface *isoc;
8419d08f504SMarcel Holtmann 	struct usb_interface *diag;
842459232fcSMarcel Holtmann 	unsigned isoc_ifnum;
8435e23b923SMarcel Holtmann 
8445e23b923SMarcel Holtmann 	unsigned long flags;
8455e23b923SMarcel Holtmann 
846800fe5ecSLuiz Augusto von Dentz 	bool poll_sync;
847800fe5ecSLuiz Augusto von Dentz 	int intr_interval;
8485e23b923SMarcel Holtmann 	struct work_struct  work;
8497bee549eSOliver Neukum 	struct work_struct  waker;
850800fe5ecSLuiz Augusto von Dentz 	struct delayed_work rx_work;
851800fe5ecSLuiz Augusto von Dentz 
852800fe5ecSLuiz Augusto von Dentz 	struct sk_buff_head acl_q;
8535e23b923SMarcel Holtmann 
854803b5836SMarcel Holtmann 	struct usb_anchor deferred;
8555e23b923SMarcel Holtmann 	struct usb_anchor tx_anchor;
856803b5836SMarcel Holtmann 	int tx_in_flight;
857803b5836SMarcel Holtmann 	spinlock_t txlock;
858803b5836SMarcel Holtmann 
8595e23b923SMarcel Holtmann 	struct usb_anchor intr_anchor;
8605e23b923SMarcel Holtmann 	struct usb_anchor bulk_anchor;
8619bfa35feSMarcel Holtmann 	struct usb_anchor isoc_anchor;
8629d08f504SMarcel Holtmann 	struct usb_anchor diag_anchor;
863a1c49c43SSean Wang 	struct usb_anchor ctrl_anchor;
864803b5836SMarcel Holtmann 	spinlock_t rxlock;
865803b5836SMarcel Holtmann 
866803b5836SMarcel Holtmann 	struct sk_buff *evt_skb;
867803b5836SMarcel Holtmann 	struct sk_buff *acl_skb;
868803b5836SMarcel Holtmann 	struct sk_buff *sco_skb;
8695e23b923SMarcel Holtmann 
8705e23b923SMarcel Holtmann 	struct usb_endpoint_descriptor *intr_ep;
8715e23b923SMarcel Holtmann 	struct usb_endpoint_descriptor *bulk_tx_ep;
8725e23b923SMarcel Holtmann 	struct usb_endpoint_descriptor *bulk_rx_ep;
8739bfa35feSMarcel Holtmann 	struct usb_endpoint_descriptor *isoc_tx_ep;
8749bfa35feSMarcel Holtmann 	struct usb_endpoint_descriptor *isoc_rx_ep;
8759d08f504SMarcel Holtmann 	struct usb_endpoint_descriptor *diag_tx_ep;
8769d08f504SMarcel Holtmann 	struct usb_endpoint_descriptor *diag_rx_ep;
8779bfa35feSMarcel Holtmann 
878dc786b2cSRajat Jain 	struct gpio_desc *reset_gpio;
879dc786b2cSRajat Jain 
8807a9d4020SMarcel Holtmann 	__u8 cmdreq_type;
881893ba544SMarcel Holtmann 	__u8 cmdreq;
8827a9d4020SMarcel Holtmann 
88343c2e57fSMarcel Holtmann 	unsigned int sco_num;
884baac6276SSathish Narasimman 	unsigned int air_mode;
885baac6276SSathish Narasimman 	bool usb_alt6_packet_flow;
8869bfa35feSMarcel Holtmann 	int isoc_altsetting;
8876a88adf2SMarcel Holtmann 	int suspend_count;
8882cbd3f5cSMarcel Holtmann 
88997307f51SMarcel Holtmann 	int (*recv_event)(struct hci_dev *hdev, struct sk_buff *skb);
8900b10c8c8Smark-yw.chen 	int (*recv_acl)(struct hci_dev *hdev, struct sk_buff *skb);
8912cbd3f5cSMarcel Holtmann 	int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
892ace31982SKim, Ben Young Tae 
893ace31982SKim, Ben Young Tae 	int (*setup_on_usb)(struct hci_dev *hdev);
894fd913ef7SRajat Jain 
8953aab20ebSChris Lu 	int (*suspend)(struct hci_dev *hdev);
8963aab20ebSChris Lu 	int (*resume)(struct hci_dev *hdev);
8979457d783SChris Lu 	int (*disconnect)(struct hci_dev *hdev);
8983aab20ebSChris Lu 
899fd913ef7SRajat Jain 	int oob_wake_irq;   /* irq for out-of-band wake-on-bt */
900dc786b2cSRajat Jain 	unsigned cmd_timeout_cnt;
90120981ce2STim Jiang 
90220981ce2STim Jiang 	struct qca_dump_info qca_dump;
9035e23b923SMarcel Holtmann };
9045e23b923SMarcel Holtmann 
btusb_reset(struct hci_dev * hdev)905c9209b26SArchie Pusaka static void btusb_reset(struct hci_dev *hdev)
906c9209b26SArchie Pusaka {
907c9209b26SArchie Pusaka 	struct btusb_data *data;
908c9209b26SArchie Pusaka 	int err;
909c9209b26SArchie Pusaka 
910c9209b26SArchie Pusaka 	if (hdev->reset) {
911c9209b26SArchie Pusaka 		hdev->reset(hdev);
912c9209b26SArchie Pusaka 		return;
913c9209b26SArchie Pusaka 	}
914c9209b26SArchie Pusaka 
915c9209b26SArchie Pusaka 	data = hci_get_drvdata(hdev);
916c9209b26SArchie Pusaka 	/* This is not an unbalanced PM reference since the device will reset */
917c9209b26SArchie Pusaka 	err = usb_autopm_get_interface(data->intf);
918c9209b26SArchie Pusaka 	if (err) {
919c9209b26SArchie Pusaka 		bt_dev_err(hdev, "Failed usb_autopm_get_interface: %d", err);
920c9209b26SArchie Pusaka 		return;
921c9209b26SArchie Pusaka 	}
922c9209b26SArchie Pusaka 
923c9209b26SArchie Pusaka 	bt_dev_err(hdev, "Resetting usb device.");
924c9209b26SArchie Pusaka 	usb_queue_reset_device(data->intf);
925c9209b26SArchie Pusaka }
926c9209b26SArchie Pusaka 
btusb_intel_cmd_timeout(struct hci_dev * hdev)927dc786b2cSRajat Jain static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
928dc786b2cSRajat Jain {
929dc786b2cSRajat Jain 	struct btusb_data *data = hci_get_drvdata(hdev);
930dc786b2cSRajat Jain 	struct gpio_desc *reset_gpio = data->reset_gpio;
9318f0a3786SKiran K 	struct btintel_data *intel_data = hci_get_priv(hdev);
932dc786b2cSRajat Jain 
933dc786b2cSRajat Jain 	if (++data->cmd_timeout_cnt < 5)
934dc786b2cSRajat Jain 		return;
935dc786b2cSRajat Jain 
9368f0a3786SKiran K 	if (intel_data->acpi_reset_method) {
9378f0a3786SKiran K 		if (test_and_set_bit(INTEL_ACPI_RESET_ACTIVE, intel_data->flags)) {
9388f0a3786SKiran K 			bt_dev_err(hdev, "acpi: last reset failed ? Not resetting again");
9398f0a3786SKiran K 			return;
9408f0a3786SKiran K 		}
9418f0a3786SKiran K 
9428f0a3786SKiran K 		bt_dev_err(hdev, "Initiating acpi reset method");
9438f0a3786SKiran K 		/* If ACPI reset method fails, lets try with legacy GPIO
9448f0a3786SKiran K 		 * toggling
9458f0a3786SKiran K 		 */
9468f0a3786SKiran K 		if (!intel_data->acpi_reset_method(hdev)) {
9478f0a3786SKiran K 			return;
9488f0a3786SKiran K 		}
9498f0a3786SKiran K 	}
9508f0a3786SKiran K 
951dc786b2cSRajat Jain 	if (!reset_gpio) {
952c9209b26SArchie Pusaka 		btusb_reset(hdev);
953dc786b2cSRajat Jain 		return;
954dc786b2cSRajat Jain 	}
955dc786b2cSRajat Jain 
956dc786b2cSRajat Jain 	/*
957dc786b2cSRajat Jain 	 * Toggle the hard reset line if the platform provides one. The reset
958dc786b2cSRajat Jain 	 * is going to yank the device off the USB and then replug. So doing
959dc786b2cSRajat Jain 	 * once is enough. The cleanup is handled correctly on the way out
960dc786b2cSRajat Jain 	 * (standard USB disconnect), and the new device is detected cleanly
961dc786b2cSRajat Jain 	 * and bound to the driver again like it should be.
962dc786b2cSRajat Jain 	 */
963dc786b2cSRajat Jain 	if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
964dc786b2cSRajat Jain 		bt_dev_err(hdev, "last reset failed? Not resetting again");
965dc786b2cSRajat Jain 		return;
966dc786b2cSRajat Jain 	}
967dc786b2cSRajat Jain 
968dc786b2cSRajat Jain 	bt_dev_err(hdev, "Initiating HW reset via gpio");
9692de66bb8SRajat Jain 	gpiod_set_value_cansleep(reset_gpio, 1);
9702de66bb8SRajat Jain 	msleep(100);
9712de66bb8SRajat Jain 	gpiod_set_value_cansleep(reset_gpio, 0);
972dc786b2cSRajat Jain }
973dc786b2cSRajat Jain 
974044014ceSHilda Wu #define RTK_DEVCOREDUMP_CODE_MEMDUMP		0x01
975044014ceSHilda Wu #define RTK_DEVCOREDUMP_CODE_HW_ERR		0x02
976044014ceSHilda Wu #define RTK_DEVCOREDUMP_CODE_CMD_TIMEOUT	0x03
977044014ceSHilda Wu 
978044014ceSHilda Wu #define RTK_SUB_EVENT_CODE_COREDUMP		0x34
979044014ceSHilda Wu 
980044014ceSHilda Wu struct rtk_dev_coredump_hdr {
981044014ceSHilda Wu 	u8 type;
982044014ceSHilda Wu 	u8 code;
983044014ceSHilda Wu 	u8 reserved[2];
984044014ceSHilda Wu } __packed;
985044014ceSHilda Wu 
btusb_rtl_alloc_devcoredump(struct hci_dev * hdev,struct rtk_dev_coredump_hdr * hdr,u8 * buf,u32 len)986044014ceSHilda Wu static inline void btusb_rtl_alloc_devcoredump(struct hci_dev *hdev,
987044014ceSHilda Wu 		struct rtk_dev_coredump_hdr *hdr, u8 *buf, u32 len)
988044014ceSHilda Wu {
989044014ceSHilda Wu 	struct sk_buff *skb;
990044014ceSHilda Wu 
991044014ceSHilda Wu 	skb = alloc_skb(len + sizeof(*hdr), GFP_ATOMIC);
992044014ceSHilda Wu 	if (!skb)
993044014ceSHilda Wu 		return;
994044014ceSHilda Wu 
995044014ceSHilda Wu 	skb_put_data(skb, hdr, sizeof(*hdr));
996044014ceSHilda Wu 	if (len)
997044014ceSHilda Wu 		skb_put_data(skb, buf, len);
998044014ceSHilda Wu 
999044014ceSHilda Wu 	if (!hci_devcd_init(hdev, skb->len)) {
1000044014ceSHilda Wu 		hci_devcd_append(hdev, skb);
1001044014ceSHilda Wu 		hci_devcd_complete(hdev);
1002044014ceSHilda Wu 	} else {
1003044014ceSHilda Wu 		bt_dev_err(hdev, "RTL: Failed to generate devcoredump");
1004044014ceSHilda Wu 		kfree_skb(skb);
1005044014ceSHilda Wu 	}
1006044014ceSHilda Wu }
1007044014ceSHilda Wu 
btusb_rtl_cmd_timeout(struct hci_dev * hdev)1008d7ef0d1eSAlex Lu static void btusb_rtl_cmd_timeout(struct hci_dev *hdev)
1009d7ef0d1eSAlex Lu {
1010d7ef0d1eSAlex Lu 	struct btusb_data *data = hci_get_drvdata(hdev);
1011d7ef0d1eSAlex Lu 	struct gpio_desc *reset_gpio = data->reset_gpio;
1012044014ceSHilda Wu 	struct rtk_dev_coredump_hdr hdr = {
1013044014ceSHilda Wu 		.type = RTK_DEVCOREDUMP_CODE_CMD_TIMEOUT,
1014044014ceSHilda Wu 	};
1015044014ceSHilda Wu 
1016044014ceSHilda Wu 	btusb_rtl_alloc_devcoredump(hdev, &hdr, NULL, 0);
1017d7ef0d1eSAlex Lu 
1018d7ef0d1eSAlex Lu 	if (++data->cmd_timeout_cnt < 5)
1019d7ef0d1eSAlex Lu 		return;
1020d7ef0d1eSAlex Lu 
1021d7ef0d1eSAlex Lu 	if (!reset_gpio) {
1022c9209b26SArchie Pusaka 		btusb_reset(hdev);
1023d7ef0d1eSAlex Lu 		return;
1024d7ef0d1eSAlex Lu 	}
1025d7ef0d1eSAlex Lu 
1026d7ef0d1eSAlex Lu 	/* Toggle the hard reset line. The Realtek device is going to
1027d7ef0d1eSAlex Lu 	 * yank itself off the USB and then replug. The cleanup is handled
1028d7ef0d1eSAlex Lu 	 * correctly on the way out (standard USB disconnect), and the new
1029d7ef0d1eSAlex Lu 	 * device is detected cleanly and bound to the driver again like
1030d7ef0d1eSAlex Lu 	 * it should be.
1031d7ef0d1eSAlex Lu 	 */
1032d7ef0d1eSAlex Lu 	if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
1033d7ef0d1eSAlex Lu 		bt_dev_err(hdev, "last reset failed? Not resetting again");
1034d7ef0d1eSAlex Lu 		return;
1035d7ef0d1eSAlex Lu 	}
1036d7ef0d1eSAlex Lu 
1037d7ef0d1eSAlex Lu 	bt_dev_err(hdev, "Reset Realtek device via gpio");
1038d7ef0d1eSAlex Lu 	gpiod_set_value_cansleep(reset_gpio, 1);
103934682110SMax Chou 	msleep(200);
104034682110SMax Chou 	gpiod_set_value_cansleep(reset_gpio, 0);
1041d7ef0d1eSAlex Lu }
1042d7ef0d1eSAlex Lu 
btusb_rtl_hw_error(struct hci_dev * hdev,u8 code)1043044014ceSHilda Wu static void btusb_rtl_hw_error(struct hci_dev *hdev, u8 code)
1044044014ceSHilda Wu {
1045044014ceSHilda Wu 	struct rtk_dev_coredump_hdr hdr = {
1046044014ceSHilda Wu 		.type = RTK_DEVCOREDUMP_CODE_HW_ERR,
1047044014ceSHilda Wu 		.code = code,
1048044014ceSHilda Wu 	};
1049044014ceSHilda Wu 
1050044014ceSHilda Wu 	bt_dev_err(hdev, "RTL: hw err, trigger devcoredump (%d)", code);
1051044014ceSHilda Wu 
1052044014ceSHilda Wu 	btusb_rtl_alloc_devcoredump(hdev, &hdr, NULL, 0);
1053044014ceSHilda Wu }
1054044014ceSHilda Wu 
btusb_qca_cmd_timeout(struct hci_dev * hdev)10556933568aSAbhishek Pandit-Subedi static void btusb_qca_cmd_timeout(struct hci_dev *hdev)
10566933568aSAbhishek Pandit-Subedi {
10576933568aSAbhishek Pandit-Subedi 	struct btusb_data *data = hci_get_drvdata(hdev);
105824ff62aeStjiang@codeaurora.org 	struct gpio_desc *reset_gpio = data->reset_gpio;
10596933568aSAbhishek Pandit-Subedi 
106020981ce2STim Jiang 	if (test_bit(BTUSB_HW_SSR_ACTIVE, &data->flags)) {
106120981ce2STim Jiang 		bt_dev_info(hdev, "Ramdump in progress, defer cmd_timeout");
106220981ce2STim Jiang 		return;
106320981ce2STim Jiang 	}
106420981ce2STim Jiang 
10656933568aSAbhishek Pandit-Subedi 	if (++data->cmd_timeout_cnt < 5)
10666933568aSAbhishek Pandit-Subedi 		return;
10676933568aSAbhishek Pandit-Subedi 
106824ff62aeStjiang@codeaurora.org 	if (reset_gpio) {
106924ff62aeStjiang@codeaurora.org 		bt_dev_err(hdev, "Reset qca device via bt_en gpio");
107024ff62aeStjiang@codeaurora.org 
107124ff62aeStjiang@codeaurora.org 		/* Toggle the hard reset line. The qca bt device is going to
107224ff62aeStjiang@codeaurora.org 		 * yank itself off the USB and then replug. The cleanup is handled
107324ff62aeStjiang@codeaurora.org 		 * correctly on the way out (standard USB disconnect), and the new
107424ff62aeStjiang@codeaurora.org 		 * device is detected cleanly and bound to the driver again like
107524ff62aeStjiang@codeaurora.org 		 * it should be.
107624ff62aeStjiang@codeaurora.org 		 */
107724ff62aeStjiang@codeaurora.org 		if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
107824ff62aeStjiang@codeaurora.org 			bt_dev_err(hdev, "last reset failed? Not resetting again");
107924ff62aeStjiang@codeaurora.org 			return;
108024ff62aeStjiang@codeaurora.org 		}
108124ff62aeStjiang@codeaurora.org 
108224ff62aeStjiang@codeaurora.org 		gpiod_set_value_cansleep(reset_gpio, 0);
108324ff62aeStjiang@codeaurora.org 		msleep(200);
108424ff62aeStjiang@codeaurora.org 		gpiod_set_value_cansleep(reset_gpio, 1);
108524ff62aeStjiang@codeaurora.org 
108624ff62aeStjiang@codeaurora.org 		return;
108724ff62aeStjiang@codeaurora.org 	}
108824ff62aeStjiang@codeaurora.org 
1089c9209b26SArchie Pusaka 	btusb_reset(hdev);
10906933568aSAbhishek Pandit-Subedi }
10916933568aSAbhishek Pandit-Subedi 
btusb_free_frags(struct btusb_data * data)1092803b5836SMarcel Holtmann static inline void btusb_free_frags(struct btusb_data *data)
1093803b5836SMarcel Holtmann {
1094803b5836SMarcel Holtmann 	unsigned long flags;
1095803b5836SMarcel Holtmann 
1096803b5836SMarcel Holtmann 	spin_lock_irqsave(&data->rxlock, flags);
1097803b5836SMarcel Holtmann 
1098b15a6bd3SYang Yingliang 	dev_kfree_skb_irq(data->evt_skb);
1099803b5836SMarcel Holtmann 	data->evt_skb = NULL;
1100803b5836SMarcel Holtmann 
1101b15a6bd3SYang Yingliang 	dev_kfree_skb_irq(data->acl_skb);
1102803b5836SMarcel Holtmann 	data->acl_skb = NULL;
1103803b5836SMarcel Holtmann 
1104b15a6bd3SYang Yingliang 	dev_kfree_skb_irq(data->sco_skb);
1105803b5836SMarcel Holtmann 	data->sco_skb = NULL;
1106803b5836SMarcel Holtmann 
1107803b5836SMarcel Holtmann 	spin_unlock_irqrestore(&data->rxlock, flags);
1108803b5836SMarcel Holtmann }
1109803b5836SMarcel Holtmann 
btusb_recv_event(struct btusb_data * data,struct sk_buff * skb)1110800fe5ecSLuiz Augusto von Dentz static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
1111800fe5ecSLuiz Augusto von Dentz {
1112800fe5ecSLuiz Augusto von Dentz 	if (data->intr_interval) {
1113800fe5ecSLuiz Augusto von Dentz 		/* Trigger dequeue immediatelly if an event is received */
1114800fe5ecSLuiz Augusto von Dentz 		schedule_delayed_work(&data->rx_work, 0);
1115800fe5ecSLuiz Augusto von Dentz 	}
1116800fe5ecSLuiz Augusto von Dentz 
1117800fe5ecSLuiz Augusto von Dentz 	return data->recv_event(data->hdev, skb);
1118800fe5ecSLuiz Augusto von Dentz }
1119800fe5ecSLuiz Augusto von Dentz 
btusb_recv_intr(struct btusb_data * data,void * buffer,int count)11201ffa4ad0SMarcel Holtmann static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
11211ffa4ad0SMarcel Holtmann {
1122803b5836SMarcel Holtmann 	struct sk_buff *skb;
1123a5e50d5bSSebastian Andrzej Siewior 	unsigned long flags;
1124803b5836SMarcel Holtmann 	int err = 0;
1125803b5836SMarcel Holtmann 
1126a5e50d5bSSebastian Andrzej Siewior 	spin_lock_irqsave(&data->rxlock, flags);
1127803b5836SMarcel Holtmann 	skb = data->evt_skb;
1128803b5836SMarcel Holtmann 
1129803b5836SMarcel Holtmann 	while (count) {
1130803b5836SMarcel Holtmann 		int len;
1131803b5836SMarcel Holtmann 
1132803b5836SMarcel Holtmann 		if (!skb) {
1133803b5836SMarcel Holtmann 			skb = bt_skb_alloc(HCI_MAX_EVENT_SIZE, GFP_ATOMIC);
1134803b5836SMarcel Holtmann 			if (!skb) {
1135803b5836SMarcel Holtmann 				err = -ENOMEM;
1136803b5836SMarcel Holtmann 				break;
1137803b5836SMarcel Holtmann 			}
1138803b5836SMarcel Holtmann 
1139618e8bc2SMarcel Holtmann 			hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
1140618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = HCI_EVENT_HDR_SIZE;
1141803b5836SMarcel Holtmann 		}
1142803b5836SMarcel Holtmann 
1143618e8bc2SMarcel Holtmann 		len = min_t(uint, hci_skb_expect(skb), count);
114459ae1d12SJohannes Berg 		skb_put_data(skb, buffer, len);
1145803b5836SMarcel Holtmann 
1146803b5836SMarcel Holtmann 		count -= len;
1147803b5836SMarcel Holtmann 		buffer += len;
1148618e8bc2SMarcel Holtmann 		hci_skb_expect(skb) -= len;
1149803b5836SMarcel Holtmann 
1150803b5836SMarcel Holtmann 		if (skb->len == HCI_EVENT_HDR_SIZE) {
1151803b5836SMarcel Holtmann 			/* Complete event header */
1152618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = hci_event_hdr(skb)->plen;
1153803b5836SMarcel Holtmann 
1154618e8bc2SMarcel Holtmann 			if (skb_tailroom(skb) < hci_skb_expect(skb)) {
1155803b5836SMarcel Holtmann 				kfree_skb(skb);
1156803b5836SMarcel Holtmann 				skb = NULL;
1157803b5836SMarcel Holtmann 
1158803b5836SMarcel Holtmann 				err = -EILSEQ;
1159803b5836SMarcel Holtmann 				break;
1160803b5836SMarcel Holtmann 			}
1161803b5836SMarcel Holtmann 		}
1162803b5836SMarcel Holtmann 
1163618e8bc2SMarcel Holtmann 		if (!hci_skb_expect(skb)) {
1164803b5836SMarcel Holtmann 			/* Complete frame */
1165800fe5ecSLuiz Augusto von Dentz 			btusb_recv_event(data, skb);
1166803b5836SMarcel Holtmann 			skb = NULL;
1167803b5836SMarcel Holtmann 		}
1168803b5836SMarcel Holtmann 	}
1169803b5836SMarcel Holtmann 
1170803b5836SMarcel Holtmann 	data->evt_skb = skb;
1171a5e50d5bSSebastian Andrzej Siewior 	spin_unlock_irqrestore(&data->rxlock, flags);
1172803b5836SMarcel Holtmann 
1173803b5836SMarcel Holtmann 	return err;
11741ffa4ad0SMarcel Holtmann }
11751ffa4ad0SMarcel Holtmann 
btusb_recv_acl(struct btusb_data * data,struct sk_buff * skb)1176800fe5ecSLuiz Augusto von Dentz static int btusb_recv_acl(struct btusb_data *data, struct sk_buff *skb)
1177800fe5ecSLuiz Augusto von Dentz {
1178800fe5ecSLuiz Augusto von Dentz 	/* Only queue ACL packet if intr_interval is set as it means
1179800fe5ecSLuiz Augusto von Dentz 	 * force_poll_sync has been enabled.
1180800fe5ecSLuiz Augusto von Dentz 	 */
1181800fe5ecSLuiz Augusto von Dentz 	if (!data->intr_interval)
1182800fe5ecSLuiz Augusto von Dentz 		return data->recv_acl(data->hdev, skb);
1183800fe5ecSLuiz Augusto von Dentz 
1184800fe5ecSLuiz Augusto von Dentz 	skb_queue_tail(&data->acl_q, skb);
1185800fe5ecSLuiz Augusto von Dentz 	schedule_delayed_work(&data->rx_work, data->intr_interval);
1186800fe5ecSLuiz Augusto von Dentz 
1187800fe5ecSLuiz Augusto von Dentz 	return 0;
1188800fe5ecSLuiz Augusto von Dentz }
1189800fe5ecSLuiz Augusto von Dentz 
btusb_recv_bulk(struct btusb_data * data,void * buffer,int count)11901ffa4ad0SMarcel Holtmann static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
11911ffa4ad0SMarcel Holtmann {
1192803b5836SMarcel Holtmann 	struct sk_buff *skb;
1193a5e50d5bSSebastian Andrzej Siewior 	unsigned long flags;
1194803b5836SMarcel Holtmann 	int err = 0;
1195803b5836SMarcel Holtmann 
1196a5e50d5bSSebastian Andrzej Siewior 	spin_lock_irqsave(&data->rxlock, flags);
1197803b5836SMarcel Holtmann 	skb = data->acl_skb;
1198803b5836SMarcel Holtmann 
1199803b5836SMarcel Holtmann 	while (count) {
1200803b5836SMarcel Holtmann 		int len;
1201803b5836SMarcel Holtmann 
1202803b5836SMarcel Holtmann 		if (!skb) {
1203803b5836SMarcel Holtmann 			skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
1204803b5836SMarcel Holtmann 			if (!skb) {
1205803b5836SMarcel Holtmann 				err = -ENOMEM;
1206803b5836SMarcel Holtmann 				break;
1207803b5836SMarcel Holtmann 			}
1208803b5836SMarcel Holtmann 
1209618e8bc2SMarcel Holtmann 			hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT;
1210618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = HCI_ACL_HDR_SIZE;
1211803b5836SMarcel Holtmann 		}
1212803b5836SMarcel Holtmann 
1213618e8bc2SMarcel Holtmann 		len = min_t(uint, hci_skb_expect(skb), count);
121459ae1d12SJohannes Berg 		skb_put_data(skb, buffer, len);
1215803b5836SMarcel Holtmann 
1216803b5836SMarcel Holtmann 		count -= len;
1217803b5836SMarcel Holtmann 		buffer += len;
1218618e8bc2SMarcel Holtmann 		hci_skb_expect(skb) -= len;
1219803b5836SMarcel Holtmann 
1220803b5836SMarcel Holtmann 		if (skb->len == HCI_ACL_HDR_SIZE) {
1221803b5836SMarcel Holtmann 			__le16 dlen = hci_acl_hdr(skb)->dlen;
1222803b5836SMarcel Holtmann 
1223803b5836SMarcel Holtmann 			/* Complete ACL header */
1224618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = __le16_to_cpu(dlen);
1225803b5836SMarcel Holtmann 
1226618e8bc2SMarcel Holtmann 			if (skb_tailroom(skb) < hci_skb_expect(skb)) {
1227803b5836SMarcel Holtmann 				kfree_skb(skb);
1228803b5836SMarcel Holtmann 				skb = NULL;
1229803b5836SMarcel Holtmann 
1230803b5836SMarcel Holtmann 				err = -EILSEQ;
1231803b5836SMarcel Holtmann 				break;
1232803b5836SMarcel Holtmann 			}
1233803b5836SMarcel Holtmann 		}
1234803b5836SMarcel Holtmann 
1235618e8bc2SMarcel Holtmann 		if (!hci_skb_expect(skb)) {
1236803b5836SMarcel Holtmann 			/* Complete frame */
1237800fe5ecSLuiz Augusto von Dentz 			btusb_recv_acl(data, skb);
1238803b5836SMarcel Holtmann 			skb = NULL;
1239803b5836SMarcel Holtmann 		}
1240803b5836SMarcel Holtmann 	}
1241803b5836SMarcel Holtmann 
1242803b5836SMarcel Holtmann 	data->acl_skb = skb;
1243a5e50d5bSSebastian Andrzej Siewior 	spin_unlock_irqrestore(&data->rxlock, flags);
1244803b5836SMarcel Holtmann 
1245803b5836SMarcel Holtmann 	return err;
12461ffa4ad0SMarcel Holtmann }
12471ffa4ad0SMarcel Holtmann 
btusb_validate_sco_handle(struct hci_dev * hdev,struct hci_sco_hdr * hdr)1248b3fdb8c9SNicolas Cavallari static bool btusb_validate_sco_handle(struct hci_dev *hdev,
1249b3fdb8c9SNicolas Cavallari 				      struct hci_sco_hdr *hdr)
1250b3fdb8c9SNicolas Cavallari {
1251b3fdb8c9SNicolas Cavallari 	__u16 handle;
1252b3fdb8c9SNicolas Cavallari 
1253b3fdb8c9SNicolas Cavallari 	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
1254b3fdb8c9SNicolas Cavallari 		// Can't validate, userspace controls everything.
1255b3fdb8c9SNicolas Cavallari 		return true;
1256b3fdb8c9SNicolas Cavallari 
1257b3fdb8c9SNicolas Cavallari 	/*
1258b3fdb8c9SNicolas Cavallari 	 * USB isochronous transfers are not designed to be reliable and may
1259b3fdb8c9SNicolas Cavallari 	 * lose fragments.  When this happens, the next first fragment
1260b3fdb8c9SNicolas Cavallari 	 * encountered might actually be a continuation fragment.
1261b3fdb8c9SNicolas Cavallari 	 * Validate the handle to detect it and drop it, or else the upper
1262b3fdb8c9SNicolas Cavallari 	 * layer will get garbage for a while.
1263b3fdb8c9SNicolas Cavallari 	 */
1264b3fdb8c9SNicolas Cavallari 
1265b3fdb8c9SNicolas Cavallari 	handle = hci_handle(__le16_to_cpu(hdr->handle));
1266b3fdb8c9SNicolas Cavallari 
1267b3fdb8c9SNicolas Cavallari 	switch (hci_conn_lookup_type(hdev, handle)) {
1268b3fdb8c9SNicolas Cavallari 	case SCO_LINK:
1269b3fdb8c9SNicolas Cavallari 	case ESCO_LINK:
1270b3fdb8c9SNicolas Cavallari 		return true;
1271b3fdb8c9SNicolas Cavallari 	default:
1272b3fdb8c9SNicolas Cavallari 		return false;
1273b3fdb8c9SNicolas Cavallari 	}
1274b3fdb8c9SNicolas Cavallari }
1275b3fdb8c9SNicolas Cavallari 
btusb_recv_isoc(struct btusb_data * data,void * buffer,int count)12761ffa4ad0SMarcel Holtmann static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
12771ffa4ad0SMarcel Holtmann {
1278803b5836SMarcel Holtmann 	struct sk_buff *skb;
1279a5e50d5bSSebastian Andrzej Siewior 	unsigned long flags;
1280803b5836SMarcel Holtmann 	int err = 0;
1281803b5836SMarcel Holtmann 
1282a5e50d5bSSebastian Andrzej Siewior 	spin_lock_irqsave(&data->rxlock, flags);
1283803b5836SMarcel Holtmann 	skb = data->sco_skb;
1284803b5836SMarcel Holtmann 
1285803b5836SMarcel Holtmann 	while (count) {
1286803b5836SMarcel Holtmann 		int len;
1287803b5836SMarcel Holtmann 
1288803b5836SMarcel Holtmann 		if (!skb) {
1289803b5836SMarcel Holtmann 			skb = bt_skb_alloc(HCI_MAX_SCO_SIZE, GFP_ATOMIC);
1290803b5836SMarcel Holtmann 			if (!skb) {
1291803b5836SMarcel Holtmann 				err = -ENOMEM;
1292803b5836SMarcel Holtmann 				break;
1293803b5836SMarcel Holtmann 			}
1294803b5836SMarcel Holtmann 
1295618e8bc2SMarcel Holtmann 			hci_skb_pkt_type(skb) = HCI_SCODATA_PKT;
1296618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = HCI_SCO_HDR_SIZE;
1297803b5836SMarcel Holtmann 		}
1298803b5836SMarcel Holtmann 
1299618e8bc2SMarcel Holtmann 		len = min_t(uint, hci_skb_expect(skb), count);
130059ae1d12SJohannes Berg 		skb_put_data(skb, buffer, len);
1301803b5836SMarcel Holtmann 
1302803b5836SMarcel Holtmann 		count -= len;
1303803b5836SMarcel Holtmann 		buffer += len;
1304618e8bc2SMarcel Holtmann 		hci_skb_expect(skb) -= len;
1305803b5836SMarcel Holtmann 
1306803b5836SMarcel Holtmann 		if (skb->len == HCI_SCO_HDR_SIZE) {
1307803b5836SMarcel Holtmann 			/* Complete SCO header */
1308b3fdb8c9SNicolas Cavallari 			struct hci_sco_hdr *hdr = hci_sco_hdr(skb);
1309803b5836SMarcel Holtmann 
1310b3fdb8c9SNicolas Cavallari 			hci_skb_expect(skb) = hdr->dlen;
1311b3fdb8c9SNicolas Cavallari 
1312b3fdb8c9SNicolas Cavallari 			if (skb_tailroom(skb) < hci_skb_expect(skb) ||
1313b3fdb8c9SNicolas Cavallari 			    !btusb_validate_sco_handle(data->hdev, hdr)) {
1314803b5836SMarcel Holtmann 				kfree_skb(skb);
1315803b5836SMarcel Holtmann 				skb = NULL;
1316803b5836SMarcel Holtmann 
1317803b5836SMarcel Holtmann 				err = -EILSEQ;
1318803b5836SMarcel Holtmann 				break;
1319803b5836SMarcel Holtmann 			}
1320803b5836SMarcel Holtmann 		}
1321803b5836SMarcel Holtmann 
1322618e8bc2SMarcel Holtmann 		if (!hci_skb_expect(skb)) {
1323803b5836SMarcel Holtmann 			/* Complete frame */
1324803b5836SMarcel Holtmann 			hci_recv_frame(data->hdev, skb);
1325803b5836SMarcel Holtmann 			skb = NULL;
1326803b5836SMarcel Holtmann 		}
1327803b5836SMarcel Holtmann 	}
1328803b5836SMarcel Holtmann 
1329803b5836SMarcel Holtmann 	data->sco_skb = skb;
1330a5e50d5bSSebastian Andrzej Siewior 	spin_unlock_irqrestore(&data->rxlock, flags);
1331803b5836SMarcel Holtmann 
1332803b5836SMarcel Holtmann 	return err;
13331ffa4ad0SMarcel Holtmann }
13341ffa4ad0SMarcel Holtmann 
btusb_intr_complete(struct urb * urb)13355e23b923SMarcel Holtmann static void btusb_intr_complete(struct urb *urb)
13365e23b923SMarcel Holtmann {
13375e23b923SMarcel Holtmann 	struct hci_dev *hdev = urb->context;
1338155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
13395e23b923SMarcel Holtmann 	int err;
13405e23b923SMarcel Holtmann 
134189e7533dSMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
134289e7533dSMarcel Holtmann 	       urb->actual_length);
13435e23b923SMarcel Holtmann 
13445e23b923SMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
13455e23b923SMarcel Holtmann 		return;
13465e23b923SMarcel Holtmann 
13475e23b923SMarcel Holtmann 	if (urb->status == 0) {
13489bfa35feSMarcel Holtmann 		hdev->stat.byte_rx += urb->actual_length;
13499bfa35feSMarcel Holtmann 
13501ffa4ad0SMarcel Holtmann 		if (btusb_recv_intr(data, urb->transfer_buffer,
13515e23b923SMarcel Holtmann 				    urb->actual_length) < 0) {
13522064ee33SMarcel Holtmann 			bt_dev_err(hdev, "corrupted event packet");
13535e23b923SMarcel Holtmann 			hdev->stat.err_rx++;
13545e23b923SMarcel Holtmann 		}
135585560c4aSChampion Chen 	} else if (urb->status == -ENOENT) {
135685560c4aSChampion Chen 		/* Avoid suspend failed when usb_kill_urb */
135785560c4aSChampion Chen 		return;
13585e23b923SMarcel Holtmann 	}
13595e23b923SMarcel Holtmann 
13605e23b923SMarcel Holtmann 	if (!test_bit(BTUSB_INTR_RUNNING, &data->flags))
13615e23b923SMarcel Holtmann 		return;
13625e23b923SMarcel Holtmann 
13637bee549eSOliver Neukum 	usb_mark_last_busy(data->udev);
13645e23b923SMarcel Holtmann 	usb_anchor_urb(urb, &data->intr_anchor);
13655e23b923SMarcel Holtmann 
13665e23b923SMarcel Holtmann 	err = usb_submit_urb(urb, GFP_ATOMIC);
13675e23b923SMarcel Holtmann 	if (err < 0) {
13684935f1c1SPaul Bolle 		/* -EPERM: urb is being killed;
1369d98422cbSDerek Robson 		 * -ENODEV: device got disconnected
1370d98422cbSDerek Robson 		 */
13714935f1c1SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
13722064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
13732064ee33SMarcel Holtmann 				   urb, -err);
1374c97a747eSBenjamin Berg 		if (err != -EPERM)
1375c97a747eSBenjamin Berg 			hci_cmd_sync_cancel(hdev, -err);
13765e23b923SMarcel Holtmann 		usb_unanchor_urb(urb);
13775e23b923SMarcel Holtmann 	}
13785e23b923SMarcel Holtmann }
13795e23b923SMarcel Holtmann 
btusb_submit_intr_urb(struct hci_dev * hdev,gfp_t mem_flags)13802eda66f4SMarcel Holtmann static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
13815e23b923SMarcel Holtmann {
1382155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
13835e23b923SMarcel Holtmann 	struct urb *urb;
13845e23b923SMarcel Holtmann 	unsigned char *buf;
13855e23b923SMarcel Holtmann 	unsigned int pipe;
13865e23b923SMarcel Holtmann 	int err, size;
13875e23b923SMarcel Holtmann 
13885e23b923SMarcel Holtmann 	BT_DBG("%s", hdev->name);
13895e23b923SMarcel Holtmann 
13909bfa35feSMarcel Holtmann 	if (!data->intr_ep)
13919bfa35feSMarcel Holtmann 		return -ENODEV;
13929bfa35feSMarcel Holtmann 
13932eda66f4SMarcel Holtmann 	urb = usb_alloc_urb(0, mem_flags);
13945e23b923SMarcel Holtmann 	if (!urb)
13955e23b923SMarcel Holtmann 		return -ENOMEM;
13965e23b923SMarcel Holtmann 
1397885f8c87SLuiz Augusto von Dentz 	if (le16_to_cpu(data->udev->descriptor.idVendor)  == 0x0a12 &&
1398885f8c87SLuiz Augusto von Dentz 	    le16_to_cpu(data->udev->descriptor.idProduct) == 0x0001)
1399885f8c87SLuiz Augusto von Dentz 		/* Fake CSR devices don't seem to support sort-transter */
1400885f8c87SLuiz Augusto von Dentz 		size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
1401885f8c87SLuiz Augusto von Dentz 	else
1402a4a70cbaSLuiz Augusto von Dentz 		/* Use maximum HCI Event size so the USB stack handles
1403a4a70cbaSLuiz Augusto von Dentz 		 * ZPL/short-transfer automatically.
1404a4a70cbaSLuiz Augusto von Dentz 		 */
1405a4a70cbaSLuiz Augusto von Dentz 		size = HCI_MAX_EVENT_SIZE;
14065e23b923SMarcel Holtmann 
14072eda66f4SMarcel Holtmann 	buf = kmalloc(size, mem_flags);
14085e23b923SMarcel Holtmann 	if (!buf) {
14095e23b923SMarcel Holtmann 		usb_free_urb(urb);
14105e23b923SMarcel Holtmann 		return -ENOMEM;
14115e23b923SMarcel Holtmann 	}
14125e23b923SMarcel Holtmann 
14135e23b923SMarcel Holtmann 	pipe = usb_rcvintpipe(data->udev, data->intr_ep->bEndpointAddress);
14145e23b923SMarcel Holtmann 
14155e23b923SMarcel Holtmann 	usb_fill_int_urb(urb, data->udev, pipe, buf, size,
141689e7533dSMarcel Holtmann 			 btusb_intr_complete, hdev, data->intr_ep->bInterval);
14175e23b923SMarcel Holtmann 
14185e23b923SMarcel Holtmann 	urb->transfer_flags |= URB_FREE_BUFFER;
14195e23b923SMarcel Holtmann 
14205e23b923SMarcel Holtmann 	usb_anchor_urb(urb, &data->intr_anchor);
14215e23b923SMarcel Holtmann 
14222eda66f4SMarcel Holtmann 	err = usb_submit_urb(urb, mem_flags);
14235e23b923SMarcel Holtmann 	if (err < 0) {
1424d4b8d1c9SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
14252064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p submission failed (%d)",
14262064ee33SMarcel Holtmann 				   urb, -err);
1427c97a747eSBenjamin Berg 		if (err != -EPERM)
1428c97a747eSBenjamin Berg 			hci_cmd_sync_cancel(hdev, -err);
14295e23b923SMarcel Holtmann 		usb_unanchor_urb(urb);
14305e23b923SMarcel Holtmann 	}
14315e23b923SMarcel Holtmann 
1432800fe5ecSLuiz Augusto von Dentz 	/* Only initialize intr_interval if URB poll sync is enabled */
1433800fe5ecSLuiz Augusto von Dentz 	if (!data->poll_sync)
1434800fe5ecSLuiz Augusto von Dentz 		goto done;
1435800fe5ecSLuiz Augusto von Dentz 
1436800fe5ecSLuiz Augusto von Dentz 	/* The units are frames (milliseconds) for full and low speed devices,
1437800fe5ecSLuiz Augusto von Dentz 	 * and microframes (1/8 millisecond) for highspeed and SuperSpeed
1438800fe5ecSLuiz Augusto von Dentz 	 * devices.
1439800fe5ecSLuiz Augusto von Dentz 	 *
1440800fe5ecSLuiz Augusto von Dentz 	 * This is done once on open/resume so it shouldn't change even if
1441800fe5ecSLuiz Augusto von Dentz 	 * force_poll_sync changes.
1442800fe5ecSLuiz Augusto von Dentz 	 */
1443800fe5ecSLuiz Augusto von Dentz 	switch (urb->dev->speed) {
1444800fe5ecSLuiz Augusto von Dentz 	case USB_SPEED_SUPER_PLUS:
1445800fe5ecSLuiz Augusto von Dentz 	case USB_SPEED_SUPER:	/* units are 125us */
1446800fe5ecSLuiz Augusto von Dentz 		data->intr_interval = usecs_to_jiffies(urb->interval * 125);
1447800fe5ecSLuiz Augusto von Dentz 		break;
1448800fe5ecSLuiz Augusto von Dentz 	default:
1449800fe5ecSLuiz Augusto von Dentz 		data->intr_interval = msecs_to_jiffies(urb->interval);
1450800fe5ecSLuiz Augusto von Dentz 		break;
1451800fe5ecSLuiz Augusto von Dentz 	}
1452800fe5ecSLuiz Augusto von Dentz 
1453800fe5ecSLuiz Augusto von Dentz done:
14545e23b923SMarcel Holtmann 	usb_free_urb(urb);
14555e23b923SMarcel Holtmann 
14565e23b923SMarcel Holtmann 	return err;
14575e23b923SMarcel Holtmann }
14585e23b923SMarcel Holtmann 
btusb_bulk_complete(struct urb * urb)14595e23b923SMarcel Holtmann static void btusb_bulk_complete(struct urb *urb)
14605e23b923SMarcel Holtmann {
14615e23b923SMarcel Holtmann 	struct hci_dev *hdev = urb->context;
1462155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
14635e23b923SMarcel Holtmann 	int err;
14645e23b923SMarcel Holtmann 
146589e7533dSMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
146689e7533dSMarcel Holtmann 	       urb->actual_length);
14675e23b923SMarcel Holtmann 
14685e23b923SMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
14695e23b923SMarcel Holtmann 		return;
14705e23b923SMarcel Holtmann 
14715e23b923SMarcel Holtmann 	if (urb->status == 0) {
14729bfa35feSMarcel Holtmann 		hdev->stat.byte_rx += urb->actual_length;
14739bfa35feSMarcel Holtmann 
14742cbd3f5cSMarcel Holtmann 		if (data->recv_bulk(data, urb->transfer_buffer,
14755e23b923SMarcel Holtmann 				    urb->actual_length) < 0) {
14762064ee33SMarcel Holtmann 			bt_dev_err(hdev, "corrupted ACL packet");
14775e23b923SMarcel Holtmann 			hdev->stat.err_rx++;
14785e23b923SMarcel Holtmann 		}
147985560c4aSChampion Chen 	} else if (urb->status == -ENOENT) {
148085560c4aSChampion Chen 		/* Avoid suspend failed when usb_kill_urb */
148185560c4aSChampion Chen 		return;
14825e23b923SMarcel Holtmann 	}
14835e23b923SMarcel Holtmann 
14845e23b923SMarcel Holtmann 	if (!test_bit(BTUSB_BULK_RUNNING, &data->flags))
14855e23b923SMarcel Holtmann 		return;
14865e23b923SMarcel Holtmann 
14875e23b923SMarcel Holtmann 	usb_anchor_urb(urb, &data->bulk_anchor);
1488652fd781SOliver Neukum 	usb_mark_last_busy(data->udev);
14895e23b923SMarcel Holtmann 
14905e23b923SMarcel Holtmann 	err = usb_submit_urb(urb, GFP_ATOMIC);
14915e23b923SMarcel Holtmann 	if (err < 0) {
14924935f1c1SPaul Bolle 		/* -EPERM: urb is being killed;
1493d98422cbSDerek Robson 		 * -ENODEV: device got disconnected
1494d98422cbSDerek Robson 		 */
14954935f1c1SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
14962064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
14972064ee33SMarcel Holtmann 				   urb, -err);
14985e23b923SMarcel Holtmann 		usb_unanchor_urb(urb);
14995e23b923SMarcel Holtmann 	}
15005e23b923SMarcel Holtmann }
15015e23b923SMarcel Holtmann 
btusb_submit_bulk_urb(struct hci_dev * hdev,gfp_t mem_flags)15022eda66f4SMarcel Holtmann static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
15035e23b923SMarcel Holtmann {
1504155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
15055e23b923SMarcel Holtmann 	struct urb *urb;
15065e23b923SMarcel Holtmann 	unsigned char *buf;
15075e23b923SMarcel Holtmann 	unsigned int pipe;
1508290ba200SVikram Kandukuri 	int err, size = HCI_MAX_FRAME_SIZE;
15095e23b923SMarcel Holtmann 
15105e23b923SMarcel Holtmann 	BT_DBG("%s", hdev->name);
15115e23b923SMarcel Holtmann 
15129bfa35feSMarcel Holtmann 	if (!data->bulk_rx_ep)
15139bfa35feSMarcel Holtmann 		return -ENODEV;
15149bfa35feSMarcel Holtmann 
15152eda66f4SMarcel Holtmann 	urb = usb_alloc_urb(0, mem_flags);
15165e23b923SMarcel Holtmann 	if (!urb)
15175e23b923SMarcel Holtmann 		return -ENOMEM;
15185e23b923SMarcel Holtmann 
15192eda66f4SMarcel Holtmann 	buf = kmalloc(size, mem_flags);
15205e23b923SMarcel Holtmann 	if (!buf) {
15215e23b923SMarcel Holtmann 		usb_free_urb(urb);
15225e23b923SMarcel Holtmann 		return -ENOMEM;
15235e23b923SMarcel Holtmann 	}
15245e23b923SMarcel Holtmann 
15255e23b923SMarcel Holtmann 	pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress);
15265e23b923SMarcel Holtmann 
152789e7533dSMarcel Holtmann 	usb_fill_bulk_urb(urb, data->udev, pipe, buf, size,
152889e7533dSMarcel Holtmann 			  btusb_bulk_complete, hdev);
15295e23b923SMarcel Holtmann 
15305e23b923SMarcel Holtmann 	urb->transfer_flags |= URB_FREE_BUFFER;
15315e23b923SMarcel Holtmann 
15327bee549eSOliver Neukum 	usb_mark_last_busy(data->udev);
15335e23b923SMarcel Holtmann 	usb_anchor_urb(urb, &data->bulk_anchor);
15345e23b923SMarcel Holtmann 
15352eda66f4SMarcel Holtmann 	err = usb_submit_urb(urb, mem_flags);
15365e23b923SMarcel Holtmann 	if (err < 0) {
1537d4b8d1c9SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
15382064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p submission failed (%d)",
15392064ee33SMarcel Holtmann 				   urb, -err);
15405e23b923SMarcel Holtmann 		usb_unanchor_urb(urb);
15415e23b923SMarcel Holtmann 	}
15425e23b923SMarcel Holtmann 
15435e23b923SMarcel Holtmann 	usb_free_urb(urb);
15445e23b923SMarcel Holtmann 
15455e23b923SMarcel Holtmann 	return err;
15465e23b923SMarcel Holtmann }
15475e23b923SMarcel Holtmann 
btusb_isoc_complete(struct urb * urb)15489bfa35feSMarcel Holtmann static void btusb_isoc_complete(struct urb *urb)
15499bfa35feSMarcel Holtmann {
15509bfa35feSMarcel Holtmann 	struct hci_dev *hdev = urb->context;
1551155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
15529bfa35feSMarcel Holtmann 	int i, err;
15539bfa35feSMarcel Holtmann 
155489e7533dSMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
155589e7533dSMarcel Holtmann 	       urb->actual_length);
15569bfa35feSMarcel Holtmann 
15579bfa35feSMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
15589bfa35feSMarcel Holtmann 		return;
15599bfa35feSMarcel Holtmann 
15609bfa35feSMarcel Holtmann 	if (urb->status == 0) {
15619bfa35feSMarcel Holtmann 		for (i = 0; i < urb->number_of_packets; i++) {
15629bfa35feSMarcel Holtmann 			unsigned int offset = urb->iso_frame_desc[i].offset;
15639bfa35feSMarcel Holtmann 			unsigned int length = urb->iso_frame_desc[i].actual_length;
15649bfa35feSMarcel Holtmann 
15659bfa35feSMarcel Holtmann 			if (urb->iso_frame_desc[i].status)
15669bfa35feSMarcel Holtmann 				continue;
15679bfa35feSMarcel Holtmann 
15689bfa35feSMarcel Holtmann 			hdev->stat.byte_rx += length;
15699bfa35feSMarcel Holtmann 
15701ffa4ad0SMarcel Holtmann 			if (btusb_recv_isoc(data, urb->transfer_buffer + offset,
15719bfa35feSMarcel Holtmann 					    length) < 0) {
15722064ee33SMarcel Holtmann 				bt_dev_err(hdev, "corrupted SCO packet");
15739bfa35feSMarcel Holtmann 				hdev->stat.err_rx++;
15749bfa35feSMarcel Holtmann 			}
15759bfa35feSMarcel Holtmann 		}
157685560c4aSChampion Chen 	} else if (urb->status == -ENOENT) {
157785560c4aSChampion Chen 		/* Avoid suspend failed when usb_kill_urb */
157885560c4aSChampion Chen 		return;
15799bfa35feSMarcel Holtmann 	}
15809bfa35feSMarcel Holtmann 
15819bfa35feSMarcel Holtmann 	if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags))
15829bfa35feSMarcel Holtmann 		return;
15839bfa35feSMarcel Holtmann 
15849bfa35feSMarcel Holtmann 	usb_anchor_urb(urb, &data->isoc_anchor);
15859bfa35feSMarcel Holtmann 
15869bfa35feSMarcel Holtmann 	err = usb_submit_urb(urb, GFP_ATOMIC);
15879bfa35feSMarcel Holtmann 	if (err < 0) {
15884935f1c1SPaul Bolle 		/* -EPERM: urb is being killed;
1589d98422cbSDerek Robson 		 * -ENODEV: device got disconnected
1590d98422cbSDerek Robson 		 */
15914935f1c1SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
15922064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
15932064ee33SMarcel Holtmann 				   urb, -err);
15949bfa35feSMarcel Holtmann 		usb_unanchor_urb(urb);
15959bfa35feSMarcel Holtmann 	}
15969bfa35feSMarcel Holtmann }
15979bfa35feSMarcel Holtmann 
__fill_isoc_descriptor_msbc(struct urb * urb,int len,int mtu,struct btusb_data * data)1598baac6276SSathish Narasimman static inline void __fill_isoc_descriptor_msbc(struct urb *urb, int len,
1599baac6276SSathish Narasimman 					       int mtu, struct btusb_data *data)
1600baac6276SSathish Narasimman {
1601a479e713SHilda Wu 	int i = 0, offset = 0;
1602baac6276SSathish Narasimman 	unsigned int interval;
1603baac6276SSathish Narasimman 
1604baac6276SSathish Narasimman 	BT_DBG("len %d mtu %d", len, mtu);
1605baac6276SSathish Narasimman 
1606a479e713SHilda Wu 	/* For mSBC ALT 6 settings some chips need to transmit the data
1607a479e713SHilda Wu 	 * continuously without the zero length of USB packets.
1608a479e713SHilda Wu 	 */
1609a479e713SHilda Wu 	if (test_bit(BTUSB_ALT6_CONTINUOUS_TX, &data->flags))
1610a479e713SHilda Wu 		goto ignore_usb_alt6_packet_flow;
1611a479e713SHilda Wu 
1612baac6276SSathish Narasimman 	/* For mSBC ALT 6 setting the host will send the packet at continuous
1613baac6276SSathish Narasimman 	 * flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting
1614baac6276SSathish Narasimman 	 * 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets.
1615baac6276SSathish Narasimman 	 * To maintain the rate we send 63bytes of usb packets alternatively for
1616baac6276SSathish Narasimman 	 * 7ms and 8ms to maintain the rate as 7.5ms.
1617baac6276SSathish Narasimman 	 */
1618baac6276SSathish Narasimman 	if (data->usb_alt6_packet_flow) {
1619baac6276SSathish Narasimman 		interval = 7;
1620baac6276SSathish Narasimman 		data->usb_alt6_packet_flow = false;
1621baac6276SSathish Narasimman 	} else {
1622baac6276SSathish Narasimman 		interval = 6;
1623baac6276SSathish Narasimman 		data->usb_alt6_packet_flow = true;
1624baac6276SSathish Narasimman 	}
1625baac6276SSathish Narasimman 
1626baac6276SSathish Narasimman 	for (i = 0; i < interval; i++) {
1627baac6276SSathish Narasimman 		urb->iso_frame_desc[i].offset = offset;
1628baac6276SSathish Narasimman 		urb->iso_frame_desc[i].length = offset;
1629baac6276SSathish Narasimman 	}
1630baac6276SSathish Narasimman 
1631a479e713SHilda Wu ignore_usb_alt6_packet_flow:
1632baac6276SSathish Narasimman 	if (len && i < BTUSB_MAX_ISOC_FRAMES) {
1633baac6276SSathish Narasimman 		urb->iso_frame_desc[i].offset = offset;
1634baac6276SSathish Narasimman 		urb->iso_frame_desc[i].length = len;
1635baac6276SSathish Narasimman 		i++;
1636baac6276SSathish Narasimman 	}
1637baac6276SSathish Narasimman 
1638baac6276SSathish Narasimman 	urb->number_of_packets = i;
1639baac6276SSathish Narasimman }
1640baac6276SSathish Narasimman 
__fill_isoc_descriptor(struct urb * urb,int len,int mtu)164142b16b3fSJesper Juhl static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
16429bfa35feSMarcel Holtmann {
16439bfa35feSMarcel Holtmann 	int i, offset = 0;
16449bfa35feSMarcel Holtmann 
16459bfa35feSMarcel Holtmann 	BT_DBG("len %d mtu %d", len, mtu);
16469bfa35feSMarcel Holtmann 
16479bfa35feSMarcel Holtmann 	for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu;
16489bfa35feSMarcel Holtmann 					i++, offset += mtu, len -= mtu) {
16499bfa35feSMarcel Holtmann 		urb->iso_frame_desc[i].offset = offset;
16509bfa35feSMarcel Holtmann 		urb->iso_frame_desc[i].length = mtu;
16519bfa35feSMarcel Holtmann 	}
16529bfa35feSMarcel Holtmann 
16539bfa35feSMarcel Holtmann 	if (len && i < BTUSB_MAX_ISOC_FRAMES) {
16549bfa35feSMarcel Holtmann 		urb->iso_frame_desc[i].offset = offset;
16559bfa35feSMarcel Holtmann 		urb->iso_frame_desc[i].length = len;
16569bfa35feSMarcel Holtmann 		i++;
16579bfa35feSMarcel Holtmann 	}
16589bfa35feSMarcel Holtmann 
16599bfa35feSMarcel Holtmann 	urb->number_of_packets = i;
16609bfa35feSMarcel Holtmann }
16619bfa35feSMarcel Holtmann 
btusb_submit_isoc_urb(struct hci_dev * hdev,gfp_t mem_flags)16622eda66f4SMarcel Holtmann static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
16639bfa35feSMarcel Holtmann {
1664155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
16659bfa35feSMarcel Holtmann 	struct urb *urb;
16669bfa35feSMarcel Holtmann 	unsigned char *buf;
16679bfa35feSMarcel Holtmann 	unsigned int pipe;
16689bfa35feSMarcel Holtmann 	int err, size;
16699bfa35feSMarcel Holtmann 
16709bfa35feSMarcel Holtmann 	BT_DBG("%s", hdev->name);
16719bfa35feSMarcel Holtmann 
16729bfa35feSMarcel Holtmann 	if (!data->isoc_rx_ep)
16739bfa35feSMarcel Holtmann 		return -ENODEV;
16749bfa35feSMarcel Holtmann 
16752eda66f4SMarcel Holtmann 	urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, mem_flags);
16769bfa35feSMarcel Holtmann 	if (!urb)
16779bfa35feSMarcel Holtmann 		return -ENOMEM;
16789bfa35feSMarcel Holtmann 
16799bfa35feSMarcel Holtmann 	size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) *
16809bfa35feSMarcel Holtmann 						BTUSB_MAX_ISOC_FRAMES;
16819bfa35feSMarcel Holtmann 
16822eda66f4SMarcel Holtmann 	buf = kmalloc(size, mem_flags);
16839bfa35feSMarcel Holtmann 	if (!buf) {
16849bfa35feSMarcel Holtmann 		usb_free_urb(urb);
16859bfa35feSMarcel Holtmann 		return -ENOMEM;
16869bfa35feSMarcel Holtmann 	}
16879bfa35feSMarcel Holtmann 
16889bfa35feSMarcel Holtmann 	pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
16899bfa35feSMarcel Holtmann 
1690fa0fb93fSBing Zhao 	usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete,
1691fa0fb93fSBing Zhao 			 hdev, data->isoc_rx_ep->bInterval);
16929bfa35feSMarcel Holtmann 
16939bfa35feSMarcel Holtmann 	urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
16949bfa35feSMarcel Holtmann 
16959bfa35feSMarcel Holtmann 	__fill_isoc_descriptor(urb, size,
16969bfa35feSMarcel Holtmann 			       le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
16979bfa35feSMarcel Holtmann 
16989bfa35feSMarcel Holtmann 	usb_anchor_urb(urb, &data->isoc_anchor);
16999bfa35feSMarcel Holtmann 
17002eda66f4SMarcel Holtmann 	err = usb_submit_urb(urb, mem_flags);
17019bfa35feSMarcel Holtmann 	if (err < 0) {
1702d4b8d1c9SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
17032064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p submission failed (%d)",
17042064ee33SMarcel Holtmann 				   urb, -err);
17059bfa35feSMarcel Holtmann 		usb_unanchor_urb(urb);
17069bfa35feSMarcel Holtmann 	}
17079bfa35feSMarcel Holtmann 
17089bfa35feSMarcel Holtmann 	usb_free_urb(urb);
17099bfa35feSMarcel Holtmann 
17109bfa35feSMarcel Holtmann 	return err;
17119bfa35feSMarcel Holtmann }
17129bfa35feSMarcel Holtmann 
btusb_diag_complete(struct urb * urb)17139d08f504SMarcel Holtmann static void btusb_diag_complete(struct urb *urb)
17149d08f504SMarcel Holtmann {
17159d08f504SMarcel Holtmann 	struct hci_dev *hdev = urb->context;
17169d08f504SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
17179d08f504SMarcel Holtmann 	int err;
17189d08f504SMarcel Holtmann 
17199d08f504SMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
17209d08f504SMarcel Holtmann 	       urb->actual_length);
17219d08f504SMarcel Holtmann 
17229d08f504SMarcel Holtmann 	if (urb->status == 0) {
17239d08f504SMarcel Holtmann 		struct sk_buff *skb;
17249d08f504SMarcel Holtmann 
17259d08f504SMarcel Holtmann 		skb = bt_skb_alloc(urb->actual_length, GFP_ATOMIC);
17269d08f504SMarcel Holtmann 		if (skb) {
172759ae1d12SJohannes Berg 			skb_put_data(skb, urb->transfer_buffer,
172859ae1d12SJohannes Berg 				     urb->actual_length);
17299d08f504SMarcel Holtmann 			hci_recv_diag(hdev, skb);
17309d08f504SMarcel Holtmann 		}
17319d08f504SMarcel Holtmann 	} else if (urb->status == -ENOENT) {
17329d08f504SMarcel Holtmann 		/* Avoid suspend failed when usb_kill_urb */
17339d08f504SMarcel Holtmann 		return;
17349d08f504SMarcel Holtmann 	}
17359d08f504SMarcel Holtmann 
17369d08f504SMarcel Holtmann 	if (!test_bit(BTUSB_DIAG_RUNNING, &data->flags))
17379d08f504SMarcel Holtmann 		return;
17389d08f504SMarcel Holtmann 
17399d08f504SMarcel Holtmann 	usb_anchor_urb(urb, &data->diag_anchor);
17409d08f504SMarcel Holtmann 	usb_mark_last_busy(data->udev);
17419d08f504SMarcel Holtmann 
17429d08f504SMarcel Holtmann 	err = usb_submit_urb(urb, GFP_ATOMIC);
17439d08f504SMarcel Holtmann 	if (err < 0) {
17449d08f504SMarcel Holtmann 		/* -EPERM: urb is being killed;
1745d98422cbSDerek Robson 		 * -ENODEV: device got disconnected
1746d98422cbSDerek Robson 		 */
17479d08f504SMarcel Holtmann 		if (err != -EPERM && err != -ENODEV)
17482064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
17492064ee33SMarcel Holtmann 				   urb, -err);
17509d08f504SMarcel Holtmann 		usb_unanchor_urb(urb);
17519d08f504SMarcel Holtmann 	}
17529d08f504SMarcel Holtmann }
17539d08f504SMarcel Holtmann 
btusb_submit_diag_urb(struct hci_dev * hdev,gfp_t mem_flags)17549d08f504SMarcel Holtmann static int btusb_submit_diag_urb(struct hci_dev *hdev, gfp_t mem_flags)
17559d08f504SMarcel Holtmann {
17569d08f504SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
17579d08f504SMarcel Holtmann 	struct urb *urb;
17589d08f504SMarcel Holtmann 	unsigned char *buf;
17599d08f504SMarcel Holtmann 	unsigned int pipe;
17609d08f504SMarcel Holtmann 	int err, size = HCI_MAX_FRAME_SIZE;
17619d08f504SMarcel Holtmann 
17629d08f504SMarcel Holtmann 	BT_DBG("%s", hdev->name);
17639d08f504SMarcel Holtmann 
17649d08f504SMarcel Holtmann 	if (!data->diag_rx_ep)
17659d08f504SMarcel Holtmann 		return -ENODEV;
17669d08f504SMarcel Holtmann 
17679d08f504SMarcel Holtmann 	urb = usb_alloc_urb(0, mem_flags);
17689d08f504SMarcel Holtmann 	if (!urb)
17699d08f504SMarcel Holtmann 		return -ENOMEM;
17709d08f504SMarcel Holtmann 
17719d08f504SMarcel Holtmann 	buf = kmalloc(size, mem_flags);
17729d08f504SMarcel Holtmann 	if (!buf) {
17739d08f504SMarcel Holtmann 		usb_free_urb(urb);
17749d08f504SMarcel Holtmann 		return -ENOMEM;
17759d08f504SMarcel Holtmann 	}
17769d08f504SMarcel Holtmann 
17779d08f504SMarcel Holtmann 	pipe = usb_rcvbulkpipe(data->udev, data->diag_rx_ep->bEndpointAddress);
17789d08f504SMarcel Holtmann 
17799d08f504SMarcel Holtmann 	usb_fill_bulk_urb(urb, data->udev, pipe, buf, size,
17809d08f504SMarcel Holtmann 			  btusb_diag_complete, hdev);
17819d08f504SMarcel Holtmann 
17829d08f504SMarcel Holtmann 	urb->transfer_flags |= URB_FREE_BUFFER;
17839d08f504SMarcel Holtmann 
17849d08f504SMarcel Holtmann 	usb_mark_last_busy(data->udev);
17859d08f504SMarcel Holtmann 	usb_anchor_urb(urb, &data->diag_anchor);
17869d08f504SMarcel Holtmann 
17879d08f504SMarcel Holtmann 	err = usb_submit_urb(urb, mem_flags);
17889d08f504SMarcel Holtmann 	if (err < 0) {
17899d08f504SMarcel Holtmann 		if (err != -EPERM && err != -ENODEV)
17902064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p submission failed (%d)",
17912064ee33SMarcel Holtmann 				   urb, -err);
17929d08f504SMarcel Holtmann 		usb_unanchor_urb(urb);
17939d08f504SMarcel Holtmann 	}
17949d08f504SMarcel Holtmann 
17959d08f504SMarcel Holtmann 	usb_free_urb(urb);
17969d08f504SMarcel Holtmann 
17979d08f504SMarcel Holtmann 	return err;
17989d08f504SMarcel Holtmann }
17999d08f504SMarcel Holtmann 
btusb_tx_complete(struct urb * urb)18005e23b923SMarcel Holtmann static void btusb_tx_complete(struct urb *urb)
18015e23b923SMarcel Holtmann {
18025e23b923SMarcel Holtmann 	struct sk_buff *skb = urb->context;
18035e23b923SMarcel Holtmann 	struct hci_dev *hdev = (struct hci_dev *)skb->dev;
1804155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
1805a5e50d5bSSebastian Andrzej Siewior 	unsigned long flags;
18067bee549eSOliver Neukum 
180789e7533dSMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
180889e7533dSMarcel Holtmann 	       urb->actual_length);
18097bee549eSOliver Neukum 
18107bee549eSOliver Neukum 	if (!test_bit(HCI_RUNNING, &hdev->flags))
18117bee549eSOliver Neukum 		goto done;
18127bee549eSOliver Neukum 
1813c97a747eSBenjamin Berg 	if (!urb->status) {
18147bee549eSOliver Neukum 		hdev->stat.byte_tx += urb->transfer_buffer_length;
1815c97a747eSBenjamin Berg 	} else {
1816c97a747eSBenjamin Berg 		if (hci_skb_pkt_type(skb) == HCI_COMMAND_PKT)
1817c97a747eSBenjamin Berg 			hci_cmd_sync_cancel(hdev, -urb->status);
18187bee549eSOliver Neukum 		hdev->stat.err_tx++;
1819c97a747eSBenjamin Berg 	}
18207bee549eSOliver Neukum 
18217bee549eSOliver Neukum done:
1822a5e50d5bSSebastian Andrzej Siewior 	spin_lock_irqsave(&data->txlock, flags);
18237bee549eSOliver Neukum 	data->tx_in_flight--;
1824a5e50d5bSSebastian Andrzej Siewior 	spin_unlock_irqrestore(&data->txlock, flags);
18257bee549eSOliver Neukum 
18267bee549eSOliver Neukum 	kfree(urb->setup_packet);
18277bee549eSOliver Neukum 
18287bee549eSOliver Neukum 	kfree_skb(skb);
18297bee549eSOliver Neukum }
18307bee549eSOliver Neukum 
btusb_isoc_tx_complete(struct urb * urb)18317bee549eSOliver Neukum static void btusb_isoc_tx_complete(struct urb *urb)
18327bee549eSOliver Neukum {
18337bee549eSOliver Neukum 	struct sk_buff *skb = urb->context;
18347bee549eSOliver Neukum 	struct hci_dev *hdev = (struct hci_dev *)skb->dev;
18355e23b923SMarcel Holtmann 
183689e7533dSMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
183789e7533dSMarcel Holtmann 	       urb->actual_length);
18385e23b923SMarcel Holtmann 
18395e23b923SMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
18405e23b923SMarcel Holtmann 		goto done;
18415e23b923SMarcel Holtmann 
18425e23b923SMarcel Holtmann 	if (!urb->status)
18435e23b923SMarcel Holtmann 		hdev->stat.byte_tx += urb->transfer_buffer_length;
18445e23b923SMarcel Holtmann 	else
18455e23b923SMarcel Holtmann 		hdev->stat.err_tx++;
18465e23b923SMarcel Holtmann 
18475e23b923SMarcel Holtmann done:
18485e23b923SMarcel Holtmann 	kfree(urb->setup_packet);
18495e23b923SMarcel Holtmann 
18505e23b923SMarcel Holtmann 	kfree_skb(skb);
18515e23b923SMarcel Holtmann }
18525e23b923SMarcel Holtmann 
btusb_open(struct hci_dev * hdev)18535e23b923SMarcel Holtmann static int btusb_open(struct hci_dev *hdev)
18545e23b923SMarcel Holtmann {
1855155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
18565e23b923SMarcel Holtmann 	int err;
18575e23b923SMarcel Holtmann 
18585e23b923SMarcel Holtmann 	BT_DBG("%s", hdev->name);
18595e23b923SMarcel Holtmann 
1860c7e163feSEthan Hsieh 	err = usb_autopm_get_interface(data->intf);
1861c7e163feSEthan Hsieh 	if (err < 0)
1862c7e163feSEthan Hsieh 		return err;
1863c7e163feSEthan Hsieh 
1864ace31982SKim, Ben Young Tae 	/* Patching USB firmware files prior to starting any URBs of HCI path
1865ace31982SKim, Ben Young Tae 	 * It is more safe to use USB bulk channel for downloading USB patch
1866ace31982SKim, Ben Young Tae 	 */
1867ace31982SKim, Ben Young Tae 	if (data->setup_on_usb) {
1868ace31982SKim, Ben Young Tae 		err = data->setup_on_usb(hdev);
1869ace31982SKim, Ben Young Tae 		if (err < 0)
18703d44a6fdSOliver Neukum 			goto setup_fail;
1871ace31982SKim, Ben Young Tae 	}
1872ace31982SKim, Ben Young Tae 
18737bee549eSOliver Neukum 	data->intf->needs_remote_wakeup = 1;
18747bee549eSOliver Neukum 
18755e23b923SMarcel Holtmann 	if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
18767bee549eSOliver Neukum 		goto done;
18775e23b923SMarcel Holtmann 
18782eda66f4SMarcel Holtmann 	err = btusb_submit_intr_urb(hdev, GFP_KERNEL);
187943c2e57fSMarcel Holtmann 	if (err < 0)
188043c2e57fSMarcel Holtmann 		goto failed;
188143c2e57fSMarcel Holtmann 
188243c2e57fSMarcel Holtmann 	err = btusb_submit_bulk_urb(hdev, GFP_KERNEL);
18835e23b923SMarcel Holtmann 	if (err < 0) {
188443c2e57fSMarcel Holtmann 		usb_kill_anchored_urbs(&data->intr_anchor);
188543c2e57fSMarcel Holtmann 		goto failed;
18865e23b923SMarcel Holtmann 	}
18875e23b923SMarcel Holtmann 
188843c2e57fSMarcel Holtmann 	set_bit(BTUSB_BULK_RUNNING, &data->flags);
188943c2e57fSMarcel Holtmann 	btusb_submit_bulk_urb(hdev, GFP_KERNEL);
189043c2e57fSMarcel Holtmann 
18919d08f504SMarcel Holtmann 	if (data->diag) {
18929d08f504SMarcel Holtmann 		if (!btusb_submit_diag_urb(hdev, GFP_KERNEL))
18939d08f504SMarcel Holtmann 			set_bit(BTUSB_DIAG_RUNNING, &data->flags);
18949d08f504SMarcel Holtmann 	}
18959d08f504SMarcel Holtmann 
18967bee549eSOliver Neukum done:
18977bee549eSOliver Neukum 	usb_autopm_put_interface(data->intf);
189843c2e57fSMarcel Holtmann 	return 0;
189943c2e57fSMarcel Holtmann 
190043c2e57fSMarcel Holtmann failed:
190143c2e57fSMarcel Holtmann 	clear_bit(BTUSB_INTR_RUNNING, &data->flags);
19023d44a6fdSOliver Neukum setup_fail:
19037bee549eSOliver Neukum 	usb_autopm_put_interface(data->intf);
19045e23b923SMarcel Holtmann 	return err;
19055e23b923SMarcel Holtmann }
19065e23b923SMarcel Holtmann 
btusb_stop_traffic(struct btusb_data * data)19077bee549eSOliver Neukum static void btusb_stop_traffic(struct btusb_data *data)
19087bee549eSOliver Neukum {
19097bee549eSOliver Neukum 	usb_kill_anchored_urbs(&data->intr_anchor);
19107bee549eSOliver Neukum 	usb_kill_anchored_urbs(&data->bulk_anchor);
19117bee549eSOliver Neukum 	usb_kill_anchored_urbs(&data->isoc_anchor);
19129d08f504SMarcel Holtmann 	usb_kill_anchored_urbs(&data->diag_anchor);
1913a1c49c43SSean Wang 	usb_kill_anchored_urbs(&data->ctrl_anchor);
19147bee549eSOliver Neukum }
19157bee549eSOliver Neukum 
btusb_close(struct hci_dev * hdev)19165e23b923SMarcel Holtmann static int btusb_close(struct hci_dev *hdev)
19175e23b923SMarcel Holtmann {
1918155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
19197bee549eSOliver Neukum 	int err;
19205e23b923SMarcel Holtmann 
19215e23b923SMarcel Holtmann 	BT_DBG("%s", hdev->name);
19225e23b923SMarcel Holtmann 
1923800fe5ecSLuiz Augusto von Dentz 	cancel_delayed_work(&data->rx_work);
1924e8c3c3d2SMarcel Holtmann 	cancel_work_sync(&data->work);
1925404291acSLinus Torvalds 	cancel_work_sync(&data->waker);
1926e8c3c3d2SMarcel Holtmann 
1927800fe5ecSLuiz Augusto von Dentz 	skb_queue_purge(&data->acl_q);
1928800fe5ecSLuiz Augusto von Dentz 
19299bfa35feSMarcel Holtmann 	clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
19305e23b923SMarcel Holtmann 	clear_bit(BTUSB_BULK_RUNNING, &data->flags);
19315e23b923SMarcel Holtmann 	clear_bit(BTUSB_INTR_RUNNING, &data->flags);
19329d08f504SMarcel Holtmann 	clear_bit(BTUSB_DIAG_RUNNING, &data->flags);
19337bee549eSOliver Neukum 
19347bee549eSOliver Neukum 	btusb_stop_traffic(data);
1935803b5836SMarcel Holtmann 	btusb_free_frags(data);
1936803b5836SMarcel Holtmann 
19377bee549eSOliver Neukum 	err = usb_autopm_get_interface(data->intf);
19387bee549eSOliver Neukum 	if (err < 0)
19397b8e2c1dSOliver Neukum 		goto failed;
19407bee549eSOliver Neukum 
19417bee549eSOliver Neukum 	data->intf->needs_remote_wakeup = 0;
19429e45524aSAlex Lu 
19439e45524aSAlex Lu 	/* Enable remote wake up for auto-suspend */
19448274db07SMax Chou 	if (test_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags))
19459e45524aSAlex Lu 		data->intf->needs_remote_wakeup = 1;
19469e45524aSAlex Lu 
19477bee549eSOliver Neukum 	usb_autopm_put_interface(data->intf);
19485e23b923SMarcel Holtmann 
19497b8e2c1dSOliver Neukum failed:
19507b8e2c1dSOliver Neukum 	usb_scuttle_anchored_urbs(&data->deferred);
19515e23b923SMarcel Holtmann 	return 0;
19525e23b923SMarcel Holtmann }
19535e23b923SMarcel Holtmann 
btusb_flush(struct hci_dev * hdev)19545e23b923SMarcel Holtmann static int btusb_flush(struct hci_dev *hdev)
19555e23b923SMarcel Holtmann {
1956155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
19575e23b923SMarcel Holtmann 
19585e23b923SMarcel Holtmann 	BT_DBG("%s", hdev->name);
19595e23b923SMarcel Holtmann 
1960800fe5ecSLuiz Augusto von Dentz 	cancel_delayed_work(&data->rx_work);
1961800fe5ecSLuiz Augusto von Dentz 
1962800fe5ecSLuiz Augusto von Dentz 	skb_queue_purge(&data->acl_q);
1963800fe5ecSLuiz Augusto von Dentz 
19645e23b923SMarcel Holtmann 	usb_kill_anchored_urbs(&data->tx_anchor);
1965803b5836SMarcel Holtmann 	btusb_free_frags(data);
19665e23b923SMarcel Holtmann 
19675e23b923SMarcel Holtmann 	return 0;
19685e23b923SMarcel Holtmann }
19695e23b923SMarcel Holtmann 
alloc_ctrl_urb(struct hci_dev * hdev,struct sk_buff * skb)1970047b2ec8SMarcel Holtmann static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb)
19715e23b923SMarcel Holtmann {
1972155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
19735e23b923SMarcel Holtmann 	struct usb_ctrlrequest *dr;
19745e23b923SMarcel Holtmann 	struct urb *urb;
19755e23b923SMarcel Holtmann 	unsigned int pipe;
19765e23b923SMarcel Holtmann 
1977e9753effSJohan Hedberg 	urb = usb_alloc_urb(0, GFP_KERNEL);
19785e23b923SMarcel Holtmann 	if (!urb)
1979047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
19805e23b923SMarcel Holtmann 
1981e9753effSJohan Hedberg 	dr = kmalloc(sizeof(*dr), GFP_KERNEL);
19825e23b923SMarcel Holtmann 	if (!dr) {
19835e23b923SMarcel Holtmann 		usb_free_urb(urb);
1984047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
19855e23b923SMarcel Holtmann 	}
19865e23b923SMarcel Holtmann 
19877a9d4020SMarcel Holtmann 	dr->bRequestType = data->cmdreq_type;
1988893ba544SMarcel Holtmann 	dr->bRequest     = data->cmdreq;
19895e23b923SMarcel Holtmann 	dr->wIndex       = 0;
19905e23b923SMarcel Holtmann 	dr->wValue       = 0;
19915e23b923SMarcel Holtmann 	dr->wLength      = __cpu_to_le16(skb->len);
19925e23b923SMarcel Holtmann 
19935e23b923SMarcel Holtmann 	pipe = usb_sndctrlpipe(data->udev, 0x00);
19945e23b923SMarcel Holtmann 
19955e23b923SMarcel Holtmann 	usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
19965e23b923SMarcel Holtmann 			     skb->data, skb->len, btusb_tx_complete, skb);
19975e23b923SMarcel Holtmann 
1998047b2ec8SMarcel Holtmann 	skb->dev = (void *)hdev;
19995e23b923SMarcel Holtmann 
2000047b2ec8SMarcel Holtmann 	return urb;
2001047b2ec8SMarcel Holtmann }
2002047b2ec8SMarcel Holtmann 
alloc_bulk_urb(struct hci_dev * hdev,struct sk_buff * skb)2003047b2ec8SMarcel Holtmann static struct urb *alloc_bulk_urb(struct hci_dev *hdev, struct sk_buff *skb)
2004047b2ec8SMarcel Holtmann {
2005047b2ec8SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
2006047b2ec8SMarcel Holtmann 	struct urb *urb;
2007047b2ec8SMarcel Holtmann 	unsigned int pipe;
2008047b2ec8SMarcel Holtmann 
20099fd481e0SPeter Hurley 	if (!data->bulk_tx_ep)
2010047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENODEV);
20119bfa35feSMarcel Holtmann 
2012e9753effSJohan Hedberg 	urb = usb_alloc_urb(0, GFP_KERNEL);
20135e23b923SMarcel Holtmann 	if (!urb)
2014047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
20155e23b923SMarcel Holtmann 
2016047b2ec8SMarcel Holtmann 	pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
20175e23b923SMarcel Holtmann 
20185e23b923SMarcel Holtmann 	usb_fill_bulk_urb(urb, data->udev, pipe,
20195e23b923SMarcel Holtmann 			  skb->data, skb->len, btusb_tx_complete, skb);
20205e23b923SMarcel Holtmann 
2021047b2ec8SMarcel Holtmann 	skb->dev = (void *)hdev;
20225e23b923SMarcel Holtmann 
2023047b2ec8SMarcel Holtmann 	return urb;
2024047b2ec8SMarcel Holtmann }
2025047b2ec8SMarcel Holtmann 
alloc_isoc_urb(struct hci_dev * hdev,struct sk_buff * skb)2026047b2ec8SMarcel Holtmann static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
2027047b2ec8SMarcel Holtmann {
2028047b2ec8SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
2029047b2ec8SMarcel Holtmann 	struct urb *urb;
2030047b2ec8SMarcel Holtmann 	unsigned int pipe;
2031047b2ec8SMarcel Holtmann 
2032047b2ec8SMarcel Holtmann 	if (!data->isoc_tx_ep)
2033047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENODEV);
20349bfa35feSMarcel Holtmann 
2035e9753effSJohan Hedberg 	urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
20369bfa35feSMarcel Holtmann 	if (!urb)
2037047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
20389bfa35feSMarcel Holtmann 
2039047b2ec8SMarcel Holtmann 	pipe = usb_sndisocpipe(data->udev, data->isoc_tx_ep->bEndpointAddress);
20409bfa35feSMarcel Holtmann 
204103c2d0e8SGustavo F. Padovan 	usb_fill_int_urb(urb, data->udev, pipe,
204203c2d0e8SGustavo F. Padovan 			 skb->data, skb->len, btusb_isoc_tx_complete,
204303c2d0e8SGustavo F. Padovan 			 skb, data->isoc_tx_ep->bInterval);
20449bfa35feSMarcel Holtmann 
20459bfa35feSMarcel Holtmann 	urb->transfer_flags  = URB_ISO_ASAP;
20469bfa35feSMarcel Holtmann 
2047baac6276SSathish Narasimman 	if (data->isoc_altsetting == 6)
2048baac6276SSathish Narasimman 		__fill_isoc_descriptor_msbc(urb, skb->len,
2049baac6276SSathish Narasimman 					    le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize),
2050baac6276SSathish Narasimman 					    data);
2051baac6276SSathish Narasimman 	else
20529bfa35feSMarcel Holtmann 		__fill_isoc_descriptor(urb, skb->len,
20539bfa35feSMarcel Holtmann 				       le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
2054047b2ec8SMarcel Holtmann 	skb->dev = (void *)hdev;
20555e23b923SMarcel Holtmann 
2056047b2ec8SMarcel Holtmann 	return urb;
20575e23b923SMarcel Holtmann }
20585e23b923SMarcel Holtmann 
submit_tx_urb(struct hci_dev * hdev,struct urb * urb)2059047b2ec8SMarcel Holtmann static int submit_tx_urb(struct hci_dev *hdev, struct urb *urb)
2060047b2ec8SMarcel Holtmann {
2061047b2ec8SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
2062047b2ec8SMarcel Holtmann 	int err;
20637bee549eSOliver Neukum 
20645e23b923SMarcel Holtmann 	usb_anchor_urb(urb, &data->tx_anchor);
20655e23b923SMarcel Holtmann 
2066e9753effSJohan Hedberg 	err = usb_submit_urb(urb, GFP_KERNEL);
20675e23b923SMarcel Holtmann 	if (err < 0) {
20685a9b80e2SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
20692064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p submission failed (%d)",
20702064ee33SMarcel Holtmann 				   urb, -err);
20715e23b923SMarcel Holtmann 		kfree(urb->setup_packet);
20725e23b923SMarcel Holtmann 		usb_unanchor_urb(urb);
20737bee549eSOliver Neukum 	} else {
20747bee549eSOliver Neukum 		usb_mark_last_busy(data->udev);
20755e23b923SMarcel Holtmann 	}
20765e23b923SMarcel Holtmann 
207754a8a79cSCong Wang 	usb_free_urb(urb);
20785e23b923SMarcel Holtmann 	return err;
20795e23b923SMarcel Holtmann }
20805e23b923SMarcel Holtmann 
submit_or_queue_tx_urb(struct hci_dev * hdev,struct urb * urb)2081047b2ec8SMarcel Holtmann static int submit_or_queue_tx_urb(struct hci_dev *hdev, struct urb *urb)
2082047b2ec8SMarcel Holtmann {
2083047b2ec8SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
2084047b2ec8SMarcel Holtmann 	unsigned long flags;
2085047b2ec8SMarcel Holtmann 	bool suspending;
2086047b2ec8SMarcel Holtmann 
2087047b2ec8SMarcel Holtmann 	spin_lock_irqsave(&data->txlock, flags);
2088047b2ec8SMarcel Holtmann 	suspending = test_bit(BTUSB_SUSPENDING, &data->flags);
2089047b2ec8SMarcel Holtmann 	if (!suspending)
2090047b2ec8SMarcel Holtmann 		data->tx_in_flight++;
2091047b2ec8SMarcel Holtmann 	spin_unlock_irqrestore(&data->txlock, flags);
2092047b2ec8SMarcel Holtmann 
2093047b2ec8SMarcel Holtmann 	if (!suspending)
2094047b2ec8SMarcel Holtmann 		return submit_tx_urb(hdev, urb);
2095047b2ec8SMarcel Holtmann 
2096047b2ec8SMarcel Holtmann 	usb_anchor_urb(urb, &data->deferred);
2097047b2ec8SMarcel Holtmann 	schedule_work(&data->waker);
2098047b2ec8SMarcel Holtmann 
2099047b2ec8SMarcel Holtmann 	usb_free_urb(urb);
2100047b2ec8SMarcel Holtmann 	return 0;
2101047b2ec8SMarcel Holtmann }
2102047b2ec8SMarcel Holtmann 
btusb_send_frame(struct hci_dev * hdev,struct sk_buff * skb)2103047b2ec8SMarcel Holtmann static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
2104047b2ec8SMarcel Holtmann {
2105047b2ec8SMarcel Holtmann 	struct urb *urb;
2106047b2ec8SMarcel Holtmann 
2107047b2ec8SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2108047b2ec8SMarcel Holtmann 
2109618e8bc2SMarcel Holtmann 	switch (hci_skb_pkt_type(skb)) {
2110047b2ec8SMarcel Holtmann 	case HCI_COMMAND_PKT:
2111047b2ec8SMarcel Holtmann 		urb = alloc_ctrl_urb(hdev, skb);
2112047b2ec8SMarcel Holtmann 		if (IS_ERR(urb))
2113047b2ec8SMarcel Holtmann 			return PTR_ERR(urb);
2114047b2ec8SMarcel Holtmann 
2115047b2ec8SMarcel Holtmann 		hdev->stat.cmd_tx++;
2116047b2ec8SMarcel Holtmann 		return submit_or_queue_tx_urb(hdev, urb);
2117047b2ec8SMarcel Holtmann 
2118047b2ec8SMarcel Holtmann 	case HCI_ACLDATA_PKT:
2119047b2ec8SMarcel Holtmann 		urb = alloc_bulk_urb(hdev, skb);
2120047b2ec8SMarcel Holtmann 		if (IS_ERR(urb))
2121047b2ec8SMarcel Holtmann 			return PTR_ERR(urb);
2122047b2ec8SMarcel Holtmann 
2123047b2ec8SMarcel Holtmann 		hdev->stat.acl_tx++;
2124047b2ec8SMarcel Holtmann 		return submit_or_queue_tx_urb(hdev, urb);
2125047b2ec8SMarcel Holtmann 
2126047b2ec8SMarcel Holtmann 	case HCI_SCODATA_PKT:
2127047b2ec8SMarcel Holtmann 		if (hci_conn_num(hdev, SCO_LINK) < 1)
2128047b2ec8SMarcel Holtmann 			return -ENODEV;
2129047b2ec8SMarcel Holtmann 
2130047b2ec8SMarcel Holtmann 		urb = alloc_isoc_urb(hdev, skb);
2131047b2ec8SMarcel Holtmann 		if (IS_ERR(urb))
2132047b2ec8SMarcel Holtmann 			return PTR_ERR(urb);
2133047b2ec8SMarcel Holtmann 
2134047b2ec8SMarcel Holtmann 		hdev->stat.sco_tx++;
2135047b2ec8SMarcel Holtmann 		return submit_tx_urb(hdev, urb);
213670405f02SLuiz Augusto von Dentz 
213770405f02SLuiz Augusto von Dentz 	case HCI_ISODATA_PKT:
213870405f02SLuiz Augusto von Dentz 		urb = alloc_bulk_urb(hdev, skb);
213970405f02SLuiz Augusto von Dentz 		if (IS_ERR(urb))
214070405f02SLuiz Augusto von Dentz 			return PTR_ERR(urb);
214170405f02SLuiz Augusto von Dentz 
214270405f02SLuiz Augusto von Dentz 		return submit_or_queue_tx_urb(hdev, urb);
2143047b2ec8SMarcel Holtmann 	}
2144047b2ec8SMarcel Holtmann 
2145047b2ec8SMarcel Holtmann 	return -EILSEQ;
2146047b2ec8SMarcel Holtmann }
2147047b2ec8SMarcel Holtmann 
btusb_notify(struct hci_dev * hdev,unsigned int evt)21485e23b923SMarcel Holtmann static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
21495e23b923SMarcel Holtmann {
2150155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
21515e23b923SMarcel Holtmann 
21525e23b923SMarcel Holtmann 	BT_DBG("%s evt %d", hdev->name, evt);
21535e23b923SMarcel Holtmann 
2154014f7bc7SMarcel Holtmann 	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
2155014f7bc7SMarcel Holtmann 		data->sco_num = hci_conn_num(hdev, SCO_LINK);
2156baac6276SSathish Narasimman 		data->air_mode = evt;
21575e23b923SMarcel Holtmann 		schedule_work(&data->work);
21585e23b923SMarcel Holtmann 	}
215943c2e57fSMarcel Holtmann }
21605e23b923SMarcel Holtmann 
__set_isoc_interface(struct hci_dev * hdev,int altsetting)216142b16b3fSJesper Juhl static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
21629bfa35feSMarcel Holtmann {
2163155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
21649bfa35feSMarcel Holtmann 	struct usb_interface *intf = data->isoc;
21659bfa35feSMarcel Holtmann 	struct usb_endpoint_descriptor *ep_desc;
21669bfa35feSMarcel Holtmann 	int i, err;
21679bfa35feSMarcel Holtmann 
21689bfa35feSMarcel Holtmann 	if (!data->isoc)
21699bfa35feSMarcel Holtmann 		return -ENODEV;
21709bfa35feSMarcel Holtmann 
2171459232fcSMarcel Holtmann 	err = usb_set_interface(data->udev, data->isoc_ifnum, altsetting);
21729bfa35feSMarcel Holtmann 	if (err < 0) {
21732064ee33SMarcel Holtmann 		bt_dev_err(hdev, "setting interface failed (%d)", -err);
21749bfa35feSMarcel Holtmann 		return err;
21759bfa35feSMarcel Holtmann 	}
21769bfa35feSMarcel Holtmann 
21779bfa35feSMarcel Holtmann 	data->isoc_altsetting = altsetting;
21789bfa35feSMarcel Holtmann 
21799bfa35feSMarcel Holtmann 	data->isoc_tx_ep = NULL;
21809bfa35feSMarcel Holtmann 	data->isoc_rx_ep = NULL;
21819bfa35feSMarcel Holtmann 
21829bfa35feSMarcel Holtmann 	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
21839bfa35feSMarcel Holtmann 		ep_desc = &intf->cur_altsetting->endpoint[i].desc;
21849bfa35feSMarcel Holtmann 
21859bfa35feSMarcel Holtmann 		if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) {
21869bfa35feSMarcel Holtmann 			data->isoc_tx_ep = ep_desc;
21879bfa35feSMarcel Holtmann 			continue;
21889bfa35feSMarcel Holtmann 		}
21899bfa35feSMarcel Holtmann 
21909bfa35feSMarcel Holtmann 		if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) {
21919bfa35feSMarcel Holtmann 			data->isoc_rx_ep = ep_desc;
21929bfa35feSMarcel Holtmann 			continue;
21939bfa35feSMarcel Holtmann 		}
21949bfa35feSMarcel Holtmann 	}
21959bfa35feSMarcel Holtmann 
21969bfa35feSMarcel Holtmann 	if (!data->isoc_tx_ep || !data->isoc_rx_ep) {
21972064ee33SMarcel Holtmann 		bt_dev_err(hdev, "invalid SCO descriptors");
21989bfa35feSMarcel Holtmann 		return -ENODEV;
21999bfa35feSMarcel Holtmann 	}
22009bfa35feSMarcel Holtmann 
22019bfa35feSMarcel Holtmann 	return 0;
22029bfa35feSMarcel Holtmann }
22039bfa35feSMarcel Holtmann 
btusb_switch_alt_setting(struct hci_dev * hdev,int new_alts)2204baac6276SSathish Narasimman static int btusb_switch_alt_setting(struct hci_dev *hdev, int new_alts)
22055e23b923SMarcel Holtmann {
2206baac6276SSathish Narasimman 	struct btusb_data *data = hci_get_drvdata(hdev);
22077bee549eSOliver Neukum 	int err;
22085e23b923SMarcel Holtmann 
2209f4001d28SMikel Astiz 	if (data->isoc_altsetting != new_alts) {
2210f6fc86f2SKuba Pawlak 		unsigned long flags;
2211f6fc86f2SKuba Pawlak 
22129bfa35feSMarcel Holtmann 		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
22139bfa35feSMarcel Holtmann 		usb_kill_anchored_urbs(&data->isoc_anchor);
22149bfa35feSMarcel Holtmann 
22158f9d02f4SKuba Pawlak 		/* When isochronous alternate setting needs to be
22168f9d02f4SKuba Pawlak 		 * changed, because SCO connection has been added
22178f9d02f4SKuba Pawlak 		 * or removed, a packet fragment may be left in the
22188f9d02f4SKuba Pawlak 		 * reassembling state. This could lead to wrongly
22198f9d02f4SKuba Pawlak 		 * assembled fragments.
22208f9d02f4SKuba Pawlak 		 *
22218f9d02f4SKuba Pawlak 		 * Clear outstanding fragment when selecting a new
22228f9d02f4SKuba Pawlak 		 * alternate setting.
22238f9d02f4SKuba Pawlak 		 */
2224f6fc86f2SKuba Pawlak 		spin_lock_irqsave(&data->rxlock, flags);
22252a05334dSJinjie Ruan 		dev_kfree_skb_irq(data->sco_skb);
22268f9d02f4SKuba Pawlak 		data->sco_skb = NULL;
2227f6fc86f2SKuba Pawlak 		spin_unlock_irqrestore(&data->rxlock, flags);
22288f9d02f4SKuba Pawlak 
2229baac6276SSathish Narasimman 		err = __set_isoc_interface(hdev, new_alts);
2230baac6276SSathish Narasimman 		if (err < 0)
2231baac6276SSathish Narasimman 			return err;
22329bfa35feSMarcel Holtmann 	}
22339bfa35feSMarcel Holtmann 
22349bfa35feSMarcel Holtmann 	if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
22352eda66f4SMarcel Holtmann 		if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
22369bfa35feSMarcel Holtmann 			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
22379bfa35feSMarcel Holtmann 		else
22382eda66f4SMarcel Holtmann 			btusb_submit_isoc_urb(hdev, GFP_KERNEL);
22399bfa35feSMarcel Holtmann 	}
2240baac6276SSathish Narasimman 
2241baac6276SSathish Narasimman 	return 0;
2242baac6276SSathish Narasimman }
2243baac6276SSathish Narasimman 
btusb_find_altsetting(struct btusb_data * data,int alt)2244baac6276SSathish Narasimman static struct usb_host_interface *btusb_find_altsetting(struct btusb_data *data,
2245baac6276SSathish Narasimman 							int alt)
2246baac6276SSathish Narasimman {
2247baac6276SSathish Narasimman 	struct usb_interface *intf = data->isoc;
2248baac6276SSathish Narasimman 	int i;
2249baac6276SSathish Narasimman 
2250baac6276SSathish Narasimman 	BT_DBG("Looking for Alt no :%d", alt);
2251baac6276SSathish Narasimman 
2252fcd156eeSSathish Narasimman 	if (!intf)
2253fcd156eeSSathish Narasimman 		return NULL;
2254fcd156eeSSathish Narasimman 
2255baac6276SSathish Narasimman 	for (i = 0; i < intf->num_altsetting; i++) {
2256baac6276SSathish Narasimman 		if (intf->altsetting[i].desc.bAlternateSetting == alt)
2257baac6276SSathish Narasimman 			return &intf->altsetting[i];
2258baac6276SSathish Narasimman 	}
2259baac6276SSathish Narasimman 
2260baac6276SSathish Narasimman 	return NULL;
2261baac6276SSathish Narasimman }
2262baac6276SSathish Narasimman 
btusb_work(struct work_struct * work)2263baac6276SSathish Narasimman static void btusb_work(struct work_struct *work)
2264baac6276SSathish Narasimman {
2265baac6276SSathish Narasimman 	struct btusb_data *data = container_of(work, struct btusb_data, work);
2266baac6276SSathish Narasimman 	struct hci_dev *hdev = data->hdev;
2267baac6276SSathish Narasimman 	int new_alts = 0;
2268baac6276SSathish Narasimman 	int err;
2269baac6276SSathish Narasimman 
2270baac6276SSathish Narasimman 	if (data->sco_num > 0) {
2271baac6276SSathish Narasimman 		if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
2272baac6276SSathish Narasimman 			err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf);
2273baac6276SSathish Narasimman 			if (err < 0) {
2274baac6276SSathish Narasimman 				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
2275baac6276SSathish Narasimman 				usb_kill_anchored_urbs(&data->isoc_anchor);
2276baac6276SSathish Narasimman 				return;
2277baac6276SSathish Narasimman 			}
2278baac6276SSathish Narasimman 
2279baac6276SSathish Narasimman 			set_bit(BTUSB_DID_ISO_RESUME, &data->flags);
2280baac6276SSathish Narasimman 		}
2281baac6276SSathish Narasimman 
2282baac6276SSathish Narasimman 		if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) {
2283baac6276SSathish Narasimman 			if (hdev->voice_setting & 0x0020) {
2284baac6276SSathish Narasimman 				static const int alts[3] = { 2, 4, 5 };
2285baac6276SSathish Narasimman 
2286baac6276SSathish Narasimman 				new_alts = alts[data->sco_num - 1];
2287baac6276SSathish Narasimman 			} else {
2288baac6276SSathish Narasimman 				new_alts = data->sco_num;
2289baac6276SSathish Narasimman 			}
2290baac6276SSathish Narasimman 		} else if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_TRANSP) {
2291517b6933STrent Piepho 			/* Bluetooth USB spec recommends alt 6 (63 bytes), but
2292517b6933STrent Piepho 			 * many adapters do not support it.  Alt 1 appears to
2293517b6933STrent Piepho 			 * work for all adapters that do not have alt 6, and
229455981d35SPauli Virtanen 			 * which work with WBS at all.  Some devices prefer
229555981d35SPauli Virtanen 			 * alt 3 (HCI payload >= 60 Bytes let air packet
229655981d35SPauli Virtanen 			 * data satisfy 60 bytes), requiring
229755981d35SPauli Virtanen 			 * MTU >= 3 (packets) * 25 (size) - 3 (headers) = 72
229855981d35SPauli Virtanen 			 * see also Core spec 5, vol 4, B 2.1.1 & Table 2.1.
2299517b6933STrent Piepho 			 */
230055981d35SPauli Virtanen 			if (btusb_find_altsetting(data, 6))
230155981d35SPauli Virtanen 				new_alts = 6;
230255981d35SPauli Virtanen 			else if (btusb_find_altsetting(data, 3) &&
230355981d35SPauli Virtanen 				 hdev->sco_mtu >= 72 &&
230455981d35SPauli Virtanen 				 test_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags))
2305e848dbd3SHilda Wu 				new_alts = 3;
230655981d35SPauli Virtanen 			else
230755981d35SPauli Virtanen 				new_alts = 1;
2308461f95f0SHilda Wu 		}
2309baac6276SSathish Narasimman 
2310baac6276SSathish Narasimman 		if (btusb_switch_alt_setting(hdev, new_alts) < 0)
2311baac6276SSathish Narasimman 			bt_dev_err(hdev, "set USB alt:(%d) failed!", new_alts);
23129bfa35feSMarcel Holtmann 	} else {
23139bfa35feSMarcel Holtmann 		usb_kill_anchored_urbs(&data->isoc_anchor);
23149bfa35feSMarcel Holtmann 
2315f9c5cbd5SChethan Tumkur Narayan 		if (test_and_clear_bit(BTUSB_ISOC_RUNNING, &data->flags))
23169bfa35feSMarcel Holtmann 			__set_isoc_interface(hdev, 0);
2317f9c5cbd5SChethan Tumkur Narayan 
231808b8b6c4SGustavo F. Padovan 		if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
23198efdd0cdSOliver Neukum 			usb_autopm_put_interface(data->isoc ? data->isoc : data->intf);
23209bfa35feSMarcel Holtmann 	}
23215e23b923SMarcel Holtmann }
23227bee549eSOliver Neukum 
btusb_waker(struct work_struct * work)23237bee549eSOliver Neukum static void btusb_waker(struct work_struct *work)
23247bee549eSOliver Neukum {
23257bee549eSOliver Neukum 	struct btusb_data *data = container_of(work, struct btusb_data, waker);
23267bee549eSOliver Neukum 	int err;
23277bee549eSOliver Neukum 
23287bee549eSOliver Neukum 	err = usb_autopm_get_interface(data->intf);
23297bee549eSOliver Neukum 	if (err < 0)
23307bee549eSOliver Neukum 		return;
23317bee549eSOliver Neukum 
23327bee549eSOliver Neukum 	usb_autopm_put_interface(data->intf);
23337bee549eSOliver Neukum }
23345e23b923SMarcel Holtmann 
btusb_rx_work(struct work_struct * work)2335800fe5ecSLuiz Augusto von Dentz static void btusb_rx_work(struct work_struct *work)
2336800fe5ecSLuiz Augusto von Dentz {
2337800fe5ecSLuiz Augusto von Dentz 	struct btusb_data *data = container_of(work, struct btusb_data,
2338800fe5ecSLuiz Augusto von Dentz 					       rx_work.work);
2339800fe5ecSLuiz Augusto von Dentz 	struct sk_buff *skb;
2340800fe5ecSLuiz Augusto von Dentz 
2341800fe5ecSLuiz Augusto von Dentz 	/* Dequeue ACL data received during the interval */
2342800fe5ecSLuiz Augusto von Dentz 	while ((skb = skb_dequeue(&data->acl_q)))
2343800fe5ecSLuiz Augusto von Dentz 		data->recv_acl(data->hdev, skb);
2344800fe5ecSLuiz Augusto von Dentz }
2345800fe5ecSLuiz Augusto von Dentz 
btusb_setup_bcm92035(struct hci_dev * hdev)23469f8f962cSMarcel Holtmann static int btusb_setup_bcm92035(struct hci_dev *hdev)
23479f8f962cSMarcel Holtmann {
23489f8f962cSMarcel Holtmann 	struct sk_buff *skb;
23499f8f962cSMarcel Holtmann 	u8 val = 0x00;
23509f8f962cSMarcel Holtmann 
23519f8f962cSMarcel Holtmann 	BT_DBG("%s", hdev->name);
23529f8f962cSMarcel Holtmann 
23539f8f962cSMarcel Holtmann 	skb = __hci_cmd_sync(hdev, 0xfc3b, 1, &val, HCI_INIT_TIMEOUT);
23549f8f962cSMarcel Holtmann 	if (IS_ERR(skb))
23552064ee33SMarcel Holtmann 		bt_dev_err(hdev, "BCM92035 command failed (%ld)", PTR_ERR(skb));
23569f8f962cSMarcel Holtmann 	else
23579f8f962cSMarcel Holtmann 		kfree_skb(skb);
23589f8f962cSMarcel Holtmann 
23599f8f962cSMarcel Holtmann 	return 0;
23609f8f962cSMarcel Holtmann }
23619f8f962cSMarcel Holtmann 
btusb_setup_csr(struct hci_dev * hdev)236281cac64bSMarcel Holtmann static int btusb_setup_csr(struct hci_dev *hdev)
236381cac64bSMarcel Holtmann {
2364d74e0ae7SHans de Goede 	struct btusb_data *data = hci_get_drvdata(hdev);
2365d74e0ae7SHans de Goede 	u16 bcdDevice = le16_to_cpu(data->udev->descriptor.bcdDevice);
236681cac64bSMarcel Holtmann 	struct hci_rp_read_local_version *rp;
236781cac64bSMarcel Holtmann 	struct sk_buff *skb;
2368cde1a8a9SIsmael Ferreras Morezuelas 	bool is_fake = false;
23690671c066SHans de Goede 	int ret;
237081cac64bSMarcel Holtmann 
237181cac64bSMarcel Holtmann 	BT_DBG("%s", hdev->name);
237281cac64bSMarcel Holtmann 
23737cd84d72SMarcel Holtmann 	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
23747cd84d72SMarcel Holtmann 			     HCI_INIT_TIMEOUT);
23757cd84d72SMarcel Holtmann 	if (IS_ERR(skb)) {
23767cd84d72SMarcel Holtmann 		int err = PTR_ERR(skb);
23772064ee33SMarcel Holtmann 		bt_dev_err(hdev, "CSR: Local version failed (%d)", err);
23787cd84d72SMarcel Holtmann 		return err;
23797cd84d72SMarcel Holtmann 	}
23807cd84d72SMarcel Holtmann 
2381cb3648a7SLuiz Augusto von Dentz 	rp = skb_pull_data(skb, sizeof(*rp));
2382cb3648a7SLuiz Augusto von Dentz 	if (!rp) {
23832064ee33SMarcel Holtmann 		bt_dev_err(hdev, "CSR: Local version length mismatch");
23847cd84d72SMarcel Holtmann 		kfree_skb(skb);
23857cd84d72SMarcel Holtmann 		return -EIO;
23867cd84d72SMarcel Holtmann 	}
238781cac64bSMarcel Holtmann 
2388cb3648a7SLuiz Augusto von Dentz 	bt_dev_info(hdev, "CSR: Setting up dongle with HCI ver=%u rev=%04x",
2389cb3648a7SLuiz Augusto von Dentz 		    rp->hci_ver, le16_to_cpu(rp->hci_rev));
239081cac64bSMarcel Holtmann 
2391cb3648a7SLuiz Augusto von Dentz 	bt_dev_info(hdev, "LMP ver=%u subver=%04x; manufacturer=%u",
2392cb3648a7SLuiz Augusto von Dentz 		    rp->lmp_ver, le16_to_cpu(rp->lmp_subver),
2393955aebd4SIsmael Ferreras Morezuelas 		    le16_to_cpu(rp->manufacturer));
2394955aebd4SIsmael Ferreras Morezuelas 
2395cde1a8a9SIsmael Ferreras Morezuelas 	/* Detect a wide host of Chinese controllers that aren't CSR.
2396cde1a8a9SIsmael Ferreras Morezuelas 	 *
2397cde1a8a9SIsmael Ferreras Morezuelas 	 * Known fake bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
2398cde1a8a9SIsmael Ferreras Morezuelas 	 *
2399cde1a8a9SIsmael Ferreras Morezuelas 	 * The main thing they have in common is that these are really popular low-cost
2400cde1a8a9SIsmael Ferreras Morezuelas 	 * options that support newer Bluetooth versions but rely on heavy VID/PID
2401cde1a8a9SIsmael Ferreras Morezuelas 	 * squatting of this poor old Bluetooth 1.1 device. Even sold as such.
2402cde1a8a9SIsmael Ferreras Morezuelas 	 *
2403cde1a8a9SIsmael Ferreras Morezuelas 	 * We detect actual CSR devices by checking that the HCI manufacturer code
2404cde1a8a9SIsmael Ferreras Morezuelas 	 * is Cambridge Silicon Radio (10) and ensuring that LMP sub-version and
2405cde1a8a9SIsmael Ferreras Morezuelas 	 * HCI rev values always match. As they both store the firmware number.
2406cde1a8a9SIsmael Ferreras Morezuelas 	 */
24076cafcd95SJohan Hedberg 	if (le16_to_cpu(rp->manufacturer) != 10 ||
2408cde1a8a9SIsmael Ferreras Morezuelas 	    le16_to_cpu(rp->hci_rev) != le16_to_cpu(rp->lmp_subver))
2409cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
2410cde1a8a9SIsmael Ferreras Morezuelas 
2411cde1a8a9SIsmael Ferreras Morezuelas 	/* Known legit CSR firmware build numbers and their supported BT versions:
2412cde1a8a9SIsmael Ferreras Morezuelas 	 * - 1.1 (0x1) -> 0x0073, 0x020d, 0x033c, 0x034e
2413cde1a8a9SIsmael Ferreras Morezuelas 	 * - 1.2 (0x2) ->                 0x04d9, 0x0529
2414cde1a8a9SIsmael Ferreras Morezuelas 	 * - 2.0 (0x3) ->         0x07a6, 0x07ad, 0x0c5c
2415cde1a8a9SIsmael Ferreras Morezuelas 	 * - 2.1 (0x4) ->         0x149c, 0x1735, 0x1899 (0x1899 is a BlueCore4-External)
2416cde1a8a9SIsmael Ferreras Morezuelas 	 * - 4.0 (0x6) ->         0x1d86, 0x2031, 0x22bb
2417cde1a8a9SIsmael Ferreras Morezuelas 	 *
2418cde1a8a9SIsmael Ferreras Morezuelas 	 * e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
2419cde1a8a9SIsmael Ferreras Morezuelas 	 *      support BT 1.1 only; so it's a dead giveaway when some
2420cde1a8a9SIsmael Ferreras Morezuelas 	 *      third-party BT 4.0 dongle reuses it.
2421cde1a8a9SIsmael Ferreras Morezuelas 	 */
2422cde1a8a9SIsmael Ferreras Morezuelas 	else if (le16_to_cpu(rp->lmp_subver) <= 0x034e &&
2423cb3648a7SLuiz Augusto von Dentz 		 rp->hci_ver > BLUETOOTH_VER_1_1)
2424cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
2425cde1a8a9SIsmael Ferreras Morezuelas 
2426cde1a8a9SIsmael Ferreras Morezuelas 	else if (le16_to_cpu(rp->lmp_subver) <= 0x0529 &&
2427cb3648a7SLuiz Augusto von Dentz 		 rp->hci_ver > BLUETOOTH_VER_1_2)
2428cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
2429cde1a8a9SIsmael Ferreras Morezuelas 
2430cde1a8a9SIsmael Ferreras Morezuelas 	else if (le16_to_cpu(rp->lmp_subver) <= 0x0c5c &&
2431cb3648a7SLuiz Augusto von Dentz 		 rp->hci_ver > BLUETOOTH_VER_2_0)
2432cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
2433cde1a8a9SIsmael Ferreras Morezuelas 
2434cde1a8a9SIsmael Ferreras Morezuelas 	else if (le16_to_cpu(rp->lmp_subver) <= 0x1899 &&
2435cb3648a7SLuiz Augusto von Dentz 		 rp->hci_ver > BLUETOOTH_VER_2_1)
2436cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
2437cde1a8a9SIsmael Ferreras Morezuelas 
2438cde1a8a9SIsmael Ferreras Morezuelas 	else if (le16_to_cpu(rp->lmp_subver) <= 0x22bb &&
2439cb3648a7SLuiz Augusto von Dentz 		 rp->hci_ver > BLUETOOTH_VER_4_0)
2440cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
2441cde1a8a9SIsmael Ferreras Morezuelas 
2442d74e0ae7SHans de Goede 	/* Other clones which beat all the above checks */
2443d74e0ae7SHans de Goede 	else if (bcdDevice == 0x0134 &&
2444d74e0ae7SHans de Goede 		 le16_to_cpu(rp->lmp_subver) == 0x0c5c &&
2445cb3648a7SLuiz Augusto von Dentz 		 rp->hci_ver == BLUETOOTH_VER_2_0)
2446d74e0ae7SHans de Goede 		is_fake = true;
2447d74e0ae7SHans de Goede 
2448cde1a8a9SIsmael Ferreras Morezuelas 	if (is_fake) {
2449f4292e2fSIsmael Ferreras Morezuelas 		bt_dev_warn(hdev, "CSR: Unbranded CSR clone detected; adding workarounds and force-suspending once...");
2450cde1a8a9SIsmael Ferreras Morezuelas 
2451cde1a8a9SIsmael Ferreras Morezuelas 		/* Generally these clones have big discrepancies between
2452cde1a8a9SIsmael Ferreras Morezuelas 		 * advertised features and what's actually supported.
2453cde1a8a9SIsmael Ferreras Morezuelas 		 * Probably will need to be expanded in the future;
2454cde1a8a9SIsmael Ferreras Morezuelas 		 * without these the controller will lock up.
2455cde1a8a9SIsmael Ferreras Morezuelas 		 */
2456cde1a8a9SIsmael Ferreras Morezuelas 		set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
245742d7731eSIsmael Ferreras Morezuelas 		set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
2458b3cf94c8SIsmael Ferreras Morezuelas 		set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks);
2459b3cf94c8SIsmael Ferreras Morezuelas 		set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks);
2460cde1a8a9SIsmael Ferreras Morezuelas 
246181cac64bSMarcel Holtmann 		/* Clear the reset quirk since this is not an actual
246281cac64bSMarcel Holtmann 		 * early Bluetooth 1.1 device from CSR.
246381cac64bSMarcel Holtmann 		 */
246481cac64bSMarcel Holtmann 		clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
2465cde1a8a9SIsmael Ferreras Morezuelas 		clear_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
24660671c066SHans de Goede 
24670671c066SHans de Goede 		/*
2468f4292e2fSIsmael Ferreras Morezuelas 		 * Special workaround for these BT 4.0 chip clones, and potentially more:
2469f4292e2fSIsmael Ferreras Morezuelas 		 *
2470b3cf94c8SIsmael Ferreras Morezuelas 		 * - 0x0134: a Barrot 8041a02                 (HCI rev: 0x0810 sub: 0x1012)
2471f4292e2fSIsmael Ferreras Morezuelas 		 * - 0x7558: IC markings FR3191AHAL 749H15143 (HCI rev/sub-version: 0x0709)
2472f4292e2fSIsmael Ferreras Morezuelas 		 *
2473f4292e2fSIsmael Ferreras Morezuelas 		 * These controllers are really messed-up.
2474f4292e2fSIsmael Ferreras Morezuelas 		 *
2475f4292e2fSIsmael Ferreras Morezuelas 		 * 1. Their bulk RX endpoint will never report any data unless
2476f4292e2fSIsmael Ferreras Morezuelas 		 *    the device was suspended at least once (yes, really).
24770671c066SHans de Goede 		 * 2. They will not wakeup when autosuspended and receiving data
2478f4292e2fSIsmael Ferreras Morezuelas 		 *    on their bulk RX endpoint from e.g. a keyboard or mouse
24790671c066SHans de Goede 		 *    (IOW remote-wakeup support is broken for the bulk endpoint).
24800671c066SHans de Goede 		 *
24810671c066SHans de Goede 		 * To fix 1. enable runtime-suspend, force-suspend the
2482f4292e2fSIsmael Ferreras Morezuelas 		 * HCI and then wake-it up by disabling runtime-suspend.
24830671c066SHans de Goede 		 *
2484f4292e2fSIsmael Ferreras Morezuelas 		 * To fix 2. clear the HCI's can_wake flag, this way the HCI
24850671c066SHans de Goede 		 * will still be autosuspended when it is not open.
2486f4292e2fSIsmael Ferreras Morezuelas 		 *
2487f4292e2fSIsmael Ferreras Morezuelas 		 * --
2488f4292e2fSIsmael Ferreras Morezuelas 		 *
2489f4292e2fSIsmael Ferreras Morezuelas 		 * Because these are widespread problems we prefer generic solutions; so
2490f4292e2fSIsmael Ferreras Morezuelas 		 * apply this initialization quirk to every controller that gets here,
2491f4292e2fSIsmael Ferreras Morezuelas 		 * it should be harmless. The alternative is to not work at all.
24920671c066SHans de Goede 		 */
24930671c066SHans de Goede 		pm_runtime_allow(&data->udev->dev);
24940671c066SHans de Goede 
24950671c066SHans de Goede 		ret = pm_runtime_suspend(&data->udev->dev);
24960671c066SHans de Goede 		if (ret >= 0)
24970671c066SHans de Goede 			msleep(200);
24980671c066SHans de Goede 		else
2499b3cf94c8SIsmael Ferreras Morezuelas 			bt_dev_warn(hdev, "CSR: Couldn't suspend the device for our Barrot 8041a02 receive-issue workaround");
25000671c066SHans de Goede 
25010671c066SHans de Goede 		pm_runtime_forbid(&data->udev->dev);
25020671c066SHans de Goede 
25030671c066SHans de Goede 		device_set_wakeup_capable(&data->udev->dev, false);
2504f4292e2fSIsmael Ferreras Morezuelas 
25050671c066SHans de Goede 		/* Re-enable autosuspend if this was requested */
25060671c066SHans de Goede 		if (enable_autosuspend)
25070671c066SHans de Goede 			usb_enable_autosuspend(data->udev);
25080671c066SHans de Goede 	}
250981cac64bSMarcel Holtmann 
251081cac64bSMarcel Holtmann 	kfree_skb(skb);
251181cac64bSMarcel Holtmann 
25129641d343SMarcel Holtmann 	return 0;
251381cac64bSMarcel Holtmann }
251481cac64bSMarcel Holtmann 
inject_cmd_complete(struct hci_dev * hdev,__u16 opcode)2515cda0dd78SMarcel Holtmann static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode)
2516cda0dd78SMarcel Holtmann {
2517cda0dd78SMarcel Holtmann 	struct sk_buff *skb;
2518cda0dd78SMarcel Holtmann 	struct hci_event_hdr *hdr;
2519cda0dd78SMarcel Holtmann 	struct hci_ev_cmd_complete *evt;
2520cda0dd78SMarcel Holtmann 
2521cf07e341SJia-Ju Bai 	skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_KERNEL);
2522cda0dd78SMarcel Holtmann 	if (!skb)
2523cda0dd78SMarcel Holtmann 		return -ENOMEM;
2524cda0dd78SMarcel Holtmann 
25254df864c1SJohannes Berg 	hdr = skb_put(skb, sizeof(*hdr));
2526cda0dd78SMarcel Holtmann 	hdr->evt = HCI_EV_CMD_COMPLETE;
2527cda0dd78SMarcel Holtmann 	hdr->plen = sizeof(*evt) + 1;
2528cda0dd78SMarcel Holtmann 
25294df864c1SJohannes Berg 	evt = skb_put(skb, sizeof(*evt));
2530cda0dd78SMarcel Holtmann 	evt->ncmd = 0x01;
2531cda0dd78SMarcel Holtmann 	evt->opcode = cpu_to_le16(opcode);
2532cda0dd78SMarcel Holtmann 
2533634fef61SJohannes Berg 	skb_put_u8(skb, 0x00);
2534cda0dd78SMarcel Holtmann 
2535618e8bc2SMarcel Holtmann 	hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
2536cda0dd78SMarcel Holtmann 
2537cda0dd78SMarcel Holtmann 	return hci_recv_frame(hdev, skb);
2538cda0dd78SMarcel Holtmann }
2539cda0dd78SMarcel Holtmann 
btusb_recv_bulk_intel(struct btusb_data * data,void * buffer,int count)2540cda0dd78SMarcel Holtmann static int btusb_recv_bulk_intel(struct btusb_data *data, void *buffer,
2541cda0dd78SMarcel Holtmann 				 int count)
2542cda0dd78SMarcel Holtmann {
2543019a1caaSTedd Ho-Jeong An 	struct hci_dev *hdev = data->hdev;
2544019a1caaSTedd Ho-Jeong An 
2545cda0dd78SMarcel Holtmann 	/* When the device is in bootloader mode, then it can send
2546cda0dd78SMarcel Holtmann 	 * events via the bulk endpoint. These events are treated the
2547cda0dd78SMarcel Holtmann 	 * same way as the ones received from the interrupt endpoint.
2548cda0dd78SMarcel Holtmann 	 */
2549019a1caaSTedd Ho-Jeong An 	if (btintel_test_flag(hdev, INTEL_BOOTLOADER))
2550cda0dd78SMarcel Holtmann 		return btusb_recv_intr(data, buffer, count);
2551cda0dd78SMarcel Holtmann 
2552cda0dd78SMarcel Holtmann 	return btusb_recv_bulk(data, buffer, count);
2553cda0dd78SMarcel Holtmann }
2554cda0dd78SMarcel Holtmann 
btusb_send_frame_intel(struct hci_dev * hdev,struct sk_buff * skb)2555cda0dd78SMarcel Holtmann static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
2556cda0dd78SMarcel Holtmann {
2557cda0dd78SMarcel Holtmann 	struct urb *urb;
2558cda0dd78SMarcel Holtmann 
2559cda0dd78SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2560cda0dd78SMarcel Holtmann 
2561618e8bc2SMarcel Holtmann 	switch (hci_skb_pkt_type(skb)) {
2562cda0dd78SMarcel Holtmann 	case HCI_COMMAND_PKT:
2563019a1caaSTedd Ho-Jeong An 		if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
2564cda0dd78SMarcel Holtmann 			struct hci_command_hdr *cmd = (void *)skb->data;
2565cda0dd78SMarcel Holtmann 			__u16 opcode = le16_to_cpu(cmd->opcode);
2566cda0dd78SMarcel Holtmann 
2567cda0dd78SMarcel Holtmann 			/* When in bootloader mode and the command 0xfc09
2568cda0dd78SMarcel Holtmann 			 * is received, it needs to be send down the
2569cda0dd78SMarcel Holtmann 			 * bulk endpoint. So allocate a bulk URB instead.
2570cda0dd78SMarcel Holtmann 			 */
2571cda0dd78SMarcel Holtmann 			if (opcode == 0xfc09)
2572cda0dd78SMarcel Holtmann 				urb = alloc_bulk_urb(hdev, skb);
2573cda0dd78SMarcel Holtmann 			else
2574cda0dd78SMarcel Holtmann 				urb = alloc_ctrl_urb(hdev, skb);
2575cda0dd78SMarcel Holtmann 
2576cda0dd78SMarcel Holtmann 			/* When the 0xfc01 command is issued to boot into
2577cda0dd78SMarcel Holtmann 			 * the operational firmware, it will actually not
2578cda0dd78SMarcel Holtmann 			 * send a command complete event. To keep the flow
2579cda0dd78SMarcel Holtmann 			 * control working inject that event here.
2580cda0dd78SMarcel Holtmann 			 */
2581cda0dd78SMarcel Holtmann 			if (opcode == 0xfc01)
2582cda0dd78SMarcel Holtmann 				inject_cmd_complete(hdev, opcode);
2583cda0dd78SMarcel Holtmann 		} else {
2584cda0dd78SMarcel Holtmann 			urb = alloc_ctrl_urb(hdev, skb);
2585cda0dd78SMarcel Holtmann 		}
2586cda0dd78SMarcel Holtmann 		if (IS_ERR(urb))
2587cda0dd78SMarcel Holtmann 			return PTR_ERR(urb);
2588cda0dd78SMarcel Holtmann 
2589cda0dd78SMarcel Holtmann 		hdev->stat.cmd_tx++;
2590cda0dd78SMarcel Holtmann 		return submit_or_queue_tx_urb(hdev, urb);
2591cda0dd78SMarcel Holtmann 
2592cda0dd78SMarcel Holtmann 	case HCI_ACLDATA_PKT:
2593cda0dd78SMarcel Holtmann 		urb = alloc_bulk_urb(hdev, skb);
2594cda0dd78SMarcel Holtmann 		if (IS_ERR(urb))
2595cda0dd78SMarcel Holtmann 			return PTR_ERR(urb);
2596cda0dd78SMarcel Holtmann 
2597cda0dd78SMarcel Holtmann 		hdev->stat.acl_tx++;
2598cda0dd78SMarcel Holtmann 		return submit_or_queue_tx_urb(hdev, urb);
2599cda0dd78SMarcel Holtmann 
2600cda0dd78SMarcel Holtmann 	case HCI_SCODATA_PKT:
2601cda0dd78SMarcel Holtmann 		if (hci_conn_num(hdev, SCO_LINK) < 1)
2602cda0dd78SMarcel Holtmann 			return -ENODEV;
2603cda0dd78SMarcel Holtmann 
2604cda0dd78SMarcel Holtmann 		urb = alloc_isoc_urb(hdev, skb);
2605cda0dd78SMarcel Holtmann 		if (IS_ERR(urb))
2606cda0dd78SMarcel Holtmann 			return PTR_ERR(urb);
2607cda0dd78SMarcel Holtmann 
2608cda0dd78SMarcel Holtmann 		hdev->stat.sco_tx++;
2609cda0dd78SMarcel Holtmann 		return submit_tx_urb(hdev, urb);
261070405f02SLuiz Augusto von Dentz 
261170405f02SLuiz Augusto von Dentz 	case HCI_ISODATA_PKT:
261270405f02SLuiz Augusto von Dentz 		urb = alloc_bulk_urb(hdev, skb);
261370405f02SLuiz Augusto von Dentz 		if (IS_ERR(urb))
261470405f02SLuiz Augusto von Dentz 			return PTR_ERR(urb);
261570405f02SLuiz Augusto von Dentz 
261670405f02SLuiz Augusto von Dentz 		return submit_or_queue_tx_urb(hdev, urb);
2617cda0dd78SMarcel Holtmann 	}
2618cda0dd78SMarcel Holtmann 
2619cda0dd78SMarcel Holtmann 	return -EILSEQ;
2620cda0dd78SMarcel Holtmann }
2621cda0dd78SMarcel Holtmann 
btusb_setup_realtek(struct hci_dev * hdev)2622a479e713SHilda Wu static int btusb_setup_realtek(struct hci_dev *hdev)
2623a479e713SHilda Wu {
2624a479e713SHilda Wu 	struct btusb_data *data = hci_get_drvdata(hdev);
2625a479e713SHilda Wu 	int ret;
2626a479e713SHilda Wu 
2627a479e713SHilda Wu 	ret = btrtl_setup_realtek(hdev);
2628a479e713SHilda Wu 
2629a479e713SHilda Wu 	if (btrealtek_test_flag(data->hdev, REALTEK_ALT6_CONTINUOUS_TX_CHIP))
2630a479e713SHilda Wu 		set_bit(BTUSB_ALT6_CONTINUOUS_TX, &data->flags);
2631a479e713SHilda Wu 
2632a479e713SHilda Wu 	return ret;
2633a479e713SHilda Wu }
2634a479e713SHilda Wu 
btusb_recv_event_realtek(struct hci_dev * hdev,struct sk_buff * skb)2635044014ceSHilda Wu static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
2636044014ceSHilda Wu {
2637044014ceSHilda Wu 	if (skb->data[0] == HCI_VENDOR_PKT && skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) {
2638044014ceSHilda Wu 		struct rtk_dev_coredump_hdr hdr = {
2639044014ceSHilda Wu 			.code = RTK_DEVCOREDUMP_CODE_MEMDUMP,
2640044014ceSHilda Wu 		};
2641044014ceSHilda Wu 
2642044014ceSHilda Wu 		bt_dev_dbg(hdev, "RTL: received coredump vendor evt, len %u",
2643044014ceSHilda Wu 			skb->len);
2644044014ceSHilda Wu 
2645044014ceSHilda Wu 		btusb_rtl_alloc_devcoredump(hdev, &hdr, skb->data, skb->len);
2646044014ceSHilda Wu 		kfree_skb(skb);
2647044014ceSHilda Wu 
2648044014ceSHilda Wu 		return 0;
2649044014ceSHilda Wu 	}
2650044014ceSHilda Wu 
2651044014ceSHilda Wu 	return hci_recv_frame(hdev, skb);
2652044014ceSHilda Wu }
2653044014ceSHilda Wu 
2654e9478026Smark-yw.chen /* UHW CR mapping */
2655e9478026Smark-yw.chen #define MTK_BT_MISC		0x70002510
2656e9478026Smark-yw.chen #define MTK_BT_SUBSYS_RST	0x70002610
2657e9478026Smark-yw.chen #define MTK_UDMA_INT_STA_BT	0x74000024
2658e9478026Smark-yw.chen #define MTK_UDMA_INT_STA_BT1	0x74000308
2659e9478026Smark-yw.chen #define MTK_BT_WDT_STATUS	0x740003A0
2660e9478026Smark-yw.chen #define MTK_EP_RST_OPT		0x74011890
2661e9478026Smark-yw.chen #define MTK_EP_RST_IN_OUT_OPT	0x00010001
2662e9478026Smark-yw.chen #define MTK_BT_RST_DONE		0x00000100
26634c92ae75SPeter Tsao #define MTK_BT_RESET_REG_CONNV3	0x70028610
26644c92ae75SPeter Tsao #define MTK_BT_READ_DEV_ID	0x70010200
26654c92ae75SPeter Tsao 
26665a87679fSmark-yw.chen 
btusb_mtk_wmt_recv(struct urb * urb)2667a1c49c43SSean Wang static void btusb_mtk_wmt_recv(struct urb *urb)
2668a1c49c43SSean Wang {
2669a1c49c43SSean Wang 	struct hci_dev *hdev = urb->context;
2670a1c49c43SSean Wang 	struct btusb_data *data = hci_get_drvdata(hdev);
2671a1c49c43SSean Wang 	struct sk_buff *skb;
2672a1c49c43SSean Wang 	int err;
2673a1c49c43SSean Wang 
2674a1c49c43SSean Wang 	if (urb->status == 0 && urb->actual_length > 0) {
2675a1c49c43SSean Wang 		hdev->stat.byte_rx += urb->actual_length;
2676a1c49c43SSean Wang 
2677a1c49c43SSean Wang 		/* WMT event shouldn't be fragmented and the size should be
2678a1c49c43SSean Wang 		 * less than HCI_WMT_MAX_EVENT_SIZE.
2679a1c49c43SSean Wang 		 */
2680a1c49c43SSean Wang 		skb = bt_skb_alloc(HCI_WMT_MAX_EVENT_SIZE, GFP_ATOMIC);
2681a1c49c43SSean Wang 		if (!skb) {
2682a1c49c43SSean Wang 			hdev->stat.err_rx++;
268360c6a63aSMark-YW.Chen 			kfree(urb->setup_packet);
2684de71a6cbSJupeng Zhong 			return;
2685a1c49c43SSean Wang 		}
2686a1c49c43SSean Wang 
2687a1c49c43SSean Wang 		hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
2688a1c49c43SSean Wang 		skb_put_data(skb, urb->transfer_buffer, urb->actual_length);
2689a1c49c43SSean Wang 
2690a1c49c43SSean Wang 		/* When someone waits for the WMT event, the skb is being cloned
2691a1c49c43SSean Wang 		 * and being processed the events from there then.
2692a1c49c43SSean Wang 		 */
2693a1c49c43SSean Wang 		if (test_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags)) {
269422cc6b7aSJohan Hovold 			data->evt_skb = skb_clone(skb, GFP_ATOMIC);
2695de71a6cbSJupeng Zhong 			if (!data->evt_skb) {
2696de71a6cbSJupeng Zhong 				kfree_skb(skb);
269760c6a63aSMark-YW.Chen 				kfree(urb->setup_packet);
2698de71a6cbSJupeng Zhong 				return;
2699de71a6cbSJupeng Zhong 			}
2700a1c49c43SSean Wang 		}
2701a1c49c43SSean Wang 
2702a1c49c43SSean Wang 		err = hci_recv_frame(hdev, skb);
2703de71a6cbSJupeng Zhong 		if (err < 0) {
2704de71a6cbSJupeng Zhong 			kfree_skb(data->evt_skb);
2705de71a6cbSJupeng Zhong 			data->evt_skb = NULL;
270660c6a63aSMark-YW.Chen 			kfree(urb->setup_packet);
2707de71a6cbSJupeng Zhong 			return;
2708de71a6cbSJupeng Zhong 		}
2709a1c49c43SSean Wang 
2710a1c49c43SSean Wang 		if (test_and_clear_bit(BTUSB_TX_WAIT_VND_EVT,
2711a1c49c43SSean Wang 				       &data->flags)) {
2712a1c49c43SSean Wang 			/* Barrier to sync with other CPUs */
2713a1c49c43SSean Wang 			smp_mb__after_atomic();
2714a1c49c43SSean Wang 			wake_up_bit(&data->flags,
2715a1c49c43SSean Wang 				    BTUSB_TX_WAIT_VND_EVT);
2716a1c49c43SSean Wang 		}
271760c6a63aSMark-YW.Chen 		kfree(urb->setup_packet);
2718a1c49c43SSean Wang 		return;
2719a1c49c43SSean Wang 	} else if (urb->status == -ENOENT) {
2720a1c49c43SSean Wang 		/* Avoid suspend failed when usb_kill_urb */
2721a1c49c43SSean Wang 		return;
2722a1c49c43SSean Wang 	}
2723a1c49c43SSean Wang 
2724a1c49c43SSean Wang 	usb_mark_last_busy(data->udev);
2725a1c49c43SSean Wang 
2726a1c49c43SSean Wang 	/* The URB complete handler is still called with urb->actual_length = 0
2727a1c49c43SSean Wang 	 * when the event is not available, so we should keep re-submitting
2728a1c49c43SSean Wang 	 * URB until WMT event returns, Also, It's necessary to wait some time
2729a1c49c43SSean Wang 	 * between the two consecutive control URBs to relax the target device
2730a1c49c43SSean Wang 	 * to generate the event. Otherwise, the WMT event cannot return from
2731a1c49c43SSean Wang 	 * the device successfully.
2732a1c49c43SSean Wang 	 */
273348c13301SMark Chen 	udelay(500);
2734a1c49c43SSean Wang 
2735a1c49c43SSean Wang 	usb_anchor_urb(urb, &data->ctrl_anchor);
2736a1c49c43SSean Wang 	err = usb_submit_urb(urb, GFP_ATOMIC);
2737a1c49c43SSean Wang 	if (err < 0) {
273860c6a63aSMark-YW.Chen 		kfree(urb->setup_packet);
2739a1c49c43SSean Wang 		/* -EPERM: urb is being killed;
2740a1c49c43SSean Wang 		 * -ENODEV: device got disconnected
2741a1c49c43SSean Wang 		 */
2742a1c49c43SSean Wang 		if (err != -EPERM && err != -ENODEV)
2743a1c49c43SSean Wang 			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
2744a1c49c43SSean Wang 				   urb, -err);
2745a1c49c43SSean Wang 		usb_unanchor_urb(urb);
2746a1c49c43SSean Wang 	}
2747a1c49c43SSean Wang }
2748a1c49c43SSean Wang 
btusb_mtk_submit_wmt_recv_urb(struct hci_dev * hdev)2749a1c49c43SSean Wang static int btusb_mtk_submit_wmt_recv_urb(struct hci_dev *hdev)
2750a1c49c43SSean Wang {
2751a1c49c43SSean Wang 	struct btusb_data *data = hci_get_drvdata(hdev);
2752a1c49c43SSean Wang 	struct usb_ctrlrequest *dr;
2753a1c49c43SSean Wang 	unsigned char *buf;
2754a1c49c43SSean Wang 	int err, size = 64;
2755a1c49c43SSean Wang 	unsigned int pipe;
2756a1c49c43SSean Wang 	struct urb *urb;
2757a1c49c43SSean Wang 
2758a1c49c43SSean Wang 	urb = usb_alloc_urb(0, GFP_KERNEL);
2759a1c49c43SSean Wang 	if (!urb)
2760a1c49c43SSean Wang 		return -ENOMEM;
2761a1c49c43SSean Wang 
2762a1c49c43SSean Wang 	dr = kmalloc(sizeof(*dr), GFP_KERNEL);
2763a1c49c43SSean Wang 	if (!dr) {
2764a1c49c43SSean Wang 		usb_free_urb(urb);
2765a1c49c43SSean Wang 		return -ENOMEM;
2766a1c49c43SSean Wang 	}
2767a1c49c43SSean Wang 
2768a1c49c43SSean Wang 	dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_IN;
2769a1c49c43SSean Wang 	dr->bRequest     = 1;
2770a1c49c43SSean Wang 	dr->wIndex       = cpu_to_le16(0);
2771a1c49c43SSean Wang 	dr->wValue       = cpu_to_le16(48);
2772a1c49c43SSean Wang 	dr->wLength      = cpu_to_le16(size);
2773a1c49c43SSean Wang 
2774a1c49c43SSean Wang 	buf = kmalloc(size, GFP_KERNEL);
2775a1c49c43SSean Wang 	if (!buf) {
2776a1c49c43SSean Wang 		kfree(dr);
2777d33fe77bSDinghao Liu 		usb_free_urb(urb);
2778a1c49c43SSean Wang 		return -ENOMEM;
2779a1c49c43SSean Wang 	}
2780a1c49c43SSean Wang 
2781a1c49c43SSean Wang 	pipe = usb_rcvctrlpipe(data->udev, 0);
2782a1c49c43SSean Wang 
2783a1c49c43SSean Wang 	usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
2784a1c49c43SSean Wang 			     buf, size, btusb_mtk_wmt_recv, hdev);
2785a1c49c43SSean Wang 
2786a1c49c43SSean Wang 	urb->transfer_flags |= URB_FREE_BUFFER;
2787a1c49c43SSean Wang 
2788a1c49c43SSean Wang 	usb_anchor_urb(urb, &data->ctrl_anchor);
2789a1c49c43SSean Wang 	err = usb_submit_urb(urb, GFP_KERNEL);
2790a1c49c43SSean Wang 	if (err < 0) {
2791a1c49c43SSean Wang 		if (err != -EPERM && err != -ENODEV)
2792a1c49c43SSean Wang 			bt_dev_err(hdev, "urb %p submission failed (%d)",
2793a1c49c43SSean Wang 				   urb, -err);
2794a1c49c43SSean Wang 		usb_unanchor_urb(urb);
2795a1c49c43SSean Wang 	}
2796a1c49c43SSean Wang 
2797a1c49c43SSean Wang 	usb_free_urb(urb);
2798a1c49c43SSean Wang 
2799a1c49c43SSean Wang 	return err;
2800a1c49c43SSean Wang }
2801a1c49c43SSean Wang 
btusb_mtk_hci_wmt_sync(struct hci_dev * hdev,struct btmtk_hci_wmt_params * wmt_params)2802a1c49c43SSean Wang static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
2803a1c49c43SSean Wang 				  struct btmtk_hci_wmt_params *wmt_params)
2804a1c49c43SSean Wang {
2805a1c49c43SSean Wang 	struct btusb_data *data = hci_get_drvdata(hdev);
2806a1c49c43SSean Wang 	struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
2807a1c49c43SSean Wang 	u32 hlen, status = BTMTK_WMT_INVALID;
2808a1c49c43SSean Wang 	struct btmtk_hci_wmt_evt *wmt_evt;
280910888140SArnd Bergmann 	struct btmtk_hci_wmt_cmd *wc;
2810a1c49c43SSean Wang 	struct btmtk_wmt_hdr *hdr;
2811a1c49c43SSean Wang 	int err;
2812a1c49c43SSean Wang 
2813a1c49c43SSean Wang 	/* Send the WMT command and wait until the WMT event returns */
2814a1c49c43SSean Wang 	hlen = sizeof(*hdr) + wmt_params->dlen;
2815a1c49c43SSean Wang 	if (hlen > 255)
2816a1c49c43SSean Wang 		return -EINVAL;
2817a1c49c43SSean Wang 
281810888140SArnd Bergmann 	wc = kzalloc(hlen, GFP_KERNEL);
281910888140SArnd Bergmann 	if (!wc)
282010888140SArnd Bergmann 		return -ENOMEM;
282110888140SArnd Bergmann 
282210888140SArnd Bergmann 	hdr = &wc->hdr;
2823a1c49c43SSean Wang 	hdr->dir = 1;
2824a1c49c43SSean Wang 	hdr->op = wmt_params->op;
2825a1c49c43SSean Wang 	hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
2826a1c49c43SSean Wang 	hdr->flag = wmt_params->flag;
282710888140SArnd Bergmann 	memcpy(wc->data, wmt_params->data, wmt_params->dlen);
2828a1c49c43SSean Wang 
2829a1c49c43SSean Wang 	set_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
2830a1c49c43SSean Wang 
2831fd3f1066SSean Wang 	/* WMT cmd/event doesn't follow up the generic HCI cmd/event handling,
2832fd3f1066SSean Wang 	 * it needs constantly polling control pipe until the host received the
2833fd3f1066SSean Wang 	 * WMT event, thus, we should require to specifically acquire PM counter
2834fd3f1066SSean Wang 	 * on the USB to prevent the interface from entering auto suspended
2835fd3f1066SSean Wang 	 * while WMT cmd/event in progress.
2836fd3f1066SSean Wang 	 */
2837fd3f1066SSean Wang 	err = usb_autopm_get_interface(data->intf);
2838fd3f1066SSean Wang 	if (err < 0)
2839fd3f1066SSean Wang 		goto err_free_wc;
2840fd3f1066SSean Wang 
284110888140SArnd Bergmann 	err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
2842a1c49c43SSean Wang 
2843a1c49c43SSean Wang 	if (err < 0) {
2844a1c49c43SSean Wang 		clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
2845fd3f1066SSean Wang 		usb_autopm_put_interface(data->intf);
284610888140SArnd Bergmann 		goto err_free_wc;
2847a1c49c43SSean Wang 	}
2848a1c49c43SSean Wang 
28498454ed9fSmark-yw.chen 	/* Submit control IN URB on demand to process the WMT event */
28508454ed9fSmark-yw.chen 	err = btusb_mtk_submit_wmt_recv_urb(hdev);
2851fd3f1066SSean Wang 
2852fd3f1066SSean Wang 	usb_autopm_put_interface(data->intf);
2853fd3f1066SSean Wang 
28548454ed9fSmark-yw.chen 	if (err < 0)
285544e936d7SMuhammad Usama Anjum 		goto err_free_wc;
28568454ed9fSmark-yw.chen 
2857a1c49c43SSean Wang 	/* The vendor specific WMT commands are all answered by a vendor
2858a1c49c43SSean Wang 	 * specific event and will have the Command Status or Command
2859a1c49c43SSean Wang 	 * Complete as with usual HCI command flow control.
2860a1c49c43SSean Wang 	 *
2861a1c49c43SSean Wang 	 * After sending the command, wait for BTUSB_TX_WAIT_VND_EVT
2862a1c49c43SSean Wang 	 * state to be cleared. The driver specific event receive routine
2863a1c49c43SSean Wang 	 * will clear that state and with that indicate completion of the
2864a1c49c43SSean Wang 	 * WMT command.
2865a1c49c43SSean Wang 	 */
2866a1c49c43SSean Wang 	err = wait_on_bit_timeout(&data->flags, BTUSB_TX_WAIT_VND_EVT,
2867a1c49c43SSean Wang 				  TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT);
2868a1c49c43SSean Wang 	if (err == -EINTR) {
2869a1c49c43SSean Wang 		bt_dev_err(hdev, "Execution of wmt command interrupted");
2870a1c49c43SSean Wang 		clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
287110888140SArnd Bergmann 		goto err_free_wc;
2872a1c49c43SSean Wang 	}
2873a1c49c43SSean Wang 
2874a1c49c43SSean Wang 	if (err) {
2875a1c49c43SSean Wang 		bt_dev_err(hdev, "Execution of wmt command timed out");
2876a1c49c43SSean Wang 		clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
287710888140SArnd Bergmann 		err = -ETIMEDOUT;
287810888140SArnd Bergmann 		goto err_free_wc;
2879a1c49c43SSean Wang 	}
2880a1c49c43SSean Wang 
288113b1ebadSyouwan Wang 	if (data->evt_skb == NULL)
288213b1ebadSyouwan Wang 		goto err_free_wc;
288313b1ebadSyouwan Wang 
2884a1c49c43SSean Wang 	/* Parse and handle the return WMT event */
2885a1c49c43SSean Wang 	wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
2886a1c49c43SSean Wang 	if (wmt_evt->whdr.op != hdr->op) {
2887a1c49c43SSean Wang 		bt_dev_err(hdev, "Wrong op received %d expected %d",
2888a1c49c43SSean Wang 			   wmt_evt->whdr.op, hdr->op);
2889a1c49c43SSean Wang 		err = -EIO;
2890a1c49c43SSean Wang 		goto err_free_skb;
2891a1c49c43SSean Wang 	}
2892a1c49c43SSean Wang 
2893a1c49c43SSean Wang 	switch (wmt_evt->whdr.op) {
2894a1c49c43SSean Wang 	case BTMTK_WMT_SEMAPHORE:
2895a1c49c43SSean Wang 		if (wmt_evt->whdr.flag == 2)
2896a1c49c43SSean Wang 			status = BTMTK_WMT_PATCH_UNDONE;
2897a1c49c43SSean Wang 		else
2898a1c49c43SSean Wang 			status = BTMTK_WMT_PATCH_DONE;
2899a1c49c43SSean Wang 		break;
2900a1c49c43SSean Wang 	case BTMTK_WMT_FUNC_CTRL:
2901a1c49c43SSean Wang 		wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
2902a1c49c43SSean Wang 		if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
2903a1c49c43SSean Wang 			status = BTMTK_WMT_ON_DONE;
2904a1c49c43SSean Wang 		else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
2905a1c49c43SSean Wang 			status = BTMTK_WMT_ON_PROGRESS;
2906a1c49c43SSean Wang 		else
2907a1c49c43SSean Wang 			status = BTMTK_WMT_ON_UNDONE;
2908a1c49c43SSean Wang 		break;
2909fc342c4dSMark Chen 	case BTMTK_WMT_PATCH_DWNLD:
2910fc342c4dSMark Chen 		if (wmt_evt->whdr.flag == 2)
2911fc342c4dSMark Chen 			status = BTMTK_WMT_PATCH_DONE;
2912fc342c4dSMark Chen 		else if (wmt_evt->whdr.flag == 1)
2913fc342c4dSMark Chen 			status = BTMTK_WMT_PATCH_PROGRESS;
2914fc342c4dSMark Chen 		else
2915fc342c4dSMark Chen 			status = BTMTK_WMT_PATCH_UNDONE;
2916fc342c4dSMark Chen 		break;
2917a1c49c43SSean Wang 	}
2918a1c49c43SSean Wang 
2919a1c49c43SSean Wang 	if (wmt_params->status)
2920a1c49c43SSean Wang 		*wmt_params->status = status;
2921a1c49c43SSean Wang 
2922a1c49c43SSean Wang err_free_skb:
2923a1c49c43SSean Wang 	kfree_skb(data->evt_skb);
2924a1c49c43SSean Wang 	data->evt_skb = NULL;
292510888140SArnd Bergmann err_free_wc:
292610888140SArnd Bergmann 	kfree(wc);
2927a1c49c43SSean Wang 	return err;
2928a1c49c43SSean Wang }
2929a1c49c43SSean Wang 
btusb_mtk_func_query(struct hci_dev * hdev)2930a1c49c43SSean Wang static int btusb_mtk_func_query(struct hci_dev *hdev)
2931a1c49c43SSean Wang {
2932a1c49c43SSean Wang 	struct btmtk_hci_wmt_params wmt_params;
2933a1c49c43SSean Wang 	int status, err;
2934a1c49c43SSean Wang 	u8 param = 0;
2935a1c49c43SSean Wang 
2936a1c49c43SSean Wang 	/* Query whether the function is enabled */
2937a1c49c43SSean Wang 	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
2938a1c49c43SSean Wang 	wmt_params.flag = 4;
2939a1c49c43SSean Wang 	wmt_params.dlen = sizeof(param);
2940a1c49c43SSean Wang 	wmt_params.data = &param;
2941a1c49c43SSean Wang 	wmt_params.status = &status;
2942a1c49c43SSean Wang 
2943a1c49c43SSean Wang 	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
2944a1c49c43SSean Wang 	if (err < 0) {
2945a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to query function status (%d)", err);
2946a1c49c43SSean Wang 		return err;
2947a1c49c43SSean Wang 	}
2948a1c49c43SSean Wang 
2949a1c49c43SSean Wang 	return status;
2950a1c49c43SSean Wang }
2951a1c49c43SSean Wang 
btusb_mtk_uhw_reg_write(struct btusb_data * data,u32 reg,u32 val)2952e9478026Smark-yw.chen static int btusb_mtk_uhw_reg_write(struct btusb_data *data, u32 reg, u32 val)
2953e9478026Smark-yw.chen {
2954e9478026Smark-yw.chen 	struct hci_dev *hdev = data->hdev;
2955e9478026Smark-yw.chen 	int pipe, err;
2956e9478026Smark-yw.chen 	void *buf;
2957e9478026Smark-yw.chen 
2958e9478026Smark-yw.chen 	buf = kzalloc(4, GFP_KERNEL);
2959e9478026Smark-yw.chen 	if (!buf)
2960e9478026Smark-yw.chen 		return -ENOMEM;
2961e9478026Smark-yw.chen 
2962e9478026Smark-yw.chen 	put_unaligned_le32(val, buf);
2963e9478026Smark-yw.chen 
2964e9478026Smark-yw.chen 	pipe = usb_sndctrlpipe(data->udev, 0);
2965e9478026Smark-yw.chen 	err = usb_control_msg(data->udev, pipe, 0x02,
2966e9478026Smark-yw.chen 			      0x5E,
2967e9478026Smark-yw.chen 			      reg >> 16, reg & 0xffff,
2968e9478026Smark-yw.chen 			      buf, 4, USB_CTRL_SET_TIMEOUT);
2969e9478026Smark-yw.chen 	if (err < 0) {
2970e9478026Smark-yw.chen 		bt_dev_err(hdev, "Failed to write uhw reg(%d)", err);
2971e9478026Smark-yw.chen 		goto err_free_buf;
2972e9478026Smark-yw.chen 	}
2973e9478026Smark-yw.chen 
2974e9478026Smark-yw.chen err_free_buf:
2975e9478026Smark-yw.chen 	kfree(buf);
2976e9478026Smark-yw.chen 
2977e9478026Smark-yw.chen 	return err;
2978e9478026Smark-yw.chen }
2979e9478026Smark-yw.chen 
btusb_mtk_uhw_reg_read(struct btusb_data * data,u32 reg,u32 * val)2980e9478026Smark-yw.chen static int btusb_mtk_uhw_reg_read(struct btusb_data *data, u32 reg, u32 *val)
2981e9478026Smark-yw.chen {
2982e9478026Smark-yw.chen 	struct hci_dev *hdev = data->hdev;
2983e9478026Smark-yw.chen 	int pipe, err;
2984e9478026Smark-yw.chen 	void *buf;
2985e9478026Smark-yw.chen 
2986e9478026Smark-yw.chen 	buf = kzalloc(4, GFP_KERNEL);
2987e9478026Smark-yw.chen 	if (!buf)
2988e9478026Smark-yw.chen 		return -ENOMEM;
2989e9478026Smark-yw.chen 
2990e9478026Smark-yw.chen 	pipe = usb_rcvctrlpipe(data->udev, 0);
2991e9478026Smark-yw.chen 	err = usb_control_msg(data->udev, pipe, 0x01,
2992e9478026Smark-yw.chen 			      0xDE,
2993e9478026Smark-yw.chen 			      reg >> 16, reg & 0xffff,
2994e9478026Smark-yw.chen 			      buf, 4, USB_CTRL_SET_TIMEOUT);
2995e9478026Smark-yw.chen 	if (err < 0) {
2996e9478026Smark-yw.chen 		bt_dev_err(hdev, "Failed to read uhw reg(%d)", err);
2997e9478026Smark-yw.chen 		goto err_free_buf;
2998e9478026Smark-yw.chen 	}
2999e9478026Smark-yw.chen 
3000e9478026Smark-yw.chen 	*val = get_unaligned_le32(buf);
3001e9478026Smark-yw.chen 	bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val);
3002e9478026Smark-yw.chen 
3003e9478026Smark-yw.chen err_free_buf:
3004e9478026Smark-yw.chen 	kfree(buf);
3005e9478026Smark-yw.chen 
3006e9478026Smark-yw.chen 	return err;
3007e9478026Smark-yw.chen }
3008e9478026Smark-yw.chen 
btusb_mtk_reg_read(struct btusb_data * data,u32 reg,u32 * val)3009a1c49c43SSean Wang static int btusb_mtk_reg_read(struct btusb_data *data, u32 reg, u32 *val)
3010a1c49c43SSean Wang {
3011a1c49c43SSean Wang 	int pipe, err, size = sizeof(u32);
3012a1c49c43SSean Wang 	void *buf;
3013a1c49c43SSean Wang 
3014a1c49c43SSean Wang 	buf = kzalloc(size, GFP_KERNEL);
3015a1c49c43SSean Wang 	if (!buf)
3016a1c49c43SSean Wang 		return -ENOMEM;
3017a1c49c43SSean Wang 
3018a1c49c43SSean Wang 	pipe = usb_rcvctrlpipe(data->udev, 0);
3019a1c49c43SSean Wang 	err = usb_control_msg(data->udev, pipe, 0x63,
3020a1c49c43SSean Wang 			      USB_TYPE_VENDOR | USB_DIR_IN,
3021a1c49c43SSean Wang 			      reg >> 16, reg & 0xffff,
3022a1c49c43SSean Wang 			      buf, size, USB_CTRL_SET_TIMEOUT);
3023a1c49c43SSean Wang 	if (err < 0)
3024a1c49c43SSean Wang 		goto err_free_buf;
3025a1c49c43SSean Wang 
3026a1c49c43SSean Wang 	*val = get_unaligned_le32(buf);
3027a1c49c43SSean Wang 
3028a1c49c43SSean Wang err_free_buf:
3029a1c49c43SSean Wang 	kfree(buf);
3030a1c49c43SSean Wang 
3031a1c49c43SSean Wang 	return err;
3032a1c49c43SSean Wang }
3033a1c49c43SSean Wang 
btusb_mtk_id_get(struct btusb_data * data,u32 reg,u32 * id)303448c13301SMark Chen static int btusb_mtk_id_get(struct btusb_data *data, u32 reg, u32 *id)
3035a1c49c43SSean Wang {
303648c13301SMark Chen 	return btusb_mtk_reg_read(data, reg, id);
3037a1c49c43SSean Wang }
3038a1c49c43SSean Wang 
btusb_mtk_reset_done(struct hci_dev * hdev)3039ca58330cSSean Wang static u32 btusb_mtk_reset_done(struct hci_dev *hdev)
3040ca58330cSSean Wang {
3041ca58330cSSean Wang 	struct btusb_data *data = hci_get_drvdata(hdev);
3042ca58330cSSean Wang 	u32 val = 0;
3043ca58330cSSean Wang 
3044ca58330cSSean Wang 	btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val);
3045ca58330cSSean Wang 
3046ca58330cSSean Wang 	return val & MTK_BT_RST_DONE;
3047ca58330cSSean Wang }
3048ca58330cSSean Wang 
btusb_mtk_reset(struct hci_dev * hdev,void * rst_data)304925b6d759SJing Cai static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
305025b6d759SJing Cai {
305125b6d759SJing Cai 	struct btusb_data *data = hci_get_drvdata(hdev);
305225b6d759SJing Cai 	struct btmediatek_data *mediatek;
305325b6d759SJing Cai 	u32 val;
305425b6d759SJing Cai 	int err;
305525b6d759SJing Cai 
305625b6d759SJing Cai 	/* It's MediaTek specific bluetooth reset mechanism via USB */
305725b6d759SJing Cai 	if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
305825b6d759SJing Cai 		bt_dev_err(hdev, "last reset failed? Not resetting again");
305925b6d759SJing Cai 		return -EBUSY;
306025b6d759SJing Cai 	}
306125b6d759SJing Cai 
306225b6d759SJing Cai 	err = usb_autopm_get_interface(data->intf);
306325b6d759SJing Cai 	if (err < 0)
306425b6d759SJing Cai 		return err;
306525b6d759SJing Cai 
306625b6d759SJing Cai 	btusb_stop_traffic(data);
306725b6d759SJing Cai 	usb_kill_anchored_urbs(&data->tx_anchor);
306825b6d759SJing Cai 	mediatek = hci_get_priv(hdev);
306925b6d759SJing Cai 
307025b6d759SJing Cai 	if (mediatek->dev_id == 0x7925) {
307125b6d759SJing Cai 		btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
307225b6d759SJing Cai 		val |= (1 << 5);
307325b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
307425b6d759SJing Cai 		btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
307525b6d759SJing Cai 		val &= 0xFFFF00FF;
307625b6d759SJing Cai 		val |= (1 << 13);
307725b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
307825b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001);
307925b6d759SJing Cai 		btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val);
308025b6d759SJing Cai 		val |= (1 << 0);
308125b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val);
308225b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
308325b6d759SJing Cai 		btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
308425b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
308525b6d759SJing Cai 		btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
308625b6d759SJing Cai 		msleep(100);
308725b6d759SJing Cai 	} else {
308825b6d759SJing Cai 		/* It's Device EndPoint Reset Option Register */
308925b6d759SJing Cai 		bt_dev_dbg(hdev, "Initiating reset mechanism via uhw");
309025b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
309125b6d759SJing Cai 		btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val);
309225b6d759SJing Cai 
309325b6d759SJing Cai 		/* Reset the bluetooth chip via USB interface. */
309425b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1);
309525b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
309625b6d759SJing Cai 		btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
309725b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
309825b6d759SJing Cai 		btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
309925b6d759SJing Cai 		/* MT7921 need to delay 20ms between toggle reset bit */
310025b6d759SJing Cai 		msleep(20);
310125b6d759SJing Cai 		btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
310225b6d759SJing Cai 		btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
310325b6d759SJing Cai 	}
310425b6d759SJing Cai 
310525b6d759SJing Cai 	err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val,
310625b6d759SJing Cai 				 val & MTK_BT_RST_DONE, 20000, 1000000);
310725b6d759SJing Cai 	if (err < 0)
310825b6d759SJing Cai 		bt_dev_err(hdev, "Reset timeout");
310925b6d759SJing Cai 
311025b6d759SJing Cai 	btusb_mtk_id_get(data, 0x70010200, &val);
311125b6d759SJing Cai 	if (!val)
311225b6d759SJing Cai 		bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
311325b6d759SJing Cai 
311425b6d759SJing Cai 	usb_queue_reset_device(data->intf);
311525b6d759SJing Cai 
311625b6d759SJing Cai 	clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags);
311725b6d759SJing Cai 
311825b6d759SJing Cai 	return err;
311925b6d759SJing Cai }
312025b6d759SJing Cai 
btusb_mtk_setup(struct hci_dev * hdev)3121a1c49c43SSean Wang static int btusb_mtk_setup(struct hci_dev *hdev)
3122a1c49c43SSean Wang {
3123a1c49c43SSean Wang 	struct btusb_data *data = hci_get_drvdata(hdev);
3124a1c49c43SSean Wang 	struct btmtk_hci_wmt_params wmt_params;
3125a1c49c43SSean Wang 	ktime_t calltime, delta, rettime;
3126a1c49c43SSean Wang 	struct btmtk_tci_sleep tci_sleep;
3127a1c49c43SSean Wang 	unsigned long long duration;
3128a1c49c43SSean Wang 	struct sk_buff *skb;
3129a1c49c43SSean Wang 	const char *fwname;
3130a1c49c43SSean Wang 	int err, status;
31314c92ae75SPeter Tsao 	u32 dev_id = 0;
3132fc342c4dSMark Chen 	char fw_bin_name[64];
3133201cf397Smark-yw.chen 	u32 fw_version = 0;
3134a1c49c43SSean Wang 	u8 param;
31354c92ae75SPeter Tsao 	struct btmediatek_data *mediatek;
3136a1c49c43SSean Wang 
3137a1c49c43SSean Wang 	calltime = ktime_get();
3138a1c49c43SSean Wang 
313948c13301SMark Chen 	err = btusb_mtk_id_get(data, 0x80000008, &dev_id);
3140a1c49c43SSean Wang 	if (err < 0) {
3141a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to get device id (%d)", err);
3142a1c49c43SSean Wang 		return err;
3143a1c49c43SSean Wang 	}
3144a1c49c43SSean Wang 
31454c92ae75SPeter Tsao 	if (!dev_id || dev_id != 0x7663) {
3146fc342c4dSMark Chen 		err = btusb_mtk_id_get(data, 0x70010200, &dev_id);
3147fc342c4dSMark Chen 		if (err < 0) {
3148fc342c4dSMark Chen 			bt_dev_err(hdev, "Failed to get device id (%d)", err);
3149fc342c4dSMark Chen 			return err;
3150fc342c4dSMark Chen 		}
3151fc342c4dSMark Chen 		err = btusb_mtk_id_get(data, 0x80021004, &fw_version);
3152fc342c4dSMark Chen 		if (err < 0) {
3153fc342c4dSMark Chen 			bt_dev_err(hdev, "Failed to get fw version (%d)", err);
3154fc342c4dSMark Chen 			return err;
3155fc342c4dSMark Chen 		}
3156fc342c4dSMark Chen 	}
3157fc342c4dSMark Chen 
31584c92ae75SPeter Tsao 	mediatek = hci_get_priv(hdev);
31594c92ae75SPeter Tsao 	mediatek->dev_id = dev_id;
316025b6d759SJing Cai 	mediatek->reset_sync = btusb_mtk_reset;
31614c92ae75SPeter Tsao 
31620b701513SJing Cai 	err = btmtk_register_coredump(hdev, btusb_driver.name, fw_version);
31630b701513SJing Cai 	if (err < 0)
31640b701513SJing Cai 		bt_dev_err(hdev, "Failed to register coredump (%d)", err);
31650b701513SJing Cai 
3166a1c49c43SSean Wang 	switch (dev_id) {
31679ce67c32SSean Wang 	case 0x7663:
31689ce67c32SSean Wang 		fwname = FIRMWARE_MT7663;
31699ce67c32SSean Wang 		break;
3170a1c49c43SSean Wang 	case 0x7668:
3171a1c49c43SSean Wang 		fwname = FIRMWARE_MT7668;
3172a1c49c43SSean Wang 		break;
317309a19d6dSmark-yw.chen 	case 0x7922:
3174fc342c4dSMark Chen 	case 0x7961:
31754c92ae75SPeter Tsao 	case 0x7925:
31764c92ae75SPeter Tsao 		if (dev_id == 0x7925)
31774c92ae75SPeter Tsao 			snprintf(fw_bin_name, sizeof(fw_bin_name),
31784c92ae75SPeter Tsao 				 "mediatek/mt%04x/BT_RAM_CODE_MT%04x_1_%x_hdr.bin",
31794c92ae75SPeter Tsao 				 dev_id & 0xffff, dev_id & 0xffff, (fw_version & 0xff) + 1);
31804c92ae75SPeter Tsao 		else
3181fc342c4dSMark Chen 			snprintf(fw_bin_name, sizeof(fw_bin_name),
3182fc342c4dSMark Chen 				 "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin",
3183fc342c4dSMark Chen 				 dev_id & 0xffff, (fw_version & 0xff) + 1);
31844c92ae75SPeter Tsao 
31858c0d17b6SSean Wang 		err = btmtk_setup_firmware_79xx(hdev, fw_bin_name,
31868c0d17b6SSean Wang 						btusb_mtk_hci_wmt_sync);
318700c0ee98SMark Chen 		if (err < 0) {
318800c0ee98SMark Chen 			bt_dev_err(hdev, "Failed to set up firmware (%d)", err);
318900c0ee98SMark Chen 			return err;
319000c0ee98SMark Chen 		}
3191fc342c4dSMark Chen 
3192e9478026Smark-yw.chen 		/* It's Device EndPoint Reset Option Register */
3193e9478026Smark-yw.chen 		btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
3194e9478026Smark-yw.chen 
3195fc342c4dSMark Chen 		/* Enable Bluetooth protocol */
3196fc342c4dSMark Chen 		param = 1;
3197fc342c4dSMark Chen 		wmt_params.op = BTMTK_WMT_FUNC_CTRL;
3198fc342c4dSMark Chen 		wmt_params.flag = 0;
3199fc342c4dSMark Chen 		wmt_params.dlen = sizeof(param);
3200fc342c4dSMark Chen 		wmt_params.data = &param;
3201fc342c4dSMark Chen 		wmt_params.status = NULL;
3202fc342c4dSMark Chen 
3203fc342c4dSMark Chen 		err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
3204fc342c4dSMark Chen 		if (err < 0) {
3205fc342c4dSMark Chen 			bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
3206fc342c4dSMark Chen 			return err;
3207fc342c4dSMark Chen 		}
3208654e6f77Smark-yw.chen 
3209654e6f77Smark-yw.chen 		hci_set_msft_opcode(hdev, 0xFD30);
321028491d7eSmark-yw.chen 		hci_set_aosp_capable(hdev);
3211fc342c4dSMark Chen 		goto done;
3212a1c49c43SSean Wang 	default:
3213a297f565SJupeng Zhong 		bt_dev_err(hdev, "Unsupported hardware variant (%08x)",
3214a1c49c43SSean Wang 			   dev_id);
3215a1c49c43SSean Wang 		return -ENODEV;
3216a1c49c43SSean Wang 	}
3217a1c49c43SSean Wang 
3218a1c49c43SSean Wang 	/* Query whether the firmware is already download */
3219a1c49c43SSean Wang 	wmt_params.op = BTMTK_WMT_SEMAPHORE;
3220a1c49c43SSean Wang 	wmt_params.flag = 1;
3221a1c49c43SSean Wang 	wmt_params.dlen = 0;
3222a1c49c43SSean Wang 	wmt_params.data = NULL;
3223a1c49c43SSean Wang 	wmt_params.status = &status;
3224a1c49c43SSean Wang 
3225a1c49c43SSean Wang 	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
3226a1c49c43SSean Wang 	if (err < 0) {
3227a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
3228a1c49c43SSean Wang 		return err;
3229a1c49c43SSean Wang 	}
3230a1c49c43SSean Wang 
3231a1c49c43SSean Wang 	if (status == BTMTK_WMT_PATCH_DONE) {
3232a1c49c43SSean Wang 		bt_dev_info(hdev, "firmware already downloaded");
3233a1c49c43SSean Wang 		goto ignore_setup_fw;
3234a1c49c43SSean Wang 	}
3235a1c49c43SSean Wang 
3236a1c49c43SSean Wang 	/* Setup a firmware which the device definitely requires */
32378c0d17b6SSean Wang 	err = btmtk_setup_firmware(hdev, fwname,
32388c0d17b6SSean Wang 				   btusb_mtk_hci_wmt_sync);
3239a1c49c43SSean Wang 	if (err < 0)
3240a1c49c43SSean Wang 		return err;
3241a1c49c43SSean Wang 
3242a1c49c43SSean Wang ignore_setup_fw:
3243a1c49c43SSean Wang 	err = readx_poll_timeout(btusb_mtk_func_query, hdev, status,
3244a1c49c43SSean Wang 				 status < 0 || status != BTMTK_WMT_ON_PROGRESS,
3245a1c49c43SSean Wang 				 2000, 5000000);
3246a1c49c43SSean Wang 	/* -ETIMEDOUT happens */
3247a1c49c43SSean Wang 	if (err < 0)
3248a1c49c43SSean Wang 		return err;
3249a1c49c43SSean Wang 
3250a1c49c43SSean Wang 	/* The other errors happen in btusb_mtk_func_query */
3251a1c49c43SSean Wang 	if (status < 0)
3252a1c49c43SSean Wang 		return status;
3253a1c49c43SSean Wang 
3254a1c49c43SSean Wang 	if (status == BTMTK_WMT_ON_DONE) {
3255a1c49c43SSean Wang 		bt_dev_info(hdev, "function already on");
3256a1c49c43SSean Wang 		goto ignore_func_on;
3257a1c49c43SSean Wang 	}
3258a1c49c43SSean Wang 
3259a1c49c43SSean Wang 	/* Enable Bluetooth protocol */
3260a1c49c43SSean Wang 	param = 1;
3261a1c49c43SSean Wang 	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
3262a1c49c43SSean Wang 	wmt_params.flag = 0;
3263a1c49c43SSean Wang 	wmt_params.dlen = sizeof(param);
3264a1c49c43SSean Wang 	wmt_params.data = &param;
3265a1c49c43SSean Wang 	wmt_params.status = NULL;
3266a1c49c43SSean Wang 
3267a1c49c43SSean Wang 	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
3268a1c49c43SSean Wang 	if (err < 0) {
3269a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
3270a1c49c43SSean Wang 		return err;
3271a1c49c43SSean Wang 	}
3272a1c49c43SSean Wang 
3273a1c49c43SSean Wang ignore_func_on:
3274a1c49c43SSean Wang 	/* Apply the low power environment setup */
3275a1c49c43SSean Wang 	tci_sleep.mode = 0x5;
3276a1c49c43SSean Wang 	tci_sleep.duration = cpu_to_le16(0x640);
3277a1c49c43SSean Wang 	tci_sleep.host_duration = cpu_to_le16(0x640);
3278a1c49c43SSean Wang 	tci_sleep.host_wakeup_pin = 0;
3279a1c49c43SSean Wang 	tci_sleep.time_compensation = 0;
3280a1c49c43SSean Wang 
3281a1c49c43SSean Wang 	skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep,
3282a1c49c43SSean Wang 			     HCI_INIT_TIMEOUT);
3283a1c49c43SSean Wang 	if (IS_ERR(skb)) {
3284a1c49c43SSean Wang 		err = PTR_ERR(skb);
3285a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to apply low power setting (%d)", err);
3286a1c49c43SSean Wang 		return err;
3287a1c49c43SSean Wang 	}
3288a1c49c43SSean Wang 	kfree_skb(skb);
3289a1c49c43SSean Wang 
3290fc342c4dSMark Chen done:
3291a1c49c43SSean Wang 	rettime = ktime_get();
3292a1c49c43SSean Wang 	delta = ktime_sub(rettime, calltime);
3293a1c49c43SSean Wang 	duration = (unsigned long long)ktime_to_ns(delta) >> 10;
3294a1c49c43SSean Wang 
3295a1c49c43SSean Wang 	bt_dev_info(hdev, "Device setup in %llu usecs", duration);
3296a1c49c43SSean Wang 
3297a1c49c43SSean Wang 	return 0;
3298a1c49c43SSean Wang }
3299a1c49c43SSean Wang 
btusb_mtk_shutdown(struct hci_dev * hdev)3300a1c49c43SSean Wang static int btusb_mtk_shutdown(struct hci_dev *hdev)
3301a1c49c43SSean Wang {
3302a1c49c43SSean Wang 	struct btmtk_hci_wmt_params wmt_params;
3303a1c49c43SSean Wang 	u8 param = 0;
3304a1c49c43SSean Wang 	int err;
3305a1c49c43SSean Wang 
3306a1c49c43SSean Wang 	/* Disable the device */
3307a1c49c43SSean Wang 	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
3308a1c49c43SSean Wang 	wmt_params.flag = 0;
3309a1c49c43SSean Wang 	wmt_params.dlen = sizeof(param);
3310a1c49c43SSean Wang 	wmt_params.data = &param;
3311a1c49c43SSean Wang 	wmt_params.status = NULL;
3312a1c49c43SSean Wang 
3313a1c49c43SSean Wang 	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
3314a1c49c43SSean Wang 	if (err < 0) {
3315a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
3316a1c49c43SSean Wang 		return err;
3317a1c49c43SSean Wang 	}
3318a1c49c43SSean Wang 
3319a1c49c43SSean Wang 	return 0;
3320a1c49c43SSean Wang }
3321a1c49c43SSean Wang 
btusb_recv_acl_mtk(struct hci_dev * hdev,struct sk_buff * skb)33220b10c8c8Smark-yw.chen static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
33230b10c8c8Smark-yw.chen {
33240b10c8c8Smark-yw.chen 	struct btusb_data *data = hci_get_drvdata(hdev);
33250b10c8c8Smark-yw.chen 	u16 handle = le16_to_cpu(hci_acl_hdr(skb)->handle);
33260b10c8c8Smark-yw.chen 
33270b10c8c8Smark-yw.chen 	switch (handle) {
33280b10c8c8Smark-yw.chen 	case 0xfc6f:		/* Firmware dump from device */
33290b10c8c8Smark-yw.chen 		/* When the firmware hangs, the device can no longer
33300b10c8c8Smark-yw.chen 		 * suspend and thus disable auto-suspend.
33310b10c8c8Smark-yw.chen 		 */
33320b10c8c8Smark-yw.chen 		usb_disable_autosuspend(data->udev);
33330b701513SJing Cai 
33340b701513SJing Cai 		/* We need to forward the diagnostic packet to userspace daemon
33350b701513SJing Cai 		 * for backward compatibility, so we have to clone the packet
33360b701513SJing Cai 		 * extraly for the in-kernel coredump support.
33370b701513SJing Cai 		 */
3338620b9e60SLuiz Augusto von Dentz 		if (IS_ENABLED(CONFIG_DEV_COREDUMP)) {
3339620b9e60SLuiz Augusto von Dentz 			struct sk_buff *skb_cd = skb_clone(skb, GFP_ATOMIC);
3340620b9e60SLuiz Augusto von Dentz 
33410b701513SJing Cai 			if (skb_cd)
33420b701513SJing Cai 				btmtk_process_coredump(hdev, skb_cd);
3343620b9e60SLuiz Augusto von Dentz 		}
33440b701513SJing Cai 
3345146af226Smark-yw.chen 		fallthrough;
33460b10c8c8Smark-yw.chen 	case 0x05ff:		/* Firmware debug logging 1 */
33470b10c8c8Smark-yw.chen 	case 0x05fe:		/* Firmware debug logging 2 */
33480b10c8c8Smark-yw.chen 		return hci_recv_diag(hdev, skb);
33490b10c8c8Smark-yw.chen 	}
33500b10c8c8Smark-yw.chen 
33510b10c8c8Smark-yw.chen 	return hci_recv_frame(hdev, skb);
33520b10c8c8Smark-yw.chen }
33530b10c8c8Smark-yw.chen 
3354a4ccc9e3SRajat Jain #ifdef CONFIG_PM
3355a4ccc9e3SRajat Jain /* Configure an out-of-band gpio as wake-up pin, if specified in device tree */
marvell_config_oob_wake(struct hci_dev * hdev)3356a4ccc9e3SRajat Jain static int marvell_config_oob_wake(struct hci_dev *hdev)
3357a4ccc9e3SRajat Jain {
3358a4ccc9e3SRajat Jain 	struct sk_buff *skb;
3359a4ccc9e3SRajat Jain 	struct btusb_data *data = hci_get_drvdata(hdev);
3360a4ccc9e3SRajat Jain 	struct device *dev = &data->udev->dev;
3361a4ccc9e3SRajat Jain 	u16 pin, gap, opcode;
3362a4ccc9e3SRajat Jain 	int ret;
3363a4ccc9e3SRajat Jain 	u8 cmd[5];
3364a4ccc9e3SRajat Jain 
3365a4ccc9e3SRajat Jain 	/* Move on if no wakeup pin specified */
3366a4ccc9e3SRajat Jain 	if (of_property_read_u16(dev->of_node, "marvell,wakeup-pin", &pin) ||
3367a4ccc9e3SRajat Jain 	    of_property_read_u16(dev->of_node, "marvell,wakeup-gap-ms", &gap))
3368a4ccc9e3SRajat Jain 		return 0;
3369a4ccc9e3SRajat Jain 
3370a4ccc9e3SRajat Jain 	/* Vendor specific command to configure a GPIO as wake-up pin */
3371a4ccc9e3SRajat Jain 	opcode = hci_opcode_pack(0x3F, 0x59);
3372a4ccc9e3SRajat Jain 	cmd[0] = opcode & 0xFF;
3373a4ccc9e3SRajat Jain 	cmd[1] = opcode >> 8;
3374a4ccc9e3SRajat Jain 	cmd[2] = 2; /* length of parameters that follow */
3375a4ccc9e3SRajat Jain 	cmd[3] = pin;
3376a4ccc9e3SRajat Jain 	cmd[4] = gap; /* time in ms, for which wakeup pin should be asserted */
3377a4ccc9e3SRajat Jain 
3378a4ccc9e3SRajat Jain 	skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
3379a4ccc9e3SRajat Jain 	if (!skb) {
3380d84fc2c9SJoe Perches 		bt_dev_err(hdev, "%s: No memory", __func__);
3381a4ccc9e3SRajat Jain 		return -ENOMEM;
3382a4ccc9e3SRajat Jain 	}
3383a4ccc9e3SRajat Jain 
338459ae1d12SJohannes Berg 	skb_put_data(skb, cmd, sizeof(cmd));
3385a4ccc9e3SRajat Jain 	hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
3386a4ccc9e3SRajat Jain 
3387a4ccc9e3SRajat Jain 	ret = btusb_send_frame(hdev, skb);
3388a4ccc9e3SRajat Jain 	if (ret) {
3389d84fc2c9SJoe Perches 		bt_dev_err(hdev, "%s: configuration failed", __func__);
3390a4ccc9e3SRajat Jain 		kfree_skb(skb);
3391a4ccc9e3SRajat Jain 		return ret;
3392a4ccc9e3SRajat Jain 	}
3393a4ccc9e3SRajat Jain 
3394a4ccc9e3SRajat Jain 	return 0;
3395a4ccc9e3SRajat Jain }
3396a4ccc9e3SRajat Jain #endif
3397a4ccc9e3SRajat Jain 
btusb_set_bdaddr_marvell(struct hci_dev * hdev,const bdaddr_t * bdaddr)3398ae8df494SAmitkumar Karwar static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
3399ae8df494SAmitkumar Karwar 				    const bdaddr_t *bdaddr)
3400ae8df494SAmitkumar Karwar {
3401ae8df494SAmitkumar Karwar 	struct sk_buff *skb;
3402ae8df494SAmitkumar Karwar 	u8 buf[8];
3403ae8df494SAmitkumar Karwar 	long ret;
3404ae8df494SAmitkumar Karwar 
3405ae8df494SAmitkumar Karwar 	buf[0] = 0xfe;
3406ae8df494SAmitkumar Karwar 	buf[1] = sizeof(bdaddr_t);
3407ae8df494SAmitkumar Karwar 	memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
3408ae8df494SAmitkumar Karwar 
3409ae8df494SAmitkumar Karwar 	skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT);
3410ae8df494SAmitkumar Karwar 	if (IS_ERR(skb)) {
3411ae8df494SAmitkumar Karwar 		ret = PTR_ERR(skb);
34122064ee33SMarcel Holtmann 		bt_dev_err(hdev, "changing Marvell device address failed (%ld)",
34132064ee33SMarcel Holtmann 			   ret);
3414ae8df494SAmitkumar Karwar 		return ret;
3415ae8df494SAmitkumar Karwar 	}
3416ae8df494SAmitkumar Karwar 	kfree_skb(skb);
3417ae8df494SAmitkumar Karwar 
3418ae8df494SAmitkumar Karwar 	return 0;
3419ae8df494SAmitkumar Karwar }
3420ae8df494SAmitkumar Karwar 
btusb_set_bdaddr_ath3012(struct hci_dev * hdev,const bdaddr_t * bdaddr)34215859223eSToshi Kikuchi static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
34225859223eSToshi Kikuchi 				    const bdaddr_t *bdaddr)
34235859223eSToshi Kikuchi {
34245859223eSToshi Kikuchi 	struct sk_buff *skb;
34255859223eSToshi Kikuchi 	u8 buf[10];
34265859223eSToshi Kikuchi 	long ret;
34275859223eSToshi Kikuchi 
34285859223eSToshi Kikuchi 	buf[0] = 0x01;
34295859223eSToshi Kikuchi 	buf[1] = 0x01;
34305859223eSToshi Kikuchi 	buf[2] = 0x00;
34315859223eSToshi Kikuchi 	buf[3] = sizeof(bdaddr_t);
34325859223eSToshi Kikuchi 	memcpy(buf + 4, bdaddr, sizeof(bdaddr_t));
34335859223eSToshi Kikuchi 
34345859223eSToshi Kikuchi 	skb = __hci_cmd_sync(hdev, 0xfc0b, sizeof(buf), buf, HCI_INIT_TIMEOUT);
34355859223eSToshi Kikuchi 	if (IS_ERR(skb)) {
34365859223eSToshi Kikuchi 		ret = PTR_ERR(skb);
34372064ee33SMarcel Holtmann 		bt_dev_err(hdev, "Change address command failed (%ld)", ret);
34385859223eSToshi Kikuchi 		return ret;
34395859223eSToshi Kikuchi 	}
34405859223eSToshi Kikuchi 	kfree_skb(skb);
34415859223eSToshi Kikuchi 
34425859223eSToshi Kikuchi 	return 0;
34435859223eSToshi Kikuchi }
34445859223eSToshi Kikuchi 
btusb_set_bdaddr_wcn6855(struct hci_dev * hdev,const bdaddr_t * bdaddr)3445b40f58b9SRocky Liao static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
3446b40f58b9SRocky Liao 				const bdaddr_t *bdaddr)
3447b40f58b9SRocky Liao {
3448b40f58b9SRocky Liao 	struct sk_buff *skb;
3449b40f58b9SRocky Liao 	u8 buf[6];
3450b40f58b9SRocky Liao 	long ret;
3451b40f58b9SRocky Liao 
3452b40f58b9SRocky Liao 	memcpy(buf, bdaddr, sizeof(bdaddr_t));
3453b40f58b9SRocky Liao 
3454b40f58b9SRocky Liao 	skb = __hci_cmd_sync_ev(hdev, 0xfc14, sizeof(buf), buf,
3455b40f58b9SRocky Liao 				HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
3456b40f58b9SRocky Liao 	if (IS_ERR(skb)) {
3457b40f58b9SRocky Liao 		ret = PTR_ERR(skb);
3458b40f58b9SRocky Liao 		bt_dev_err(hdev, "Change address command failed (%ld)", ret);
3459b40f58b9SRocky Liao 		return ret;
3460b40f58b9SRocky Liao 	}
3461b40f58b9SRocky Liao 	kfree_skb(skb);
3462b40f58b9SRocky Liao 
3463b40f58b9SRocky Liao 	return 0;
3464b40f58b9SRocky Liao }
3465b40f58b9SRocky Liao 
346620981ce2STim Jiang #define QCA_MEMDUMP_ACL_HANDLE 0x2EDD
346720981ce2STim Jiang #define QCA_MEMDUMP_SIZE_MAX  0x100000
346820981ce2STim Jiang #define QCA_MEMDUMP_VSE_CLASS 0x01
346920981ce2STim Jiang #define QCA_MEMDUMP_MSG_TYPE 0x08
347020981ce2STim Jiang #define QCA_MEMDUMP_PKT_SIZE 248
347120981ce2STim Jiang #define QCA_LAST_SEQUENCE_NUM 0xffff
347220981ce2STim Jiang 
347320981ce2STim Jiang struct qca_dump_hdr {
347420981ce2STim Jiang 	u8 vse_class;
347520981ce2STim Jiang 	u8 msg_type;
347620981ce2STim Jiang 	__le16 seqno;
347720981ce2STim Jiang 	u8 reserved;
347820981ce2STim Jiang 	union {
347920981ce2STim Jiang 		u8 data[0];
348020981ce2STim Jiang 		struct {
348120981ce2STim Jiang 			__le32 ram_dump_size;
348220981ce2STim Jiang 			u8 data0[0];
348320981ce2STim Jiang 		} __packed;
348420981ce2STim Jiang 	};
348520981ce2STim Jiang } __packed;
348620981ce2STim Jiang 
348720981ce2STim Jiang 
btusb_dump_hdr_qca(struct hci_dev * hdev,struct sk_buff * skb)348820981ce2STim Jiang static void btusb_dump_hdr_qca(struct hci_dev *hdev, struct sk_buff *skb)
348920981ce2STim Jiang {
349020981ce2STim Jiang 	char buf[128];
349120981ce2STim Jiang 	struct btusb_data *btdata = hci_get_drvdata(hdev);
349220981ce2STim Jiang 
349320981ce2STim Jiang 	snprintf(buf, sizeof(buf), "Controller Name: 0x%x\n",
349420981ce2STim Jiang 			btdata->qca_dump.controller_id);
349520981ce2STim Jiang 	skb_put_data(skb, buf, strlen(buf));
349620981ce2STim Jiang 
349720981ce2STim Jiang 	snprintf(buf, sizeof(buf), "Firmware Version: 0x%x\n",
349820981ce2STim Jiang 			btdata->qca_dump.fw_version);
349920981ce2STim Jiang 	skb_put_data(skb, buf, strlen(buf));
350020981ce2STim Jiang 
350120981ce2STim Jiang 	snprintf(buf, sizeof(buf), "Driver: %s\nVendor: qca\n",
350220981ce2STim Jiang 			btusb_driver.name);
350320981ce2STim Jiang 	skb_put_data(skb, buf, strlen(buf));
350420981ce2STim Jiang 
350520981ce2STim Jiang 	snprintf(buf, sizeof(buf), "VID: 0x%x\nPID:0x%x\n",
350620981ce2STim Jiang 			btdata->qca_dump.id_vendor, btdata->qca_dump.id_product);
350720981ce2STim Jiang 	skb_put_data(skb, buf, strlen(buf));
350820981ce2STim Jiang 
350920981ce2STim Jiang 	snprintf(buf, sizeof(buf), "Lmp Subversion: 0x%x\n",
351020981ce2STim Jiang 			hdev->lmp_subver);
351120981ce2STim Jiang 	skb_put_data(skb, buf, strlen(buf));
351220981ce2STim Jiang }
351320981ce2STim Jiang 
btusb_coredump_qca(struct hci_dev * hdev)351420981ce2STim Jiang static void btusb_coredump_qca(struct hci_dev *hdev)
351520981ce2STim Jiang {
3516190d33b0SZijun Hu 	int err;
351720981ce2STim Jiang 	static const u8 param[] = { 0x26 };
351820981ce2STim Jiang 
3519190d33b0SZijun Hu 	err = __hci_cmd_send(hdev, 0xfc0c, 1, param);
3520190d33b0SZijun Hu 	if (err < 0)
3521190d33b0SZijun Hu 		bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err);
352220981ce2STim Jiang }
352320981ce2STim Jiang 
352420981ce2STim Jiang /*
352520981ce2STim Jiang  * ==0: not a dump pkt.
352620981ce2STim Jiang  * < 0: fails to handle a dump pkt
352720981ce2STim Jiang  * > 0: otherwise.
352820981ce2STim Jiang  */
handle_dump_pkt_qca(struct hci_dev * hdev,struct sk_buff * skb)352920981ce2STim Jiang static int handle_dump_pkt_qca(struct hci_dev *hdev, struct sk_buff *skb)
353020981ce2STim Jiang {
353120981ce2STim Jiang 	int ret = 1;
353220981ce2STim Jiang 	u8 pkt_type;
353320981ce2STim Jiang 	u8 *sk_ptr;
353420981ce2STim Jiang 	unsigned int sk_len;
353520981ce2STim Jiang 	u16 seqno;
353620981ce2STim Jiang 	u32 dump_size;
353720981ce2STim Jiang 
353820981ce2STim Jiang 	struct hci_event_hdr *event_hdr;
353920981ce2STim Jiang 	struct hci_acl_hdr *acl_hdr;
354020981ce2STim Jiang 	struct qca_dump_hdr *dump_hdr;
354120981ce2STim Jiang 	struct btusb_data *btdata = hci_get_drvdata(hdev);
354220981ce2STim Jiang 	struct usb_device *udev = btdata->udev;
354320981ce2STim Jiang 
354420981ce2STim Jiang 	pkt_type = hci_skb_pkt_type(skb);
354520981ce2STim Jiang 	sk_ptr = skb->data;
354620981ce2STim Jiang 	sk_len = skb->len;
354720981ce2STim Jiang 
354820981ce2STim Jiang 	if (pkt_type == HCI_ACLDATA_PKT) {
354920981ce2STim Jiang 		acl_hdr = hci_acl_hdr(skb);
355020981ce2STim Jiang 		if (le16_to_cpu(acl_hdr->handle) != QCA_MEMDUMP_ACL_HANDLE)
355120981ce2STim Jiang 			return 0;
355220981ce2STim Jiang 		sk_ptr += HCI_ACL_HDR_SIZE;
355320981ce2STim Jiang 		sk_len -= HCI_ACL_HDR_SIZE;
355420981ce2STim Jiang 		event_hdr = (struct hci_event_hdr *)sk_ptr;
355520981ce2STim Jiang 	} else {
355620981ce2STim Jiang 		event_hdr = hci_event_hdr(skb);
355720981ce2STim Jiang 	}
355820981ce2STim Jiang 
355920981ce2STim Jiang 	if ((event_hdr->evt != HCI_VENDOR_PKT)
356020981ce2STim Jiang 		|| (event_hdr->plen != (sk_len - HCI_EVENT_HDR_SIZE)))
356120981ce2STim Jiang 		return 0;
356220981ce2STim Jiang 
356320981ce2STim Jiang 	sk_ptr += HCI_EVENT_HDR_SIZE;
356420981ce2STim Jiang 	sk_len -= HCI_EVENT_HDR_SIZE;
356520981ce2STim Jiang 
356620981ce2STim Jiang 	dump_hdr = (struct qca_dump_hdr *)sk_ptr;
356720981ce2STim Jiang 	if ((sk_len < offsetof(struct qca_dump_hdr, data))
356820981ce2STim Jiang 		|| (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS)
356920981ce2STim Jiang 	    || (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE))
357020981ce2STim Jiang 		return 0;
357120981ce2STim Jiang 
357220981ce2STim Jiang 	/*it is dump pkt now*/
357320981ce2STim Jiang 	seqno = le16_to_cpu(dump_hdr->seqno);
357420981ce2STim Jiang 	if (seqno == 0) {
357520981ce2STim Jiang 		set_bit(BTUSB_HW_SSR_ACTIVE, &btdata->flags);
357620981ce2STim Jiang 		dump_size = le32_to_cpu(dump_hdr->ram_dump_size);
357720981ce2STim Jiang 		if (!dump_size || (dump_size > QCA_MEMDUMP_SIZE_MAX)) {
357820981ce2STim Jiang 			ret = -EILSEQ;
357920981ce2STim Jiang 			bt_dev_err(hdev, "Invalid memdump size(%u)",
358020981ce2STim Jiang 				   dump_size);
358120981ce2STim Jiang 			goto out;
358220981ce2STim Jiang 		}
358320981ce2STim Jiang 
358420981ce2STim Jiang 		ret = hci_devcd_init(hdev, dump_size);
358520981ce2STim Jiang 		if (ret < 0) {
358620981ce2STim Jiang 			bt_dev_err(hdev, "memdump init error(%d)", ret);
358720981ce2STim Jiang 			goto out;
358820981ce2STim Jiang 		}
358920981ce2STim Jiang 
359020981ce2STim Jiang 		btdata->qca_dump.ram_dump_size = dump_size;
359120981ce2STim Jiang 		btdata->qca_dump.ram_dump_seqno = 0;
359220981ce2STim Jiang 		sk_ptr += offsetof(struct qca_dump_hdr, data0);
359320981ce2STim Jiang 		sk_len -= offsetof(struct qca_dump_hdr, data0);
359420981ce2STim Jiang 
359520981ce2STim Jiang 		usb_disable_autosuspend(udev);
359620981ce2STim Jiang 		bt_dev_info(hdev, "%s memdump size(%u)\n",
359720981ce2STim Jiang 			    (pkt_type == HCI_ACLDATA_PKT) ? "ACL" : "event",
359820981ce2STim Jiang 			    dump_size);
359920981ce2STim Jiang 	} else {
360020981ce2STim Jiang 		sk_ptr += offsetof(struct qca_dump_hdr, data);
360120981ce2STim Jiang 		sk_len -= offsetof(struct qca_dump_hdr, data);
360220981ce2STim Jiang 	}
360320981ce2STim Jiang 
360420981ce2STim Jiang 	if (!btdata->qca_dump.ram_dump_size) {
360520981ce2STim Jiang 		ret = -EINVAL;
360620981ce2STim Jiang 		bt_dev_err(hdev, "memdump is not active");
360720981ce2STim Jiang 		goto out;
360820981ce2STim Jiang 	}
360920981ce2STim Jiang 
361020981ce2STim Jiang 	if ((seqno > btdata->qca_dump.ram_dump_seqno + 1) && (seqno != QCA_LAST_SEQUENCE_NUM)) {
361120981ce2STim Jiang 		dump_size = QCA_MEMDUMP_PKT_SIZE * (seqno - btdata->qca_dump.ram_dump_seqno - 1);
361220981ce2STim Jiang 		hci_devcd_append_pattern(hdev, 0x0, dump_size);
361320981ce2STim Jiang 		bt_dev_err(hdev,
361420981ce2STim Jiang 			   "expected memdump seqno(%u) is not received(%u)\n",
361520981ce2STim Jiang 			   btdata->qca_dump.ram_dump_seqno, seqno);
361620981ce2STim Jiang 		btdata->qca_dump.ram_dump_seqno = seqno;
361720981ce2STim Jiang 		kfree_skb(skb);
361820981ce2STim Jiang 		return ret;
361920981ce2STim Jiang 	}
362020981ce2STim Jiang 
362120981ce2STim Jiang 	skb_pull(skb, skb->len - sk_len);
362220981ce2STim Jiang 	hci_devcd_append(hdev, skb);
362320981ce2STim Jiang 	btdata->qca_dump.ram_dump_seqno++;
362420981ce2STim Jiang 	if (seqno == QCA_LAST_SEQUENCE_NUM) {
362520981ce2STim Jiang 		bt_dev_info(hdev,
362620981ce2STim Jiang 				"memdump done: pkts(%u), total(%u)\n",
362720981ce2STim Jiang 				btdata->qca_dump.ram_dump_seqno, btdata->qca_dump.ram_dump_size);
362820981ce2STim Jiang 
362920981ce2STim Jiang 		hci_devcd_complete(hdev);
363020981ce2STim Jiang 		goto out;
363120981ce2STim Jiang 	}
363220981ce2STim Jiang 	return ret;
363320981ce2STim Jiang 
363420981ce2STim Jiang out:
363520981ce2STim Jiang 	if (btdata->qca_dump.ram_dump_size)
363620981ce2STim Jiang 		usb_enable_autosuspend(udev);
363720981ce2STim Jiang 	btdata->qca_dump.ram_dump_size = 0;
363820981ce2STim Jiang 	btdata->qca_dump.ram_dump_seqno = 0;
363920981ce2STim Jiang 	clear_bit(BTUSB_HW_SSR_ACTIVE, &btdata->flags);
364020981ce2STim Jiang 
364120981ce2STim Jiang 	if (ret < 0)
364220981ce2STim Jiang 		kfree_skb(skb);
364320981ce2STim Jiang 	return ret;
364420981ce2STim Jiang }
364520981ce2STim Jiang 
btusb_recv_acl_qca(struct hci_dev * hdev,struct sk_buff * skb)364620981ce2STim Jiang static int btusb_recv_acl_qca(struct hci_dev *hdev, struct sk_buff *skb)
364720981ce2STim Jiang {
364820981ce2STim Jiang 	if (handle_dump_pkt_qca(hdev, skb))
364920981ce2STim Jiang 		return 0;
365020981ce2STim Jiang 	return hci_recv_frame(hdev, skb);
365120981ce2STim Jiang }
365220981ce2STim Jiang 
btusb_recv_evt_qca(struct hci_dev * hdev,struct sk_buff * skb)365320981ce2STim Jiang static int btusb_recv_evt_qca(struct hci_dev *hdev, struct sk_buff *skb)
365420981ce2STim Jiang {
365520981ce2STim Jiang 	if (handle_dump_pkt_qca(hdev, skb))
365620981ce2STim Jiang 		return 0;
365720981ce2STim Jiang 	return hci_recv_frame(hdev, skb);
365820981ce2STim Jiang }
365920981ce2STim Jiang 
366020981ce2STim Jiang 
36613267c884SKim, Ben Young Tae #define QCA_DFU_PACKET_LEN	4096
36623267c884SKim, Ben Young Tae 
36633267c884SKim, Ben Young Tae #define QCA_GET_TARGET_VERSION	0x09
36643267c884SKim, Ben Young Tae #define QCA_CHECK_STATUS	0x05
36653267c884SKim, Ben Young Tae #define QCA_DFU_DOWNLOAD	0x01
36663267c884SKim, Ben Young Tae 
36673267c884SKim, Ben Young Tae #define QCA_SYSCFG_UPDATED	0x40
36683267c884SKim, Ben Young Tae #define QCA_PATCH_UPDATED	0x80
36693267c884SKim, Ben Young Tae #define QCA_DFU_TIMEOUT		3000
3670ef2862a1STim Jiang #define QCA_FLAG_MULTI_NVM      0x80
3671599ece4fSZijun Hu #define QCA_BT_RESET_WAIT_MS    100
36723267c884SKim, Ben Young Tae 
3673d6cba4e6STim Jiang #define WCN6855_2_0_RAM_VERSION_GF 0x400c1200
3674d6cba4e6STim Jiang #define WCN6855_2_1_RAM_VERSION_GF 0x400c1211
3675d6cba4e6STim Jiang 
36763267c884SKim, Ben Young Tae struct qca_version {
36773267c884SKim, Ben Young Tae 	__le32	rom_version;
36783267c884SKim, Ben Young Tae 	__le32	patch_version;
36793267c884SKim, Ben Young Tae 	__le32	ram_version;
3680741268adStjiang@codeaurora.org 	__u8	chip_id;
3681741268adStjiang@codeaurora.org 	__u8	platform_id;
3682ef2862a1STim Jiang 	__le16	flag;
36833267c884SKim, Ben Young Tae 	__u8	reserved[4];
36843267c884SKim, Ben Young Tae } __packed;
36853267c884SKim, Ben Young Tae 
36863267c884SKim, Ben Young Tae struct qca_rampatch_version {
3687b40f58b9SRocky Liao 	__le16	rom_version_high;
3688b40f58b9SRocky Liao 	__le16  rom_version_low;
36893267c884SKim, Ben Young Tae 	__le16	patch_version;
36903267c884SKim, Ben Young Tae } __packed;
36913267c884SKim, Ben Young Tae 
36923267c884SKim, Ben Young Tae struct qca_device_info {
3693bf906b3dSKim, Ben Young Tae 	u32	rom_version;
3694bf906b3dSKim, Ben Young Tae 	u8	rampatch_hdr;	/* length of header in rampatch */
3695bf906b3dSKim, Ben Young Tae 	u8	nvm_hdr;	/* length of header in NVM */
3696bf906b3dSKim, Ben Young Tae 	u8	ver_offset;	/* offset of version structure in rampatch */
36973267c884SKim, Ben Young Tae };
36983267c884SKim, Ben Young Tae 
36993267c884SKim, Ben Young Tae static const struct qca_device_info qca_devices_table[] = {
3700b40f58b9SRocky Liao 	{ 0x00000100, 20, 4,  8 }, /* Rome 1.0 */
3701b40f58b9SRocky Liao 	{ 0x00000101, 20, 4,  8 }, /* Rome 1.1 */
3702b40f58b9SRocky Liao 	{ 0x00000200, 28, 4, 16 }, /* Rome 2.0 */
3703b40f58b9SRocky Liao 	{ 0x00000201, 28, 4, 16 }, /* Rome 2.1 */
3704b40f58b9SRocky Liao 	{ 0x00000300, 28, 4, 16 }, /* Rome 3.0 */
3705b40f58b9SRocky Liao 	{ 0x00000302, 28, 4, 16 }, /* Rome 3.2 */
3706b40f58b9SRocky Liao 	{ 0x00130100, 40, 4, 16 }, /* WCN6855 1.0 */
3707b40f58b9SRocky Liao 	{ 0x00130200, 40, 4, 16 }, /* WCN6855 2.0 */
3708d6cba4e6STim Jiang 	{ 0x00130201, 40, 4, 16 }, /* WCN6855 2.1 */
370946225947SZijun Hu 	{ 0x00190200, 40, 4, 16 }, /* WCN785x 2.0 */
37103267c884SKim, Ben Young Tae };
37113267c884SKim, Ben Young Tae 
btusb_qca_send_vendor_req(struct usb_device * udev,u8 request,void * data,u16 size)3712803cdb8cSTakashi Iwai static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
37133267c884SKim, Ben Young Tae 				     void *data, u16 size)
37143267c884SKim, Ben Young Tae {
37153267c884SKim, Ben Young Tae 	int pipe, err;
37163267c884SKim, Ben Young Tae 	u8 *buf;
37173267c884SKim, Ben Young Tae 
37183267c884SKim, Ben Young Tae 	buf = kmalloc(size, GFP_KERNEL);
37193267c884SKim, Ben Young Tae 	if (!buf)
37203267c884SKim, Ben Young Tae 		return -ENOMEM;
37213267c884SKim, Ben Young Tae 
37223267c884SKim, Ben Young Tae 	/* Found some of USB hosts have IOT issues with ours so that we should
37233267c884SKim, Ben Young Tae 	 * not wait until HCI layer is ready.
37243267c884SKim, Ben Young Tae 	 */
37253267c884SKim, Ben Young Tae 	pipe = usb_rcvctrlpipe(udev, 0);
37263267c884SKim, Ben Young Tae 	err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN,
37273267c884SKim, Ben Young Tae 			      0, 0, buf, size, USB_CTRL_SET_TIMEOUT);
37283267c884SKim, Ben Young Tae 	if (err < 0) {
3729803cdb8cSTakashi Iwai 		dev_err(&udev->dev, "Failed to access otp area (%d)", err);
37303267c884SKim, Ben Young Tae 		goto done;
37313267c884SKim, Ben Young Tae 	}
37323267c884SKim, Ben Young Tae 
37333267c884SKim, Ben Young Tae 	memcpy(data, buf, size);
37343267c884SKim, Ben Young Tae 
37353267c884SKim, Ben Young Tae done:
37363267c884SKim, Ben Young Tae 	kfree(buf);
37373267c884SKim, Ben Young Tae 
37383267c884SKim, Ben Young Tae 	return err;
37393267c884SKim, Ben Young Tae }
37403267c884SKim, Ben Young Tae 
btusb_setup_qca_download_fw(struct hci_dev * hdev,const struct firmware * firmware,size_t hdr_size)37413267c884SKim, Ben Young Tae static int btusb_setup_qca_download_fw(struct hci_dev *hdev,
37423267c884SKim, Ben Young Tae 				       const struct firmware *firmware,
37433267c884SKim, Ben Young Tae 				       size_t hdr_size)
37443267c884SKim, Ben Young Tae {
37453267c884SKim, Ben Young Tae 	struct btusb_data *btdata = hci_get_drvdata(hdev);
37463267c884SKim, Ben Young Tae 	struct usb_device *udev = btdata->udev;
37473267c884SKim, Ben Young Tae 	size_t count, size, sent = 0;
37483267c884SKim, Ben Young Tae 	int pipe, len, err;
37493267c884SKim, Ben Young Tae 	u8 *buf;
37503267c884SKim, Ben Young Tae 
37513267c884SKim, Ben Young Tae 	buf = kmalloc(QCA_DFU_PACKET_LEN, GFP_KERNEL);
37523267c884SKim, Ben Young Tae 	if (!buf)
37533267c884SKim, Ben Young Tae 		return -ENOMEM;
37543267c884SKim, Ben Young Tae 
37553267c884SKim, Ben Young Tae 	count = firmware->size;
37563267c884SKim, Ben Young Tae 
37573267c884SKim, Ben Young Tae 	size = min_t(size_t, count, hdr_size);
37583267c884SKim, Ben Young Tae 	memcpy(buf, firmware->data, size);
37593267c884SKim, Ben Young Tae 
37603267c884SKim, Ben Young Tae 	/* USB patches should go down to controller through USB path
37613267c884SKim, Ben Young Tae 	 * because binary format fits to go down through USB channel.
37623267c884SKim, Ben Young Tae 	 * USB control path is for patching headers and USB bulk is for
37633267c884SKim, Ben Young Tae 	 * patch body.
37643267c884SKim, Ben Young Tae 	 */
37653267c884SKim, Ben Young Tae 	pipe = usb_sndctrlpipe(udev, 0);
37663267c884SKim, Ben Young Tae 	err = usb_control_msg(udev, pipe, QCA_DFU_DOWNLOAD, USB_TYPE_VENDOR,
37673267c884SKim, Ben Young Tae 			      0, 0, buf, size, USB_CTRL_SET_TIMEOUT);
37683267c884SKim, Ben Young Tae 	if (err < 0) {
37692064ee33SMarcel Holtmann 		bt_dev_err(hdev, "Failed to send headers (%d)", err);
37703267c884SKim, Ben Young Tae 		goto done;
37713267c884SKim, Ben Young Tae 	}
37723267c884SKim, Ben Young Tae 
37733267c884SKim, Ben Young Tae 	sent += size;
37743267c884SKim, Ben Young Tae 	count -= size;
37753267c884SKim, Ben Young Tae 
37764f00bfb3STim Jiang 	/* ep2 need time to switch from function acl to function dfu,
37774f00bfb3STim Jiang 	 * so we add 20ms delay here.
37784f00bfb3STim Jiang 	 */
37794f00bfb3STim Jiang 	msleep(20);
37804f00bfb3STim Jiang 
37813267c884SKim, Ben Young Tae 	while (count) {
37823267c884SKim, Ben Young Tae 		size = min_t(size_t, count, QCA_DFU_PACKET_LEN);
37833267c884SKim, Ben Young Tae 
37843267c884SKim, Ben Young Tae 		memcpy(buf, firmware->data + sent, size);
37853267c884SKim, Ben Young Tae 
37863267c884SKim, Ben Young Tae 		pipe = usb_sndbulkpipe(udev, 0x02);
37873267c884SKim, Ben Young Tae 		err = usb_bulk_msg(udev, pipe, buf, size, &len,
37883267c884SKim, Ben Young Tae 				   QCA_DFU_TIMEOUT);
37893267c884SKim, Ben Young Tae 		if (err < 0) {
37902064ee33SMarcel Holtmann 			bt_dev_err(hdev, "Failed to send body at %zd of %zd (%d)",
37912064ee33SMarcel Holtmann 				   sent, firmware->size, err);
37923267c884SKim, Ben Young Tae 			break;
37933267c884SKim, Ben Young Tae 		}
37943267c884SKim, Ben Young Tae 
37953267c884SKim, Ben Young Tae 		if (size != len) {
37962064ee33SMarcel Holtmann 			bt_dev_err(hdev, "Failed to get bulk buffer");
37973267c884SKim, Ben Young Tae 			err = -EILSEQ;
37983267c884SKim, Ben Young Tae 			break;
37993267c884SKim, Ben Young Tae 		}
38003267c884SKim, Ben Young Tae 
38013267c884SKim, Ben Young Tae 		sent  += size;
38023267c884SKim, Ben Young Tae 		count -= size;
38033267c884SKim, Ben Young Tae 	}
38043267c884SKim, Ben Young Tae 
38053267c884SKim, Ben Young Tae done:
38063267c884SKim, Ben Young Tae 	kfree(buf);
38073267c884SKim, Ben Young Tae 	return err;
38083267c884SKim, Ben Young Tae }
38093267c884SKim, Ben Young Tae 
btusb_setup_qca_load_rampatch(struct hci_dev * hdev,struct qca_version * ver,const struct qca_device_info * info)38103267c884SKim, Ben Young Tae static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
38113267c884SKim, Ben Young Tae 					 struct qca_version *ver,
38123267c884SKim, Ben Young Tae 					 const struct qca_device_info *info)
38133267c884SKim, Ben Young Tae {
38143267c884SKim, Ben Young Tae 	struct qca_rampatch_version *rver;
38153267c884SKim, Ben Young Tae 	const struct firmware *fw;
3816b40f58b9SRocky Liao 	u32 ver_rom, ver_patch, rver_rom;
3817b40f58b9SRocky Liao 	u16 rver_rom_low, rver_rom_high, rver_patch;
38183267c884SKim, Ben Young Tae 	char fwname[64];
38193267c884SKim, Ben Young Tae 	int err;
38203267c884SKim, Ben Young Tae 
3821bf906b3dSKim, Ben Young Tae 	ver_rom = le32_to_cpu(ver->rom_version);
3822bf906b3dSKim, Ben Young Tae 	ver_patch = le32_to_cpu(ver->patch_version);
3823bf906b3dSKim, Ben Young Tae 
3824bf906b3dSKim, Ben Young Tae 	snprintf(fwname, sizeof(fwname), "qca/rampatch_usb_%08x.bin", ver_rom);
38253267c884SKim, Ben Young Tae 
38263267c884SKim, Ben Young Tae 	err = request_firmware(&fw, fwname, &hdev->dev);
38273267c884SKim, Ben Young Tae 	if (err) {
38282064ee33SMarcel Holtmann 		bt_dev_err(hdev, "failed to request rampatch file: %s (%d)",
38292064ee33SMarcel Holtmann 			   fwname, err);
38303267c884SKim, Ben Young Tae 		return err;
38313267c884SKim, Ben Young Tae 	}
38323267c884SKim, Ben Young Tae 
38332064ee33SMarcel Holtmann 	bt_dev_info(hdev, "using rampatch file: %s", fwname);
38343267c884SKim, Ben Young Tae 
3835bf906b3dSKim, Ben Young Tae 	rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);
3836b40f58b9SRocky Liao 	rver_rom_low = le16_to_cpu(rver->rom_version_low);
3837bf906b3dSKim, Ben Young Tae 	rver_patch = le16_to_cpu(rver->patch_version);
3838bf906b3dSKim, Ben Young Tae 
3839b40f58b9SRocky Liao 	if (ver_rom & ~0xffffU) {
3840b40f58b9SRocky Liao 		rver_rom_high = le16_to_cpu(rver->rom_version_high);
384142d3b43eSLuiz Augusto von Dentz 		rver_rom = rver_rom_high << 16 | rver_rom_low;
3842b40f58b9SRocky Liao 	} else {
3843b40f58b9SRocky Liao 		rver_rom = rver_rom_low;
3844b40f58b9SRocky Liao 	}
3845b40f58b9SRocky Liao 
38462064ee33SMarcel Holtmann 	bt_dev_info(hdev, "QCA: patch rome 0x%x build 0x%x, "
38472064ee33SMarcel Holtmann 		    "firmware rome 0x%x build 0x%x",
38482064ee33SMarcel Holtmann 		    rver_rom, rver_patch, ver_rom, ver_patch);
3849bf906b3dSKim, Ben Young Tae 
3850bf906b3dSKim, Ben Young Tae 	if (rver_rom != ver_rom || rver_patch <= ver_patch) {
38512064ee33SMarcel Holtmann 		bt_dev_err(hdev, "rampatch file version did not match with firmware");
38523267c884SKim, Ben Young Tae 		err = -EINVAL;
38533267c884SKim, Ben Young Tae 		goto done;
38543267c884SKim, Ben Young Tae 	}
38553267c884SKim, Ben Young Tae 
38563267c884SKim, Ben Young Tae 	err = btusb_setup_qca_download_fw(hdev, fw, info->rampatch_hdr);
38573267c884SKim, Ben Young Tae 
38583267c884SKim, Ben Young Tae done:
38593267c884SKim, Ben Young Tae 	release_firmware(fw);
38603267c884SKim, Ben Young Tae 
38613267c884SKim, Ben Young Tae 	return err;
38623267c884SKim, Ben Young Tae }
38633267c884SKim, Ben Young Tae 
btusb_generate_qca_nvm_name(char * fwname,size_t max_size,const struct qca_version * ver)3864d6cba4e6STim Jiang static void btusb_generate_qca_nvm_name(char *fwname, size_t max_size,
3865d6cba4e6STim Jiang 					const struct qca_version *ver)
3866d6cba4e6STim Jiang {
3867d6cba4e6STim Jiang 	u32 rom_version = le32_to_cpu(ver->rom_version);
3868d6cba4e6STim Jiang 	u16 flag = le16_to_cpu(ver->flag);
3869d6cba4e6STim Jiang 
3870d6cba4e6STim Jiang 	if (((flag >> 8) & 0xff) == QCA_FLAG_MULTI_NVM) {
3871741268adStjiang@codeaurora.org 		/* The board_id should be split into two bytes
3872741268adStjiang@codeaurora.org 		 * The 1st byte is chip ID, and the 2nd byte is platform ID
3873741268adStjiang@codeaurora.org 		 * For example, board ID 0x010A, 0x01 is platform ID. 0x0A is chip ID
387421a241b3Stjiang@codeaurora.org 		 * we have several platforms, and platform IDs are continuously added
3875741268adStjiang@codeaurora.org 		 * Platform ID:
3876741268adStjiang@codeaurora.org 		 * 0x00 is for Mobile
3877741268adStjiang@codeaurora.org 		 * 0x01 is for X86
3878741268adStjiang@codeaurora.org 		 * 0x02 is for Automotive
3879741268adStjiang@codeaurora.org 		 * 0x03 is for Consumer electronic
3880741268adStjiang@codeaurora.org 		 */
3881741268adStjiang@codeaurora.org 		u16 board_id = (ver->chip_id << 8) + ver->platform_id;
3882d6cba4e6STim Jiang 		const char *variant;
3883d6cba4e6STim Jiang 
3884d6cba4e6STim Jiang 		switch (le32_to_cpu(ver->ram_version)) {
3885d6cba4e6STim Jiang 		case WCN6855_2_0_RAM_VERSION_GF:
3886d6cba4e6STim Jiang 		case WCN6855_2_1_RAM_VERSION_GF:
3887d6cba4e6STim Jiang 			variant = "_gf";
3888d6cba4e6STim Jiang 			break;
3889d6cba4e6STim Jiang 		default:
3890d6cba4e6STim Jiang 			variant = "";
3891d6cba4e6STim Jiang 			break;
3892d6cba4e6STim Jiang 		}
3893d6cba4e6STim Jiang 
3894d6cba4e6STim Jiang 		if (board_id == 0) {
3895d6cba4e6STim Jiang 			snprintf(fwname, max_size, "qca/nvm_usb_%08x%s.bin",
3896d6cba4e6STim Jiang 				rom_version, variant);
3897d6cba4e6STim Jiang 		} else {
3898d6cba4e6STim Jiang 			snprintf(fwname, max_size, "qca/nvm_usb_%08x%s_%04x.bin",
3899d6cba4e6STim Jiang 				rom_version, variant, board_id);
3900d6cba4e6STim Jiang 		}
3901d6cba4e6STim Jiang 	} else {
3902d6cba4e6STim Jiang 		snprintf(fwname, max_size, "qca/nvm_usb_%08x.bin",
3903d6cba4e6STim Jiang 			rom_version);
3904d6cba4e6STim Jiang 	}
3905d6cba4e6STim Jiang 
3906d6cba4e6STim Jiang }
3907d6cba4e6STim Jiang 
btusb_setup_qca_load_nvm(struct hci_dev * hdev,struct qca_version * ver,const struct qca_device_info * info)39083267c884SKim, Ben Young Tae static int btusb_setup_qca_load_nvm(struct hci_dev *hdev,
39093267c884SKim, Ben Young Tae 				    struct qca_version *ver,
39103267c884SKim, Ben Young Tae 				    const struct qca_device_info *info)
39113267c884SKim, Ben Young Tae {
39123267c884SKim, Ben Young Tae 	const struct firmware *fw;
39133267c884SKim, Ben Young Tae 	char fwname[64];
39143267c884SKim, Ben Young Tae 	int err;
39153267c884SKim, Ben Young Tae 
3916d6cba4e6STim Jiang 	btusb_generate_qca_nvm_name(fwname, sizeof(fwname), ver);
39173267c884SKim, Ben Young Tae 
39183267c884SKim, Ben Young Tae 	err = request_firmware(&fw, fwname, &hdev->dev);
39193267c884SKim, Ben Young Tae 	if (err) {
39202064ee33SMarcel Holtmann 		bt_dev_err(hdev, "failed to request NVM file: %s (%d)",
39212064ee33SMarcel Holtmann 			   fwname, err);
39223267c884SKim, Ben Young Tae 		return err;
39233267c884SKim, Ben Young Tae 	}
39243267c884SKim, Ben Young Tae 
39252064ee33SMarcel Holtmann 	bt_dev_info(hdev, "using NVM file: %s", fwname);
39263267c884SKim, Ben Young Tae 
39273267c884SKim, Ben Young Tae 	err = btusb_setup_qca_download_fw(hdev, fw, info->nvm_hdr);
39283267c884SKim, Ben Young Tae 
39293267c884SKim, Ben Young Tae 	release_firmware(fw);
39303267c884SKim, Ben Young Tae 
39313267c884SKim, Ben Young Tae 	return err;
39323267c884SKim, Ben Young Tae }
39333267c884SKim, Ben Young Tae 
3934803cdb8cSTakashi Iwai /* identify the ROM version and check whether patches are needed */
btusb_qca_need_patch(struct usb_device * udev)3935803cdb8cSTakashi Iwai static bool btusb_qca_need_patch(struct usb_device *udev)
3936803cdb8cSTakashi Iwai {
3937803cdb8cSTakashi Iwai 	struct qca_version ver;
3938803cdb8cSTakashi Iwai 
3939803cdb8cSTakashi Iwai 	if (btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
3940803cdb8cSTakashi Iwai 				      sizeof(ver)) < 0)
3941803cdb8cSTakashi Iwai 		return false;
3942803cdb8cSTakashi Iwai 	/* only low ROM versions need patches */
3943803cdb8cSTakashi Iwai 	return !(le32_to_cpu(ver.rom_version) & ~0xffffU);
3944803cdb8cSTakashi Iwai }
3945803cdb8cSTakashi Iwai 
btusb_setup_qca(struct hci_dev * hdev)39463267c884SKim, Ben Young Tae static int btusb_setup_qca(struct hci_dev *hdev)
39473267c884SKim, Ben Young Tae {
3948803cdb8cSTakashi Iwai 	struct btusb_data *btdata = hci_get_drvdata(hdev);
3949803cdb8cSTakashi Iwai 	struct usb_device *udev = btdata->udev;
39503267c884SKim, Ben Young Tae 	const struct qca_device_info *info = NULL;
39513267c884SKim, Ben Young Tae 	struct qca_version ver;
3952bf906b3dSKim, Ben Young Tae 	u32 ver_rom;
39533267c884SKim, Ben Young Tae 	u8 status;
39543267c884SKim, Ben Young Tae 	int i, err;
39553267c884SKim, Ben Young Tae 
3956803cdb8cSTakashi Iwai 	err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
39573267c884SKim, Ben Young Tae 					sizeof(ver));
39583267c884SKim, Ben Young Tae 	if (err < 0)
39593267c884SKim, Ben Young Tae 		return err;
39603267c884SKim, Ben Young Tae 
3961bf906b3dSKim, Ben Young Tae 	ver_rom = le32_to_cpu(ver.rom_version);
3962803cdb8cSTakashi Iwai 
39633267c884SKim, Ben Young Tae 	for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
3964bf906b3dSKim, Ben Young Tae 		if (ver_rom == qca_devices_table[i].rom_version)
39653267c884SKim, Ben Young Tae 			info = &qca_devices_table[i];
39663267c884SKim, Ben Young Tae 	}
39673267c884SKim, Ben Young Tae 	if (!info) {
3968234f414eSHui Wang 		/* If the rom_version is not matched in the qca_devices_table
3969234f414eSHui Wang 		 * and the high ROM version is not zero, we assume this chip no
3970234f414eSHui Wang 		 * need to load the rampatch and nvm.
3971234f414eSHui Wang 		 */
3972234f414eSHui Wang 		if (ver_rom & ~0xffffU)
3973234f414eSHui Wang 			return 0;
3974234f414eSHui Wang 
39752064ee33SMarcel Holtmann 		bt_dev_err(hdev, "don't support firmware rome 0x%x", ver_rom);
39763267c884SKim, Ben Young Tae 		return -ENODEV;
39773267c884SKim, Ben Young Tae 	}
39783267c884SKim, Ben Young Tae 
3979803cdb8cSTakashi Iwai 	err = btusb_qca_send_vendor_req(udev, QCA_CHECK_STATUS, &status,
39803267c884SKim, Ben Young Tae 					sizeof(status));
39813267c884SKim, Ben Young Tae 	if (err < 0)
39823267c884SKim, Ben Young Tae 		return err;
39833267c884SKim, Ben Young Tae 
39843267c884SKim, Ben Young Tae 	if (!(status & QCA_PATCH_UPDATED)) {
39853267c884SKim, Ben Young Tae 		err = btusb_setup_qca_load_rampatch(hdev, &ver, info);
39863267c884SKim, Ben Young Tae 		if (err < 0)
39873267c884SKim, Ben Young Tae 			return err;
39883267c884SKim, Ben Young Tae 	}
39893267c884SKim, Ben Young Tae 
3990ef2862a1STim Jiang 	err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
3991ef2862a1STim Jiang 					sizeof(ver));
3992ef2862a1STim Jiang 	if (err < 0)
3993ef2862a1STim Jiang 		return err;
3994ef2862a1STim Jiang 
399520981ce2STim Jiang 	btdata->qca_dump.fw_version = le32_to_cpu(ver.patch_version);
399620981ce2STim Jiang 	btdata->qca_dump.controller_id = le32_to_cpu(ver.rom_version);
399720981ce2STim Jiang 
39983267c884SKim, Ben Young Tae 	if (!(status & QCA_SYSCFG_UPDATED)) {
39993267c884SKim, Ben Young Tae 		err = btusb_setup_qca_load_nvm(hdev, &ver, info);
40003267c884SKim, Ben Young Tae 		if (err < 0)
40013267c884SKim, Ben Young Tae 			return err;
4002599ece4fSZijun Hu 
400346225947SZijun Hu 		/* WCN6855 2.1 and later will reset to apply firmware downloaded here, so
4004599ece4fSZijun Hu 		 * wait ~100ms for reset Done then go ahead, otherwise, it maybe
4005599ece4fSZijun Hu 		 * cause potential enable failure.
4006599ece4fSZijun Hu 		 */
400746225947SZijun Hu 		if (info->rom_version >= 0x00130201)
4008599ece4fSZijun Hu 			msleep(QCA_BT_RESET_WAIT_MS);
40093267c884SKim, Ben Young Tae 	}
40103267c884SKim, Ben Young Tae 
4011d44e1dbdSLuiz Augusto von Dentz 	/* Mark HCI_OP_ENHANCED_SETUP_SYNC_CONN as broken as it doesn't seem to
4012d44e1dbdSLuiz Augusto von Dentz 	 * work with the likes of HSP/HFP mSBC.
4013d44e1dbdSLuiz Augusto von Dentz 	 */
4014d44e1dbdSLuiz Augusto von Dentz 	set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
4015d44e1dbdSLuiz Augusto von Dentz 
40163267c884SKim, Ben Young Tae 	return 0;
40173267c884SKim, Ben Young Tae }
40183267c884SKim, Ben Young Tae 
__set_diag_interface(struct hci_dev * hdev)40199d08f504SMarcel Holtmann static inline int __set_diag_interface(struct hci_dev *hdev)
40209d08f504SMarcel Holtmann {
40219d08f504SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
40229d08f504SMarcel Holtmann 	struct usb_interface *intf = data->diag;
40239d08f504SMarcel Holtmann 	int i;
40249d08f504SMarcel Holtmann 
40259d08f504SMarcel Holtmann 	if (!data->diag)
40269d08f504SMarcel Holtmann 		return -ENODEV;
40279d08f504SMarcel Holtmann 
40289d08f504SMarcel Holtmann 	data->diag_tx_ep = NULL;
40299d08f504SMarcel Holtmann 	data->diag_rx_ep = NULL;
40309d08f504SMarcel Holtmann 
40319d08f504SMarcel Holtmann 	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
40329d08f504SMarcel Holtmann 		struct usb_endpoint_descriptor *ep_desc;
40339d08f504SMarcel Holtmann 
40349d08f504SMarcel Holtmann 		ep_desc = &intf->cur_altsetting->endpoint[i].desc;
40359d08f504SMarcel Holtmann 
40369d08f504SMarcel Holtmann 		if (!data->diag_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
40379d08f504SMarcel Holtmann 			data->diag_tx_ep = ep_desc;
40389d08f504SMarcel Holtmann 			continue;
40399d08f504SMarcel Holtmann 		}
40409d08f504SMarcel Holtmann 
40419d08f504SMarcel Holtmann 		if (!data->diag_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
40429d08f504SMarcel Holtmann 			data->diag_rx_ep = ep_desc;
40439d08f504SMarcel Holtmann 			continue;
40449d08f504SMarcel Holtmann 		}
40459d08f504SMarcel Holtmann 	}
40469d08f504SMarcel Holtmann 
40479d08f504SMarcel Holtmann 	if (!data->diag_tx_ep || !data->diag_rx_ep) {
40482064ee33SMarcel Holtmann 		bt_dev_err(hdev, "invalid diagnostic descriptors");
40499d08f504SMarcel Holtmann 		return -ENODEV;
40509d08f504SMarcel Holtmann 	}
40519d08f504SMarcel Holtmann 
40529d08f504SMarcel Holtmann 	return 0;
40539d08f504SMarcel Holtmann }
40549d08f504SMarcel Holtmann 
alloc_diag_urb(struct hci_dev * hdev,bool enable)40559d08f504SMarcel Holtmann static struct urb *alloc_diag_urb(struct hci_dev *hdev, bool enable)
40569d08f504SMarcel Holtmann {
40579d08f504SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
40589d08f504SMarcel Holtmann 	struct sk_buff *skb;
40599d08f504SMarcel Holtmann 	struct urb *urb;
40609d08f504SMarcel Holtmann 	unsigned int pipe;
40619d08f504SMarcel Holtmann 
40629d08f504SMarcel Holtmann 	if (!data->diag_tx_ep)
40639d08f504SMarcel Holtmann 		return ERR_PTR(-ENODEV);
40649d08f504SMarcel Holtmann 
40659d08f504SMarcel Holtmann 	urb = usb_alloc_urb(0, GFP_KERNEL);
40669d08f504SMarcel Holtmann 	if (!urb)
40679d08f504SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
40689d08f504SMarcel Holtmann 
40699d08f504SMarcel Holtmann 	skb = bt_skb_alloc(2, GFP_KERNEL);
40709d08f504SMarcel Holtmann 	if (!skb) {
40719d08f504SMarcel Holtmann 		usb_free_urb(urb);
40729d08f504SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
40739d08f504SMarcel Holtmann 	}
40749d08f504SMarcel Holtmann 
4075634fef61SJohannes Berg 	skb_put_u8(skb, 0xf0);
4076634fef61SJohannes Berg 	skb_put_u8(skb, enable);
40779d08f504SMarcel Holtmann 
40789d08f504SMarcel Holtmann 	pipe = usb_sndbulkpipe(data->udev, data->diag_tx_ep->bEndpointAddress);
40799d08f504SMarcel Holtmann 
40809d08f504SMarcel Holtmann 	usb_fill_bulk_urb(urb, data->udev, pipe,
40819d08f504SMarcel Holtmann 			  skb->data, skb->len, btusb_tx_complete, skb);
40829d08f504SMarcel Holtmann 
40839d08f504SMarcel Holtmann 	skb->dev = (void *)hdev;
40849d08f504SMarcel Holtmann 
40859d08f504SMarcel Holtmann 	return urb;
40869d08f504SMarcel Holtmann }
40879d08f504SMarcel Holtmann 
btusb_bcm_set_diag(struct hci_dev * hdev,bool enable)40889d08f504SMarcel Holtmann static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable)
40899d08f504SMarcel Holtmann {
40909d08f504SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
40919d08f504SMarcel Holtmann 	struct urb *urb;
40929d08f504SMarcel Holtmann 
40939d08f504SMarcel Holtmann 	if (!data->diag)
40949d08f504SMarcel Holtmann 		return -ENODEV;
40959d08f504SMarcel Holtmann 
40969d08f504SMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
40979d08f504SMarcel Holtmann 		return -ENETDOWN;
40989d08f504SMarcel Holtmann 
40999d08f504SMarcel Holtmann 	urb = alloc_diag_urb(hdev, enable);
41009d08f504SMarcel Holtmann 	if (IS_ERR(urb))
41019d08f504SMarcel Holtmann 		return PTR_ERR(urb);
41029d08f504SMarcel Holtmann 
41039d08f504SMarcel Holtmann 	return submit_or_queue_tx_urb(hdev, urb);
41049d08f504SMarcel Holtmann }
41059d08f504SMarcel Holtmann 
4106fd913ef7SRajat Jain #ifdef CONFIG_PM
btusb_oob_wake_handler(int irq,void * priv)4107fd913ef7SRajat Jain static irqreturn_t btusb_oob_wake_handler(int irq, void *priv)
4108fd913ef7SRajat Jain {
4109fd913ef7SRajat Jain 	struct btusb_data *data = priv;
4110fd913ef7SRajat Jain 
4111fd913ef7SRajat Jain 	pm_wakeup_event(&data->udev->dev, 0);
4112017789f3SJeffy Chen 	pm_system_wakeup();
4113fd913ef7SRajat Jain 
4114fd913ef7SRajat Jain 	/* Disable only if not already disabled (keep it balanced) */
4115fd913ef7SRajat Jain 	if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) {
4116fd913ef7SRajat Jain 		disable_irq_nosync(irq);
4117fd913ef7SRajat Jain 		disable_irq_wake(irq);
4118fd913ef7SRajat Jain 	}
4119fd913ef7SRajat Jain 	return IRQ_HANDLED;
4120fd913ef7SRajat Jain }
4121fd913ef7SRajat Jain 
4122fd913ef7SRajat Jain static const struct of_device_id btusb_match_table[] = {
4123fd913ef7SRajat Jain 	{ .compatible = "usb1286,204e" },
41244c409af0SBrian Norris 	{ .compatible = "usbcf3,e300" }, /* QCA6174A */
41254c409af0SBrian Norris 	{ .compatible = "usb4ca,301a" }, /* QCA6174A (Lite-On) */
4126fd913ef7SRajat Jain 	{ }
4127fd913ef7SRajat Jain };
4128fd913ef7SRajat Jain MODULE_DEVICE_TABLE(of, btusb_match_table);
4129fd913ef7SRajat Jain 
4130fd913ef7SRajat Jain /* Use an oob wakeup pin? */
btusb_config_oob_wake(struct hci_dev * hdev)4131fd913ef7SRajat Jain static int btusb_config_oob_wake(struct hci_dev *hdev)
4132fd913ef7SRajat Jain {
4133fd913ef7SRajat Jain 	struct btusb_data *data = hci_get_drvdata(hdev);
4134fd913ef7SRajat Jain 	struct device *dev = &data->udev->dev;
4135fd913ef7SRajat Jain 	int irq, ret;
4136fd913ef7SRajat Jain 
4137fd913ef7SRajat Jain 	clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags);
4138fd913ef7SRajat Jain 
4139fd913ef7SRajat Jain 	if (!of_match_device(btusb_match_table, dev))
4140fd913ef7SRajat Jain 		return 0;
4141fd913ef7SRajat Jain 
4142fd913ef7SRajat Jain 	/* Move on if no IRQ specified */
4143fd913ef7SRajat Jain 	irq = of_irq_get_byname(dev->of_node, "wakeup");
4144fd913ef7SRajat Jain 	if (irq <= 0) {
4145fd913ef7SRajat Jain 		bt_dev_dbg(hdev, "%s: no OOB Wakeup IRQ in DT", __func__);
4146fd913ef7SRajat Jain 		return 0;
4147fd913ef7SRajat Jain 	}
4148fd913ef7SRajat Jain 
4149771acc7eSBrian Norris 	irq_set_status_flags(irq, IRQ_NOAUTOEN);
4150fd913ef7SRajat Jain 	ret = devm_request_irq(&hdev->dev, irq, btusb_oob_wake_handler,
4151fd913ef7SRajat Jain 			       0, "OOB Wake-on-BT", data);
4152fd913ef7SRajat Jain 	if (ret) {
4153fd913ef7SRajat Jain 		bt_dev_err(hdev, "%s: IRQ request failed", __func__);
4154fd913ef7SRajat Jain 		return ret;
4155fd913ef7SRajat Jain 	}
4156fd913ef7SRajat Jain 
4157fd913ef7SRajat Jain 	ret = device_init_wakeup(dev, true);
4158fd913ef7SRajat Jain 	if (ret) {
4159fd913ef7SRajat Jain 		bt_dev_err(hdev, "%s: failed to init_wakeup", __func__);
4160fd913ef7SRajat Jain 		return ret;
4161fd913ef7SRajat Jain 	}
4162fd913ef7SRajat Jain 
4163fd913ef7SRajat Jain 	data->oob_wake_irq = irq;
4164fd913ef7SRajat Jain 	bt_dev_info(hdev, "OOB Wake-on-BT configured at IRQ %u", irq);
4165fd913ef7SRajat Jain 	return 0;
4166fd913ef7SRajat Jain }
4167fd913ef7SRajat Jain #endif
4168fd913ef7SRajat Jain 
btusb_check_needs_reset_resume(struct usb_interface * intf)4169fc549102SHans de Goede static void btusb_check_needs_reset_resume(struct usb_interface *intf)
4170fc549102SHans de Goede {
4171fc549102SHans de Goede 	if (dmi_check_system(btusb_needs_reset_resume_table))
4172fc549102SHans de Goede 		interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
4173fc549102SHans de Goede }
4174fc549102SHans de Goede 
btusb_wakeup(struct hci_dev * hdev)41754539ca67SLuiz Augusto von Dentz static bool btusb_wakeup(struct hci_dev *hdev)
4176b7d0bf11SAbhishek Pandit-Subedi {
4177b7d0bf11SAbhishek Pandit-Subedi 	struct btusb_data *data = hci_get_drvdata(hdev);
4178b7d0bf11SAbhishek Pandit-Subedi 
41794539ca67SLuiz Augusto von Dentz 	return device_may_wakeup(&data->udev->dev);
4180b7d0bf11SAbhishek Pandit-Subedi }
4181b7d0bf11SAbhishek Pandit-Subedi 
btusb_shutdown_qca(struct hci_dev * hdev)41823b0d5250STim Jiang static int btusb_shutdown_qca(struct hci_dev *hdev)
41833b0d5250STim Jiang {
41843b0d5250STim Jiang 	struct sk_buff *skb;
41853b0d5250STim Jiang 
41863b0d5250STim Jiang 	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
41873b0d5250STim Jiang 	if (IS_ERR(skb)) {
41883b0d5250STim Jiang 		bt_dev_err(hdev, "HCI reset during shutdown failed");
41893b0d5250STim Jiang 		return PTR_ERR(skb);
41903b0d5250STim Jiang 	}
41913b0d5250STim Jiang 	kfree_skb(skb);
41923b0d5250STim Jiang 
41933b0d5250STim Jiang 	return 0;
41943b0d5250STim Jiang }
41953b0d5250STim Jiang 
force_poll_sync_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)4196800fe5ecSLuiz Augusto von Dentz static ssize_t force_poll_sync_read(struct file *file, char __user *user_buf,
4197800fe5ecSLuiz Augusto von Dentz 				    size_t count, loff_t *ppos)
4198800fe5ecSLuiz Augusto von Dentz {
4199800fe5ecSLuiz Augusto von Dentz 	struct btusb_data *data = file->private_data;
4200800fe5ecSLuiz Augusto von Dentz 	char buf[3];
4201800fe5ecSLuiz Augusto von Dentz 
4202800fe5ecSLuiz Augusto von Dentz 	buf[0] = data->poll_sync ? 'Y' : 'N';
4203800fe5ecSLuiz Augusto von Dentz 	buf[1] = '\n';
4204800fe5ecSLuiz Augusto von Dentz 	buf[2] = '\0';
4205800fe5ecSLuiz Augusto von Dentz 	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
4206800fe5ecSLuiz Augusto von Dentz }
4207800fe5ecSLuiz Augusto von Dentz 
force_poll_sync_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)4208800fe5ecSLuiz Augusto von Dentz static ssize_t force_poll_sync_write(struct file *file,
4209800fe5ecSLuiz Augusto von Dentz 				     const char __user *user_buf,
4210800fe5ecSLuiz Augusto von Dentz 				     size_t count, loff_t *ppos)
4211800fe5ecSLuiz Augusto von Dentz {
4212800fe5ecSLuiz Augusto von Dentz 	struct btusb_data *data = file->private_data;
4213800fe5ecSLuiz Augusto von Dentz 	bool enable;
4214800fe5ecSLuiz Augusto von Dentz 	int err;
4215800fe5ecSLuiz Augusto von Dentz 
4216800fe5ecSLuiz Augusto von Dentz 	err = kstrtobool_from_user(user_buf, count, &enable);
4217800fe5ecSLuiz Augusto von Dentz 	if (err)
4218800fe5ecSLuiz Augusto von Dentz 		return err;
4219800fe5ecSLuiz Augusto von Dentz 
4220800fe5ecSLuiz Augusto von Dentz 	/* Only allow changes while the adapter is down */
4221800fe5ecSLuiz Augusto von Dentz 	if (test_bit(HCI_UP, &data->hdev->flags))
4222800fe5ecSLuiz Augusto von Dentz 		return -EPERM;
4223800fe5ecSLuiz Augusto von Dentz 
4224800fe5ecSLuiz Augusto von Dentz 	if (data->poll_sync == enable)
4225800fe5ecSLuiz Augusto von Dentz 		return -EALREADY;
4226800fe5ecSLuiz Augusto von Dentz 
4227800fe5ecSLuiz Augusto von Dentz 	data->poll_sync = enable;
4228800fe5ecSLuiz Augusto von Dentz 
4229800fe5ecSLuiz Augusto von Dentz 	return count;
4230800fe5ecSLuiz Augusto von Dentz }
4231800fe5ecSLuiz Augusto von Dentz 
4232800fe5ecSLuiz Augusto von Dentz static const struct file_operations force_poll_sync_fops = {
4233*127c8905SSalah Triki 	.owner		= THIS_MODULE,
4234800fe5ecSLuiz Augusto von Dentz 	.open		= simple_open,
4235800fe5ecSLuiz Augusto von Dentz 	.read		= force_poll_sync_read,
4236800fe5ecSLuiz Augusto von Dentz 	.write		= force_poll_sync_write,
4237800fe5ecSLuiz Augusto von Dentz 	.llseek		= default_llseek,
4238800fe5ecSLuiz Augusto von Dentz };
4239800fe5ecSLuiz Augusto von Dentz 
btusb_probe(struct usb_interface * intf,const struct usb_device_id * id)42405e23b923SMarcel Holtmann static int btusb_probe(struct usb_interface *intf,
42415e23b923SMarcel Holtmann 		       const struct usb_device_id *id)
42425e23b923SMarcel Holtmann {
42435e23b923SMarcel Holtmann 	struct usb_endpoint_descriptor *ep_desc;
4244dc786b2cSRajat Jain 	struct gpio_desc *reset_gpio;
42455e23b923SMarcel Holtmann 	struct btusb_data *data;
42465e23b923SMarcel Holtmann 	struct hci_dev *hdev;
424722f8e9dbSMarcel Holtmann 	unsigned ifnum_base;
424853492a66STedd Ho-Jeong An 	int i, err, priv_size;
42495e23b923SMarcel Holtmann 
42505e23b923SMarcel Holtmann 	BT_DBG("intf %p id %p", intf, id);
42515e23b923SMarcel Holtmann 
4252c13380a5STomasz Moń 	if ((id->driver_info & BTUSB_IFNUM_2) &&
425395b70154STomasz Moń 	    (intf->cur_altsetting->desc.bInterfaceNumber != 0) &&
4254c13380a5STomasz Moń 	    (intf->cur_altsetting->desc.bInterfaceNumber != 2))
42555e23b923SMarcel Holtmann 		return -ENODEV;
425622f8e9dbSMarcel Holtmann 
425722f8e9dbSMarcel Holtmann 	ifnum_base = intf->cur_altsetting->desc.bInterfaceNumber;
42585e23b923SMarcel Holtmann 
42595e23b923SMarcel Holtmann 	if (!id->driver_info) {
42605e23b923SMarcel Holtmann 		const struct usb_device_id *match;
426189e7533dSMarcel Holtmann 
4262d831e361SBastien Nocera 		match = usb_match_id(intf, quirks_table);
42635e23b923SMarcel Holtmann 		if (match)
42645e23b923SMarcel Holtmann 			id = match;
42655e23b923SMarcel Holtmann 	}
42665e23b923SMarcel Holtmann 
4267cfeb4145SMarcel Holtmann 	if (id->driver_info == BTUSB_IGNORE)
4268cfeb4145SMarcel Holtmann 		return -ENODEV;
4269cfeb4145SMarcel Holtmann 
42702d25f8b4SSteven.Li 	if (id->driver_info & BTUSB_ATH3012) {
42712d25f8b4SSteven.Li 		struct usb_device *udev = interface_to_usbdev(intf);
42722d25f8b4SSteven.Li 
42732d25f8b4SSteven.Li 		/* Old firmware would otherwise let ath3k driver load
4274d98422cbSDerek Robson 		 * patch and sysconfig files
4275d98422cbSDerek Robson 		 */
4276803cdb8cSTakashi Iwai 		if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001 &&
4277803cdb8cSTakashi Iwai 		    !btusb_qca_need_patch(udev))
42782d25f8b4SSteven.Li 			return -ENODEV;
42792d25f8b4SSteven.Li 	}
42802d25f8b4SSteven.Li 
428198921dbdSSachin Kamat 	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
42825e23b923SMarcel Holtmann 	if (!data)
42835e23b923SMarcel Holtmann 		return -ENOMEM;
42845e23b923SMarcel Holtmann 
42855e23b923SMarcel Holtmann 	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
42865e23b923SMarcel Holtmann 		ep_desc = &intf->cur_altsetting->endpoint[i].desc;
42875e23b923SMarcel Holtmann 
42885e23b923SMarcel Holtmann 		if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) {
42895e23b923SMarcel Holtmann 			data->intr_ep = ep_desc;
42905e23b923SMarcel Holtmann 			continue;
42915e23b923SMarcel Holtmann 		}
42925e23b923SMarcel Holtmann 
42935e23b923SMarcel Holtmann 		if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
42945e23b923SMarcel Holtmann 			data->bulk_tx_ep = ep_desc;
42955e23b923SMarcel Holtmann 			continue;
42965e23b923SMarcel Holtmann 		}
42975e23b923SMarcel Holtmann 
42985e23b923SMarcel Holtmann 		if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
42995e23b923SMarcel Holtmann 			data->bulk_rx_ep = ep_desc;
43005e23b923SMarcel Holtmann 			continue;
43015e23b923SMarcel Holtmann 		}
43025e23b923SMarcel Holtmann 	}
43035e23b923SMarcel Holtmann 
430498921dbdSSachin Kamat 	if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
43055e23b923SMarcel Holtmann 		return -ENODEV;
43065e23b923SMarcel Holtmann 
4307893ba544SMarcel Holtmann 	if (id->driver_info & BTUSB_AMP) {
4308893ba544SMarcel Holtmann 		data->cmdreq_type = USB_TYPE_CLASS | 0x01;
4309893ba544SMarcel Holtmann 		data->cmdreq = 0x2b;
4310893ba544SMarcel Holtmann 	} else {
43117a9d4020SMarcel Holtmann 		data->cmdreq_type = USB_TYPE_CLASS;
4312893ba544SMarcel Holtmann 		data->cmdreq = 0x00;
4313893ba544SMarcel Holtmann 	}
43147a9d4020SMarcel Holtmann 
43155e23b923SMarcel Holtmann 	data->udev = interface_to_usbdev(intf);
43165fbcd260SMarcel Holtmann 	data->intf = intf;
43175e23b923SMarcel Holtmann 
43185e23b923SMarcel Holtmann 	INIT_WORK(&data->work, btusb_work);
43197bee549eSOliver Neukum 	INIT_WORK(&data->waker, btusb_waker);
4320800fe5ecSLuiz Augusto von Dentz 	INIT_DELAYED_WORK(&data->rx_work, btusb_rx_work);
4321800fe5ecSLuiz Augusto von Dentz 
4322800fe5ecSLuiz Augusto von Dentz 	skb_queue_head_init(&data->acl_q);
4323800fe5ecSLuiz Augusto von Dentz 
4324803b5836SMarcel Holtmann 	init_usb_anchor(&data->deferred);
4325803b5836SMarcel Holtmann 	init_usb_anchor(&data->tx_anchor);
43267bee549eSOliver Neukum 	spin_lock_init(&data->txlock);
43275e23b923SMarcel Holtmann 
43285e23b923SMarcel Holtmann 	init_usb_anchor(&data->intr_anchor);
43295e23b923SMarcel Holtmann 	init_usb_anchor(&data->bulk_anchor);
43309bfa35feSMarcel Holtmann 	init_usb_anchor(&data->isoc_anchor);
43319d08f504SMarcel Holtmann 	init_usb_anchor(&data->diag_anchor);
4332a1c49c43SSean Wang 	init_usb_anchor(&data->ctrl_anchor);
4333803b5836SMarcel Holtmann 	spin_lock_init(&data->rxlock);
43345e23b923SMarcel Holtmann 
433553492a66STedd Ho-Jeong An 	priv_size = 0;
433653492a66STedd Ho-Jeong An 
4337019a1caaSTedd Ho-Jeong An 	data->recv_event = hci_recv_frame;
4338019a1caaSTedd Ho-Jeong An 	data->recv_bulk = btusb_recv_bulk;
4339019a1caaSTedd Ho-Jeong An 
434053492a66STedd Ho-Jeong An 	if (id->driver_info & BTUSB_INTEL_COMBINED) {
434153492a66STedd Ho-Jeong An 		/* Allocate extra space for Intel device */
434253492a66STedd Ho-Jeong An 		priv_size += sizeof(struct btintel_data);
434353492a66STedd Ho-Jeong An 
4344019a1caaSTedd Ho-Jeong An 		/* Override the rx handlers */
4345123c2631SLuiz Augusto von Dentz 		data->recv_event = btintel_recv_event;
4346cda0dd78SMarcel Holtmann 		data->recv_bulk = btusb_recv_bulk_intel;
43475b355944SHilda Wu 	} else if (id->driver_info & BTUSB_REALTEK) {
43485b355944SHilda Wu 		/* Allocate extra space for Realtek device */
43495b355944SHilda Wu 		priv_size += sizeof(struct btrealtek_data);
4350044014ceSHilda Wu 
4351044014ceSHilda Wu 		data->recv_event = btusb_recv_event_realtek;
43524c92ae75SPeter Tsao 	} else if (id->driver_info & BTUSB_MEDIATEK) {
43534c92ae75SPeter Tsao 		/* Allocate extra space for Mediatek device */
43544c92ae75SPeter Tsao 		priv_size += sizeof(struct btmediatek_data);
4355cda0dd78SMarcel Holtmann 	}
43562cbd3f5cSMarcel Holtmann 
43570b10c8c8Smark-yw.chen 	data->recv_acl = hci_recv_frame;
43580b10c8c8Smark-yw.chen 
435953492a66STedd Ho-Jeong An 	hdev = hci_alloc_dev_priv(priv_size);
436098921dbdSSachin Kamat 	if (!hdev)
43615e23b923SMarcel Holtmann 		return -ENOMEM;
43625e23b923SMarcel Holtmann 
4363c13854ceSMarcel Holtmann 	hdev->bus = HCI_USB;
4364155961e8SDavid Herrmann 	hci_set_drvdata(hdev, data);
43655e23b923SMarcel Holtmann 
43665e23b923SMarcel Holtmann 	data->hdev = hdev;
43675e23b923SMarcel Holtmann 
43685e23b923SMarcel Holtmann 	SET_HCIDEV_DEV(hdev, &intf->dev);
43695e23b923SMarcel Holtmann 
4370dc786b2cSRajat Jain 	reset_gpio = gpiod_get_optional(&data->udev->dev, "reset",
4371dc786b2cSRajat Jain 					GPIOD_OUT_LOW);
4372dc786b2cSRajat Jain 	if (IS_ERR(reset_gpio)) {
4373dc786b2cSRajat Jain 		err = PTR_ERR(reset_gpio);
4374dc786b2cSRajat Jain 		goto out_free_dev;
4375dc786b2cSRajat Jain 	} else if (reset_gpio) {
4376dc786b2cSRajat Jain 		data->reset_gpio = reset_gpio;
4377dc786b2cSRajat Jain 	}
4378dc786b2cSRajat Jain 
43795e23b923SMarcel Holtmann 	hdev->open   = btusb_open;
43805e23b923SMarcel Holtmann 	hdev->close  = btusb_close;
43815e23b923SMarcel Holtmann 	hdev->flush  = btusb_flush;
43825e23b923SMarcel Holtmann 	hdev->send   = btusb_send_frame;
43835e23b923SMarcel Holtmann 	hdev->notify = btusb_notify;
43844539ca67SLuiz Augusto von Dentz 	hdev->wakeup = btusb_wakeup;
43855e23b923SMarcel Holtmann 
4386fd913ef7SRajat Jain #ifdef CONFIG_PM
4387fd913ef7SRajat Jain 	err = btusb_config_oob_wake(hdev);
4388fd913ef7SRajat Jain 	if (err)
4389fd913ef7SRajat Jain 		goto out_free_dev;
4390a4ccc9e3SRajat Jain 
4391a4ccc9e3SRajat Jain 	/* Marvell devices may need a specific chip configuration */
4392a4ccc9e3SRajat Jain 	if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
4393a4ccc9e3SRajat Jain 		err = marvell_config_oob_wake(hdev);
4394a4ccc9e3SRajat Jain 		if (err)
4395a4ccc9e3SRajat Jain 			goto out_free_dev;
4396a4ccc9e3SRajat Jain 	}
4397fd913ef7SRajat Jain #endif
4398418678b0SSzymon Janc 	if (id->driver_info & BTUSB_CW6622)
4399418678b0SSzymon Janc 		set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
4400418678b0SSzymon Janc 
44016c9d435dSMarcel Holtmann 	if (id->driver_info & BTUSB_BCM2045)
44026c9d435dSMarcel Holtmann 		set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
44036c9d435dSMarcel Holtmann 
44049f8f962cSMarcel Holtmann 	if (id->driver_info & BTUSB_BCM92035)
44059f8f962cSMarcel Holtmann 		hdev->setup = btusb_setup_bcm92035;
44069f8f962cSMarcel Holtmann 
4407c0a21a52SMarcel Holtmann 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) &&
4408c0a21a52SMarcel Holtmann 	    (id->driver_info & BTUSB_BCM_PATCHRAM)) {
440949a5f782SMarcel Holtmann 		hdev->manufacturer = 15;
4410c2bfb100SMarcel Holtmann 		hdev->setup = btbcm_setup_patchram;
44119d08f504SMarcel Holtmann 		hdev->set_diag = btusb_bcm_set_diag;
44121df1f591SMarcel Holtmann 		hdev->set_bdaddr = btbcm_set_bdaddr;
44139d08f504SMarcel Holtmann 
44149d08f504SMarcel Holtmann 		/* Broadcom LM_DIAG Interface numbers are hardcoded */
441522f8e9dbSMarcel Holtmann 		data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2);
4416abbaf50eSMarcel Holtmann 	}
441710d4c673SPetri Gynther 
4418c0a21a52SMarcel Holtmann 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) &&
4419c0a21a52SMarcel Holtmann 	    (id->driver_info & BTUSB_BCM_APPLE)) {
442049a5f782SMarcel Holtmann 		hdev->manufacturer = 15;
4421c2bfb100SMarcel Holtmann 		hdev->setup = btbcm_setup_apple;
44229d08f504SMarcel Holtmann 		hdev->set_diag = btusb_bcm_set_diag;
44239d08f504SMarcel Holtmann 
44249d08f504SMarcel Holtmann 		/* Broadcom LM_DIAG Interface numbers are hardcoded */
442522f8e9dbSMarcel Holtmann 		data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2);
44269d08f504SMarcel Holtmann 	}
442717b2772bSMarcel Holtmann 
442883f2dafeSTedd Ho-Jeong An 	/* Combined Intel Device setup to support multiple setup routine */
442983f2dafeSTedd Ho-Jeong An 	if (id->driver_info & BTUSB_INTEL_COMBINED) {
4430af395330SAbhishek Pandit-Subedi 		err = btintel_configure_setup(hdev, btusb_driver.name);
443183f2dafeSTedd Ho-Jeong An 		if (err)
443283f2dafeSTedd Ho-Jeong An 			goto out_free_dev;
443383f2dafeSTedd Ho-Jeong An 
443483f2dafeSTedd Ho-Jeong An 		/* Transport specific configuration */
4435019a1caaSTedd Ho-Jeong An 		hdev->send = btusb_send_frame_intel;
4436dc786b2cSRajat Jain 		hdev->cmd_timeout = btusb_intel_cmd_timeout;
443783f2dafeSTedd Ho-Jeong An 
443855235304STedd Ho-Jeong An 		if (id->driver_info & BTUSB_INTEL_NO_WBS_SUPPORT)
443955235304STedd Ho-Jeong An 			btintel_set_flag(hdev, INTEL_ROM_LEGACY_NO_WBS_SUPPORT);
444055235304STedd Ho-Jeong An 
4441ea7c4c0eSTedd Ho-Jeong An 		if (id->driver_info & BTUSB_INTEL_BROKEN_INITIAL_NCMD)
4442ea7c4c0eSTedd Ho-Jeong An 			btintel_set_flag(hdev, INTEL_BROKEN_INITIAL_NCMD);
444395655456STedd Ho-Jeong An 
444495655456STedd Ho-Jeong An 		if (id->driver_info & BTUSB_INTEL_BROKEN_SHUTDOWN_LED)
444595655456STedd Ho-Jeong An 			btintel_set_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED);
4446cb8d6597SMarcel Holtmann 	}
4447dffd30eeSTedd Ho-Jeong An 
4448ae8df494SAmitkumar Karwar 	if (id->driver_info & BTUSB_MARVELL)
4449ae8df494SAmitkumar Karwar 		hdev->set_bdaddr = btusb_set_bdaddr_marvell;
4450ae8df494SAmitkumar Karwar 
4451c0a21a52SMarcel Holtmann 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_MTK) &&
4452c0a21a52SMarcel Holtmann 	    (id->driver_info & BTUSB_MEDIATEK)) {
4453a1c49c43SSean Wang 		hdev->setup = btusb_mtk_setup;
4454a1c49c43SSean Wang 		hdev->shutdown = btusb_mtk_shutdown;
4455a1c49c43SSean Wang 		hdev->manufacturer = 70;
445625b6d759SJing Cai 		hdev->cmd_timeout = btmtk_reset_sync;
44578c0d17b6SSean Wang 		hdev->set_bdaddr = btmtk_set_bdaddr;
4458e11523e9SYuri D'Elia 		set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
4459a1c49c43SSean Wang 		set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
44600b10c8c8Smark-yw.chen 		data->recv_acl = btusb_recv_acl_mtk;
4461a1c49c43SSean Wang 	}
4462a1c49c43SSean Wang 
4463661cf88aSMarcel Holtmann 	if (id->driver_info & BTUSB_SWAVE) {
4464661cf88aSMarcel Holtmann 		set_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks);
4465d57dbe77SMarcel Holtmann 		set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks);
4466661cf88aSMarcel Holtmann 	}
4467d57dbe77SMarcel Holtmann 
4468e4c534bbSMarcel Holtmann 	if (id->driver_info & BTUSB_INTEL_BOOT) {
4469e4c534bbSMarcel Holtmann 		hdev->manufacturer = 2;
447040df783dSMarcel Holtmann 		set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
4471e4c534bbSMarcel Holtmann 	}
447240df783dSMarcel Holtmann 
447379f0c87dSJakub Pawlowski 	if (id->driver_info & BTUSB_ATH3012) {
4474803cdb8cSTakashi Iwai 		data->setup_on_usb = btusb_setup_qca;
44755859223eSToshi Kikuchi 		hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
44763d50d51aSJakub Pawlowski 		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
447779f0c87dSJakub Pawlowski 		set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
447879f0c87dSJakub Pawlowski 	}
44795859223eSToshi Kikuchi 
44803267c884SKim, Ben Young Tae 	if (id->driver_info & BTUSB_QCA_ROME) {
44813267c884SKim, Ben Young Tae 		data->setup_on_usb = btusb_setup_qca;
4482187f8b64SRocky Liao 		hdev->shutdown = btusb_shutdown_qca;
44833267c884SKim, Ben Young Tae 		hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
44846933568aSAbhishek Pandit-Subedi 		hdev->cmd_timeout = btusb_qca_cmd_timeout;
448596e58d36SVic Wei 		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
4486fc549102SHans de Goede 		btusb_check_needs_reset_resume(intf);
44873267c884SKim, Ben Young Tae 	}
44883267c884SKim, Ben Young Tae 
4489b40f58b9SRocky Liao 	if (id->driver_info & BTUSB_QCA_WCN6855) {
449020981ce2STim Jiang 		data->qca_dump.id_vendor = id->idVendor;
449120981ce2STim Jiang 		data->qca_dump.id_product = id->idProduct;
449220981ce2STim Jiang 		data->recv_event = btusb_recv_evt_qca;
449320981ce2STim Jiang 		data->recv_acl = btusb_recv_acl_qca;
449420981ce2STim Jiang 		hci_devcd_register(hdev, btusb_coredump_qca, btusb_dump_hdr_qca, NULL);
4495b40f58b9SRocky Liao 		data->setup_on_usb = btusb_setup_qca;
44963b0d5250STim Jiang 		hdev->shutdown = btusb_shutdown_qca;
4497b40f58b9SRocky Liao 		hdev->set_bdaddr = btusb_set_bdaddr_wcn6855;
4498b40f58b9SRocky Liao 		hdev->cmd_timeout = btusb_qca_cmd_timeout;
4499b40f58b9SRocky Liao 		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
4500cbe6a044SMichael Sun 		hci_set_msft_opcode(hdev, 0xFD70);
4501b40f58b9SRocky Liao 	}
4502b40f58b9SRocky Liao 
4503461f95f0SHilda Wu 	if (id->driver_info & BTUSB_AMP) {
4504461f95f0SHilda Wu 		/* AMP controllers do not support SCO packets */
4505461f95f0SHilda Wu 		data->isoc = NULL;
4506461f95f0SHilda Wu 	} else {
4507461f95f0SHilda Wu 		/* Interface orders are hardcoded in the specification */
4508461f95f0SHilda Wu 		data->isoc = usb_ifnum_to_if(data->udev, ifnum_base + 1);
4509461f95f0SHilda Wu 		data->isoc_ifnum = ifnum_base + 1;
4510461f95f0SHilda Wu 	}
4511461f95f0SHilda Wu 
451242d22098SArnd Bergmann 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_RTL) &&
451342d22098SArnd Bergmann 	    (id->driver_info & BTUSB_REALTEK)) {
4514044014ceSHilda Wu 		btrtl_set_driver_name(hdev, btusb_driver.name);
4515a479e713SHilda Wu 		hdev->setup = btusb_setup_realtek;
45167af3f558SJian-Hong Pan 		hdev->shutdown = btrtl_shutdown_realtek;
4517d7ef0d1eSAlex Lu 		hdev->cmd_timeout = btusb_rtl_cmd_timeout;
4518044014ceSHilda Wu 		hdev->hw_error = btusb_rtl_hw_error;
451904b8c814SDaniel Drake 
45208274db07SMax Chou 		/* Realtek devices need to set remote wakeup on auto-suspend */
45218274db07SMax Chou 		set_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags);
452255981d35SPauli Virtanen 		set_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags);
452304b8c814SDaniel Drake 	}
4524a2698a9bSDaniel Drake 
45255d44f76fSMarcel Holtmann 	if (id->driver_info & BTUSB_ACTIONS_SEMI) {
45265d44f76fSMarcel Holtmann 		/* Support is advertised, but not implemented */
45275d44f76fSMarcel Holtmann 		set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
45287c2b2d2dSRaul Cheleguini 		set_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks);
452991b6d02dSRaul Cheleguini 		set_bit(HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT, &hdev->quirks);
45307c2b2d2dSRaul Cheleguini 		set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
45318677a14aSVinicius Peixoto 		set_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks);
4532d87c7db6SDanil Pylaev 		set_bit(HCI_QUIRK_BROKEN_EXT_CREATE_CONN, &hdev->quirks);
4533d87c7db6SDanil Pylaev 		set_bit(HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT, &hdev->quirks);
45345d44f76fSMarcel Holtmann 	}
45355d44f76fSMarcel Holtmann 
45367a9d4020SMarcel Holtmann 	if (!reset)
4537a6c511c6SSzymon Janc 		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
45385e23b923SMarcel Holtmann 
4539cfeb4145SMarcel Holtmann 	if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
4540cfeb4145SMarcel Holtmann 		if (!disable_scofix)
4541cfeb4145SMarcel Holtmann 			set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
4542cfeb4145SMarcel Holtmann 	}
4543cfeb4145SMarcel Holtmann 
45449bfa35feSMarcel Holtmann 	if (id->driver_info & BTUSB_BROKEN_ISOC)
45459bfa35feSMarcel Holtmann 		data->isoc = NULL;
45469bfa35feSMarcel Holtmann 
45474b127bd5SAlain Michaud 	if (id->driver_info & BTUSB_WIDEBAND_SPEECH)
454800bce3fbSAlain Michaud 		set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
45494b127bd5SAlain Michaud 
4550aff8c489SAlain Michaud 	if (id->driver_info & BTUSB_VALID_LE_STATES)
4551aff8c489SAlain Michaud 		set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
4552aff8c489SAlain Michaud 
45537a9d4020SMarcel Holtmann 	if (id->driver_info & BTUSB_DIGIANSWER) {
45547a9d4020SMarcel Holtmann 		data->cmdreq_type = USB_TYPE_VENDOR;
4555a6c511c6SSzymon Janc 		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
45567a9d4020SMarcel Holtmann 	}
45577a9d4020SMarcel Holtmann 
45587a9d4020SMarcel Holtmann 	if (id->driver_info & BTUSB_CSR) {
45597a9d4020SMarcel Holtmann 		struct usb_device *udev = data->udev;
456081cac64bSMarcel Holtmann 		u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);
45617a9d4020SMarcel Holtmann 
45627a9d4020SMarcel Holtmann 		/* Old firmware would otherwise execute USB reset */
456381cac64bSMarcel Holtmann 		if (bcdDevice < 0x117)
4564a6c511c6SSzymon Janc 			set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
456581cac64bSMarcel Holtmann 
4566cde1a8a9SIsmael Ferreras Morezuelas 		/* This must be set first in case we disable it for fakes */
456749c989a0SJakub Pawlowski 		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
4568cde1a8a9SIsmael Ferreras Morezuelas 
4569cde1a8a9SIsmael Ferreras Morezuelas 		/* Fake CSR devices with broken commands */
4570cde1a8a9SIsmael Ferreras Morezuelas 		if (le16_to_cpu(udev->descriptor.idVendor)  == 0x0a12 &&
4571cde1a8a9SIsmael Ferreras Morezuelas 		    le16_to_cpu(udev->descriptor.idProduct) == 0x0001)
4572cde1a8a9SIsmael Ferreras Morezuelas 			hdev->setup = btusb_setup_csr;
45737a9d4020SMarcel Holtmann 	}
45747a9d4020SMarcel Holtmann 
4575cfeb4145SMarcel Holtmann 	if (id->driver_info & BTUSB_SNIFFER) {
45769bfa35feSMarcel Holtmann 		struct usb_device *udev = data->udev;
4577cfeb4145SMarcel Holtmann 
45787a9d4020SMarcel Holtmann 		/* New sniffer firmware has crippled HCI interface */
4579cfeb4145SMarcel Holtmann 		if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
4580cfeb4145SMarcel Holtmann 			set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
4581cfeb4145SMarcel Holtmann 	}
4582cfeb4145SMarcel Holtmann 
45833a5ef20cSMarcel Holtmann 	if (id->driver_info & BTUSB_INTEL_BOOT) {
45843a5ef20cSMarcel Holtmann 		/* A bug in the bootloader causes that interrupt interface is
45853a5ef20cSMarcel Holtmann 		 * only enabled after receiving SetInterface(0, AltSetting=0).
45863a5ef20cSMarcel Holtmann 		 */
45873a5ef20cSMarcel Holtmann 		err = usb_set_interface(data->udev, 0, 0);
45883a5ef20cSMarcel Holtmann 		if (err < 0) {
45893a5ef20cSMarcel Holtmann 			BT_ERR("failed to set interface 0, alt 0 %d", err);
459010ab133bSRajat Jain 			goto out_free_dev;
45913a5ef20cSMarcel Holtmann 		}
45923a5ef20cSMarcel Holtmann 	}
45933a5ef20cSMarcel Holtmann 
45949bfa35feSMarcel Holtmann 	if (data->isoc) {
45959bfa35feSMarcel Holtmann 		err = usb_driver_claim_interface(&btusb_driver,
45965fbcd260SMarcel Holtmann 						 data->isoc, data);
459710ab133bSRajat Jain 		if (err < 0)
459810ab133bSRajat Jain 			goto out_free_dev;
45999bfa35feSMarcel Holtmann 	}
46009bfa35feSMarcel Holtmann 
4601c0a21a52SMarcel Holtmann 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) && data->diag) {
46029d08f504SMarcel Holtmann 		if (!usb_driver_claim_interface(&btusb_driver,
46039d08f504SMarcel Holtmann 						data->diag, data))
46049d08f504SMarcel Holtmann 			__set_diag_interface(hdev);
46059d08f504SMarcel Holtmann 		else
46069d08f504SMarcel Holtmann 			data->diag = NULL;
46079d08f504SMarcel Holtmann 	}
46089d08f504SMarcel Holtmann 
460989591522SHans de Goede 	if (enable_autosuspend)
461089591522SHans de Goede 		usb_enable_autosuspend(data->udev);
4611eff2d68cSHans de Goede 
4612bb1afb29SLuiz Augusto von Dentz 	data->poll_sync = enable_poll_sync;
4613bb1afb29SLuiz Augusto von Dentz 
46145e23b923SMarcel Holtmann 	err = hci_register_dev(hdev);
461510ab133bSRajat Jain 	if (err < 0)
461610ab133bSRajat Jain 		goto out_free_dev;
46175e23b923SMarcel Holtmann 
46185e23b923SMarcel Holtmann 	usb_set_intfdata(intf, data);
46195e23b923SMarcel Holtmann 
4620800fe5ecSLuiz Augusto von Dentz 	debugfs_create_file("force_poll_sync", 0644, hdev->debugfs, data,
4621800fe5ecSLuiz Augusto von Dentz 			    &force_poll_sync_fops);
4622800fe5ecSLuiz Augusto von Dentz 
46235e23b923SMarcel Holtmann 	return 0;
462410ab133bSRajat Jain 
462510ab133bSRajat Jain out_free_dev:
4626dc786b2cSRajat Jain 	if (data->reset_gpio)
4627dc786b2cSRajat Jain 		gpiod_put(data->reset_gpio);
462810ab133bSRajat Jain 	hci_free_dev(hdev);
462910ab133bSRajat Jain 	return err;
46305e23b923SMarcel Holtmann }
46315e23b923SMarcel Holtmann 
btusb_disconnect(struct usb_interface * intf)46325e23b923SMarcel Holtmann static void btusb_disconnect(struct usb_interface *intf)
46335e23b923SMarcel Holtmann {
46345e23b923SMarcel Holtmann 	struct btusb_data *data = usb_get_intfdata(intf);
46355e23b923SMarcel Holtmann 	struct hci_dev *hdev;
46365e23b923SMarcel Holtmann 
46375e23b923SMarcel Holtmann 	BT_DBG("intf %p", intf);
46385e23b923SMarcel Holtmann 
46395e23b923SMarcel Holtmann 	if (!data)
46405e23b923SMarcel Holtmann 		return;
46415e23b923SMarcel Holtmann 
46425e23b923SMarcel Holtmann 	hdev = data->hdev;
46435fbcd260SMarcel Holtmann 	usb_set_intfdata(data->intf, NULL);
46445fbcd260SMarcel Holtmann 
46455fbcd260SMarcel Holtmann 	if (data->isoc)
46465fbcd260SMarcel Holtmann 		usb_set_intfdata(data->isoc, NULL);
46475e23b923SMarcel Holtmann 
46489d08f504SMarcel Holtmann 	if (data->diag)
46499d08f504SMarcel Holtmann 		usb_set_intfdata(data->diag, NULL);
46509d08f504SMarcel Holtmann 
46519457d783SChris Lu 	if (data->disconnect)
46529457d783SChris Lu 		data->disconnect(hdev);
46539457d783SChris Lu 
46545e23b923SMarcel Holtmann 	hci_unregister_dev(hdev);
46555e23b923SMarcel Holtmann 
46569d08f504SMarcel Holtmann 	if (intf == data->intf) {
46579d08f504SMarcel Holtmann 		if (data->isoc)
46585fbcd260SMarcel Holtmann 			usb_driver_release_interface(&btusb_driver, data->isoc);
46599d08f504SMarcel Holtmann 		if (data->diag)
46609d08f504SMarcel Holtmann 			usb_driver_release_interface(&btusb_driver, data->diag);
46619d08f504SMarcel Holtmann 	} else if (intf == data->isoc) {
46629d08f504SMarcel Holtmann 		if (data->diag)
46639d08f504SMarcel Holtmann 			usb_driver_release_interface(&btusb_driver, data->diag);
46649d08f504SMarcel Holtmann 		usb_driver_release_interface(&btusb_driver, data->intf);
46659d08f504SMarcel Holtmann 	} else if (intf == data->diag) {
46669d08f504SMarcel Holtmann 		usb_driver_release_interface(&btusb_driver, data->intf);
46679d08f504SMarcel Holtmann 		if (data->isoc)
46689d08f504SMarcel Holtmann 			usb_driver_release_interface(&btusb_driver, data->isoc);
46699d08f504SMarcel Holtmann 	}
46705fbcd260SMarcel Holtmann 
4671fd913ef7SRajat Jain 	if (data->oob_wake_irq)
4672fd913ef7SRajat Jain 		device_init_wakeup(&data->udev->dev, false);
4673fd913ef7SRajat Jain 
4674dc786b2cSRajat Jain 	if (data->reset_gpio)
4675dc786b2cSRajat Jain 		gpiod_put(data->reset_gpio);
4676dc786b2cSRajat Jain 
46775e23b923SMarcel Holtmann 	hci_free_dev(hdev);
46785e23b923SMarcel Holtmann }
46795e23b923SMarcel Holtmann 
46807bee549eSOliver Neukum #ifdef CONFIG_PM
btusb_suspend(struct usb_interface * intf,pm_message_t message)46816a88adf2SMarcel Holtmann static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
46826a88adf2SMarcel Holtmann {
46836a88adf2SMarcel Holtmann 	struct btusb_data *data = usb_get_intfdata(intf);
46846a88adf2SMarcel Holtmann 
46856a88adf2SMarcel Holtmann 	BT_DBG("intf %p", intf);
46866a88adf2SMarcel Holtmann 
46876a88adf2SMarcel Holtmann 	if (data->suspend_count++)
46886a88adf2SMarcel Holtmann 		return 0;
46896a88adf2SMarcel Holtmann 
46907bee549eSOliver Neukum 	spin_lock_irq(&data->txlock);
46915b1b0b81SAlan Stern 	if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) {
46927bee549eSOliver Neukum 		set_bit(BTUSB_SUSPENDING, &data->flags);
46937bee549eSOliver Neukum 		spin_unlock_irq(&data->txlock);
46947bee549eSOliver Neukum 	} else {
46957bee549eSOliver Neukum 		spin_unlock_irq(&data->txlock);
46967bee549eSOliver Neukum 		data->suspend_count--;
46977bee549eSOliver Neukum 		return -EBUSY;
46987bee549eSOliver Neukum 	}
46997bee549eSOliver Neukum 
47006a88adf2SMarcel Holtmann 	cancel_work_sync(&data->work);
47016a88adf2SMarcel Holtmann 
47023aab20ebSChris Lu 	if (data->suspend)
47033aab20ebSChris Lu 		data->suspend(data->hdev);
47043aab20ebSChris Lu 
47057bee549eSOliver Neukum 	btusb_stop_traffic(data);
47066a88adf2SMarcel Holtmann 	usb_kill_anchored_urbs(&data->tx_anchor);
47076a88adf2SMarcel Holtmann 
4708fd913ef7SRajat Jain 	if (data->oob_wake_irq && device_may_wakeup(&data->udev->dev)) {
4709fd913ef7SRajat Jain 		set_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags);
4710fd913ef7SRajat Jain 		enable_irq_wake(data->oob_wake_irq);
4711fd913ef7SRajat Jain 		enable_irq(data->oob_wake_irq);
4712fd913ef7SRajat Jain 	}
4713fd913ef7SRajat Jain 
47149e45524aSAlex Lu 	/* For global suspend, Realtek devices lose the loaded fw
47159e45524aSAlex Lu 	 * in them. But for autosuspend, firmware should remain.
47169e45524aSAlex Lu 	 * Actually, it depends on whether the usb host sends
47179e45524aSAlex Lu 	 * set feature (enable wakeup) or not.
47189e45524aSAlex Lu 	 */
47198274db07SMax Chou 	if (test_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags)) {
47209e45524aSAlex Lu 		if (PMSG_IS_AUTO(message) &&
47219e45524aSAlex Lu 		    device_can_wakeup(&data->udev->dev))
47229e45524aSAlex Lu 			data->udev->do_remote_wakeup = 1;
47238274db07SMax Chou 		else if (!PMSG_IS_AUTO(message) &&
47248274db07SMax Chou 			 !device_may_wakeup(&data->udev->dev)) {
47258274db07SMax Chou 			data->udev->do_remote_wakeup = 0;
47269e45524aSAlex Lu 			data->udev->reset_resume = 1;
47279e45524aSAlex Lu 		}
47288274db07SMax Chou 	}
47299e45524aSAlex Lu 
47306a88adf2SMarcel Holtmann 	return 0;
47316a88adf2SMarcel Holtmann }
47326a88adf2SMarcel Holtmann 
play_deferred(struct btusb_data * data)47337bee549eSOliver Neukum static void play_deferred(struct btusb_data *data)
47347bee549eSOliver Neukum {
47357bee549eSOliver Neukum 	struct urb *urb;
47367bee549eSOliver Neukum 	int err;
47377bee549eSOliver Neukum 
47387bee549eSOliver Neukum 	while ((urb = usb_get_from_anchor(&data->deferred))) {
473919cfe912SJeffy Chen 		usb_anchor_urb(urb, &data->tx_anchor);
474019cfe912SJeffy Chen 
47417bee549eSOliver Neukum 		err = usb_submit_urb(urb, GFP_ATOMIC);
474219cfe912SJeffy Chen 		if (err < 0) {
474319cfe912SJeffy Chen 			if (err != -EPERM && err != -ENODEV)
474419cfe912SJeffy Chen 				BT_ERR("%s urb %p submission failed (%d)",
474519cfe912SJeffy Chen 				       data->hdev->name, urb, -err);
474619cfe912SJeffy Chen 			kfree(urb->setup_packet);
474719cfe912SJeffy Chen 			usb_unanchor_urb(urb);
474819cfe912SJeffy Chen 			usb_free_urb(urb);
47497bee549eSOliver Neukum 			break;
475019cfe912SJeffy Chen 		}
47517bee549eSOliver Neukum 
47527bee549eSOliver Neukum 		data->tx_in_flight++;
475319cfe912SJeffy Chen 		usb_free_urb(urb);
47547bee549eSOliver Neukum 	}
475519cfe912SJeffy Chen 
475619cfe912SJeffy Chen 	/* Cleanup the rest deferred urbs. */
475719cfe912SJeffy Chen 	while ((urb = usb_get_from_anchor(&data->deferred))) {
475819cfe912SJeffy Chen 		kfree(urb->setup_packet);
475919cfe912SJeffy Chen 		usb_free_urb(urb);
476019cfe912SJeffy Chen 	}
47617bee549eSOliver Neukum }
47627bee549eSOliver Neukum 
btusb_resume(struct usb_interface * intf)47636a88adf2SMarcel Holtmann static int btusb_resume(struct usb_interface *intf)
47646a88adf2SMarcel Holtmann {
47656a88adf2SMarcel Holtmann 	struct btusb_data *data = usb_get_intfdata(intf);
47666a88adf2SMarcel Holtmann 	struct hci_dev *hdev = data->hdev;
47677bee549eSOliver Neukum 	int err = 0;
47686a88adf2SMarcel Holtmann 
47696a88adf2SMarcel Holtmann 	BT_DBG("intf %p", intf);
47706a88adf2SMarcel Holtmann 
47716a88adf2SMarcel Holtmann 	if (--data->suspend_count)
47726a88adf2SMarcel Holtmann 		return 0;
47736a88adf2SMarcel Holtmann 
4774fd913ef7SRajat Jain 	/* Disable only if not already disabled (keep it balanced) */
4775fd913ef7SRajat Jain 	if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) {
4776fd913ef7SRajat Jain 		disable_irq(data->oob_wake_irq);
4777fd913ef7SRajat Jain 		disable_irq_wake(data->oob_wake_irq);
4778fd913ef7SRajat Jain 	}
4779fd913ef7SRajat Jain 
47806a88adf2SMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
47817bee549eSOliver Neukum 		goto done;
47826a88adf2SMarcel Holtmann 
47836a88adf2SMarcel Holtmann 	if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) {
47846a88adf2SMarcel Holtmann 		err = btusb_submit_intr_urb(hdev, GFP_NOIO);
47856a88adf2SMarcel Holtmann 		if (err < 0) {
47866a88adf2SMarcel Holtmann 			clear_bit(BTUSB_INTR_RUNNING, &data->flags);
47877bee549eSOliver Neukum 			goto failed;
47886a88adf2SMarcel Holtmann 		}
47896a88adf2SMarcel Holtmann 	}
47906a88adf2SMarcel Holtmann 
47916a88adf2SMarcel Holtmann 	if (test_bit(BTUSB_BULK_RUNNING, &data->flags)) {
479243c2e57fSMarcel Holtmann 		err = btusb_submit_bulk_urb(hdev, GFP_NOIO);
479343c2e57fSMarcel Holtmann 		if (err < 0) {
47946a88adf2SMarcel Holtmann 			clear_bit(BTUSB_BULK_RUNNING, &data->flags);
47957bee549eSOliver Neukum 			goto failed;
47967bee549eSOliver Neukum 		}
47977bee549eSOliver Neukum 
47986a88adf2SMarcel Holtmann 		btusb_submit_bulk_urb(hdev, GFP_NOIO);
47996a88adf2SMarcel Holtmann 	}
48006a88adf2SMarcel Holtmann 
48016a88adf2SMarcel Holtmann 	if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
48026a88adf2SMarcel Holtmann 		if (btusb_submit_isoc_urb(hdev, GFP_NOIO) < 0)
48036a88adf2SMarcel Holtmann 			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
48046a88adf2SMarcel Holtmann 		else
48056a88adf2SMarcel Holtmann 			btusb_submit_isoc_urb(hdev, GFP_NOIO);
48066a88adf2SMarcel Holtmann 	}
48076a88adf2SMarcel Holtmann 
48083aab20ebSChris Lu 	if (data->resume)
48093aab20ebSChris Lu 		data->resume(hdev);
48103aab20ebSChris Lu 
48117bee549eSOliver Neukum 	spin_lock_irq(&data->txlock);
48127bee549eSOliver Neukum 	play_deferred(data);
48137bee549eSOliver Neukum 	clear_bit(BTUSB_SUSPENDING, &data->flags);
48147bee549eSOliver Neukum 	spin_unlock_irq(&data->txlock);
48157bee549eSOliver Neukum 	schedule_work(&data->work);
48167bee549eSOliver Neukum 
48176a88adf2SMarcel Holtmann 	return 0;
48187bee549eSOliver Neukum 
48197bee549eSOliver Neukum failed:
48207bee549eSOliver Neukum 	usb_scuttle_anchored_urbs(&data->deferred);
48217bee549eSOliver Neukum done:
48227bee549eSOliver Neukum 	spin_lock_irq(&data->txlock);
48237bee549eSOliver Neukum 	clear_bit(BTUSB_SUSPENDING, &data->flags);
48247bee549eSOliver Neukum 	spin_unlock_irq(&data->txlock);
48257bee549eSOliver Neukum 
48267bee549eSOliver Neukum 	return err;
48276a88adf2SMarcel Holtmann }
48287bee549eSOliver Neukum #endif
48296a88adf2SMarcel Holtmann 
48304f9c1a08SManish Mandlik #ifdef CONFIG_DEV_COREDUMP
btusb_coredump(struct device * dev)48314f9c1a08SManish Mandlik static void btusb_coredump(struct device *dev)
48324f9c1a08SManish Mandlik {
48334f9c1a08SManish Mandlik 	struct btusb_data *data = dev_get_drvdata(dev);
48344f9c1a08SManish Mandlik 	struct hci_dev *hdev = data->hdev;
48354f9c1a08SManish Mandlik 
48364f9c1a08SManish Mandlik 	if (hdev->dump.coredump)
48374f9c1a08SManish Mandlik 		hdev->dump.coredump(hdev);
48384f9c1a08SManish Mandlik }
48394f9c1a08SManish Mandlik #endif
48404f9c1a08SManish Mandlik 
48415e23b923SMarcel Holtmann static struct usb_driver btusb_driver = {
48425e23b923SMarcel Holtmann 	.name		= "btusb",
48435e23b923SMarcel Holtmann 	.probe		= btusb_probe,
48445e23b923SMarcel Holtmann 	.disconnect	= btusb_disconnect,
48457bee549eSOliver Neukum #ifdef CONFIG_PM
48466a88adf2SMarcel Holtmann 	.suspend	= btusb_suspend,
48476a88adf2SMarcel Holtmann 	.resume		= btusb_resume,
48487bee549eSOliver Neukum #endif
48495e23b923SMarcel Holtmann 	.id_table	= btusb_table,
48507bee549eSOliver Neukum 	.supports_autosuspend = 1,
4851e1f12eb6SSarah Sharp 	.disable_hub_initiated_lpm = 1,
48524f9c1a08SManish Mandlik 
48534f9c1a08SManish Mandlik #ifdef CONFIG_DEV_COREDUMP
48544f9c1a08SManish Mandlik 	.drvwrap = {
48554f9c1a08SManish Mandlik 		.driver = {
48564f9c1a08SManish Mandlik 			.coredump = btusb_coredump,
48574f9c1a08SManish Mandlik 		},
48584f9c1a08SManish Mandlik 	},
48594f9c1a08SManish Mandlik #endif
48605e23b923SMarcel Holtmann };
48615e23b923SMarcel Holtmann 
486293f1508cSGreg Kroah-Hartman module_usb_driver(btusb_driver);
48635e23b923SMarcel Holtmann 
4864cfeb4145SMarcel Holtmann module_param(disable_scofix, bool, 0644);
4865cfeb4145SMarcel Holtmann MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
4866cfeb4145SMarcel Holtmann 
4867cfeb4145SMarcel Holtmann module_param(force_scofix, bool, 0644);
4868cfeb4145SMarcel Holtmann MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size");
4869cfeb4145SMarcel Holtmann 
4870eff2d68cSHans de Goede module_param(enable_autosuspend, bool, 0644);
4871eff2d68cSHans de Goede MODULE_PARM_DESC(enable_autosuspend, "Enable USB autosuspend by default");
4872eff2d68cSHans de Goede 
4873cfeb4145SMarcel Holtmann module_param(reset, bool, 0644);
4874cfeb4145SMarcel Holtmann MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
4875cfeb4145SMarcel Holtmann 
48765e23b923SMarcel Holtmann MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
48775e23b923SMarcel Holtmann MODULE_DESCRIPTION("Generic Bluetooth USB driver ver " VERSION);
48785e23b923SMarcel Holtmann MODULE_VERSION(VERSION);
48795e23b923SMarcel Holtmann MODULE_LICENSE("GPL");
4880