xref: /openbmc/linux/drivers/bluetooth/btusb.c (revision 27fe097bc60a344ccd8107522184c2750f45df5c)
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>
19a2698a9bSDaniel Drake #include <asm/unaligned.h>
205e23b923SMarcel Holtmann 
215e23b923SMarcel Holtmann #include <net/bluetooth/bluetooth.h>
225e23b923SMarcel Holtmann #include <net/bluetooth/hci_core.h>
235e23b923SMarcel Holtmann 
244185a0f5SMarcel Holtmann #include "btintel.h"
251df1f591SMarcel Holtmann #include "btbcm.h"
26db33c77dSCarlo Caione #include "btrtl.h"
278c0d17b6SSean Wang #include "btmtk.h"
281df1f591SMarcel Holtmann 
2934dced9bSMarcel Holtmann #define VERSION "0.8"
30cfeb4145SMarcel Holtmann 
3190ab5ee9SRusty Russell static bool disable_scofix;
3290ab5ee9SRusty Russell static bool force_scofix;
33eff2d68cSHans de Goede static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
347a9d4020SMarcel Holtmann 
35917a3337SShailendra Verma static bool reset = true;
36cfeb4145SMarcel Holtmann 
37cfeb4145SMarcel Holtmann static struct usb_driver btusb_driver;
38cfeb4145SMarcel Holtmann 
39cfeb4145SMarcel Holtmann #define BTUSB_IGNORE		0x01
407a9d4020SMarcel Holtmann #define BTUSB_DIGIANSWER	0x02
417a9d4020SMarcel Holtmann #define BTUSB_CSR		0x04
427a9d4020SMarcel Holtmann #define BTUSB_SNIFFER		0x08
437a9d4020SMarcel Holtmann #define BTUSB_BCM92035		0x10
447a9d4020SMarcel Holtmann #define BTUSB_BROKEN_ISOC	0x20
457a9d4020SMarcel Holtmann #define BTUSB_WRONG_SCO_MTU	0x40
462d25f8b4SSteven.Li #define BTUSB_ATH3012		0x80
4783f2dafeSTedd Ho-Jeong An #define BTUSB_INTEL_COMBINED	0x100
4840df783dSMarcel Holtmann #define BTUSB_INTEL_BOOT	0x200
4940df783dSMarcel Holtmann #define BTUSB_BCM_PATCHRAM	0x400
50ae8df494SAmitkumar Karwar #define BTUSB_MARVELL		0x800
514fcef8edSMarcel Holtmann #define BTUSB_SWAVE		0x1000
52893ba544SMarcel Holtmann #define BTUSB_AMP		0x4000
533267c884SKim, Ben Young Tae #define BTUSB_QCA_ROME		0x8000
5417b2772bSMarcel Holtmann #define BTUSB_BCM_APPLE		0x10000
55a2698a9bSDaniel Drake #define BTUSB_REALTEK		0x20000
566c9d435dSMarcel Holtmann #define BTUSB_BCM2045		0x40000
5722f8e9dbSMarcel Holtmann #define BTUSB_IFNUM_2		0x80000
58418678b0SSzymon Janc #define BTUSB_CW6622		0x100000
59a1c49c43SSean Wang #define BTUSB_MEDIATEK		0x200000
603e4e3f73SAlain Michaud #define BTUSB_WIDEBAND_SPEECH	0x400000
6122091585SAlain Michaud #define BTUSB_VALID_LE_STATES   0x800000
62b40f58b9SRocky Liao #define BTUSB_QCA_WCN6855	0x1000000
63ea7c4c0eSTedd Ho-Jeong An #define BTUSB_INTEL_BROKEN_INITIAL_NCMD 0x4000000
645e23b923SMarcel Holtmann 
6554265202SMarcel Holtmann static const struct usb_device_id btusb_table[] = {
665e23b923SMarcel Holtmann 	/* Generic Bluetooth USB device */
675e23b923SMarcel Holtmann 	{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
685e23b923SMarcel Holtmann 
69893ba544SMarcel Holtmann 	/* Generic Bluetooth AMP device */
70893ba544SMarcel Holtmann 	{ USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP },
71893ba544SMarcel Holtmann 
72d63b2826SDaniel Drake 	/* Generic Bluetooth USB interface */
73d63b2826SDaniel Drake 	{ USB_INTERFACE_INFO(0xe0, 0x01, 0x01) },
74d63b2826SDaniel Drake 
751fa6535fSHenrik Rydberg 	/* Apple-specific (Broadcom) devices */
7617b2772bSMarcel Holtmann 	{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01),
7722f8e9dbSMarcel Holtmann 	  .driver_info = BTUSB_BCM_APPLE | BTUSB_IFNUM_2 },
781fa6535fSHenrik Rydberg 
79178c059eSCho, Yu-Chen 	/* MediaTek MT76x0E */
80178c059eSCho, Yu-Chen 	{ USB_DEVICE(0x0e8d, 0x763f) },
81178c059eSCho, Yu-Chen 
82c510eae3SOliver Neukum 	/* Broadcom SoftSailing reporting vendor specific */
832e8b5063SDon Zickus 	{ USB_DEVICE(0x0a5c, 0x21e1) },
84c510eae3SOliver Neukum 
853cd01976SNobuhiro Iwamatsu 	/* Apple MacBookPro 7,1 */
863cd01976SNobuhiro Iwamatsu 	{ USB_DEVICE(0x05ac, 0x8213) },
873cd01976SNobuhiro Iwamatsu 
880a79f674SCyril Lacoux 	/* Apple iMac11,1 */
890a79f674SCyril Lacoux 	{ USB_DEVICE(0x05ac, 0x8215) },
900a79f674SCyril Lacoux 
919c047157SNobuhiro Iwamatsu 	/* Apple MacBookPro6,2 */
929c047157SNobuhiro Iwamatsu 	{ USB_DEVICE(0x05ac, 0x8218) },
939c047157SNobuhiro Iwamatsu 
943e3ede7dSEdgar (gimli) Hucek 	/* Apple MacBookAir3,1, MacBookAir3,2 */
953e3ede7dSEdgar (gimli) Hucek 	{ USB_DEVICE(0x05ac, 0x821b) },
963e3ede7dSEdgar (gimli) Hucek 
97a63b723dSPieter-Augustijn Van Malleghem 	/* Apple MacBookAir4,1 */
98a63b723dSPieter-Augustijn Van Malleghem 	{ USB_DEVICE(0x05ac, 0x821f) },
99a63b723dSPieter-Augustijn Van Malleghem 
10088d377b6SMarc-Antoine Perennou 	/* Apple MacBookPro8,2 */
10188d377b6SMarc-Antoine Perennou 	{ USB_DEVICE(0x05ac, 0x821a) },
10288d377b6SMarc-Antoine Perennou 
103f78b6826SJurgen Kramer 	/* Apple MacMini5,1 */
104f78b6826SJurgen Kramer 	{ USB_DEVICE(0x05ac, 0x8281) },
105f78b6826SJurgen Kramer 
106cfeb4145SMarcel Holtmann 	/* AVM BlueFRITZ! USB v2.0 */
1074fcef8edSMarcel Holtmann 	{ USB_DEVICE(0x057c, 0x3800), .driver_info = BTUSB_SWAVE },
108cfeb4145SMarcel Holtmann 
109cfeb4145SMarcel Holtmann 	/* Bluetooth Ultraport Module from IBM */
110cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x04bf, 0x030a) },
111cfeb4145SMarcel Holtmann 
112cfeb4145SMarcel Holtmann 	/* ALPS Modules with non-standard id */
113cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x044e, 0x3001) },
114cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x044e, 0x3002) },
115cfeb4145SMarcel Holtmann 
116cfeb4145SMarcel Holtmann 	/* Ericsson with non-standard id */
117cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x0bdb, 0x1002) },
118cfeb4145SMarcel Holtmann 
119cfeb4145SMarcel Holtmann 	/* Canyon CN-BTU1 with HID interfaces */
1207a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0c10, 0x0000) },
121cfeb4145SMarcel Holtmann 
122d049f4e5SMarcel Holtmann 	/* Broadcom BCM20702B0 (Dynex/Insignia) */
123d049f4e5SMarcel Holtmann 	{ USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM },
124d049f4e5SMarcel Holtmann 
1252faf71ceSSanttu Rekilä 	/* Broadcom BCM43142A0 (Foxconn/Lenovo) */
126628c26b4SDmitry Tunin 	{ USB_VENDOR_AND_INTERFACE_INFO(0x105b, 0xff, 0x01, 0x01),
127628c26b4SDmitry Tunin 	  .driver_info = BTUSB_BCM_PATCHRAM },
1282faf71ceSSanttu Rekilä 
129a57bac43SChristoph Haag 	/* Broadcom BCM920703 (HTC Vive) */
130a57bac43SChristoph Haag 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0bb4, 0xff, 0x01, 0x01),
131a57bac43SChristoph Haag 	  .driver_info = BTUSB_BCM_PATCHRAM },
132a57bac43SChristoph Haag 
13398514036SSteven Harms 	/* Foxconn - Hon Hai */
1346029ddc2SHeinrich Siebmanns 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
1356029ddc2SHeinrich Siebmanns 	  .driver_info = BTUSB_BCM_PATCHRAM },
13698514036SSteven Harms 
1378f0c304cSMatej Dubovy 	/* Lite-On Technology - Broadcom based */
1388f0c304cSMatej Dubovy 	{ USB_VENDOR_AND_INTERFACE_INFO(0x04ca, 0xff, 0x01, 0x01),
1398f0c304cSMatej Dubovy 	  .driver_info = BTUSB_BCM_PATCHRAM },
1408f0c304cSMatej Dubovy 
14192c385f4SGustavo Padovan 	/* Broadcom devices with vendor specific id */
14210d4c673SPetri Gynther 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
14310d4c673SPetri Gynther 	  .driver_info = BTUSB_BCM_PATCHRAM },
14492c385f4SGustavo Padovan 
145c2aef6e8SMarcel Holtmann 	/* ASUSTek Computer - Broadcom based */
1469a5abdaaSRick Dunn 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01),
1479a5abdaaSRick Dunn 	  .driver_info = BTUSB_BCM_PATCHRAM },
148c2aef6e8SMarcel Holtmann 
1495bcecf32SKen O'Brien 	/* Belkin F8065bf - Broadcom based */
1506331c686SMarcel Holtmann 	{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01),
1516331c686SMarcel Holtmann 	  .driver_info = BTUSB_BCM_PATCHRAM },
1525bcecf32SKen O'Brien 
1539113bfd8SJurgen Kramer 	/* IMC Networks - Broadcom based */
1546331c686SMarcel Holtmann 	{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),
1556331c686SMarcel Holtmann 	  .driver_info = BTUSB_BCM_PATCHRAM },
1569113bfd8SJurgen Kramer 
157fdfddc60SWen-chien Jesse Sung 	/* Dell Computer - Broadcom based  */
158fdfddc60SWen-chien Jesse Sung 	{ USB_VENDOR_AND_INTERFACE_INFO(0x413c, 0xff, 0x01, 0x01),
159fdfddc60SWen-chien Jesse Sung 	  .driver_info = BTUSB_BCM_PATCHRAM },
160fdfddc60SWen-chien Jesse Sung 
1611623d0bfSDmitry Tunin 	/* Toshiba Corp - Broadcom based */
1621623d0bfSDmitry Tunin 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
1631623d0bfSDmitry Tunin 	  .driver_info = BTUSB_BCM_PATCHRAM },
1641623d0bfSDmitry Tunin 
16540df783dSMarcel Holtmann 	/* Intel Bluetooth USB Bootloader (RAM module) */
166d92f2df0SMarcel Holtmann 	{ USB_DEVICE(0x8087, 0x0a5a),
167d92f2df0SMarcel Holtmann 	  .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
16840df783dSMarcel Holtmann 
1695e23b923SMarcel Holtmann 	{ }	/* Terminating entry */
1705e23b923SMarcel Holtmann };
1715e23b923SMarcel Holtmann 
1725e23b923SMarcel Holtmann MODULE_DEVICE_TABLE(usb, btusb_table);
1735e23b923SMarcel Holtmann 
17454265202SMarcel Holtmann static const struct usb_device_id blacklist_table[] = {
175cfeb4145SMarcel Holtmann 	/* CSR BlueCore devices */
176cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR },
177cfeb4145SMarcel Holtmann 
178cfeb4145SMarcel Holtmann 	/* Broadcom BCM2033 without firmware */
179cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
180cfeb4145SMarcel Holtmann 
1816c9d435dSMarcel Holtmann 	/* Broadcom BCM2045 devices */
1826c9d435dSMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2045), .driver_info = BTUSB_BCM2045 },
1836c9d435dSMarcel Holtmann 
184be93112aSBala Shanmugam 	/* Atheros 3011 with sflash firmware */
1850b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
1860b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
1872eeff0b4SAlexander Ploumistos 	{ USB_DEVICE(0x04f2, 0xaff1), .driver_info = BTUSB_IGNORE },
1880b880062SAndy Shevchenko 	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
189be93112aSBala Shanmugam 	{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
1906eda541dSMarek Vasut 	{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
1912a7bccccSAndy Ross 	{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
192be93112aSBala Shanmugam 
193509e7861SCho, Yu-Chen 	/* Atheros AR9285 Malbec with sflash firmware */
194509e7861SCho, Yu-Chen 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
195509e7861SCho, Yu-Chen 
196d9f51b51SBala Shanmugam 	/* Atheros 3012 with sflash firmware */
1970b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
1980b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
1990b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
2000b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
2010b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
202692c062eSDmitry Tunin 	{ USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
2034b552bc9SAnantha Krishnan 	{ USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
20428c971d8SDmitry Tunin 	{ USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 },
2050b880062SAndy Shevchenko 	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
2060b880062SAndy Shevchenko 	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
2070b880062SAndy Shevchenko 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
2080b880062SAndy Shevchenko 	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
2091fb4e09aSMohammed Habibulla 	{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
2100b880062SAndy Shevchenko 	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
2110b880062SAndy Shevchenko 	{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
2127e730c7fSDmitry Tunin 	{ USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 },
213ec0810d2SDmitry Tunin 	{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
214134d3b35SJanne Heikkinen 	{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
21581d90442SDmitry Tunin 	{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
216441ad62dSDmitry Tunin 	{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
2170b880062SAndy Shevchenko 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
218cd355ff0SDmitry Tunin 	{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
2190b880062SAndy Shevchenko 	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
22089d2975fSVincent Zwanenburg 	{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
221a735f9e2SAndy Shevchenko 	{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
222d66629c1SMing Lei 	{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
223544a5916SHans de Goede 	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
22494a32d10SSunguk Lee 	{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
22507c0ea87SCho, Yu-Chen 	{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
226b131237cSOliver Neukum 	{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
2271e56f1ebSOliver Neukum 	{ USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
2280b880062SAndy Shevchenko 	{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
229ebaf5795SMing Lei 	{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
23018e0afabSDmitry Tunin 	{ USB_DEVICE(0x0cf3, 0x817b), .driver_info = BTUSB_ATH3012 },
2310b880062SAndy Shevchenko 	{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
232ac71311eSAceLan Kao 	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
2330a3658ccSPeng Chen 	{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
234ca79f232SWen-chien Jesse Sung 	{ USB_DEVICE(0x0cf3, 0xe006), .driver_info = BTUSB_ATH3012 },
2350b880062SAndy Shevchenko 	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
2360b880062SAndy Shevchenko 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
237eed307e2SAceLan Kao 	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
238609574ebSDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 },
2395b77a1f3SSujith Manoharan 	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
2403bb30a7cSDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
241033efa92SDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
242fa2f1394SAnantha Krishnan 	{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
24375c6aca4SDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
2440d0cef61SDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
24572f9f8b5SLauro Costa 	{ USB_DEVICE(0x13d3, 0x3487), .driver_info = BTUSB_ATH3012 },
24612d86896SDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3490), .driver_info = BTUSB_ATH3012 },
247d9f51b51SBala Shanmugam 
248e9036e33SCho, Yu-Chen 	/* Atheros AR5BBU12 with sflash firmware */
249e9036e33SCho, Yu-Chen 	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
250e9036e33SCho, Yu-Chen 
25185d59726SMichael Gruetzner 	/* Atheros AR5BBU12 with sflash firmware */
252bc21fde2SYevgeniy Melnichuk 	{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
2530b880062SAndy Shevchenko 	{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
25485d59726SMichael Gruetzner 
2553267c884SKim, Ben Young Tae 	/* QCA ROME chipset */
256e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0x535b), .driver_info = BTUSB_QCA_ROME |
257e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
258e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME |
259e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
260e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME |
261e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
262e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe010), .driver_info = BTUSB_QCA_ROME |
263e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
264e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME |
265e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
266e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME |
267e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
268e99f38b8SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME |
269e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
2700324d19cSDaniel Lenski 	{ USB_DEVICE(0x0cf3, 0xe500), .driver_info = BTUSB_QCA_ROME |
2710324d19cSDaniel Lenski 						     BTUSB_WIDEBAND_SPEECH },
272e99f38b8SRocky Liao 	{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME |
273e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
274e99f38b8SRocky Liao 	{ USB_DEVICE(0x0489, 0xe09f), .driver_info = BTUSB_QCA_ROME |
275e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
276e99f38b8SRocky Liao 	{ USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME |
277e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
278e99f38b8SRocky Liao 	{ USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME |
279e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
280e99f38b8SRocky Liao 	{ USB_DEVICE(0x04ca, 0x3015), .driver_info = BTUSB_QCA_ROME |
281e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
282e99f38b8SRocky Liao 	{ USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME |
283e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
284e99f38b8SRocky Liao 	{ USB_DEVICE(0x04ca, 0x301a), .driver_info = BTUSB_QCA_ROME |
285e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
286e99f38b8SRocky Liao 	{ USB_DEVICE(0x04ca, 0x3021), .driver_info = BTUSB_QCA_ROME |
287e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
288e99f38b8SRocky Liao 	{ USB_DEVICE(0x13d3, 0x3491), .driver_info = BTUSB_QCA_ROME |
289e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
290e99f38b8SRocky Liao 	{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME |
291e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
292e99f38b8SRocky Liao 	{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME |
293e99f38b8SRocky Liao 						     BTUSB_WIDEBAND_SPEECH },
2943267c884SKim, Ben Young Tae 
295b40f58b9SRocky Liao 	/* QCA WCN6855 chipset */
296b40f58b9SRocky Liao 	{ USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
297acd5aea4SMichael Sun 						     BTUSB_WIDEBAND_SPEECH |
298acd5aea4SMichael Sun 						     BTUSB_VALID_LE_STATES },
299b40f58b9SRocky Liao 
300cfeb4145SMarcel Holtmann 	/* Broadcom BCM2035 */
3017a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
3020b880062SAndy Shevchenko 	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
3030b880062SAndy Shevchenko 	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
304cfeb4145SMarcel Holtmann 
305cfeb4145SMarcel Holtmann 	/* Broadcom BCM2045 */
3067a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
3077a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_WRONG_SCO_MTU },
308bdbef3d6SMarcel Holtmann 
309cfeb4145SMarcel Holtmann 	/* IBM/Lenovo ThinkPad with Broadcom chip */
3107a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_WRONG_SCO_MTU },
3117a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_WRONG_SCO_MTU },
312cfeb4145SMarcel Holtmann 
313cfeb4145SMarcel Holtmann 	/* HP laptop with Broadcom chip */
3147a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x03f0, 0x171d), .driver_info = BTUSB_WRONG_SCO_MTU },
315cfeb4145SMarcel Holtmann 
316cfeb4145SMarcel Holtmann 	/* Dell laptop with Broadcom chip */
3177a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x413c, 0x8126), .driver_info = BTUSB_WRONG_SCO_MTU },
318cfeb4145SMarcel Holtmann 
3195ddd4a60SMarcel Holtmann 	/* Dell Wireless 370 and 410 devices */
3207a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x413c, 0x8152), .driver_info = BTUSB_WRONG_SCO_MTU },
3215ddd4a60SMarcel Holtmann 	{ USB_DEVICE(0x413c, 0x8156), .driver_info = BTUSB_WRONG_SCO_MTU },
322cfeb4145SMarcel Holtmann 
3237a9d4020SMarcel Holtmann 	/* Belkin F8T012 and F8T013 devices */
3247a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_WRONG_SCO_MTU },
3257a9d4020SMarcel Holtmann 	{ USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_WRONG_SCO_MTU },
326cfeb4145SMarcel Holtmann 
3275ddd4a60SMarcel Holtmann 	/* Asus WL-BTD202 device */
3285ddd4a60SMarcel Holtmann 	{ USB_DEVICE(0x0b05, 0x1715), .driver_info = BTUSB_WRONG_SCO_MTU },
3295ddd4a60SMarcel Holtmann 
3305ddd4a60SMarcel Holtmann 	/* Kensington Bluetooth USB adapter */
3315ddd4a60SMarcel Holtmann 	{ USB_DEVICE(0x047d, 0x105e), .driver_info = BTUSB_WRONG_SCO_MTU },
3325ddd4a60SMarcel Holtmann 
333cfeb4145SMarcel Holtmann 	/* RTX Telecom based adapters with buggy SCO support */
334cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x0400, 0x0807), .driver_info = BTUSB_BROKEN_ISOC },
335cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x0400, 0x080a), .driver_info = BTUSB_BROKEN_ISOC },
336cfeb4145SMarcel Holtmann 
337cfeb4145SMarcel Holtmann 	/* CONWISE Technology based adapters with buggy SCO support */
338418678b0SSzymon Janc 	{ USB_DEVICE(0x0e5e, 0x6622),
339418678b0SSzymon Janc 	  .driver_info = BTUSB_BROKEN_ISOC | BTUSB_CW6622},
340cfeb4145SMarcel Holtmann 
3414fcef8edSMarcel Holtmann 	/* Roper Class 1 Bluetooth Dongle (Silicon Wave based) */
3422eeac871SAleksei Volkov 	{ USB_DEVICE(0x1310, 0x0001), .driver_info = BTUSB_SWAVE },
3434fcef8edSMarcel Holtmann 
344cfeb4145SMarcel Holtmann 	/* Digianswer devices */
345cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
346cfeb4145SMarcel Holtmann 	{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
347cfeb4145SMarcel Holtmann 
348cfeb4145SMarcel Holtmann 	/* CSR BlueCore Bluetooth Sniffer */
3494f64fa80SMarcel Holtmann 	{ USB_DEVICE(0x0a12, 0x0002),
3504f64fa80SMarcel Holtmann 	  .driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
351cfeb4145SMarcel Holtmann 
352cfeb4145SMarcel Holtmann 	/* Frontline ComProbe Bluetooth Sniffer */
3534f64fa80SMarcel Holtmann 	{ USB_DEVICE(0x16d3, 0x0002),
3544f64fa80SMarcel Holtmann 	  .driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
355cfeb4145SMarcel Holtmann 
356cb1ee89fSMarcel Holtmann 	/* Marvell Bluetooth devices */
357cb1ee89fSMarcel Holtmann 	{ USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL },
358cb1ee89fSMarcel Holtmann 	{ USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
3591165df0eSAmitkumar Karwar 	{ USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL },
360cb1ee89fSMarcel Holtmann 
361d0ac9eb7SMarcel Holtmann 	/* Intel Bluetooth devices */
3623df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_COMBINED },
3633df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_COMBINED },
3643df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_COMBINED },
3653df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_COMBINED },
3663df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED },
367407550feSMarcel Holtmann 	{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
368ea7c4c0eSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
369ea7c4c0eSTedd Ho-Jeong An 						     BTUSB_INTEL_BROKEN_INITIAL_NCMD },
37083f2dafeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED },
3713df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_COMBINED },
3723df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED },
3733df4dfbeSTedd Ho-Jeong An 	{ USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_COMBINED },
374dffd30eeSTedd Ho-Jeong An 
375d0ac9eb7SMarcel Holtmann 	/* Other Intel Bluetooth devices */
376d0ac9eb7SMarcel Holtmann 	{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
377d0ac9eb7SMarcel Holtmann 	  .driver_info = BTUSB_IGNORE },
378ae8df494SAmitkumar Karwar 
37933bfd94aSJoseph Hwang 	/* Realtek 8822CE Bluetooth devices */
38033bfd94aSJoseph Hwang 	{ USB_DEVICE(0x0bda, 0xb00c), .driver_info = BTUSB_REALTEK |
38133bfd94aSJoseph Hwang 						     BTUSB_WIDEBAND_SPEECH },
3824d96d3b0SLarry Finger 	{ USB_DEVICE(0x0bda, 0xc822), .driver_info = BTUSB_REALTEK |
3834d96d3b0SLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
38433bfd94aSJoseph Hwang 
3850d484db6SMax Chou 	/* Realtek 8852AE Bluetooth devices */
3860d484db6SMax Chou 	{ USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK |
3870d484db6SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
388*27fe097bSLarry Finger 	{ USB_DEVICE(0x0bda, 0x385a), .driver_info = BTUSB_REALTEK |
389*27fe097bSLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
390d1dcbf61SLarry Finger 	{ USB_DEVICE(0x0bda, 0x4852), .driver_info = BTUSB_REALTEK |
391d1dcbf61SLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
3929bba1286SMax Chou 	{ USB_DEVICE(0x04c5, 0x165c), .driver_info = BTUSB_REALTEK |
3939bba1286SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
394d1dcbf61SLarry Finger 	{ USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK |
395d1dcbf61SLarry Finger 						     BTUSB_WIDEBAND_SPEECH },
3960d484db6SMax Chou 
397a2698a9bSDaniel Drake 	/* Realtek Bluetooth devices */
398a2698a9bSDaniel Drake 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
399a2698a9bSDaniel Drake 	  .driver_info = BTUSB_REALTEK },
400a2698a9bSDaniel Drake 
401a1c49c43SSean Wang 	/* MediaTek Bluetooth devices */
402a1c49c43SSean Wang 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0e8d, 0xe0, 0x01, 0x01),
40327e554a4Smark-yw.chen 	  .driver_info = BTUSB_MEDIATEK |
40427e554a4Smark-yw.chen 			 BTUSB_WIDEBAND_SPEECH |
40527e554a4Smark-yw.chen 			 BTUSB_VALID_LE_STATES },
406a1c49c43SSean Wang 
4073a567b95SChris Chiu 	/* Additional MediaTek MT7615E Bluetooth devices */
4083a567b95SChris Chiu 	{ USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK},
4093a567b95SChris Chiu 
41037356827SForest Crossman 	/* Additional MediaTek MT7668 Bluetooth devices */
41137356827SForest Crossman 	{ USB_DEVICE(0x043e, 0x3109), .driver_info = BTUSB_MEDIATEK |
41237356827SForest Crossman 						     BTUSB_WIDEBAND_SPEECH |
41337356827SForest Crossman 						     BTUSB_VALID_LE_STATES },
41437356827SForest Crossman 
415393dc5d1Smark-yw.chen 	/* Additional MediaTek MT7921 Bluetooth devices */
416393dc5d1Smark-yw.chen 	{ USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK |
417393dc5d1Smark-yw.chen 						     BTUSB_WIDEBAND_SPEECH |
418393dc5d1Smark-yw.chen 						     BTUSB_VALID_LE_STATES },
4192cdff8caSWai Paulo Valerio Wang 	{ USB_DEVICE(0x13d3, 0x3563), .driver_info = BTUSB_MEDIATEK |
4202cdff8caSWai Paulo Valerio Wang 						     BTUSB_WIDEBAND_SPEECH |
4212cdff8caSWai Paulo Valerio Wang 						     BTUSB_VALID_LE_STATES },
42215957cabSmark-yw.chen 	{ USB_DEVICE(0x13d3, 0x3564), .driver_info = BTUSB_MEDIATEK |
42315957cabSmark-yw.chen 						     BTUSB_WIDEBAND_SPEECH |
42415957cabSmark-yw.chen 						     BTUSB_VALID_LE_STATES },
42564832df2SAaron Ma 	{ USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK |
42664832df2SAaron Ma 						     BTUSB_WIDEBAND_SPEECH |
42764832df2SAaron Ma 						     BTUSB_VALID_LE_STATES },
428393dc5d1Smark-yw.chen 
429a2698a9bSDaniel Drake 	/* Additional Realtek 8723AE Bluetooth devices */
430a2698a9bSDaniel Drake 	{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
431a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3394), .driver_info = BTUSB_REALTEK },
432a2698a9bSDaniel Drake 
433a2698a9bSDaniel Drake 	/* Additional Realtek 8723BE Bluetooth devices */
434a2698a9bSDaniel Drake 	{ USB_DEVICE(0x0489, 0xe085), .driver_info = BTUSB_REALTEK },
435a2698a9bSDaniel Drake 	{ USB_DEVICE(0x0489, 0xe08b), .driver_info = BTUSB_REALTEK },
436a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
437a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
438a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
439a81d72d2SDmitry Tunin 	{ USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK },
440a2698a9bSDaniel Drake 
441a41e0796SVicente Bergas 	/* Additional Realtek 8723BU Bluetooth devices */
442a41e0796SVicente Bergas 	{ USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
443a41e0796SVicente Bergas 
44466d9975cSJian-Hong Pan 	/* Additional Realtek 8723DE Bluetooth devices */
44545ae68b8SJian-Hong Pan 	{ USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK },
44666d9975cSJian-Hong Pan 	{ USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK },
44766d9975cSJian-Hong Pan 
4484fd6d490SNicholas Flintham 	/* Additional Realtek 8761B Bluetooth devices */
4494fd6d490SNicholas Flintham 	{ USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK |
4504fd6d490SNicholas Flintham 						     BTUSB_WIDEBAND_SPEECH },
4514fd6d490SNicholas Flintham 
45233404381SJoakim Tjernlund 	/* Additional Realtek 8761BU Bluetooth devices */
45333404381SJoakim Tjernlund 	{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
45433404381SJoakim Tjernlund 	  					     BTUSB_WIDEBAND_SPEECH },
45533404381SJoakim Tjernlund 
456a2698a9bSDaniel Drake 	/* Additional Realtek 8821AE Bluetooth devices */
457a2698a9bSDaniel Drake 	{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
458a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
459a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3458), .driver_info = BTUSB_REALTEK },
460a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK },
461a2698a9bSDaniel Drake 	{ USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
462a2698a9bSDaniel Drake 
463fed03fe7SLarry Finger 	/* Additional Realtek 8822BE Bluetooth devices */
4641cd2fabfSArtiom Vaskov 	{ USB_DEVICE(0x13d3, 0x3526), .driver_info = BTUSB_REALTEK },
465fed03fe7SLarry Finger 	{ USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK },
466fed03fe7SLarry Finger 
4676d0762b1SJian-Hong Pan 	/* Additional Realtek 8822CE Bluetooth devices */
46873280f13SMax Chou 	{ USB_DEVICE(0x04ca, 0x4005), .driver_info = BTUSB_REALTEK |
46973280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
47073280f13SMax Chou 	{ USB_DEVICE(0x04c5, 0x161f), .driver_info = BTUSB_REALTEK |
47173280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
47273280f13SMax Chou 	{ USB_DEVICE(0x0b05, 0x18ef), .driver_info = BTUSB_REALTEK |
47373280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
47473280f13SMax Chou 	{ USB_DEVICE(0x13d3, 0x3548), .driver_info = BTUSB_REALTEK |
47573280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
47673280f13SMax Chou 	{ USB_DEVICE(0x13d3, 0x3549), .driver_info = BTUSB_REALTEK |
47773280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
47873280f13SMax Chou 	{ USB_DEVICE(0x13d3, 0x3553), .driver_info = BTUSB_REALTEK |
47973280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
48073280f13SMax Chou 	{ USB_DEVICE(0x13d3, 0x3555), .driver_info = BTUSB_REALTEK |
48173280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
48273280f13SMax Chou 	{ USB_DEVICE(0x2ff8, 0x3051), .driver_info = BTUSB_REALTEK |
48373280f13SMax Chou 						     BTUSB_WIDEBAND_SPEECH },
484f496297eSJulian Pidancet 	{ USB_DEVICE(0x1358, 0xc123), .driver_info = BTUSB_REALTEK |
485f496297eSJulian Pidancet 						     BTUSB_WIDEBAND_SPEECH },
48624d6a6d2SCadel Watson 	{ USB_DEVICE(0x0bda, 0xc123), .driver_info = BTUSB_REALTEK |
48724d6a6d2SCadel Watson 						     BTUSB_WIDEBAND_SPEECH },
4883edc5782SRasmus Moorats 	{ USB_DEVICE(0x0cb5, 0xc547), .driver_info = BTUSB_REALTEK |
4893edc5782SRasmus Moorats 						     BTUSB_WIDEBAND_SPEECH },
4906d0762b1SJian-Hong Pan 
4914481c076SPeter Poklop 	/* Silicon Wave based devices */
4924481c076SPeter Poklop 	{ USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
4934481c076SPeter Poklop 
4945e23b923SMarcel Holtmann 	{ }	/* Terminating entry */
4955e23b923SMarcel Holtmann };
4965e23b923SMarcel Holtmann 
4971fdb9269SHans de Goede /* The Bluetooth USB module build into some devices needs to be reset on resume,
4981fdb9269SHans de Goede  * this is a problem with the platform (likely shutting off all power) not with
4991fdb9269SHans de Goede  * the module itself. So we use a DMI list to match known broken platforms.
5001fdb9269SHans de Goede  */
5011fdb9269SHans de Goede static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
5021fdb9269SHans de Goede 	{
5030c6e5266SKai-Heng Feng 		/* Dell OptiPlex 3060 (QCA ROME device 0cf3:e007) */
5041fdb9269SHans de Goede 		.matches = {
5050c6e5266SKai-Heng Feng 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
5060c6e5266SKai-Heng Feng 			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 3060"),
5071fdb9269SHans de Goede 		},
5081fdb9269SHans de Goede 	},
509596b07a9SHans de Goede 	{
510596b07a9SHans de Goede 		/* Dell XPS 9360 (QCA ROME device 0cf3:e300) */
511596b07a9SHans de Goede 		.matches = {
512596b07a9SHans de Goede 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
513596b07a9SHans de Goede 			DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"),
514596b07a9SHans de Goede 		},
515596b07a9SHans de Goede 	},
516939bc6c5SHans de Goede 	{
517939bc6c5SHans de Goede 		/* Dell Inspiron 5565 (QCA ROME device 0cf3:e009) */
518939bc6c5SHans de Goede 		.matches = {
519939bc6c5SHans de Goede 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
520939bc6c5SHans de Goede 			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5565"),
521939bc6c5SHans de Goede 		},
522939bc6c5SHans de Goede 	},
5231fdb9269SHans de Goede 	{}
5241fdb9269SHans de Goede };
5251fdb9269SHans de Goede 
5269bfa35feSMarcel Holtmann #define BTUSB_MAX_ISOC_FRAMES	10
5279bfa35feSMarcel Holtmann 
5285e23b923SMarcel Holtmann #define BTUSB_INTR_RUNNING	0
5295e23b923SMarcel Holtmann #define BTUSB_BULK_RUNNING	1
5309bfa35feSMarcel Holtmann #define BTUSB_ISOC_RUNNING	2
5317bee549eSOliver Neukum #define BTUSB_SUSPENDING	3
53208b8b6c4SGustavo F. Padovan #define BTUSB_DID_ISO_RESUME	4
533cda0dd78SMarcel Holtmann #define BTUSB_BOOTLOADER	5
534cda0dd78SMarcel Holtmann #define BTUSB_DOWNLOADING	6
535ce6bb929SMarcel Holtmann #define BTUSB_FIRMWARE_LOADED	7
536cda0dd78SMarcel Holtmann #define BTUSB_FIRMWARE_FAILED	8
537ce6bb929SMarcel Holtmann #define BTUSB_BOOTING		9
53861f5aceaSHans de Goede #define BTUSB_DIAG_RUNNING	10
53961f5aceaSHans de Goede #define BTUSB_OOB_WAKE_ENABLED	11
540dc786b2cSRajat Jain #define BTUSB_HW_RESET_ACTIVE	12
541a1c49c43SSean Wang #define BTUSB_TX_WAIT_VND_EVT	13
5428274db07SMax Chou #define BTUSB_WAKEUP_AUTOSUSPEND	14
54355981d35SPauli Virtanen #define BTUSB_USE_ALT3_FOR_WBS	15
5445e23b923SMarcel Holtmann 
5455e23b923SMarcel Holtmann struct btusb_data {
5465e23b923SMarcel Holtmann 	struct hci_dev       *hdev;
5475e23b923SMarcel Holtmann 	struct usb_device    *udev;
5485fbcd260SMarcel Holtmann 	struct usb_interface *intf;
5499bfa35feSMarcel Holtmann 	struct usb_interface *isoc;
5509d08f504SMarcel Holtmann 	struct usb_interface *diag;
551459232fcSMarcel Holtmann 	unsigned isoc_ifnum;
5525e23b923SMarcel Holtmann 
5535e23b923SMarcel Holtmann 	unsigned long flags;
5545e23b923SMarcel Holtmann 
5555e23b923SMarcel Holtmann 	struct work_struct work;
5567bee549eSOliver Neukum 	struct work_struct waker;
5575e23b923SMarcel Holtmann 
558803b5836SMarcel Holtmann 	struct usb_anchor deferred;
5595e23b923SMarcel Holtmann 	struct usb_anchor tx_anchor;
560803b5836SMarcel Holtmann 	int tx_in_flight;
561803b5836SMarcel Holtmann 	spinlock_t txlock;
562803b5836SMarcel Holtmann 
5635e23b923SMarcel Holtmann 	struct usb_anchor intr_anchor;
5645e23b923SMarcel Holtmann 	struct usb_anchor bulk_anchor;
5659bfa35feSMarcel Holtmann 	struct usb_anchor isoc_anchor;
5669d08f504SMarcel Holtmann 	struct usb_anchor diag_anchor;
567a1c49c43SSean Wang 	struct usb_anchor ctrl_anchor;
568803b5836SMarcel Holtmann 	spinlock_t rxlock;
569803b5836SMarcel Holtmann 
570803b5836SMarcel Holtmann 	struct sk_buff *evt_skb;
571803b5836SMarcel Holtmann 	struct sk_buff *acl_skb;
572803b5836SMarcel Holtmann 	struct sk_buff *sco_skb;
5735e23b923SMarcel Holtmann 
5745e23b923SMarcel Holtmann 	struct usb_endpoint_descriptor *intr_ep;
5755e23b923SMarcel Holtmann 	struct usb_endpoint_descriptor *bulk_tx_ep;
5765e23b923SMarcel Holtmann 	struct usb_endpoint_descriptor *bulk_rx_ep;
5779bfa35feSMarcel Holtmann 	struct usb_endpoint_descriptor *isoc_tx_ep;
5789bfa35feSMarcel Holtmann 	struct usb_endpoint_descriptor *isoc_rx_ep;
5799d08f504SMarcel Holtmann 	struct usb_endpoint_descriptor *diag_tx_ep;
5809d08f504SMarcel Holtmann 	struct usb_endpoint_descriptor *diag_rx_ep;
5819bfa35feSMarcel Holtmann 
582dc786b2cSRajat Jain 	struct gpio_desc *reset_gpio;
583dc786b2cSRajat Jain 
5847a9d4020SMarcel Holtmann 	__u8 cmdreq_type;
585893ba544SMarcel Holtmann 	__u8 cmdreq;
5867a9d4020SMarcel Holtmann 
58743c2e57fSMarcel Holtmann 	unsigned int sco_num;
588baac6276SSathish Narasimman 	unsigned int air_mode;
589baac6276SSathish Narasimman 	bool usb_alt6_packet_flow;
5909bfa35feSMarcel Holtmann 	int isoc_altsetting;
5916a88adf2SMarcel Holtmann 	int suspend_count;
5922cbd3f5cSMarcel Holtmann 
59397307f51SMarcel Holtmann 	int (*recv_event)(struct hci_dev *hdev, struct sk_buff *skb);
5940b10c8c8Smark-yw.chen 	int (*recv_acl)(struct hci_dev *hdev, struct sk_buff *skb);
5952cbd3f5cSMarcel Holtmann 	int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
596ace31982SKim, Ben Young Tae 
597ace31982SKim, Ben Young Tae 	int (*setup_on_usb)(struct hci_dev *hdev);
598fd913ef7SRajat Jain 
599fd913ef7SRajat Jain 	int oob_wake_irq;   /* irq for out-of-band wake-on-bt */
600dc786b2cSRajat Jain 	unsigned cmd_timeout_cnt;
6015e23b923SMarcel Holtmann };
6025e23b923SMarcel Holtmann 
603dc786b2cSRajat Jain static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
604dc786b2cSRajat Jain {
605dc786b2cSRajat Jain 	struct btusb_data *data = hci_get_drvdata(hdev);
606dc786b2cSRajat Jain 	struct gpio_desc *reset_gpio = data->reset_gpio;
607dc786b2cSRajat Jain 
608dc786b2cSRajat Jain 	if (++data->cmd_timeout_cnt < 5)
609dc786b2cSRajat Jain 		return;
610dc786b2cSRajat Jain 
611dc786b2cSRajat Jain 	if (!reset_gpio) {
612dc786b2cSRajat Jain 		bt_dev_err(hdev, "No way to reset. Ignoring and continuing");
613dc786b2cSRajat Jain 		return;
614dc786b2cSRajat Jain 	}
615dc786b2cSRajat Jain 
616dc786b2cSRajat Jain 	/*
617dc786b2cSRajat Jain 	 * Toggle the hard reset line if the platform provides one. The reset
618dc786b2cSRajat Jain 	 * is going to yank the device off the USB and then replug. So doing
619dc786b2cSRajat Jain 	 * once is enough. The cleanup is handled correctly on the way out
620dc786b2cSRajat Jain 	 * (standard USB disconnect), and the new device is detected cleanly
621dc786b2cSRajat Jain 	 * and bound to the driver again like it should be.
622dc786b2cSRajat Jain 	 */
623dc786b2cSRajat Jain 	if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
624dc786b2cSRajat Jain 		bt_dev_err(hdev, "last reset failed? Not resetting again");
625dc786b2cSRajat Jain 		return;
626dc786b2cSRajat Jain 	}
627dc786b2cSRajat Jain 
628dc786b2cSRajat Jain 	bt_dev_err(hdev, "Initiating HW reset via gpio");
6292de66bb8SRajat Jain 	gpiod_set_value_cansleep(reset_gpio, 1);
6302de66bb8SRajat Jain 	msleep(100);
6312de66bb8SRajat Jain 	gpiod_set_value_cansleep(reset_gpio, 0);
632dc786b2cSRajat Jain }
633dc786b2cSRajat Jain 
634d7ef0d1eSAlex Lu static void btusb_rtl_cmd_timeout(struct hci_dev *hdev)
635d7ef0d1eSAlex Lu {
636d7ef0d1eSAlex Lu 	struct btusb_data *data = hci_get_drvdata(hdev);
637d7ef0d1eSAlex Lu 	struct gpio_desc *reset_gpio = data->reset_gpio;
638d7ef0d1eSAlex Lu 
639d7ef0d1eSAlex Lu 	if (++data->cmd_timeout_cnt < 5)
640d7ef0d1eSAlex Lu 		return;
641d7ef0d1eSAlex Lu 
642d7ef0d1eSAlex Lu 	if (!reset_gpio) {
643d7ef0d1eSAlex Lu 		bt_dev_err(hdev, "No gpio to reset Realtek device, ignoring");
644d7ef0d1eSAlex Lu 		return;
645d7ef0d1eSAlex Lu 	}
646d7ef0d1eSAlex Lu 
647d7ef0d1eSAlex Lu 	/* Toggle the hard reset line. The Realtek device is going to
648d7ef0d1eSAlex Lu 	 * yank itself off the USB and then replug. The cleanup is handled
649d7ef0d1eSAlex Lu 	 * correctly on the way out (standard USB disconnect), and the new
650d7ef0d1eSAlex Lu 	 * device is detected cleanly and bound to the driver again like
651d7ef0d1eSAlex Lu 	 * it should be.
652d7ef0d1eSAlex Lu 	 */
653d7ef0d1eSAlex Lu 	if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
654d7ef0d1eSAlex Lu 		bt_dev_err(hdev, "last reset failed? Not resetting again");
655d7ef0d1eSAlex Lu 		return;
656d7ef0d1eSAlex Lu 	}
657d7ef0d1eSAlex Lu 
658d7ef0d1eSAlex Lu 	bt_dev_err(hdev, "Reset Realtek device via gpio");
659d7ef0d1eSAlex Lu 	gpiod_set_value_cansleep(reset_gpio, 1);
66034682110SMax Chou 	msleep(200);
66134682110SMax Chou 	gpiod_set_value_cansleep(reset_gpio, 0);
662d7ef0d1eSAlex Lu }
663d7ef0d1eSAlex Lu 
6646933568aSAbhishek Pandit-Subedi static void btusb_qca_cmd_timeout(struct hci_dev *hdev)
6656933568aSAbhishek Pandit-Subedi {
6666933568aSAbhishek Pandit-Subedi 	struct btusb_data *data = hci_get_drvdata(hdev);
66724ff62aeStjiang@codeaurora.org 	struct gpio_desc *reset_gpio = data->reset_gpio;
6686933568aSAbhishek Pandit-Subedi 	int err;
6696933568aSAbhishek Pandit-Subedi 
6706933568aSAbhishek Pandit-Subedi 	if (++data->cmd_timeout_cnt < 5)
6716933568aSAbhishek Pandit-Subedi 		return;
6726933568aSAbhishek Pandit-Subedi 
67324ff62aeStjiang@codeaurora.org 	if (reset_gpio) {
67424ff62aeStjiang@codeaurora.org 		bt_dev_err(hdev, "Reset qca device via bt_en gpio");
67524ff62aeStjiang@codeaurora.org 
67624ff62aeStjiang@codeaurora.org 		/* Toggle the hard reset line. The qca bt device is going to
67724ff62aeStjiang@codeaurora.org 		 * yank itself off the USB and then replug. The cleanup is handled
67824ff62aeStjiang@codeaurora.org 		 * correctly on the way out (standard USB disconnect), and the new
67924ff62aeStjiang@codeaurora.org 		 * device is detected cleanly and bound to the driver again like
68024ff62aeStjiang@codeaurora.org 		 * it should be.
68124ff62aeStjiang@codeaurora.org 		 */
68224ff62aeStjiang@codeaurora.org 		if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
68324ff62aeStjiang@codeaurora.org 			bt_dev_err(hdev, "last reset failed? Not resetting again");
68424ff62aeStjiang@codeaurora.org 			return;
68524ff62aeStjiang@codeaurora.org 		}
68624ff62aeStjiang@codeaurora.org 
68724ff62aeStjiang@codeaurora.org 		gpiod_set_value_cansleep(reset_gpio, 0);
68824ff62aeStjiang@codeaurora.org 		msleep(200);
68924ff62aeStjiang@codeaurora.org 		gpiod_set_value_cansleep(reset_gpio, 1);
69024ff62aeStjiang@codeaurora.org 
69124ff62aeStjiang@codeaurora.org 		return;
69224ff62aeStjiang@codeaurora.org 	}
69324ff62aeStjiang@codeaurora.org 
6946933568aSAbhishek Pandit-Subedi 	bt_dev_err(hdev, "Multiple cmd timeouts seen. Resetting usb device.");
695b980d477SAbhishek Pandit-Subedi 	/* This is not an unbalanced PM reference since the device will reset */
6966933568aSAbhishek Pandit-Subedi 	err = usb_autopm_get_interface(data->intf);
6976933568aSAbhishek Pandit-Subedi 	if (!err)
6986933568aSAbhishek Pandit-Subedi 		usb_queue_reset_device(data->intf);
6996933568aSAbhishek Pandit-Subedi 	else
7006933568aSAbhishek Pandit-Subedi 		bt_dev_err(hdev, "Failed usb_autopm_get_interface with %d", err);
7016933568aSAbhishek Pandit-Subedi }
7026933568aSAbhishek Pandit-Subedi 
703803b5836SMarcel Holtmann static inline void btusb_free_frags(struct btusb_data *data)
704803b5836SMarcel Holtmann {
705803b5836SMarcel Holtmann 	unsigned long flags;
706803b5836SMarcel Holtmann 
707803b5836SMarcel Holtmann 	spin_lock_irqsave(&data->rxlock, flags);
708803b5836SMarcel Holtmann 
709803b5836SMarcel Holtmann 	kfree_skb(data->evt_skb);
710803b5836SMarcel Holtmann 	data->evt_skb = NULL;
711803b5836SMarcel Holtmann 
712803b5836SMarcel Holtmann 	kfree_skb(data->acl_skb);
713803b5836SMarcel Holtmann 	data->acl_skb = NULL;
714803b5836SMarcel Holtmann 
715803b5836SMarcel Holtmann 	kfree_skb(data->sco_skb);
716803b5836SMarcel Holtmann 	data->sco_skb = NULL;
717803b5836SMarcel Holtmann 
718803b5836SMarcel Holtmann 	spin_unlock_irqrestore(&data->rxlock, flags);
719803b5836SMarcel Holtmann }
720803b5836SMarcel Holtmann 
7211ffa4ad0SMarcel Holtmann static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
7221ffa4ad0SMarcel Holtmann {
723803b5836SMarcel Holtmann 	struct sk_buff *skb;
724a5e50d5bSSebastian Andrzej Siewior 	unsigned long flags;
725803b5836SMarcel Holtmann 	int err = 0;
726803b5836SMarcel Holtmann 
727a5e50d5bSSebastian Andrzej Siewior 	spin_lock_irqsave(&data->rxlock, flags);
728803b5836SMarcel Holtmann 	skb = data->evt_skb;
729803b5836SMarcel Holtmann 
730803b5836SMarcel Holtmann 	while (count) {
731803b5836SMarcel Holtmann 		int len;
732803b5836SMarcel Holtmann 
733803b5836SMarcel Holtmann 		if (!skb) {
734803b5836SMarcel Holtmann 			skb = bt_skb_alloc(HCI_MAX_EVENT_SIZE, GFP_ATOMIC);
735803b5836SMarcel Holtmann 			if (!skb) {
736803b5836SMarcel Holtmann 				err = -ENOMEM;
737803b5836SMarcel Holtmann 				break;
738803b5836SMarcel Holtmann 			}
739803b5836SMarcel Holtmann 
740618e8bc2SMarcel Holtmann 			hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
741618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = HCI_EVENT_HDR_SIZE;
742803b5836SMarcel Holtmann 		}
743803b5836SMarcel Holtmann 
744618e8bc2SMarcel Holtmann 		len = min_t(uint, hci_skb_expect(skb), count);
74559ae1d12SJohannes Berg 		skb_put_data(skb, buffer, len);
746803b5836SMarcel Holtmann 
747803b5836SMarcel Holtmann 		count -= len;
748803b5836SMarcel Holtmann 		buffer += len;
749618e8bc2SMarcel Holtmann 		hci_skb_expect(skb) -= len;
750803b5836SMarcel Holtmann 
751803b5836SMarcel Holtmann 		if (skb->len == HCI_EVENT_HDR_SIZE) {
752803b5836SMarcel Holtmann 			/* Complete event header */
753618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = hci_event_hdr(skb)->plen;
754803b5836SMarcel Holtmann 
755618e8bc2SMarcel Holtmann 			if (skb_tailroom(skb) < hci_skb_expect(skb)) {
756803b5836SMarcel Holtmann 				kfree_skb(skb);
757803b5836SMarcel Holtmann 				skb = NULL;
758803b5836SMarcel Holtmann 
759803b5836SMarcel Holtmann 				err = -EILSEQ;
760803b5836SMarcel Holtmann 				break;
761803b5836SMarcel Holtmann 			}
762803b5836SMarcel Holtmann 		}
763803b5836SMarcel Holtmann 
764618e8bc2SMarcel Holtmann 		if (!hci_skb_expect(skb)) {
765803b5836SMarcel Holtmann 			/* Complete frame */
76697307f51SMarcel Holtmann 			data->recv_event(data->hdev, skb);
767803b5836SMarcel Holtmann 			skb = NULL;
768803b5836SMarcel Holtmann 		}
769803b5836SMarcel Holtmann 	}
770803b5836SMarcel Holtmann 
771803b5836SMarcel Holtmann 	data->evt_skb = skb;
772a5e50d5bSSebastian Andrzej Siewior 	spin_unlock_irqrestore(&data->rxlock, flags);
773803b5836SMarcel Holtmann 
774803b5836SMarcel Holtmann 	return err;
7751ffa4ad0SMarcel Holtmann }
7761ffa4ad0SMarcel Holtmann 
7771ffa4ad0SMarcel Holtmann static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
7781ffa4ad0SMarcel Holtmann {
779803b5836SMarcel Holtmann 	struct sk_buff *skb;
780a5e50d5bSSebastian Andrzej Siewior 	unsigned long flags;
781803b5836SMarcel Holtmann 	int err = 0;
782803b5836SMarcel Holtmann 
783a5e50d5bSSebastian Andrzej Siewior 	spin_lock_irqsave(&data->rxlock, flags);
784803b5836SMarcel Holtmann 	skb = data->acl_skb;
785803b5836SMarcel Holtmann 
786803b5836SMarcel Holtmann 	while (count) {
787803b5836SMarcel Holtmann 		int len;
788803b5836SMarcel Holtmann 
789803b5836SMarcel Holtmann 		if (!skb) {
790803b5836SMarcel Holtmann 			skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
791803b5836SMarcel Holtmann 			if (!skb) {
792803b5836SMarcel Holtmann 				err = -ENOMEM;
793803b5836SMarcel Holtmann 				break;
794803b5836SMarcel Holtmann 			}
795803b5836SMarcel Holtmann 
796618e8bc2SMarcel Holtmann 			hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT;
797618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = HCI_ACL_HDR_SIZE;
798803b5836SMarcel Holtmann 		}
799803b5836SMarcel Holtmann 
800618e8bc2SMarcel Holtmann 		len = min_t(uint, hci_skb_expect(skb), count);
80159ae1d12SJohannes Berg 		skb_put_data(skb, buffer, len);
802803b5836SMarcel Holtmann 
803803b5836SMarcel Holtmann 		count -= len;
804803b5836SMarcel Holtmann 		buffer += len;
805618e8bc2SMarcel Holtmann 		hci_skb_expect(skb) -= len;
806803b5836SMarcel Holtmann 
807803b5836SMarcel Holtmann 		if (skb->len == HCI_ACL_HDR_SIZE) {
808803b5836SMarcel Holtmann 			__le16 dlen = hci_acl_hdr(skb)->dlen;
809803b5836SMarcel Holtmann 
810803b5836SMarcel Holtmann 			/* Complete ACL header */
811618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = __le16_to_cpu(dlen);
812803b5836SMarcel Holtmann 
813618e8bc2SMarcel Holtmann 			if (skb_tailroom(skb) < hci_skb_expect(skb)) {
814803b5836SMarcel Holtmann 				kfree_skb(skb);
815803b5836SMarcel Holtmann 				skb = NULL;
816803b5836SMarcel Holtmann 
817803b5836SMarcel Holtmann 				err = -EILSEQ;
818803b5836SMarcel Holtmann 				break;
819803b5836SMarcel Holtmann 			}
820803b5836SMarcel Holtmann 		}
821803b5836SMarcel Holtmann 
822618e8bc2SMarcel Holtmann 		if (!hci_skb_expect(skb)) {
823803b5836SMarcel Holtmann 			/* Complete frame */
8240b10c8c8Smark-yw.chen 			data->recv_acl(data->hdev, skb);
825803b5836SMarcel Holtmann 			skb = NULL;
826803b5836SMarcel Holtmann 		}
827803b5836SMarcel Holtmann 	}
828803b5836SMarcel Holtmann 
829803b5836SMarcel Holtmann 	data->acl_skb = skb;
830a5e50d5bSSebastian Andrzej Siewior 	spin_unlock_irqrestore(&data->rxlock, flags);
831803b5836SMarcel Holtmann 
832803b5836SMarcel Holtmann 	return err;
8331ffa4ad0SMarcel Holtmann }
8341ffa4ad0SMarcel Holtmann 
8351ffa4ad0SMarcel Holtmann static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
8361ffa4ad0SMarcel Holtmann {
837803b5836SMarcel Holtmann 	struct sk_buff *skb;
838a5e50d5bSSebastian Andrzej Siewior 	unsigned long flags;
839803b5836SMarcel Holtmann 	int err = 0;
840803b5836SMarcel Holtmann 
841a5e50d5bSSebastian Andrzej Siewior 	spin_lock_irqsave(&data->rxlock, flags);
842803b5836SMarcel Holtmann 	skb = data->sco_skb;
843803b5836SMarcel Holtmann 
844803b5836SMarcel Holtmann 	while (count) {
845803b5836SMarcel Holtmann 		int len;
846803b5836SMarcel Holtmann 
847803b5836SMarcel Holtmann 		if (!skb) {
848803b5836SMarcel Holtmann 			skb = bt_skb_alloc(HCI_MAX_SCO_SIZE, GFP_ATOMIC);
849803b5836SMarcel Holtmann 			if (!skb) {
850803b5836SMarcel Holtmann 				err = -ENOMEM;
851803b5836SMarcel Holtmann 				break;
852803b5836SMarcel Holtmann 			}
853803b5836SMarcel Holtmann 
854618e8bc2SMarcel Holtmann 			hci_skb_pkt_type(skb) = HCI_SCODATA_PKT;
855618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = HCI_SCO_HDR_SIZE;
856803b5836SMarcel Holtmann 		}
857803b5836SMarcel Holtmann 
858618e8bc2SMarcel Holtmann 		len = min_t(uint, hci_skb_expect(skb), count);
85959ae1d12SJohannes Berg 		skb_put_data(skb, buffer, len);
860803b5836SMarcel Holtmann 
861803b5836SMarcel Holtmann 		count -= len;
862803b5836SMarcel Holtmann 		buffer += len;
863618e8bc2SMarcel Holtmann 		hci_skb_expect(skb) -= len;
864803b5836SMarcel Holtmann 
865803b5836SMarcel Holtmann 		if (skb->len == HCI_SCO_HDR_SIZE) {
866803b5836SMarcel Holtmann 			/* Complete SCO header */
867618e8bc2SMarcel Holtmann 			hci_skb_expect(skb) = hci_sco_hdr(skb)->dlen;
868803b5836SMarcel Holtmann 
869618e8bc2SMarcel Holtmann 			if (skb_tailroom(skb) < hci_skb_expect(skb)) {
870803b5836SMarcel Holtmann 				kfree_skb(skb);
871803b5836SMarcel Holtmann 				skb = NULL;
872803b5836SMarcel Holtmann 
873803b5836SMarcel Holtmann 				err = -EILSEQ;
874803b5836SMarcel Holtmann 				break;
875803b5836SMarcel Holtmann 			}
876803b5836SMarcel Holtmann 		}
877803b5836SMarcel Holtmann 
878618e8bc2SMarcel Holtmann 		if (!hci_skb_expect(skb)) {
879803b5836SMarcel Holtmann 			/* Complete frame */
880803b5836SMarcel Holtmann 			hci_recv_frame(data->hdev, skb);
881803b5836SMarcel Holtmann 			skb = NULL;
882803b5836SMarcel Holtmann 		}
883803b5836SMarcel Holtmann 	}
884803b5836SMarcel Holtmann 
885803b5836SMarcel Holtmann 	data->sco_skb = skb;
886a5e50d5bSSebastian Andrzej Siewior 	spin_unlock_irqrestore(&data->rxlock, flags);
887803b5836SMarcel Holtmann 
888803b5836SMarcel Holtmann 	return err;
8891ffa4ad0SMarcel Holtmann }
8901ffa4ad0SMarcel Holtmann 
8915e23b923SMarcel Holtmann static void btusb_intr_complete(struct urb *urb)
8925e23b923SMarcel Holtmann {
8935e23b923SMarcel Holtmann 	struct hci_dev *hdev = urb->context;
894155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
8955e23b923SMarcel Holtmann 	int err;
8965e23b923SMarcel Holtmann 
89789e7533dSMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
89889e7533dSMarcel Holtmann 	       urb->actual_length);
8995e23b923SMarcel Holtmann 
9005e23b923SMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
9015e23b923SMarcel Holtmann 		return;
9025e23b923SMarcel Holtmann 
9035e23b923SMarcel Holtmann 	if (urb->status == 0) {
9049bfa35feSMarcel Holtmann 		hdev->stat.byte_rx += urb->actual_length;
9059bfa35feSMarcel Holtmann 
9061ffa4ad0SMarcel Holtmann 		if (btusb_recv_intr(data, urb->transfer_buffer,
9075e23b923SMarcel Holtmann 				    urb->actual_length) < 0) {
9082064ee33SMarcel Holtmann 			bt_dev_err(hdev, "corrupted event packet");
9095e23b923SMarcel Holtmann 			hdev->stat.err_rx++;
9105e23b923SMarcel Holtmann 		}
91185560c4aSChampion Chen 	} else if (urb->status == -ENOENT) {
91285560c4aSChampion Chen 		/* Avoid suspend failed when usb_kill_urb */
91385560c4aSChampion Chen 		return;
9145e23b923SMarcel Holtmann 	}
9155e23b923SMarcel Holtmann 
9165e23b923SMarcel Holtmann 	if (!test_bit(BTUSB_INTR_RUNNING, &data->flags))
9175e23b923SMarcel Holtmann 		return;
9185e23b923SMarcel Holtmann 
9197bee549eSOliver Neukum 	usb_mark_last_busy(data->udev);
9205e23b923SMarcel Holtmann 	usb_anchor_urb(urb, &data->intr_anchor);
9215e23b923SMarcel Holtmann 
9225e23b923SMarcel Holtmann 	err = usb_submit_urb(urb, GFP_ATOMIC);
9235e23b923SMarcel Holtmann 	if (err < 0) {
9244935f1c1SPaul Bolle 		/* -EPERM: urb is being killed;
925d98422cbSDerek Robson 		 * -ENODEV: device got disconnected
926d98422cbSDerek Robson 		 */
9274935f1c1SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
9282064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
9292064ee33SMarcel Holtmann 				   urb, -err);
9305e23b923SMarcel Holtmann 		usb_unanchor_urb(urb);
9315e23b923SMarcel Holtmann 	}
9325e23b923SMarcel Holtmann }
9335e23b923SMarcel Holtmann 
9342eda66f4SMarcel Holtmann static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
9355e23b923SMarcel Holtmann {
936155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
9375e23b923SMarcel Holtmann 	struct urb *urb;
9385e23b923SMarcel Holtmann 	unsigned char *buf;
9395e23b923SMarcel Holtmann 	unsigned int pipe;
9405e23b923SMarcel Holtmann 	int err, size;
9415e23b923SMarcel Holtmann 
9425e23b923SMarcel Holtmann 	BT_DBG("%s", hdev->name);
9435e23b923SMarcel Holtmann 
9449bfa35feSMarcel Holtmann 	if (!data->intr_ep)
9459bfa35feSMarcel Holtmann 		return -ENODEV;
9469bfa35feSMarcel Holtmann 
9472eda66f4SMarcel Holtmann 	urb = usb_alloc_urb(0, mem_flags);
9485e23b923SMarcel Holtmann 	if (!urb)
9495e23b923SMarcel Holtmann 		return -ENOMEM;
9505e23b923SMarcel Holtmann 
9515e23b923SMarcel Holtmann 	size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
9525e23b923SMarcel Holtmann 
9532eda66f4SMarcel Holtmann 	buf = kmalloc(size, mem_flags);
9545e23b923SMarcel Holtmann 	if (!buf) {
9555e23b923SMarcel Holtmann 		usb_free_urb(urb);
9565e23b923SMarcel Holtmann 		return -ENOMEM;
9575e23b923SMarcel Holtmann 	}
9585e23b923SMarcel Holtmann 
9595e23b923SMarcel Holtmann 	pipe = usb_rcvintpipe(data->udev, data->intr_ep->bEndpointAddress);
9605e23b923SMarcel Holtmann 
9615e23b923SMarcel Holtmann 	usb_fill_int_urb(urb, data->udev, pipe, buf, size,
96289e7533dSMarcel Holtmann 			 btusb_intr_complete, hdev, data->intr_ep->bInterval);
9635e23b923SMarcel Holtmann 
9645e23b923SMarcel Holtmann 	urb->transfer_flags |= URB_FREE_BUFFER;
9655e23b923SMarcel Holtmann 
9665e23b923SMarcel Holtmann 	usb_anchor_urb(urb, &data->intr_anchor);
9675e23b923SMarcel Holtmann 
9682eda66f4SMarcel Holtmann 	err = usb_submit_urb(urb, mem_flags);
9695e23b923SMarcel Holtmann 	if (err < 0) {
970d4b8d1c9SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
9712064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p submission failed (%d)",
9722064ee33SMarcel Holtmann 				   urb, -err);
9735e23b923SMarcel Holtmann 		usb_unanchor_urb(urb);
9745e23b923SMarcel Holtmann 	}
9755e23b923SMarcel Holtmann 
9765e23b923SMarcel Holtmann 	usb_free_urb(urb);
9775e23b923SMarcel Holtmann 
9785e23b923SMarcel Holtmann 	return err;
9795e23b923SMarcel Holtmann }
9805e23b923SMarcel Holtmann 
9815e23b923SMarcel Holtmann static void btusb_bulk_complete(struct urb *urb)
9825e23b923SMarcel Holtmann {
9835e23b923SMarcel Holtmann 	struct hci_dev *hdev = urb->context;
984155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
9855e23b923SMarcel Holtmann 	int err;
9865e23b923SMarcel Holtmann 
98789e7533dSMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
98889e7533dSMarcel Holtmann 	       urb->actual_length);
9895e23b923SMarcel Holtmann 
9905e23b923SMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
9915e23b923SMarcel Holtmann 		return;
9925e23b923SMarcel Holtmann 
9935e23b923SMarcel Holtmann 	if (urb->status == 0) {
9949bfa35feSMarcel Holtmann 		hdev->stat.byte_rx += urb->actual_length;
9959bfa35feSMarcel Holtmann 
9962cbd3f5cSMarcel Holtmann 		if (data->recv_bulk(data, urb->transfer_buffer,
9975e23b923SMarcel Holtmann 				    urb->actual_length) < 0) {
9982064ee33SMarcel Holtmann 			bt_dev_err(hdev, "corrupted ACL packet");
9995e23b923SMarcel Holtmann 			hdev->stat.err_rx++;
10005e23b923SMarcel Holtmann 		}
100185560c4aSChampion Chen 	} else if (urb->status == -ENOENT) {
100285560c4aSChampion Chen 		/* Avoid suspend failed when usb_kill_urb */
100385560c4aSChampion Chen 		return;
10045e23b923SMarcel Holtmann 	}
10055e23b923SMarcel Holtmann 
10065e23b923SMarcel Holtmann 	if (!test_bit(BTUSB_BULK_RUNNING, &data->flags))
10075e23b923SMarcel Holtmann 		return;
10085e23b923SMarcel Holtmann 
10095e23b923SMarcel Holtmann 	usb_anchor_urb(urb, &data->bulk_anchor);
1010652fd781SOliver Neukum 	usb_mark_last_busy(data->udev);
10115e23b923SMarcel Holtmann 
10125e23b923SMarcel Holtmann 	err = usb_submit_urb(urb, GFP_ATOMIC);
10135e23b923SMarcel Holtmann 	if (err < 0) {
10144935f1c1SPaul Bolle 		/* -EPERM: urb is being killed;
1015d98422cbSDerek Robson 		 * -ENODEV: device got disconnected
1016d98422cbSDerek Robson 		 */
10174935f1c1SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
10182064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
10192064ee33SMarcel Holtmann 				   urb, -err);
10205e23b923SMarcel Holtmann 		usb_unanchor_urb(urb);
10215e23b923SMarcel Holtmann 	}
10225e23b923SMarcel Holtmann }
10235e23b923SMarcel Holtmann 
10242eda66f4SMarcel Holtmann static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
10255e23b923SMarcel Holtmann {
1026155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
10275e23b923SMarcel Holtmann 	struct urb *urb;
10285e23b923SMarcel Holtmann 	unsigned char *buf;
10295e23b923SMarcel Holtmann 	unsigned int pipe;
1030290ba200SVikram Kandukuri 	int err, size = HCI_MAX_FRAME_SIZE;
10315e23b923SMarcel Holtmann 
10325e23b923SMarcel Holtmann 	BT_DBG("%s", hdev->name);
10335e23b923SMarcel Holtmann 
10349bfa35feSMarcel Holtmann 	if (!data->bulk_rx_ep)
10359bfa35feSMarcel Holtmann 		return -ENODEV;
10369bfa35feSMarcel Holtmann 
10372eda66f4SMarcel Holtmann 	urb = usb_alloc_urb(0, mem_flags);
10385e23b923SMarcel Holtmann 	if (!urb)
10395e23b923SMarcel Holtmann 		return -ENOMEM;
10405e23b923SMarcel Holtmann 
10412eda66f4SMarcel Holtmann 	buf = kmalloc(size, mem_flags);
10425e23b923SMarcel Holtmann 	if (!buf) {
10435e23b923SMarcel Holtmann 		usb_free_urb(urb);
10445e23b923SMarcel Holtmann 		return -ENOMEM;
10455e23b923SMarcel Holtmann 	}
10465e23b923SMarcel Holtmann 
10475e23b923SMarcel Holtmann 	pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress);
10485e23b923SMarcel Holtmann 
104989e7533dSMarcel Holtmann 	usb_fill_bulk_urb(urb, data->udev, pipe, buf, size,
105089e7533dSMarcel Holtmann 			  btusb_bulk_complete, hdev);
10515e23b923SMarcel Holtmann 
10525e23b923SMarcel Holtmann 	urb->transfer_flags |= URB_FREE_BUFFER;
10535e23b923SMarcel Holtmann 
10547bee549eSOliver Neukum 	usb_mark_last_busy(data->udev);
10555e23b923SMarcel Holtmann 	usb_anchor_urb(urb, &data->bulk_anchor);
10565e23b923SMarcel Holtmann 
10572eda66f4SMarcel Holtmann 	err = usb_submit_urb(urb, mem_flags);
10585e23b923SMarcel Holtmann 	if (err < 0) {
1059d4b8d1c9SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
10602064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p submission failed (%d)",
10612064ee33SMarcel Holtmann 				   urb, -err);
10625e23b923SMarcel Holtmann 		usb_unanchor_urb(urb);
10635e23b923SMarcel Holtmann 	}
10645e23b923SMarcel Holtmann 
10655e23b923SMarcel Holtmann 	usb_free_urb(urb);
10665e23b923SMarcel Holtmann 
10675e23b923SMarcel Holtmann 	return err;
10685e23b923SMarcel Holtmann }
10695e23b923SMarcel Holtmann 
10709bfa35feSMarcel Holtmann static void btusb_isoc_complete(struct urb *urb)
10719bfa35feSMarcel Holtmann {
10729bfa35feSMarcel Holtmann 	struct hci_dev *hdev = urb->context;
1073155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
10749bfa35feSMarcel Holtmann 	int i, err;
10759bfa35feSMarcel Holtmann 
107689e7533dSMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
107789e7533dSMarcel Holtmann 	       urb->actual_length);
10789bfa35feSMarcel Holtmann 
10799bfa35feSMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
10809bfa35feSMarcel Holtmann 		return;
10819bfa35feSMarcel Holtmann 
10829bfa35feSMarcel Holtmann 	if (urb->status == 0) {
10839bfa35feSMarcel Holtmann 		for (i = 0; i < urb->number_of_packets; i++) {
10849bfa35feSMarcel Holtmann 			unsigned int offset = urb->iso_frame_desc[i].offset;
10859bfa35feSMarcel Holtmann 			unsigned int length = urb->iso_frame_desc[i].actual_length;
10869bfa35feSMarcel Holtmann 
10879bfa35feSMarcel Holtmann 			if (urb->iso_frame_desc[i].status)
10889bfa35feSMarcel Holtmann 				continue;
10899bfa35feSMarcel Holtmann 
10909bfa35feSMarcel Holtmann 			hdev->stat.byte_rx += length;
10919bfa35feSMarcel Holtmann 
10921ffa4ad0SMarcel Holtmann 			if (btusb_recv_isoc(data, urb->transfer_buffer + offset,
10939bfa35feSMarcel Holtmann 					    length) < 0) {
10942064ee33SMarcel Holtmann 				bt_dev_err(hdev, "corrupted SCO packet");
10959bfa35feSMarcel Holtmann 				hdev->stat.err_rx++;
10969bfa35feSMarcel Holtmann 			}
10979bfa35feSMarcel Holtmann 		}
109885560c4aSChampion Chen 	} else if (urb->status == -ENOENT) {
109985560c4aSChampion Chen 		/* Avoid suspend failed when usb_kill_urb */
110085560c4aSChampion Chen 		return;
11019bfa35feSMarcel Holtmann 	}
11029bfa35feSMarcel Holtmann 
11039bfa35feSMarcel Holtmann 	if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags))
11049bfa35feSMarcel Holtmann 		return;
11059bfa35feSMarcel Holtmann 
11069bfa35feSMarcel Holtmann 	usb_anchor_urb(urb, &data->isoc_anchor);
11079bfa35feSMarcel Holtmann 
11089bfa35feSMarcel Holtmann 	err = usb_submit_urb(urb, GFP_ATOMIC);
11099bfa35feSMarcel Holtmann 	if (err < 0) {
11104935f1c1SPaul Bolle 		/* -EPERM: urb is being killed;
1111d98422cbSDerek Robson 		 * -ENODEV: device got disconnected
1112d98422cbSDerek Robson 		 */
11134935f1c1SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
11142064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
11152064ee33SMarcel Holtmann 				   urb, -err);
11169bfa35feSMarcel Holtmann 		usb_unanchor_urb(urb);
11179bfa35feSMarcel Holtmann 	}
11189bfa35feSMarcel Holtmann }
11199bfa35feSMarcel Holtmann 
1120baac6276SSathish Narasimman static inline void __fill_isoc_descriptor_msbc(struct urb *urb, int len,
1121baac6276SSathish Narasimman 					       int mtu, struct btusb_data *data)
1122baac6276SSathish Narasimman {
1123baac6276SSathish Narasimman 	int i, offset = 0;
1124baac6276SSathish Narasimman 	unsigned int interval;
1125baac6276SSathish Narasimman 
1126baac6276SSathish Narasimman 	BT_DBG("len %d mtu %d", len, mtu);
1127baac6276SSathish Narasimman 
1128baac6276SSathish Narasimman 	/* For mSBC ALT 6 setting the host will send the packet at continuous
1129baac6276SSathish Narasimman 	 * flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting
1130baac6276SSathish Narasimman 	 * 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets.
1131baac6276SSathish Narasimman 	 * To maintain the rate we send 63bytes of usb packets alternatively for
1132baac6276SSathish Narasimman 	 * 7ms and 8ms to maintain the rate as 7.5ms.
1133baac6276SSathish Narasimman 	 */
1134baac6276SSathish Narasimman 	if (data->usb_alt6_packet_flow) {
1135baac6276SSathish Narasimman 		interval = 7;
1136baac6276SSathish Narasimman 		data->usb_alt6_packet_flow = false;
1137baac6276SSathish Narasimman 	} else {
1138baac6276SSathish Narasimman 		interval = 6;
1139baac6276SSathish Narasimman 		data->usb_alt6_packet_flow = true;
1140baac6276SSathish Narasimman 	}
1141baac6276SSathish Narasimman 
1142baac6276SSathish Narasimman 	for (i = 0; i < interval; i++) {
1143baac6276SSathish Narasimman 		urb->iso_frame_desc[i].offset = offset;
1144baac6276SSathish Narasimman 		urb->iso_frame_desc[i].length = offset;
1145baac6276SSathish Narasimman 	}
1146baac6276SSathish Narasimman 
1147baac6276SSathish Narasimman 	if (len && i < BTUSB_MAX_ISOC_FRAMES) {
1148baac6276SSathish Narasimman 		urb->iso_frame_desc[i].offset = offset;
1149baac6276SSathish Narasimman 		urb->iso_frame_desc[i].length = len;
1150baac6276SSathish Narasimman 		i++;
1151baac6276SSathish Narasimman 	}
1152baac6276SSathish Narasimman 
1153baac6276SSathish Narasimman 	urb->number_of_packets = i;
1154baac6276SSathish Narasimman }
1155baac6276SSathish Narasimman 
115642b16b3fSJesper Juhl static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
11579bfa35feSMarcel Holtmann {
11589bfa35feSMarcel Holtmann 	int i, offset = 0;
11599bfa35feSMarcel Holtmann 
11609bfa35feSMarcel Holtmann 	BT_DBG("len %d mtu %d", len, mtu);
11619bfa35feSMarcel Holtmann 
11629bfa35feSMarcel Holtmann 	for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu;
11639bfa35feSMarcel Holtmann 					i++, offset += mtu, len -= mtu) {
11649bfa35feSMarcel Holtmann 		urb->iso_frame_desc[i].offset = offset;
11659bfa35feSMarcel Holtmann 		urb->iso_frame_desc[i].length = mtu;
11669bfa35feSMarcel Holtmann 	}
11679bfa35feSMarcel Holtmann 
11689bfa35feSMarcel Holtmann 	if (len && i < BTUSB_MAX_ISOC_FRAMES) {
11699bfa35feSMarcel Holtmann 		urb->iso_frame_desc[i].offset = offset;
11709bfa35feSMarcel Holtmann 		urb->iso_frame_desc[i].length = len;
11719bfa35feSMarcel Holtmann 		i++;
11729bfa35feSMarcel Holtmann 	}
11739bfa35feSMarcel Holtmann 
11749bfa35feSMarcel Holtmann 	urb->number_of_packets = i;
11759bfa35feSMarcel Holtmann }
11769bfa35feSMarcel Holtmann 
11772eda66f4SMarcel Holtmann static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
11789bfa35feSMarcel Holtmann {
1179155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
11809bfa35feSMarcel Holtmann 	struct urb *urb;
11819bfa35feSMarcel Holtmann 	unsigned char *buf;
11829bfa35feSMarcel Holtmann 	unsigned int pipe;
11839bfa35feSMarcel Holtmann 	int err, size;
11849bfa35feSMarcel Holtmann 
11859bfa35feSMarcel Holtmann 	BT_DBG("%s", hdev->name);
11869bfa35feSMarcel Holtmann 
11879bfa35feSMarcel Holtmann 	if (!data->isoc_rx_ep)
11889bfa35feSMarcel Holtmann 		return -ENODEV;
11899bfa35feSMarcel Holtmann 
11902eda66f4SMarcel Holtmann 	urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, mem_flags);
11919bfa35feSMarcel Holtmann 	if (!urb)
11929bfa35feSMarcel Holtmann 		return -ENOMEM;
11939bfa35feSMarcel Holtmann 
11949bfa35feSMarcel Holtmann 	size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) *
11959bfa35feSMarcel Holtmann 						BTUSB_MAX_ISOC_FRAMES;
11969bfa35feSMarcel Holtmann 
11972eda66f4SMarcel Holtmann 	buf = kmalloc(size, mem_flags);
11989bfa35feSMarcel Holtmann 	if (!buf) {
11999bfa35feSMarcel Holtmann 		usb_free_urb(urb);
12009bfa35feSMarcel Holtmann 		return -ENOMEM;
12019bfa35feSMarcel Holtmann 	}
12029bfa35feSMarcel Holtmann 
12039bfa35feSMarcel Holtmann 	pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
12049bfa35feSMarcel Holtmann 
1205fa0fb93fSBing Zhao 	usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete,
1206fa0fb93fSBing Zhao 			 hdev, data->isoc_rx_ep->bInterval);
12079bfa35feSMarcel Holtmann 
12089bfa35feSMarcel Holtmann 	urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
12099bfa35feSMarcel Holtmann 
12109bfa35feSMarcel Holtmann 	__fill_isoc_descriptor(urb, size,
12119bfa35feSMarcel Holtmann 			       le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
12129bfa35feSMarcel Holtmann 
12139bfa35feSMarcel Holtmann 	usb_anchor_urb(urb, &data->isoc_anchor);
12149bfa35feSMarcel Holtmann 
12152eda66f4SMarcel Holtmann 	err = usb_submit_urb(urb, mem_flags);
12169bfa35feSMarcel Holtmann 	if (err < 0) {
1217d4b8d1c9SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
12182064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p submission failed (%d)",
12192064ee33SMarcel Holtmann 				   urb, -err);
12209bfa35feSMarcel Holtmann 		usb_unanchor_urb(urb);
12219bfa35feSMarcel Holtmann 	}
12229bfa35feSMarcel Holtmann 
12239bfa35feSMarcel Holtmann 	usb_free_urb(urb);
12249bfa35feSMarcel Holtmann 
12259bfa35feSMarcel Holtmann 	return err;
12269bfa35feSMarcel Holtmann }
12279bfa35feSMarcel Holtmann 
12289d08f504SMarcel Holtmann static void btusb_diag_complete(struct urb *urb)
12299d08f504SMarcel Holtmann {
12309d08f504SMarcel Holtmann 	struct hci_dev *hdev = urb->context;
12319d08f504SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
12329d08f504SMarcel Holtmann 	int err;
12339d08f504SMarcel Holtmann 
12349d08f504SMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
12359d08f504SMarcel Holtmann 	       urb->actual_length);
12369d08f504SMarcel Holtmann 
12379d08f504SMarcel Holtmann 	if (urb->status == 0) {
12389d08f504SMarcel Holtmann 		struct sk_buff *skb;
12399d08f504SMarcel Holtmann 
12409d08f504SMarcel Holtmann 		skb = bt_skb_alloc(urb->actual_length, GFP_ATOMIC);
12419d08f504SMarcel Holtmann 		if (skb) {
124259ae1d12SJohannes Berg 			skb_put_data(skb, urb->transfer_buffer,
124359ae1d12SJohannes Berg 				     urb->actual_length);
12449d08f504SMarcel Holtmann 			hci_recv_diag(hdev, skb);
12459d08f504SMarcel Holtmann 		}
12469d08f504SMarcel Holtmann 	} else if (urb->status == -ENOENT) {
12479d08f504SMarcel Holtmann 		/* Avoid suspend failed when usb_kill_urb */
12489d08f504SMarcel Holtmann 		return;
12499d08f504SMarcel Holtmann 	}
12509d08f504SMarcel Holtmann 
12519d08f504SMarcel Holtmann 	if (!test_bit(BTUSB_DIAG_RUNNING, &data->flags))
12529d08f504SMarcel Holtmann 		return;
12539d08f504SMarcel Holtmann 
12549d08f504SMarcel Holtmann 	usb_anchor_urb(urb, &data->diag_anchor);
12559d08f504SMarcel Holtmann 	usb_mark_last_busy(data->udev);
12569d08f504SMarcel Holtmann 
12579d08f504SMarcel Holtmann 	err = usb_submit_urb(urb, GFP_ATOMIC);
12589d08f504SMarcel Holtmann 	if (err < 0) {
12599d08f504SMarcel Holtmann 		/* -EPERM: urb is being killed;
1260d98422cbSDerek Robson 		 * -ENODEV: device got disconnected
1261d98422cbSDerek Robson 		 */
12629d08f504SMarcel Holtmann 		if (err != -EPERM && err != -ENODEV)
12632064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
12642064ee33SMarcel Holtmann 				   urb, -err);
12659d08f504SMarcel Holtmann 		usb_unanchor_urb(urb);
12669d08f504SMarcel Holtmann 	}
12679d08f504SMarcel Holtmann }
12689d08f504SMarcel Holtmann 
12699d08f504SMarcel Holtmann static int btusb_submit_diag_urb(struct hci_dev *hdev, gfp_t mem_flags)
12709d08f504SMarcel Holtmann {
12719d08f504SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
12729d08f504SMarcel Holtmann 	struct urb *urb;
12739d08f504SMarcel Holtmann 	unsigned char *buf;
12749d08f504SMarcel Holtmann 	unsigned int pipe;
12759d08f504SMarcel Holtmann 	int err, size = HCI_MAX_FRAME_SIZE;
12769d08f504SMarcel Holtmann 
12779d08f504SMarcel Holtmann 	BT_DBG("%s", hdev->name);
12789d08f504SMarcel Holtmann 
12799d08f504SMarcel Holtmann 	if (!data->diag_rx_ep)
12809d08f504SMarcel Holtmann 		return -ENODEV;
12819d08f504SMarcel Holtmann 
12829d08f504SMarcel Holtmann 	urb = usb_alloc_urb(0, mem_flags);
12839d08f504SMarcel Holtmann 	if (!urb)
12849d08f504SMarcel Holtmann 		return -ENOMEM;
12859d08f504SMarcel Holtmann 
12869d08f504SMarcel Holtmann 	buf = kmalloc(size, mem_flags);
12879d08f504SMarcel Holtmann 	if (!buf) {
12889d08f504SMarcel Holtmann 		usb_free_urb(urb);
12899d08f504SMarcel Holtmann 		return -ENOMEM;
12909d08f504SMarcel Holtmann 	}
12919d08f504SMarcel Holtmann 
12929d08f504SMarcel Holtmann 	pipe = usb_rcvbulkpipe(data->udev, data->diag_rx_ep->bEndpointAddress);
12939d08f504SMarcel Holtmann 
12949d08f504SMarcel Holtmann 	usb_fill_bulk_urb(urb, data->udev, pipe, buf, size,
12959d08f504SMarcel Holtmann 			  btusb_diag_complete, hdev);
12969d08f504SMarcel Holtmann 
12979d08f504SMarcel Holtmann 	urb->transfer_flags |= URB_FREE_BUFFER;
12989d08f504SMarcel Holtmann 
12999d08f504SMarcel Holtmann 	usb_mark_last_busy(data->udev);
13009d08f504SMarcel Holtmann 	usb_anchor_urb(urb, &data->diag_anchor);
13019d08f504SMarcel Holtmann 
13029d08f504SMarcel Holtmann 	err = usb_submit_urb(urb, mem_flags);
13039d08f504SMarcel Holtmann 	if (err < 0) {
13049d08f504SMarcel Holtmann 		if (err != -EPERM && err != -ENODEV)
13052064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p submission failed (%d)",
13062064ee33SMarcel Holtmann 				   urb, -err);
13079d08f504SMarcel Holtmann 		usb_unanchor_urb(urb);
13089d08f504SMarcel Holtmann 	}
13099d08f504SMarcel Holtmann 
13109d08f504SMarcel Holtmann 	usb_free_urb(urb);
13119d08f504SMarcel Holtmann 
13129d08f504SMarcel Holtmann 	return err;
13139d08f504SMarcel Holtmann }
13149d08f504SMarcel Holtmann 
13155e23b923SMarcel Holtmann static void btusb_tx_complete(struct urb *urb)
13165e23b923SMarcel Holtmann {
13175e23b923SMarcel Holtmann 	struct sk_buff *skb = urb->context;
13185e23b923SMarcel Holtmann 	struct hci_dev *hdev = (struct hci_dev *)skb->dev;
1319155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
1320a5e50d5bSSebastian Andrzej Siewior 	unsigned long flags;
13217bee549eSOliver Neukum 
132289e7533dSMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
132389e7533dSMarcel Holtmann 	       urb->actual_length);
13247bee549eSOliver Neukum 
13257bee549eSOliver Neukum 	if (!test_bit(HCI_RUNNING, &hdev->flags))
13267bee549eSOliver Neukum 		goto done;
13277bee549eSOliver Neukum 
13287bee549eSOliver Neukum 	if (!urb->status)
13297bee549eSOliver Neukum 		hdev->stat.byte_tx += urb->transfer_buffer_length;
13307bee549eSOliver Neukum 	else
13317bee549eSOliver Neukum 		hdev->stat.err_tx++;
13327bee549eSOliver Neukum 
13337bee549eSOliver Neukum done:
1334a5e50d5bSSebastian Andrzej Siewior 	spin_lock_irqsave(&data->txlock, flags);
13357bee549eSOliver Neukum 	data->tx_in_flight--;
1336a5e50d5bSSebastian Andrzej Siewior 	spin_unlock_irqrestore(&data->txlock, flags);
13377bee549eSOliver Neukum 
13387bee549eSOliver Neukum 	kfree(urb->setup_packet);
13397bee549eSOliver Neukum 
13407bee549eSOliver Neukum 	kfree_skb(skb);
13417bee549eSOliver Neukum }
13427bee549eSOliver Neukum 
13437bee549eSOliver Neukum static void btusb_isoc_tx_complete(struct urb *urb)
13447bee549eSOliver Neukum {
13457bee549eSOliver Neukum 	struct sk_buff *skb = urb->context;
13467bee549eSOliver Neukum 	struct hci_dev *hdev = (struct hci_dev *)skb->dev;
13475e23b923SMarcel Holtmann 
134889e7533dSMarcel Holtmann 	BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
134989e7533dSMarcel Holtmann 	       urb->actual_length);
13505e23b923SMarcel Holtmann 
13515e23b923SMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
13525e23b923SMarcel Holtmann 		goto done;
13535e23b923SMarcel Holtmann 
13545e23b923SMarcel Holtmann 	if (!urb->status)
13555e23b923SMarcel Holtmann 		hdev->stat.byte_tx += urb->transfer_buffer_length;
13565e23b923SMarcel Holtmann 	else
13575e23b923SMarcel Holtmann 		hdev->stat.err_tx++;
13585e23b923SMarcel Holtmann 
13595e23b923SMarcel Holtmann done:
13605e23b923SMarcel Holtmann 	kfree(urb->setup_packet);
13615e23b923SMarcel Holtmann 
13625e23b923SMarcel Holtmann 	kfree_skb(skb);
13635e23b923SMarcel Holtmann }
13645e23b923SMarcel Holtmann 
13655e23b923SMarcel Holtmann static int btusb_open(struct hci_dev *hdev)
13665e23b923SMarcel Holtmann {
1367155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
13685e23b923SMarcel Holtmann 	int err;
13695e23b923SMarcel Holtmann 
13705e23b923SMarcel Holtmann 	BT_DBG("%s", hdev->name);
13715e23b923SMarcel Holtmann 
1372c7e163feSEthan Hsieh 	err = usb_autopm_get_interface(data->intf);
1373c7e163feSEthan Hsieh 	if (err < 0)
1374c7e163feSEthan Hsieh 		return err;
1375c7e163feSEthan Hsieh 
1376ace31982SKim, Ben Young Tae 	/* Patching USB firmware files prior to starting any URBs of HCI path
1377ace31982SKim, Ben Young Tae 	 * It is more safe to use USB bulk channel for downloading USB patch
1378ace31982SKim, Ben Young Tae 	 */
1379ace31982SKim, Ben Young Tae 	if (data->setup_on_usb) {
1380ace31982SKim, Ben Young Tae 		err = data->setup_on_usb(hdev);
1381ace31982SKim, Ben Young Tae 		if (err < 0)
13823d44a6fdSOliver Neukum 			goto setup_fail;
1383ace31982SKim, Ben Young Tae 	}
1384ace31982SKim, Ben Young Tae 
13857bee549eSOliver Neukum 	data->intf->needs_remote_wakeup = 1;
13867bee549eSOliver Neukum 
13875e23b923SMarcel Holtmann 	if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
13887bee549eSOliver Neukum 		goto done;
13895e23b923SMarcel Holtmann 
13902eda66f4SMarcel Holtmann 	err = btusb_submit_intr_urb(hdev, GFP_KERNEL);
139143c2e57fSMarcel Holtmann 	if (err < 0)
139243c2e57fSMarcel Holtmann 		goto failed;
139343c2e57fSMarcel Holtmann 
139443c2e57fSMarcel Holtmann 	err = btusb_submit_bulk_urb(hdev, GFP_KERNEL);
13955e23b923SMarcel Holtmann 	if (err < 0) {
139643c2e57fSMarcel Holtmann 		usb_kill_anchored_urbs(&data->intr_anchor);
139743c2e57fSMarcel Holtmann 		goto failed;
13985e23b923SMarcel Holtmann 	}
13995e23b923SMarcel Holtmann 
140043c2e57fSMarcel Holtmann 	set_bit(BTUSB_BULK_RUNNING, &data->flags);
140143c2e57fSMarcel Holtmann 	btusb_submit_bulk_urb(hdev, GFP_KERNEL);
140243c2e57fSMarcel Holtmann 
14039d08f504SMarcel Holtmann 	if (data->diag) {
14049d08f504SMarcel Holtmann 		if (!btusb_submit_diag_urb(hdev, GFP_KERNEL))
14059d08f504SMarcel Holtmann 			set_bit(BTUSB_DIAG_RUNNING, &data->flags);
14069d08f504SMarcel Holtmann 	}
14079d08f504SMarcel Holtmann 
14087bee549eSOliver Neukum done:
14097bee549eSOliver Neukum 	usb_autopm_put_interface(data->intf);
141043c2e57fSMarcel Holtmann 	return 0;
141143c2e57fSMarcel Holtmann 
141243c2e57fSMarcel Holtmann failed:
141343c2e57fSMarcel Holtmann 	clear_bit(BTUSB_INTR_RUNNING, &data->flags);
14143d44a6fdSOliver Neukum setup_fail:
14157bee549eSOliver Neukum 	usb_autopm_put_interface(data->intf);
14165e23b923SMarcel Holtmann 	return err;
14175e23b923SMarcel Holtmann }
14185e23b923SMarcel Holtmann 
14197bee549eSOliver Neukum static void btusb_stop_traffic(struct btusb_data *data)
14207bee549eSOliver Neukum {
14217bee549eSOliver Neukum 	usb_kill_anchored_urbs(&data->intr_anchor);
14227bee549eSOliver Neukum 	usb_kill_anchored_urbs(&data->bulk_anchor);
14237bee549eSOliver Neukum 	usb_kill_anchored_urbs(&data->isoc_anchor);
14249d08f504SMarcel Holtmann 	usb_kill_anchored_urbs(&data->diag_anchor);
1425a1c49c43SSean Wang 	usb_kill_anchored_urbs(&data->ctrl_anchor);
14267bee549eSOliver Neukum }
14277bee549eSOliver Neukum 
14285e23b923SMarcel Holtmann static int btusb_close(struct hci_dev *hdev)
14295e23b923SMarcel Holtmann {
1430155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
14317bee549eSOliver Neukum 	int err;
14325e23b923SMarcel Holtmann 
14335e23b923SMarcel Holtmann 	BT_DBG("%s", hdev->name);
14345e23b923SMarcel Holtmann 
1435e8c3c3d2SMarcel Holtmann 	cancel_work_sync(&data->work);
1436404291acSLinus Torvalds 	cancel_work_sync(&data->waker);
1437e8c3c3d2SMarcel Holtmann 
14389bfa35feSMarcel Holtmann 	clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
14395e23b923SMarcel Holtmann 	clear_bit(BTUSB_BULK_RUNNING, &data->flags);
14405e23b923SMarcel Holtmann 	clear_bit(BTUSB_INTR_RUNNING, &data->flags);
14419d08f504SMarcel Holtmann 	clear_bit(BTUSB_DIAG_RUNNING, &data->flags);
14427bee549eSOliver Neukum 
14437bee549eSOliver Neukum 	btusb_stop_traffic(data);
1444803b5836SMarcel Holtmann 	btusb_free_frags(data);
1445803b5836SMarcel Holtmann 
14467bee549eSOliver Neukum 	err = usb_autopm_get_interface(data->intf);
14477bee549eSOliver Neukum 	if (err < 0)
14487b8e2c1dSOliver Neukum 		goto failed;
14497bee549eSOliver Neukum 
14507bee549eSOliver Neukum 	data->intf->needs_remote_wakeup = 0;
14519e45524aSAlex Lu 
14529e45524aSAlex Lu 	/* Enable remote wake up for auto-suspend */
14538274db07SMax Chou 	if (test_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags))
14549e45524aSAlex Lu 		data->intf->needs_remote_wakeup = 1;
14559e45524aSAlex Lu 
14567bee549eSOliver Neukum 	usb_autopm_put_interface(data->intf);
14575e23b923SMarcel Holtmann 
14587b8e2c1dSOliver Neukum failed:
14597b8e2c1dSOliver Neukum 	usb_scuttle_anchored_urbs(&data->deferred);
14605e23b923SMarcel Holtmann 	return 0;
14615e23b923SMarcel Holtmann }
14625e23b923SMarcel Holtmann 
14635e23b923SMarcel Holtmann static int btusb_flush(struct hci_dev *hdev)
14645e23b923SMarcel Holtmann {
1465155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
14665e23b923SMarcel Holtmann 
14675e23b923SMarcel Holtmann 	BT_DBG("%s", hdev->name);
14685e23b923SMarcel Holtmann 
14695e23b923SMarcel Holtmann 	usb_kill_anchored_urbs(&data->tx_anchor);
1470803b5836SMarcel Holtmann 	btusb_free_frags(data);
14715e23b923SMarcel Holtmann 
14725e23b923SMarcel Holtmann 	return 0;
14735e23b923SMarcel Holtmann }
14745e23b923SMarcel Holtmann 
1475047b2ec8SMarcel Holtmann static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb)
14765e23b923SMarcel Holtmann {
1477155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
14785e23b923SMarcel Holtmann 	struct usb_ctrlrequest *dr;
14795e23b923SMarcel Holtmann 	struct urb *urb;
14805e23b923SMarcel Holtmann 	unsigned int pipe;
14815e23b923SMarcel Holtmann 
1482e9753effSJohan Hedberg 	urb = usb_alloc_urb(0, GFP_KERNEL);
14835e23b923SMarcel Holtmann 	if (!urb)
1484047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
14855e23b923SMarcel Holtmann 
1486e9753effSJohan Hedberg 	dr = kmalloc(sizeof(*dr), GFP_KERNEL);
14875e23b923SMarcel Holtmann 	if (!dr) {
14885e23b923SMarcel Holtmann 		usb_free_urb(urb);
1489047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
14905e23b923SMarcel Holtmann 	}
14915e23b923SMarcel Holtmann 
14927a9d4020SMarcel Holtmann 	dr->bRequestType = data->cmdreq_type;
1493893ba544SMarcel Holtmann 	dr->bRequest     = data->cmdreq;
14945e23b923SMarcel Holtmann 	dr->wIndex       = 0;
14955e23b923SMarcel Holtmann 	dr->wValue       = 0;
14965e23b923SMarcel Holtmann 	dr->wLength      = __cpu_to_le16(skb->len);
14975e23b923SMarcel Holtmann 
14985e23b923SMarcel Holtmann 	pipe = usb_sndctrlpipe(data->udev, 0x00);
14995e23b923SMarcel Holtmann 
15005e23b923SMarcel Holtmann 	usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
15015e23b923SMarcel Holtmann 			     skb->data, skb->len, btusb_tx_complete, skb);
15025e23b923SMarcel Holtmann 
1503047b2ec8SMarcel Holtmann 	skb->dev = (void *)hdev;
15045e23b923SMarcel Holtmann 
1505047b2ec8SMarcel Holtmann 	return urb;
1506047b2ec8SMarcel Holtmann }
1507047b2ec8SMarcel Holtmann 
1508047b2ec8SMarcel Holtmann static struct urb *alloc_bulk_urb(struct hci_dev *hdev, struct sk_buff *skb)
1509047b2ec8SMarcel Holtmann {
1510047b2ec8SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
1511047b2ec8SMarcel Holtmann 	struct urb *urb;
1512047b2ec8SMarcel Holtmann 	unsigned int pipe;
1513047b2ec8SMarcel Holtmann 
15149fd481e0SPeter Hurley 	if (!data->bulk_tx_ep)
1515047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENODEV);
15169bfa35feSMarcel Holtmann 
1517e9753effSJohan Hedberg 	urb = usb_alloc_urb(0, GFP_KERNEL);
15185e23b923SMarcel Holtmann 	if (!urb)
1519047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
15205e23b923SMarcel Holtmann 
1521047b2ec8SMarcel Holtmann 	pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
15225e23b923SMarcel Holtmann 
15235e23b923SMarcel Holtmann 	usb_fill_bulk_urb(urb, data->udev, pipe,
15245e23b923SMarcel Holtmann 			  skb->data, skb->len, btusb_tx_complete, skb);
15255e23b923SMarcel Holtmann 
1526047b2ec8SMarcel Holtmann 	skb->dev = (void *)hdev;
15275e23b923SMarcel Holtmann 
1528047b2ec8SMarcel Holtmann 	return urb;
1529047b2ec8SMarcel Holtmann }
1530047b2ec8SMarcel Holtmann 
1531047b2ec8SMarcel Holtmann static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
1532047b2ec8SMarcel Holtmann {
1533047b2ec8SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
1534047b2ec8SMarcel Holtmann 	struct urb *urb;
1535047b2ec8SMarcel Holtmann 	unsigned int pipe;
1536047b2ec8SMarcel Holtmann 
1537047b2ec8SMarcel Holtmann 	if (!data->isoc_tx_ep)
1538047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENODEV);
15399bfa35feSMarcel Holtmann 
1540e9753effSJohan Hedberg 	urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
15419bfa35feSMarcel Holtmann 	if (!urb)
1542047b2ec8SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
15439bfa35feSMarcel Holtmann 
1544047b2ec8SMarcel Holtmann 	pipe = usb_sndisocpipe(data->udev, data->isoc_tx_ep->bEndpointAddress);
15459bfa35feSMarcel Holtmann 
154603c2d0e8SGustavo F. Padovan 	usb_fill_int_urb(urb, data->udev, pipe,
154703c2d0e8SGustavo F. Padovan 			 skb->data, skb->len, btusb_isoc_tx_complete,
154803c2d0e8SGustavo F. Padovan 			 skb, data->isoc_tx_ep->bInterval);
15499bfa35feSMarcel Holtmann 
15509bfa35feSMarcel Holtmann 	urb->transfer_flags  = URB_ISO_ASAP;
15519bfa35feSMarcel Holtmann 
1552baac6276SSathish Narasimman 	if (data->isoc_altsetting == 6)
1553baac6276SSathish Narasimman 		__fill_isoc_descriptor_msbc(urb, skb->len,
1554baac6276SSathish Narasimman 					    le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize),
1555baac6276SSathish Narasimman 					    data);
1556baac6276SSathish Narasimman 	else
15579bfa35feSMarcel Holtmann 		__fill_isoc_descriptor(urb, skb->len,
15589bfa35feSMarcel Holtmann 				       le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
1559047b2ec8SMarcel Holtmann 	skb->dev = (void *)hdev;
15605e23b923SMarcel Holtmann 
1561047b2ec8SMarcel Holtmann 	return urb;
15625e23b923SMarcel Holtmann }
15635e23b923SMarcel Holtmann 
1564047b2ec8SMarcel Holtmann static int submit_tx_urb(struct hci_dev *hdev, struct urb *urb)
1565047b2ec8SMarcel Holtmann {
1566047b2ec8SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
1567047b2ec8SMarcel Holtmann 	int err;
15687bee549eSOliver Neukum 
15695e23b923SMarcel Holtmann 	usb_anchor_urb(urb, &data->tx_anchor);
15705e23b923SMarcel Holtmann 
1571e9753effSJohan Hedberg 	err = usb_submit_urb(urb, GFP_KERNEL);
15725e23b923SMarcel Holtmann 	if (err < 0) {
15735a9b80e2SPaul Bolle 		if (err != -EPERM && err != -ENODEV)
15742064ee33SMarcel Holtmann 			bt_dev_err(hdev, "urb %p submission failed (%d)",
15752064ee33SMarcel Holtmann 				   urb, -err);
15765e23b923SMarcel Holtmann 		kfree(urb->setup_packet);
15775e23b923SMarcel Holtmann 		usb_unanchor_urb(urb);
15787bee549eSOliver Neukum 	} else {
15797bee549eSOliver Neukum 		usb_mark_last_busy(data->udev);
15805e23b923SMarcel Holtmann 	}
15815e23b923SMarcel Holtmann 
158254a8a79cSCong Wang 	usb_free_urb(urb);
15835e23b923SMarcel Holtmann 	return err;
15845e23b923SMarcel Holtmann }
15855e23b923SMarcel Holtmann 
1586047b2ec8SMarcel Holtmann static int submit_or_queue_tx_urb(struct hci_dev *hdev, struct urb *urb)
1587047b2ec8SMarcel Holtmann {
1588047b2ec8SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
1589047b2ec8SMarcel Holtmann 	unsigned long flags;
1590047b2ec8SMarcel Holtmann 	bool suspending;
1591047b2ec8SMarcel Holtmann 
1592047b2ec8SMarcel Holtmann 	spin_lock_irqsave(&data->txlock, flags);
1593047b2ec8SMarcel Holtmann 	suspending = test_bit(BTUSB_SUSPENDING, &data->flags);
1594047b2ec8SMarcel Holtmann 	if (!suspending)
1595047b2ec8SMarcel Holtmann 		data->tx_in_flight++;
1596047b2ec8SMarcel Holtmann 	spin_unlock_irqrestore(&data->txlock, flags);
1597047b2ec8SMarcel Holtmann 
1598047b2ec8SMarcel Holtmann 	if (!suspending)
1599047b2ec8SMarcel Holtmann 		return submit_tx_urb(hdev, urb);
1600047b2ec8SMarcel Holtmann 
1601047b2ec8SMarcel Holtmann 	usb_anchor_urb(urb, &data->deferred);
1602047b2ec8SMarcel Holtmann 	schedule_work(&data->waker);
1603047b2ec8SMarcel Holtmann 
1604047b2ec8SMarcel Holtmann 	usb_free_urb(urb);
1605047b2ec8SMarcel Holtmann 	return 0;
1606047b2ec8SMarcel Holtmann }
1607047b2ec8SMarcel Holtmann 
1608047b2ec8SMarcel Holtmann static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
1609047b2ec8SMarcel Holtmann {
1610047b2ec8SMarcel Holtmann 	struct urb *urb;
1611047b2ec8SMarcel Holtmann 
1612047b2ec8SMarcel Holtmann 	BT_DBG("%s", hdev->name);
1613047b2ec8SMarcel Holtmann 
1614618e8bc2SMarcel Holtmann 	switch (hci_skb_pkt_type(skb)) {
1615047b2ec8SMarcel Holtmann 	case HCI_COMMAND_PKT:
1616047b2ec8SMarcel Holtmann 		urb = alloc_ctrl_urb(hdev, skb);
1617047b2ec8SMarcel Holtmann 		if (IS_ERR(urb))
1618047b2ec8SMarcel Holtmann 			return PTR_ERR(urb);
1619047b2ec8SMarcel Holtmann 
1620047b2ec8SMarcel Holtmann 		hdev->stat.cmd_tx++;
1621047b2ec8SMarcel Holtmann 		return submit_or_queue_tx_urb(hdev, urb);
1622047b2ec8SMarcel Holtmann 
1623047b2ec8SMarcel Holtmann 	case HCI_ACLDATA_PKT:
1624047b2ec8SMarcel Holtmann 		urb = alloc_bulk_urb(hdev, skb);
1625047b2ec8SMarcel Holtmann 		if (IS_ERR(urb))
1626047b2ec8SMarcel Holtmann 			return PTR_ERR(urb);
1627047b2ec8SMarcel Holtmann 
1628047b2ec8SMarcel Holtmann 		hdev->stat.acl_tx++;
1629047b2ec8SMarcel Holtmann 		return submit_or_queue_tx_urb(hdev, urb);
1630047b2ec8SMarcel Holtmann 
1631047b2ec8SMarcel Holtmann 	case HCI_SCODATA_PKT:
1632047b2ec8SMarcel Holtmann 		if (hci_conn_num(hdev, SCO_LINK) < 1)
1633047b2ec8SMarcel Holtmann 			return -ENODEV;
1634047b2ec8SMarcel Holtmann 
1635047b2ec8SMarcel Holtmann 		urb = alloc_isoc_urb(hdev, skb);
1636047b2ec8SMarcel Holtmann 		if (IS_ERR(urb))
1637047b2ec8SMarcel Holtmann 			return PTR_ERR(urb);
1638047b2ec8SMarcel Holtmann 
1639047b2ec8SMarcel Holtmann 		hdev->stat.sco_tx++;
1640047b2ec8SMarcel Holtmann 		return submit_tx_urb(hdev, urb);
1641047b2ec8SMarcel Holtmann 	}
1642047b2ec8SMarcel Holtmann 
1643047b2ec8SMarcel Holtmann 	return -EILSEQ;
1644047b2ec8SMarcel Holtmann }
1645047b2ec8SMarcel Holtmann 
16465e23b923SMarcel Holtmann static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
16475e23b923SMarcel Holtmann {
1648155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
16495e23b923SMarcel Holtmann 
16505e23b923SMarcel Holtmann 	BT_DBG("%s evt %d", hdev->name, evt);
16515e23b923SMarcel Holtmann 
1652014f7bc7SMarcel Holtmann 	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
1653014f7bc7SMarcel Holtmann 		data->sco_num = hci_conn_num(hdev, SCO_LINK);
1654baac6276SSathish Narasimman 		data->air_mode = evt;
16555e23b923SMarcel Holtmann 		schedule_work(&data->work);
16565e23b923SMarcel Holtmann 	}
165743c2e57fSMarcel Holtmann }
16585e23b923SMarcel Holtmann 
165942b16b3fSJesper Juhl static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
16609bfa35feSMarcel Holtmann {
1661155961e8SDavid Herrmann 	struct btusb_data *data = hci_get_drvdata(hdev);
16629bfa35feSMarcel Holtmann 	struct usb_interface *intf = data->isoc;
16639bfa35feSMarcel Holtmann 	struct usb_endpoint_descriptor *ep_desc;
16649bfa35feSMarcel Holtmann 	int i, err;
16659bfa35feSMarcel Holtmann 
16669bfa35feSMarcel Holtmann 	if (!data->isoc)
16679bfa35feSMarcel Holtmann 		return -ENODEV;
16689bfa35feSMarcel Holtmann 
1669459232fcSMarcel Holtmann 	err = usb_set_interface(data->udev, data->isoc_ifnum, altsetting);
16709bfa35feSMarcel Holtmann 	if (err < 0) {
16712064ee33SMarcel Holtmann 		bt_dev_err(hdev, "setting interface failed (%d)", -err);
16729bfa35feSMarcel Holtmann 		return err;
16739bfa35feSMarcel Holtmann 	}
16749bfa35feSMarcel Holtmann 
16759bfa35feSMarcel Holtmann 	data->isoc_altsetting = altsetting;
16769bfa35feSMarcel Holtmann 
16779bfa35feSMarcel Holtmann 	data->isoc_tx_ep = NULL;
16789bfa35feSMarcel Holtmann 	data->isoc_rx_ep = NULL;
16799bfa35feSMarcel Holtmann 
16809bfa35feSMarcel Holtmann 	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
16819bfa35feSMarcel Holtmann 		ep_desc = &intf->cur_altsetting->endpoint[i].desc;
16829bfa35feSMarcel Holtmann 
16839bfa35feSMarcel Holtmann 		if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) {
16849bfa35feSMarcel Holtmann 			data->isoc_tx_ep = ep_desc;
16859bfa35feSMarcel Holtmann 			continue;
16869bfa35feSMarcel Holtmann 		}
16879bfa35feSMarcel Holtmann 
16889bfa35feSMarcel Holtmann 		if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) {
16899bfa35feSMarcel Holtmann 			data->isoc_rx_ep = ep_desc;
16909bfa35feSMarcel Holtmann 			continue;
16919bfa35feSMarcel Holtmann 		}
16929bfa35feSMarcel Holtmann 	}
16939bfa35feSMarcel Holtmann 
16949bfa35feSMarcel Holtmann 	if (!data->isoc_tx_ep || !data->isoc_rx_ep) {
16952064ee33SMarcel Holtmann 		bt_dev_err(hdev, "invalid SCO descriptors");
16969bfa35feSMarcel Holtmann 		return -ENODEV;
16979bfa35feSMarcel Holtmann 	}
16989bfa35feSMarcel Holtmann 
16999bfa35feSMarcel Holtmann 	return 0;
17009bfa35feSMarcel Holtmann }
17019bfa35feSMarcel Holtmann 
1702baac6276SSathish Narasimman static int btusb_switch_alt_setting(struct hci_dev *hdev, int new_alts)
17035e23b923SMarcel Holtmann {
1704baac6276SSathish Narasimman 	struct btusb_data *data = hci_get_drvdata(hdev);
17057bee549eSOliver Neukum 	int err;
17065e23b923SMarcel Holtmann 
1707f4001d28SMikel Astiz 	if (data->isoc_altsetting != new_alts) {
1708f6fc86f2SKuba Pawlak 		unsigned long flags;
1709f6fc86f2SKuba Pawlak 
17109bfa35feSMarcel Holtmann 		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
17119bfa35feSMarcel Holtmann 		usb_kill_anchored_urbs(&data->isoc_anchor);
17129bfa35feSMarcel Holtmann 
17138f9d02f4SKuba Pawlak 		/* When isochronous alternate setting needs to be
17148f9d02f4SKuba Pawlak 		 * changed, because SCO connection has been added
17158f9d02f4SKuba Pawlak 		 * or removed, a packet fragment may be left in the
17168f9d02f4SKuba Pawlak 		 * reassembling state. This could lead to wrongly
17178f9d02f4SKuba Pawlak 		 * assembled fragments.
17188f9d02f4SKuba Pawlak 		 *
17198f9d02f4SKuba Pawlak 		 * Clear outstanding fragment when selecting a new
17208f9d02f4SKuba Pawlak 		 * alternate setting.
17218f9d02f4SKuba Pawlak 		 */
1722f6fc86f2SKuba Pawlak 		spin_lock_irqsave(&data->rxlock, flags);
17238f9d02f4SKuba Pawlak 		kfree_skb(data->sco_skb);
17248f9d02f4SKuba Pawlak 		data->sco_skb = NULL;
1725f6fc86f2SKuba Pawlak 		spin_unlock_irqrestore(&data->rxlock, flags);
17268f9d02f4SKuba Pawlak 
1727baac6276SSathish Narasimman 		err = __set_isoc_interface(hdev, new_alts);
1728baac6276SSathish Narasimman 		if (err < 0)
1729baac6276SSathish Narasimman 			return err;
17309bfa35feSMarcel Holtmann 	}
17319bfa35feSMarcel Holtmann 
17329bfa35feSMarcel Holtmann 	if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
17332eda66f4SMarcel Holtmann 		if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
17349bfa35feSMarcel Holtmann 			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
17359bfa35feSMarcel Holtmann 		else
17362eda66f4SMarcel Holtmann 			btusb_submit_isoc_urb(hdev, GFP_KERNEL);
17379bfa35feSMarcel Holtmann 	}
1738baac6276SSathish Narasimman 
1739baac6276SSathish Narasimman 	return 0;
1740baac6276SSathish Narasimman }
1741baac6276SSathish Narasimman 
1742baac6276SSathish Narasimman static struct usb_host_interface *btusb_find_altsetting(struct btusb_data *data,
1743baac6276SSathish Narasimman 							int alt)
1744baac6276SSathish Narasimman {
1745baac6276SSathish Narasimman 	struct usb_interface *intf = data->isoc;
1746baac6276SSathish Narasimman 	int i;
1747baac6276SSathish Narasimman 
1748baac6276SSathish Narasimman 	BT_DBG("Looking for Alt no :%d", alt);
1749baac6276SSathish Narasimman 
1750fcd156eeSSathish Narasimman 	if (!intf)
1751fcd156eeSSathish Narasimman 		return NULL;
1752fcd156eeSSathish Narasimman 
1753baac6276SSathish Narasimman 	for (i = 0; i < intf->num_altsetting; i++) {
1754baac6276SSathish Narasimman 		if (intf->altsetting[i].desc.bAlternateSetting == alt)
1755baac6276SSathish Narasimman 			return &intf->altsetting[i];
1756baac6276SSathish Narasimman 	}
1757baac6276SSathish Narasimman 
1758baac6276SSathish Narasimman 	return NULL;
1759baac6276SSathish Narasimman }
1760baac6276SSathish Narasimman 
1761baac6276SSathish Narasimman static void btusb_work(struct work_struct *work)
1762baac6276SSathish Narasimman {
1763baac6276SSathish Narasimman 	struct btusb_data *data = container_of(work, struct btusb_data, work);
1764baac6276SSathish Narasimman 	struct hci_dev *hdev = data->hdev;
1765baac6276SSathish Narasimman 	int new_alts = 0;
1766baac6276SSathish Narasimman 	int err;
1767baac6276SSathish Narasimman 
1768baac6276SSathish Narasimman 	if (data->sco_num > 0) {
1769baac6276SSathish Narasimman 		if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
1770baac6276SSathish Narasimman 			err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf);
1771baac6276SSathish Narasimman 			if (err < 0) {
1772baac6276SSathish Narasimman 				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
1773baac6276SSathish Narasimman 				usb_kill_anchored_urbs(&data->isoc_anchor);
1774baac6276SSathish Narasimman 				return;
1775baac6276SSathish Narasimman 			}
1776baac6276SSathish Narasimman 
1777baac6276SSathish Narasimman 			set_bit(BTUSB_DID_ISO_RESUME, &data->flags);
1778baac6276SSathish Narasimman 		}
1779baac6276SSathish Narasimman 
1780baac6276SSathish Narasimman 		if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) {
1781baac6276SSathish Narasimman 			if (hdev->voice_setting & 0x0020) {
1782baac6276SSathish Narasimman 				static const int alts[3] = { 2, 4, 5 };
1783baac6276SSathish Narasimman 
1784baac6276SSathish Narasimman 				new_alts = alts[data->sco_num - 1];
1785baac6276SSathish Narasimman 			} else {
1786baac6276SSathish Narasimman 				new_alts = data->sco_num;
1787baac6276SSathish Narasimman 			}
1788baac6276SSathish Narasimman 		} else if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_TRANSP) {
1789517b6933STrent Piepho 			/* Bluetooth USB spec recommends alt 6 (63 bytes), but
1790517b6933STrent Piepho 			 * many adapters do not support it.  Alt 1 appears to
1791517b6933STrent Piepho 			 * work for all adapters that do not have alt 6, and
179255981d35SPauli Virtanen 			 * which work with WBS at all.  Some devices prefer
179355981d35SPauli Virtanen 			 * alt 3 (HCI payload >= 60 Bytes let air packet
179455981d35SPauli Virtanen 			 * data satisfy 60 bytes), requiring
179555981d35SPauli Virtanen 			 * MTU >= 3 (packets) * 25 (size) - 3 (headers) = 72
179655981d35SPauli Virtanen 			 * see also Core spec 5, vol 4, B 2.1.1 & Table 2.1.
1797517b6933STrent Piepho 			 */
179855981d35SPauli Virtanen 			if (btusb_find_altsetting(data, 6))
179955981d35SPauli Virtanen 				new_alts = 6;
180055981d35SPauli Virtanen 			else if (btusb_find_altsetting(data, 3) &&
180155981d35SPauli Virtanen 				 hdev->sco_mtu >= 72 &&
180255981d35SPauli Virtanen 				 test_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags))
1803e848dbd3SHilda Wu 				new_alts = 3;
180455981d35SPauli Virtanen 			else
180555981d35SPauli Virtanen 				new_alts = 1;
1806461f95f0SHilda Wu 		}
1807baac6276SSathish Narasimman 
1808baac6276SSathish Narasimman 		if (btusb_switch_alt_setting(hdev, new_alts) < 0)
1809baac6276SSathish Narasimman 			bt_dev_err(hdev, "set USB alt:(%d) failed!", new_alts);
18109bfa35feSMarcel Holtmann 	} else {
18119bfa35feSMarcel Holtmann 		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
18129bfa35feSMarcel Holtmann 		usb_kill_anchored_urbs(&data->isoc_anchor);
18139bfa35feSMarcel Holtmann 
18149bfa35feSMarcel Holtmann 		__set_isoc_interface(hdev, 0);
181508b8b6c4SGustavo F. Padovan 		if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
18168efdd0cdSOliver Neukum 			usb_autopm_put_interface(data->isoc ? data->isoc : data->intf);
18179bfa35feSMarcel Holtmann 	}
18185e23b923SMarcel Holtmann }
18197bee549eSOliver Neukum 
18207bee549eSOliver Neukum static void btusb_waker(struct work_struct *work)
18217bee549eSOliver Neukum {
18227bee549eSOliver Neukum 	struct btusb_data *data = container_of(work, struct btusb_data, waker);
18237bee549eSOliver Neukum 	int err;
18247bee549eSOliver Neukum 
18257bee549eSOliver Neukum 	err = usb_autopm_get_interface(data->intf);
18267bee549eSOliver Neukum 	if (err < 0)
18277bee549eSOliver Neukum 		return;
18287bee549eSOliver Neukum 
18297bee549eSOliver Neukum 	usb_autopm_put_interface(data->intf);
18307bee549eSOliver Neukum }
18315e23b923SMarcel Holtmann 
18329f8f962cSMarcel Holtmann static int btusb_setup_bcm92035(struct hci_dev *hdev)
18339f8f962cSMarcel Holtmann {
18349f8f962cSMarcel Holtmann 	struct sk_buff *skb;
18359f8f962cSMarcel Holtmann 	u8 val = 0x00;
18369f8f962cSMarcel Holtmann 
18379f8f962cSMarcel Holtmann 	BT_DBG("%s", hdev->name);
18389f8f962cSMarcel Holtmann 
18399f8f962cSMarcel Holtmann 	skb = __hci_cmd_sync(hdev, 0xfc3b, 1, &val, HCI_INIT_TIMEOUT);
18409f8f962cSMarcel Holtmann 	if (IS_ERR(skb))
18412064ee33SMarcel Holtmann 		bt_dev_err(hdev, "BCM92035 command failed (%ld)", PTR_ERR(skb));
18429f8f962cSMarcel Holtmann 	else
18439f8f962cSMarcel Holtmann 		kfree_skb(skb);
18449f8f962cSMarcel Holtmann 
18459f8f962cSMarcel Holtmann 	return 0;
18469f8f962cSMarcel Holtmann }
18479f8f962cSMarcel Holtmann 
184881cac64bSMarcel Holtmann static int btusb_setup_csr(struct hci_dev *hdev)
184981cac64bSMarcel Holtmann {
1850d74e0ae7SHans de Goede 	struct btusb_data *data = hci_get_drvdata(hdev);
1851d74e0ae7SHans de Goede 	u16 bcdDevice = le16_to_cpu(data->udev->descriptor.bcdDevice);
185281cac64bSMarcel Holtmann 	struct hci_rp_read_local_version *rp;
185381cac64bSMarcel Holtmann 	struct sk_buff *skb;
1854cde1a8a9SIsmael Ferreras Morezuelas 	bool is_fake = false;
18550671c066SHans de Goede 	int ret;
185681cac64bSMarcel Holtmann 
185781cac64bSMarcel Holtmann 	BT_DBG("%s", hdev->name);
185881cac64bSMarcel Holtmann 
18597cd84d72SMarcel Holtmann 	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
18607cd84d72SMarcel Holtmann 			     HCI_INIT_TIMEOUT);
18617cd84d72SMarcel Holtmann 	if (IS_ERR(skb)) {
18627cd84d72SMarcel Holtmann 		int err = PTR_ERR(skb);
18632064ee33SMarcel Holtmann 		bt_dev_err(hdev, "CSR: Local version failed (%d)", err);
18647cd84d72SMarcel Holtmann 		return err;
18657cd84d72SMarcel Holtmann 	}
18667cd84d72SMarcel Holtmann 
18677cd84d72SMarcel Holtmann 	if (skb->len != sizeof(struct hci_rp_read_local_version)) {
18682064ee33SMarcel Holtmann 		bt_dev_err(hdev, "CSR: Local version length mismatch");
18697cd84d72SMarcel Holtmann 		kfree_skb(skb);
18707cd84d72SMarcel Holtmann 		return -EIO;
18717cd84d72SMarcel Holtmann 	}
187281cac64bSMarcel Holtmann 
187381cac64bSMarcel Holtmann 	rp = (struct hci_rp_read_local_version *)skb->data;
187481cac64bSMarcel Holtmann 
1875cde1a8a9SIsmael Ferreras Morezuelas 	/* Detect a wide host of Chinese controllers that aren't CSR.
1876cde1a8a9SIsmael Ferreras Morezuelas 	 *
1877cde1a8a9SIsmael Ferreras Morezuelas 	 * Known fake bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
1878cde1a8a9SIsmael Ferreras Morezuelas 	 *
1879cde1a8a9SIsmael Ferreras Morezuelas 	 * The main thing they have in common is that these are really popular low-cost
1880cde1a8a9SIsmael Ferreras Morezuelas 	 * options that support newer Bluetooth versions but rely on heavy VID/PID
1881cde1a8a9SIsmael Ferreras Morezuelas 	 * squatting of this poor old Bluetooth 1.1 device. Even sold as such.
1882cde1a8a9SIsmael Ferreras Morezuelas 	 *
1883cde1a8a9SIsmael Ferreras Morezuelas 	 * We detect actual CSR devices by checking that the HCI manufacturer code
1884cde1a8a9SIsmael Ferreras Morezuelas 	 * is Cambridge Silicon Radio (10) and ensuring that LMP sub-version and
1885cde1a8a9SIsmael Ferreras Morezuelas 	 * HCI rev values always match. As they both store the firmware number.
1886cde1a8a9SIsmael Ferreras Morezuelas 	 */
18876cafcd95SJohan Hedberg 	if (le16_to_cpu(rp->manufacturer) != 10 ||
1888cde1a8a9SIsmael Ferreras Morezuelas 	    le16_to_cpu(rp->hci_rev) != le16_to_cpu(rp->lmp_subver))
1889cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
1890cde1a8a9SIsmael Ferreras Morezuelas 
1891cde1a8a9SIsmael Ferreras Morezuelas 	/* Known legit CSR firmware build numbers and their supported BT versions:
1892cde1a8a9SIsmael Ferreras Morezuelas 	 * - 1.1 (0x1) -> 0x0073, 0x020d, 0x033c, 0x034e
1893cde1a8a9SIsmael Ferreras Morezuelas 	 * - 1.2 (0x2) ->                 0x04d9, 0x0529
1894cde1a8a9SIsmael Ferreras Morezuelas 	 * - 2.0 (0x3) ->         0x07a6, 0x07ad, 0x0c5c
1895cde1a8a9SIsmael Ferreras Morezuelas 	 * - 2.1 (0x4) ->         0x149c, 0x1735, 0x1899 (0x1899 is a BlueCore4-External)
1896cde1a8a9SIsmael Ferreras Morezuelas 	 * - 4.0 (0x6) ->         0x1d86, 0x2031, 0x22bb
1897cde1a8a9SIsmael Ferreras Morezuelas 	 *
1898cde1a8a9SIsmael Ferreras Morezuelas 	 * e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
1899cde1a8a9SIsmael Ferreras Morezuelas 	 *      support BT 1.1 only; so it's a dead giveaway when some
1900cde1a8a9SIsmael Ferreras Morezuelas 	 *      third-party BT 4.0 dongle reuses it.
1901cde1a8a9SIsmael Ferreras Morezuelas 	 */
1902cde1a8a9SIsmael Ferreras Morezuelas 	else if (le16_to_cpu(rp->lmp_subver) <= 0x034e &&
1903cde1a8a9SIsmael Ferreras Morezuelas 		 le16_to_cpu(rp->hci_ver) > BLUETOOTH_VER_1_1)
1904cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
1905cde1a8a9SIsmael Ferreras Morezuelas 
1906cde1a8a9SIsmael Ferreras Morezuelas 	else if (le16_to_cpu(rp->lmp_subver) <= 0x0529 &&
1907cde1a8a9SIsmael Ferreras Morezuelas 		 le16_to_cpu(rp->hci_ver) > BLUETOOTH_VER_1_2)
1908cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
1909cde1a8a9SIsmael Ferreras Morezuelas 
1910cde1a8a9SIsmael Ferreras Morezuelas 	else if (le16_to_cpu(rp->lmp_subver) <= 0x0c5c &&
1911cde1a8a9SIsmael Ferreras Morezuelas 		 le16_to_cpu(rp->hci_ver) > BLUETOOTH_VER_2_0)
1912cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
1913cde1a8a9SIsmael Ferreras Morezuelas 
1914cde1a8a9SIsmael Ferreras Morezuelas 	else if (le16_to_cpu(rp->lmp_subver) <= 0x1899 &&
1915cde1a8a9SIsmael Ferreras Morezuelas 		 le16_to_cpu(rp->hci_ver) > BLUETOOTH_VER_2_1)
1916cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
1917cde1a8a9SIsmael Ferreras Morezuelas 
1918cde1a8a9SIsmael Ferreras Morezuelas 	else if (le16_to_cpu(rp->lmp_subver) <= 0x22bb &&
1919cde1a8a9SIsmael Ferreras Morezuelas 		 le16_to_cpu(rp->hci_ver) > BLUETOOTH_VER_4_0)
1920cde1a8a9SIsmael Ferreras Morezuelas 		is_fake = true;
1921cde1a8a9SIsmael Ferreras Morezuelas 
1922d74e0ae7SHans de Goede 	/* Other clones which beat all the above checks */
1923d74e0ae7SHans de Goede 	else if (bcdDevice == 0x0134 &&
1924d74e0ae7SHans de Goede 		 le16_to_cpu(rp->lmp_subver) == 0x0c5c &&
1925d74e0ae7SHans de Goede 		 le16_to_cpu(rp->hci_ver) == BLUETOOTH_VER_2_0)
1926d74e0ae7SHans de Goede 		is_fake = true;
1927d74e0ae7SHans de Goede 
1928cde1a8a9SIsmael Ferreras Morezuelas 	if (is_fake) {
1929f4292e2fSIsmael Ferreras Morezuelas 		bt_dev_warn(hdev, "CSR: Unbranded CSR clone detected; adding workarounds and force-suspending once...");
1930cde1a8a9SIsmael Ferreras Morezuelas 
1931cde1a8a9SIsmael Ferreras Morezuelas 		/* Generally these clones have big discrepancies between
1932cde1a8a9SIsmael Ferreras Morezuelas 		 * advertised features and what's actually supported.
1933cde1a8a9SIsmael Ferreras Morezuelas 		 * Probably will need to be expanded in the future;
1934cde1a8a9SIsmael Ferreras Morezuelas 		 * without these the controller will lock up.
1935cde1a8a9SIsmael Ferreras Morezuelas 		 */
1936cde1a8a9SIsmael Ferreras Morezuelas 		set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
1937cde1a8a9SIsmael Ferreras Morezuelas 		set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
1938cde1a8a9SIsmael Ferreras Morezuelas 
193981cac64bSMarcel Holtmann 		/* Clear the reset quirk since this is not an actual
194081cac64bSMarcel Holtmann 		 * early Bluetooth 1.1 device from CSR.
194181cac64bSMarcel Holtmann 		 */
194281cac64bSMarcel Holtmann 		clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
1943cde1a8a9SIsmael Ferreras Morezuelas 		clear_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
19440671c066SHans de Goede 
19450671c066SHans de Goede 		/*
1946f4292e2fSIsmael Ferreras Morezuelas 		 * Special workaround for these BT 4.0 chip clones, and potentially more:
1947f4292e2fSIsmael Ferreras Morezuelas 		 *
1948f4292e2fSIsmael Ferreras Morezuelas 		 * - 0x0134: a Barrot 8041a02                 (HCI rev: 0x1012 sub: 0x0810)
1949f4292e2fSIsmael Ferreras Morezuelas 		 * - 0x7558: IC markings FR3191AHAL 749H15143 (HCI rev/sub-version: 0x0709)
1950f4292e2fSIsmael Ferreras Morezuelas 		 *
1951f4292e2fSIsmael Ferreras Morezuelas 		 * These controllers are really messed-up.
1952f4292e2fSIsmael Ferreras Morezuelas 		 *
1953f4292e2fSIsmael Ferreras Morezuelas 		 * 1. Their bulk RX endpoint will never report any data unless
1954f4292e2fSIsmael Ferreras Morezuelas 		 * the device was suspended at least once (yes, really).
19550671c066SHans de Goede 		 * 2. They will not wakeup when autosuspended and receiving data
1956f4292e2fSIsmael Ferreras Morezuelas 		 * on their bulk RX endpoint from e.g. a keyboard or mouse
19570671c066SHans de Goede 		 * (IOW remote-wakeup support is broken for the bulk endpoint).
19580671c066SHans de Goede 		 *
19590671c066SHans de Goede 		 * To fix 1. enable runtime-suspend, force-suspend the
1960f4292e2fSIsmael Ferreras Morezuelas 		 * HCI and then wake-it up by disabling runtime-suspend.
19610671c066SHans de Goede 		 *
1962f4292e2fSIsmael Ferreras Morezuelas 		 * To fix 2. clear the HCI's can_wake flag, this way the HCI
19630671c066SHans de Goede 		 * will still be autosuspended when it is not open.
1964f4292e2fSIsmael Ferreras Morezuelas 		 *
1965f4292e2fSIsmael Ferreras Morezuelas 		 * --
1966f4292e2fSIsmael Ferreras Morezuelas 		 *
1967f4292e2fSIsmael Ferreras Morezuelas 		 * Because these are widespread problems we prefer generic solutions; so
1968f4292e2fSIsmael Ferreras Morezuelas 		 * apply this initialization quirk to every controller that gets here,
1969f4292e2fSIsmael Ferreras Morezuelas 		 * it should be harmless. The alternative is to not work at all.
19700671c066SHans de Goede 		 */
19710671c066SHans de Goede 		pm_runtime_allow(&data->udev->dev);
19720671c066SHans de Goede 
19730671c066SHans de Goede 		ret = pm_runtime_suspend(&data->udev->dev);
19740671c066SHans de Goede 		if (ret >= 0)
19750671c066SHans de Goede 			msleep(200);
19760671c066SHans de Goede 		else
1977f4292e2fSIsmael Ferreras Morezuelas 			bt_dev_err(hdev, "CSR: Failed to suspend the device for our Barrot 8041a02 receive-issue workaround");
19780671c066SHans de Goede 
19790671c066SHans de Goede 		pm_runtime_forbid(&data->udev->dev);
19800671c066SHans de Goede 
19810671c066SHans de Goede 		device_set_wakeup_capable(&data->udev->dev, false);
1982f4292e2fSIsmael Ferreras Morezuelas 
19830671c066SHans de Goede 		/* Re-enable autosuspend if this was requested */
19840671c066SHans de Goede 		if (enable_autosuspend)
19850671c066SHans de Goede 			usb_enable_autosuspend(data->udev);
19860671c066SHans de Goede 	}
198781cac64bSMarcel Holtmann 
198881cac64bSMarcel Holtmann 	kfree_skb(skb);
198981cac64bSMarcel Holtmann 
19909641d343SMarcel Holtmann 	return 0;
199181cac64bSMarcel Holtmann }
199281cac64bSMarcel Holtmann 
1993cda0dd78SMarcel Holtmann static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode)
1994cda0dd78SMarcel Holtmann {
1995cda0dd78SMarcel Holtmann 	struct sk_buff *skb;
1996cda0dd78SMarcel Holtmann 	struct hci_event_hdr *hdr;
1997cda0dd78SMarcel Holtmann 	struct hci_ev_cmd_complete *evt;
1998cda0dd78SMarcel Holtmann 
1999cf07e341SJia-Ju Bai 	skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_KERNEL);
2000cda0dd78SMarcel Holtmann 	if (!skb)
2001cda0dd78SMarcel Holtmann 		return -ENOMEM;
2002cda0dd78SMarcel Holtmann 
20034df864c1SJohannes Berg 	hdr = skb_put(skb, sizeof(*hdr));
2004cda0dd78SMarcel Holtmann 	hdr->evt = HCI_EV_CMD_COMPLETE;
2005cda0dd78SMarcel Holtmann 	hdr->plen = sizeof(*evt) + 1;
2006cda0dd78SMarcel Holtmann 
20074df864c1SJohannes Berg 	evt = skb_put(skb, sizeof(*evt));
2008cda0dd78SMarcel Holtmann 	evt->ncmd = 0x01;
2009cda0dd78SMarcel Holtmann 	evt->opcode = cpu_to_le16(opcode);
2010cda0dd78SMarcel Holtmann 
2011634fef61SJohannes Berg 	skb_put_u8(skb, 0x00);
2012cda0dd78SMarcel Holtmann 
2013618e8bc2SMarcel Holtmann 	hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
2014cda0dd78SMarcel Holtmann 
2015cda0dd78SMarcel Holtmann 	return hci_recv_frame(hdev, skb);
2016cda0dd78SMarcel Holtmann }
2017cda0dd78SMarcel Holtmann 
2018cda0dd78SMarcel Holtmann static int btusb_recv_bulk_intel(struct btusb_data *data, void *buffer,
2019cda0dd78SMarcel Holtmann 				 int count)
2020cda0dd78SMarcel Holtmann {
2021019a1caaSTedd Ho-Jeong An 	struct hci_dev *hdev = data->hdev;
2022019a1caaSTedd Ho-Jeong An 
2023cda0dd78SMarcel Holtmann 	/* When the device is in bootloader mode, then it can send
2024cda0dd78SMarcel Holtmann 	 * events via the bulk endpoint. These events are treated the
2025cda0dd78SMarcel Holtmann 	 * same way as the ones received from the interrupt endpoint.
2026cda0dd78SMarcel Holtmann 	 */
2027019a1caaSTedd Ho-Jeong An 	if (btintel_test_flag(hdev, INTEL_BOOTLOADER))
2028cda0dd78SMarcel Holtmann 		return btusb_recv_intr(data, buffer, count);
2029cda0dd78SMarcel Holtmann 
2030cda0dd78SMarcel Holtmann 	return btusb_recv_bulk(data, buffer, count);
2031cda0dd78SMarcel Holtmann }
2032cda0dd78SMarcel Holtmann 
2033cda0dd78SMarcel Holtmann static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb)
2034cda0dd78SMarcel Holtmann {
2035019a1caaSTedd Ho-Jeong An 	if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
2036cda0dd78SMarcel Holtmann 		struct hci_event_hdr *hdr = (void *)skb->data;
2037cda0dd78SMarcel Holtmann 
2038ccd6da2aSMarcel Holtmann 		if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff &&
2039ccd6da2aSMarcel Holtmann 		    hdr->plen > 0) {
2040ccd6da2aSMarcel Holtmann 			const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1;
2041ccd6da2aSMarcel Holtmann 			unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1;
2042cda0dd78SMarcel Holtmann 
2043ccd6da2aSMarcel Holtmann 			switch (skb->data[2]) {
2044ccd6da2aSMarcel Holtmann 			case 0x02:
2045ccd6da2aSMarcel Holtmann 				/* When switching to the operational firmware
2046ccd6da2aSMarcel Holtmann 				 * the device sends a vendor specific event
2047ccd6da2aSMarcel Holtmann 				 * indicating that the bootup completed.
2048cda0dd78SMarcel Holtmann 				 */
2049019a1caaSTedd Ho-Jeong An 				btintel_bootup(hdev, ptr, len);
2050ccd6da2aSMarcel Holtmann 				break;
2051ccd6da2aSMarcel Holtmann 			case 0x06:
2052ccd6da2aSMarcel Holtmann 				/* When the firmware loading completes the
2053ccd6da2aSMarcel Holtmann 				 * device sends out a vendor specific event
2054ccd6da2aSMarcel Holtmann 				 * indicating the result of the firmware
2055ccd6da2aSMarcel Holtmann 				 * loading.
2056ccd6da2aSMarcel Holtmann 				 */
2057019a1caaSTedd Ho-Jeong An 				btintel_secure_send_result(hdev, ptr, len);
2058ccd6da2aSMarcel Holtmann 				break;
2059fad70972SJohan Hedberg 			}
2060cda0dd78SMarcel Holtmann 		}
2061cda0dd78SMarcel Holtmann 	}
2062cda0dd78SMarcel Holtmann 
2063cda0dd78SMarcel Holtmann 	return hci_recv_frame(hdev, skb);
2064cda0dd78SMarcel Holtmann }
2065cda0dd78SMarcel Holtmann 
2066cda0dd78SMarcel Holtmann static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
2067cda0dd78SMarcel Holtmann {
2068cda0dd78SMarcel Holtmann 	struct urb *urb;
2069cda0dd78SMarcel Holtmann 
2070cda0dd78SMarcel Holtmann 	BT_DBG("%s", hdev->name);
2071cda0dd78SMarcel Holtmann 
2072618e8bc2SMarcel Holtmann 	switch (hci_skb_pkt_type(skb)) {
2073cda0dd78SMarcel Holtmann 	case HCI_COMMAND_PKT:
2074019a1caaSTedd Ho-Jeong An 		if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
2075cda0dd78SMarcel Holtmann 			struct hci_command_hdr *cmd = (void *)skb->data;
2076cda0dd78SMarcel Holtmann 			__u16 opcode = le16_to_cpu(cmd->opcode);
2077cda0dd78SMarcel Holtmann 
2078cda0dd78SMarcel Holtmann 			/* When in bootloader mode and the command 0xfc09
2079cda0dd78SMarcel Holtmann 			 * is received, it needs to be send down the
2080cda0dd78SMarcel Holtmann 			 * bulk endpoint. So allocate a bulk URB instead.
2081cda0dd78SMarcel Holtmann 			 */
2082cda0dd78SMarcel Holtmann 			if (opcode == 0xfc09)
2083cda0dd78SMarcel Holtmann 				urb = alloc_bulk_urb(hdev, skb);
2084cda0dd78SMarcel Holtmann 			else
2085cda0dd78SMarcel Holtmann 				urb = alloc_ctrl_urb(hdev, skb);
2086cda0dd78SMarcel Holtmann 
2087cda0dd78SMarcel Holtmann 			/* When the 0xfc01 command is issued to boot into
2088cda0dd78SMarcel Holtmann 			 * the operational firmware, it will actually not
2089cda0dd78SMarcel Holtmann 			 * send a command complete event. To keep the flow
2090cda0dd78SMarcel Holtmann 			 * control working inject that event here.
2091cda0dd78SMarcel Holtmann 			 */
2092cda0dd78SMarcel Holtmann 			if (opcode == 0xfc01)
2093cda0dd78SMarcel Holtmann 				inject_cmd_complete(hdev, opcode);
2094cda0dd78SMarcel Holtmann 		} else {
2095cda0dd78SMarcel Holtmann 			urb = alloc_ctrl_urb(hdev, skb);
2096cda0dd78SMarcel Holtmann 		}
2097cda0dd78SMarcel Holtmann 		if (IS_ERR(urb))
2098cda0dd78SMarcel Holtmann 			return PTR_ERR(urb);
2099cda0dd78SMarcel Holtmann 
2100cda0dd78SMarcel Holtmann 		hdev->stat.cmd_tx++;
2101cda0dd78SMarcel Holtmann 		return submit_or_queue_tx_urb(hdev, urb);
2102cda0dd78SMarcel Holtmann 
2103cda0dd78SMarcel Holtmann 	case HCI_ACLDATA_PKT:
2104cda0dd78SMarcel Holtmann 		urb = alloc_bulk_urb(hdev, skb);
2105cda0dd78SMarcel Holtmann 		if (IS_ERR(urb))
2106cda0dd78SMarcel Holtmann 			return PTR_ERR(urb);
2107cda0dd78SMarcel Holtmann 
2108cda0dd78SMarcel Holtmann 		hdev->stat.acl_tx++;
2109cda0dd78SMarcel Holtmann 		return submit_or_queue_tx_urb(hdev, urb);
2110cda0dd78SMarcel Holtmann 
2111cda0dd78SMarcel Holtmann 	case HCI_SCODATA_PKT:
2112cda0dd78SMarcel Holtmann 		if (hci_conn_num(hdev, SCO_LINK) < 1)
2113cda0dd78SMarcel Holtmann 			return -ENODEV;
2114cda0dd78SMarcel Holtmann 
2115cda0dd78SMarcel Holtmann 		urb = alloc_isoc_urb(hdev, skb);
2116cda0dd78SMarcel Holtmann 		if (IS_ERR(urb))
2117cda0dd78SMarcel Holtmann 			return PTR_ERR(urb);
2118cda0dd78SMarcel Holtmann 
2119cda0dd78SMarcel Holtmann 		hdev->stat.sco_tx++;
2120cda0dd78SMarcel Holtmann 		return submit_tx_urb(hdev, urb);
2121cda0dd78SMarcel Holtmann 	}
2122cda0dd78SMarcel Holtmann 
2123cda0dd78SMarcel Holtmann 	return -EILSEQ;
2124cda0dd78SMarcel Holtmann }
2125cda0dd78SMarcel Holtmann 
2126e9478026Smark-yw.chen /* UHW CR mapping */
2127e9478026Smark-yw.chen #define MTK_BT_MISC		0x70002510
2128e9478026Smark-yw.chen #define MTK_BT_SUBSYS_RST	0x70002610
2129e9478026Smark-yw.chen #define MTK_UDMA_INT_STA_BT	0x74000024
2130e9478026Smark-yw.chen #define MTK_UDMA_INT_STA_BT1	0x74000308
2131e9478026Smark-yw.chen #define MTK_BT_WDT_STATUS	0x740003A0
2132e9478026Smark-yw.chen #define MTK_EP_RST_OPT		0x74011890
2133e9478026Smark-yw.chen #define MTK_EP_RST_IN_OUT_OPT	0x00010001
2134e9478026Smark-yw.chen #define MTK_BT_RST_DONE		0x00000100
2135e9478026Smark-yw.chen #define MTK_BT_RESET_WAIT_MS	100
2136e9478026Smark-yw.chen #define MTK_BT_RESET_NUM_TRIES	10
21375a87679fSmark-yw.chen 
2138a1c49c43SSean Wang static void btusb_mtk_wmt_recv(struct urb *urb)
2139a1c49c43SSean Wang {
2140a1c49c43SSean Wang 	struct hci_dev *hdev = urb->context;
2141a1c49c43SSean Wang 	struct btusb_data *data = hci_get_drvdata(hdev);
2142a1c49c43SSean Wang 	struct hci_event_hdr *hdr;
2143a1c49c43SSean Wang 	struct sk_buff *skb;
2144a1c49c43SSean Wang 	int err;
2145a1c49c43SSean Wang 
2146a1c49c43SSean Wang 	if (urb->status == 0 && urb->actual_length > 0) {
2147a1c49c43SSean Wang 		hdev->stat.byte_rx += urb->actual_length;
2148a1c49c43SSean Wang 
2149a1c49c43SSean Wang 		/* WMT event shouldn't be fragmented and the size should be
2150a1c49c43SSean Wang 		 * less than HCI_WMT_MAX_EVENT_SIZE.
2151a1c49c43SSean Wang 		 */
2152a1c49c43SSean Wang 		skb = bt_skb_alloc(HCI_WMT_MAX_EVENT_SIZE, GFP_ATOMIC);
2153a1c49c43SSean Wang 		if (!skb) {
2154a1c49c43SSean Wang 			hdev->stat.err_rx++;
215560c6a63aSMark-YW.Chen 			kfree(urb->setup_packet);
2156de71a6cbSJupeng Zhong 			return;
2157a1c49c43SSean Wang 		}
2158a1c49c43SSean Wang 
2159a1c49c43SSean Wang 		hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
2160a1c49c43SSean Wang 		skb_put_data(skb, urb->transfer_buffer, urb->actual_length);
2161a1c49c43SSean Wang 
2162a1c49c43SSean Wang 		hdr = (void *)skb->data;
2163a1c49c43SSean Wang 		/* Fix up the vendor event id with 0xff for vendor specific
2164a1c49c43SSean Wang 		 * instead of 0xe4 so that event send via monitoring socket can
2165a1c49c43SSean Wang 		 * be parsed properly.
2166a1c49c43SSean Wang 		 */
2167a1c49c43SSean Wang 		hdr->evt = 0xff;
2168a1c49c43SSean Wang 
2169a1c49c43SSean Wang 		/* When someone waits for the WMT event, the skb is being cloned
2170a1c49c43SSean Wang 		 * and being processed the events from there then.
2171a1c49c43SSean Wang 		 */
2172a1c49c43SSean Wang 		if (test_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags)) {
217322cc6b7aSJohan Hovold 			data->evt_skb = skb_clone(skb, GFP_ATOMIC);
2174de71a6cbSJupeng Zhong 			if (!data->evt_skb) {
2175de71a6cbSJupeng Zhong 				kfree_skb(skb);
217660c6a63aSMark-YW.Chen 				kfree(urb->setup_packet);
2177de71a6cbSJupeng Zhong 				return;
2178de71a6cbSJupeng Zhong 			}
2179a1c49c43SSean Wang 		}
2180a1c49c43SSean Wang 
2181a1c49c43SSean Wang 		err = hci_recv_frame(hdev, skb);
2182de71a6cbSJupeng Zhong 		if (err < 0) {
2183de71a6cbSJupeng Zhong 			kfree_skb(data->evt_skb);
2184de71a6cbSJupeng Zhong 			data->evt_skb = NULL;
218560c6a63aSMark-YW.Chen 			kfree(urb->setup_packet);
2186de71a6cbSJupeng Zhong 			return;
2187de71a6cbSJupeng Zhong 		}
2188a1c49c43SSean Wang 
2189a1c49c43SSean Wang 		if (test_and_clear_bit(BTUSB_TX_WAIT_VND_EVT,
2190a1c49c43SSean Wang 				       &data->flags)) {
2191a1c49c43SSean Wang 			/* Barrier to sync with other CPUs */
2192a1c49c43SSean Wang 			smp_mb__after_atomic();
2193a1c49c43SSean Wang 			wake_up_bit(&data->flags,
2194a1c49c43SSean Wang 				    BTUSB_TX_WAIT_VND_EVT);
2195a1c49c43SSean Wang 		}
219660c6a63aSMark-YW.Chen 		kfree(urb->setup_packet);
2197a1c49c43SSean Wang 		return;
2198a1c49c43SSean Wang 	} else if (urb->status == -ENOENT) {
2199a1c49c43SSean Wang 		/* Avoid suspend failed when usb_kill_urb */
2200a1c49c43SSean Wang 		return;
2201a1c49c43SSean Wang 	}
2202a1c49c43SSean Wang 
2203a1c49c43SSean Wang 	usb_mark_last_busy(data->udev);
2204a1c49c43SSean Wang 
2205a1c49c43SSean Wang 	/* The URB complete handler is still called with urb->actual_length = 0
2206a1c49c43SSean Wang 	 * when the event is not available, so we should keep re-submitting
2207a1c49c43SSean Wang 	 * URB until WMT event returns, Also, It's necessary to wait some time
2208a1c49c43SSean Wang 	 * between the two consecutive control URBs to relax the target device
2209a1c49c43SSean Wang 	 * to generate the event. Otherwise, the WMT event cannot return from
2210a1c49c43SSean Wang 	 * the device successfully.
2211a1c49c43SSean Wang 	 */
221248c13301SMark Chen 	udelay(500);
2213a1c49c43SSean Wang 
2214a1c49c43SSean Wang 	usb_anchor_urb(urb, &data->ctrl_anchor);
2215a1c49c43SSean Wang 	err = usb_submit_urb(urb, GFP_ATOMIC);
2216a1c49c43SSean Wang 	if (err < 0) {
221760c6a63aSMark-YW.Chen 		kfree(urb->setup_packet);
2218a1c49c43SSean Wang 		/* -EPERM: urb is being killed;
2219a1c49c43SSean Wang 		 * -ENODEV: device got disconnected
2220a1c49c43SSean Wang 		 */
2221a1c49c43SSean Wang 		if (err != -EPERM && err != -ENODEV)
2222a1c49c43SSean Wang 			bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
2223a1c49c43SSean Wang 				   urb, -err);
2224a1c49c43SSean Wang 		usb_unanchor_urb(urb);
2225a1c49c43SSean Wang 	}
2226a1c49c43SSean Wang }
2227a1c49c43SSean Wang 
2228a1c49c43SSean Wang static int btusb_mtk_submit_wmt_recv_urb(struct hci_dev *hdev)
2229a1c49c43SSean Wang {
2230a1c49c43SSean Wang 	struct btusb_data *data = hci_get_drvdata(hdev);
2231a1c49c43SSean Wang 	struct usb_ctrlrequest *dr;
2232a1c49c43SSean Wang 	unsigned char *buf;
2233a1c49c43SSean Wang 	int err, size = 64;
2234a1c49c43SSean Wang 	unsigned int pipe;
2235a1c49c43SSean Wang 	struct urb *urb;
2236a1c49c43SSean Wang 
2237a1c49c43SSean Wang 	urb = usb_alloc_urb(0, GFP_KERNEL);
2238a1c49c43SSean Wang 	if (!urb)
2239a1c49c43SSean Wang 		return -ENOMEM;
2240a1c49c43SSean Wang 
2241a1c49c43SSean Wang 	dr = kmalloc(sizeof(*dr), GFP_KERNEL);
2242a1c49c43SSean Wang 	if (!dr) {
2243a1c49c43SSean Wang 		usb_free_urb(urb);
2244a1c49c43SSean Wang 		return -ENOMEM;
2245a1c49c43SSean Wang 	}
2246a1c49c43SSean Wang 
2247a1c49c43SSean Wang 	dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_IN;
2248a1c49c43SSean Wang 	dr->bRequest     = 1;
2249a1c49c43SSean Wang 	dr->wIndex       = cpu_to_le16(0);
2250a1c49c43SSean Wang 	dr->wValue       = cpu_to_le16(48);
2251a1c49c43SSean Wang 	dr->wLength      = cpu_to_le16(size);
2252a1c49c43SSean Wang 
2253a1c49c43SSean Wang 	buf = kmalloc(size, GFP_KERNEL);
2254a1c49c43SSean Wang 	if (!buf) {
2255a1c49c43SSean Wang 		kfree(dr);
2256d33fe77bSDinghao Liu 		usb_free_urb(urb);
2257a1c49c43SSean Wang 		return -ENOMEM;
2258a1c49c43SSean Wang 	}
2259a1c49c43SSean Wang 
2260a1c49c43SSean Wang 	pipe = usb_rcvctrlpipe(data->udev, 0);
2261a1c49c43SSean Wang 
2262a1c49c43SSean Wang 	usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
2263a1c49c43SSean Wang 			     buf, size, btusb_mtk_wmt_recv, hdev);
2264a1c49c43SSean Wang 
2265a1c49c43SSean Wang 	urb->transfer_flags |= URB_FREE_BUFFER;
2266a1c49c43SSean Wang 
2267a1c49c43SSean Wang 	usb_anchor_urb(urb, &data->ctrl_anchor);
2268a1c49c43SSean Wang 	err = usb_submit_urb(urb, GFP_KERNEL);
2269a1c49c43SSean Wang 	if (err < 0) {
2270a1c49c43SSean Wang 		if (err != -EPERM && err != -ENODEV)
2271a1c49c43SSean Wang 			bt_dev_err(hdev, "urb %p submission failed (%d)",
2272a1c49c43SSean Wang 				   urb, -err);
2273a1c49c43SSean Wang 		usb_unanchor_urb(urb);
2274a1c49c43SSean Wang 	}
2275a1c49c43SSean Wang 
2276a1c49c43SSean Wang 	usb_free_urb(urb);
2277a1c49c43SSean Wang 
2278a1c49c43SSean Wang 	return err;
2279a1c49c43SSean Wang }
2280a1c49c43SSean Wang 
2281a1c49c43SSean Wang static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
2282a1c49c43SSean Wang 				  struct btmtk_hci_wmt_params *wmt_params)
2283a1c49c43SSean Wang {
2284a1c49c43SSean Wang 	struct btusb_data *data = hci_get_drvdata(hdev);
2285a1c49c43SSean Wang 	struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
2286a1c49c43SSean Wang 	u32 hlen, status = BTMTK_WMT_INVALID;
2287a1c49c43SSean Wang 	struct btmtk_hci_wmt_evt *wmt_evt;
228810888140SArnd Bergmann 	struct btmtk_hci_wmt_cmd *wc;
2289a1c49c43SSean Wang 	struct btmtk_wmt_hdr *hdr;
2290a1c49c43SSean Wang 	int err;
2291a1c49c43SSean Wang 
2292a1c49c43SSean Wang 	/* Send the WMT command and wait until the WMT event returns */
2293a1c49c43SSean Wang 	hlen = sizeof(*hdr) + wmt_params->dlen;
2294a1c49c43SSean Wang 	if (hlen > 255)
2295a1c49c43SSean Wang 		return -EINVAL;
2296a1c49c43SSean Wang 
229710888140SArnd Bergmann 	wc = kzalloc(hlen, GFP_KERNEL);
229810888140SArnd Bergmann 	if (!wc)
229910888140SArnd Bergmann 		return -ENOMEM;
230010888140SArnd Bergmann 
230110888140SArnd Bergmann 	hdr = &wc->hdr;
2302a1c49c43SSean Wang 	hdr->dir = 1;
2303a1c49c43SSean Wang 	hdr->op = wmt_params->op;
2304a1c49c43SSean Wang 	hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
2305a1c49c43SSean Wang 	hdr->flag = wmt_params->flag;
230610888140SArnd Bergmann 	memcpy(wc->data, wmt_params->data, wmt_params->dlen);
2307a1c49c43SSean Wang 
2308a1c49c43SSean Wang 	set_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
2309a1c49c43SSean Wang 
231010888140SArnd Bergmann 	err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
2311a1c49c43SSean Wang 
2312a1c49c43SSean Wang 	if (err < 0) {
2313a1c49c43SSean Wang 		clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
231410888140SArnd Bergmann 		goto err_free_wc;
2315a1c49c43SSean Wang 	}
2316a1c49c43SSean Wang 
23178454ed9fSmark-yw.chen 	/* Submit control IN URB on demand to process the WMT event */
23188454ed9fSmark-yw.chen 	err = btusb_mtk_submit_wmt_recv_urb(hdev);
23198454ed9fSmark-yw.chen 	if (err < 0)
232044e936d7SMuhammad Usama Anjum 		goto err_free_wc;
23218454ed9fSmark-yw.chen 
2322a1c49c43SSean Wang 	/* The vendor specific WMT commands are all answered by a vendor
2323a1c49c43SSean Wang 	 * specific event and will have the Command Status or Command
2324a1c49c43SSean Wang 	 * Complete as with usual HCI command flow control.
2325a1c49c43SSean Wang 	 *
2326a1c49c43SSean Wang 	 * After sending the command, wait for BTUSB_TX_WAIT_VND_EVT
2327a1c49c43SSean Wang 	 * state to be cleared. The driver specific event receive routine
2328a1c49c43SSean Wang 	 * will clear that state and with that indicate completion of the
2329a1c49c43SSean Wang 	 * WMT command.
2330a1c49c43SSean Wang 	 */
2331a1c49c43SSean Wang 	err = wait_on_bit_timeout(&data->flags, BTUSB_TX_WAIT_VND_EVT,
2332a1c49c43SSean Wang 				  TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT);
2333a1c49c43SSean Wang 	if (err == -EINTR) {
2334a1c49c43SSean Wang 		bt_dev_err(hdev, "Execution of wmt command interrupted");
2335a1c49c43SSean Wang 		clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
233610888140SArnd Bergmann 		goto err_free_wc;
2337a1c49c43SSean Wang 	}
2338a1c49c43SSean Wang 
2339a1c49c43SSean Wang 	if (err) {
2340a1c49c43SSean Wang 		bt_dev_err(hdev, "Execution of wmt command timed out");
2341a1c49c43SSean Wang 		clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
234210888140SArnd Bergmann 		err = -ETIMEDOUT;
234310888140SArnd Bergmann 		goto err_free_wc;
2344a1c49c43SSean Wang 	}
2345a1c49c43SSean Wang 
2346a1c49c43SSean Wang 	/* Parse and handle the return WMT event */
2347a1c49c43SSean Wang 	wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
2348a1c49c43SSean Wang 	if (wmt_evt->whdr.op != hdr->op) {
2349a1c49c43SSean Wang 		bt_dev_err(hdev, "Wrong op received %d expected %d",
2350a1c49c43SSean Wang 			   wmt_evt->whdr.op, hdr->op);
2351a1c49c43SSean Wang 		err = -EIO;
2352a1c49c43SSean Wang 		goto err_free_skb;
2353a1c49c43SSean Wang 	}
2354a1c49c43SSean Wang 
2355a1c49c43SSean Wang 	switch (wmt_evt->whdr.op) {
2356a1c49c43SSean Wang 	case BTMTK_WMT_SEMAPHORE:
2357a1c49c43SSean Wang 		if (wmt_evt->whdr.flag == 2)
2358a1c49c43SSean Wang 			status = BTMTK_WMT_PATCH_UNDONE;
2359a1c49c43SSean Wang 		else
2360a1c49c43SSean Wang 			status = BTMTK_WMT_PATCH_DONE;
2361a1c49c43SSean Wang 		break;
2362a1c49c43SSean Wang 	case BTMTK_WMT_FUNC_CTRL:
2363a1c49c43SSean Wang 		wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
2364a1c49c43SSean Wang 		if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
2365a1c49c43SSean Wang 			status = BTMTK_WMT_ON_DONE;
2366a1c49c43SSean Wang 		else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
2367a1c49c43SSean Wang 			status = BTMTK_WMT_ON_PROGRESS;
2368a1c49c43SSean Wang 		else
2369a1c49c43SSean Wang 			status = BTMTK_WMT_ON_UNDONE;
2370a1c49c43SSean Wang 		break;
2371fc342c4dSMark Chen 	case BTMTK_WMT_PATCH_DWNLD:
2372fc342c4dSMark Chen 		if (wmt_evt->whdr.flag == 2)
2373fc342c4dSMark Chen 			status = BTMTK_WMT_PATCH_DONE;
2374fc342c4dSMark Chen 		else if (wmt_evt->whdr.flag == 1)
2375fc342c4dSMark Chen 			status = BTMTK_WMT_PATCH_PROGRESS;
2376fc342c4dSMark Chen 		else
2377fc342c4dSMark Chen 			status = BTMTK_WMT_PATCH_UNDONE;
2378fc342c4dSMark Chen 		break;
2379a1c49c43SSean Wang 	}
2380a1c49c43SSean Wang 
2381a1c49c43SSean Wang 	if (wmt_params->status)
2382a1c49c43SSean Wang 		*wmt_params->status = status;
2383a1c49c43SSean Wang 
2384a1c49c43SSean Wang err_free_skb:
2385a1c49c43SSean Wang 	kfree_skb(data->evt_skb);
2386a1c49c43SSean Wang 	data->evt_skb = NULL;
238710888140SArnd Bergmann err_free_wc:
238810888140SArnd Bergmann 	kfree(wc);
2389a1c49c43SSean Wang 	return err;
2390a1c49c43SSean Wang }
2391a1c49c43SSean Wang 
2392a1c49c43SSean Wang static int btusb_mtk_func_query(struct hci_dev *hdev)
2393a1c49c43SSean Wang {
2394a1c49c43SSean Wang 	struct btmtk_hci_wmt_params wmt_params;
2395a1c49c43SSean Wang 	int status, err;
2396a1c49c43SSean Wang 	u8 param = 0;
2397a1c49c43SSean Wang 
2398a1c49c43SSean Wang 	/* Query whether the function is enabled */
2399a1c49c43SSean Wang 	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
2400a1c49c43SSean Wang 	wmt_params.flag = 4;
2401a1c49c43SSean Wang 	wmt_params.dlen = sizeof(param);
2402a1c49c43SSean Wang 	wmt_params.data = &param;
2403a1c49c43SSean Wang 	wmt_params.status = &status;
2404a1c49c43SSean Wang 
2405a1c49c43SSean Wang 	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
2406a1c49c43SSean Wang 	if (err < 0) {
2407a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to query function status (%d)", err);
2408a1c49c43SSean Wang 		return err;
2409a1c49c43SSean Wang 	}
2410a1c49c43SSean Wang 
2411a1c49c43SSean Wang 	return status;
2412a1c49c43SSean Wang }
2413a1c49c43SSean Wang 
2414e9478026Smark-yw.chen static int btusb_mtk_uhw_reg_write(struct btusb_data *data, u32 reg, u32 val)
2415e9478026Smark-yw.chen {
2416e9478026Smark-yw.chen 	struct hci_dev *hdev = data->hdev;
2417e9478026Smark-yw.chen 	int pipe, err;
2418e9478026Smark-yw.chen 	void *buf;
2419e9478026Smark-yw.chen 
2420e9478026Smark-yw.chen 	buf = kzalloc(4, GFP_KERNEL);
2421e9478026Smark-yw.chen 	if (!buf)
2422e9478026Smark-yw.chen 		return -ENOMEM;
2423e9478026Smark-yw.chen 
2424e9478026Smark-yw.chen 	put_unaligned_le32(val, buf);
2425e9478026Smark-yw.chen 
2426e9478026Smark-yw.chen 	pipe = usb_sndctrlpipe(data->udev, 0);
2427e9478026Smark-yw.chen 	err = usb_control_msg(data->udev, pipe, 0x02,
2428e9478026Smark-yw.chen 			      0x5E,
2429e9478026Smark-yw.chen 			      reg >> 16, reg & 0xffff,
2430e9478026Smark-yw.chen 			      buf, 4, USB_CTRL_SET_TIMEOUT);
2431e9478026Smark-yw.chen 	if (err < 0) {
2432e9478026Smark-yw.chen 		bt_dev_err(hdev, "Failed to write uhw reg(%d)", err);
2433e9478026Smark-yw.chen 		goto err_free_buf;
2434e9478026Smark-yw.chen 	}
2435e9478026Smark-yw.chen 
2436e9478026Smark-yw.chen err_free_buf:
2437e9478026Smark-yw.chen 	kfree(buf);
2438e9478026Smark-yw.chen 
2439e9478026Smark-yw.chen 	return err;
2440e9478026Smark-yw.chen }
2441e9478026Smark-yw.chen 
2442e9478026Smark-yw.chen static int btusb_mtk_uhw_reg_read(struct btusb_data *data, u32 reg, u32 *val)
2443e9478026Smark-yw.chen {
2444e9478026Smark-yw.chen 	struct hci_dev *hdev = data->hdev;
2445e9478026Smark-yw.chen 	int pipe, err;
2446e9478026Smark-yw.chen 	void *buf;
2447e9478026Smark-yw.chen 
2448e9478026Smark-yw.chen 	buf = kzalloc(4, GFP_KERNEL);
2449e9478026Smark-yw.chen 	if (!buf)
2450e9478026Smark-yw.chen 		return -ENOMEM;
2451e9478026Smark-yw.chen 
2452e9478026Smark-yw.chen 	pipe = usb_rcvctrlpipe(data->udev, 0);
2453e9478026Smark-yw.chen 	err = usb_control_msg(data->udev, pipe, 0x01,
2454e9478026Smark-yw.chen 			      0xDE,
2455e9478026Smark-yw.chen 			      reg >> 16, reg & 0xffff,
2456e9478026Smark-yw.chen 			      buf, 4, USB_CTRL_SET_TIMEOUT);
2457e9478026Smark-yw.chen 	if (err < 0) {
2458e9478026Smark-yw.chen 		bt_dev_err(hdev, "Failed to read uhw reg(%d)", err);
2459e9478026Smark-yw.chen 		goto err_free_buf;
2460e9478026Smark-yw.chen 	}
2461e9478026Smark-yw.chen 
2462e9478026Smark-yw.chen 	*val = get_unaligned_le32(buf);
2463e9478026Smark-yw.chen 	bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val);
2464e9478026Smark-yw.chen 
2465e9478026Smark-yw.chen err_free_buf:
2466e9478026Smark-yw.chen 	kfree(buf);
2467e9478026Smark-yw.chen 
2468e9478026Smark-yw.chen 	return err;
2469e9478026Smark-yw.chen }
2470e9478026Smark-yw.chen 
2471a1c49c43SSean Wang static int btusb_mtk_reg_read(struct btusb_data *data, u32 reg, u32 *val)
2472a1c49c43SSean Wang {
2473a1c49c43SSean Wang 	int pipe, err, size = sizeof(u32);
2474a1c49c43SSean Wang 	void *buf;
2475a1c49c43SSean Wang 
2476a1c49c43SSean Wang 	buf = kzalloc(size, GFP_KERNEL);
2477a1c49c43SSean Wang 	if (!buf)
2478a1c49c43SSean Wang 		return -ENOMEM;
2479a1c49c43SSean Wang 
2480a1c49c43SSean Wang 	pipe = usb_rcvctrlpipe(data->udev, 0);
2481a1c49c43SSean Wang 	err = usb_control_msg(data->udev, pipe, 0x63,
2482a1c49c43SSean Wang 			      USB_TYPE_VENDOR | USB_DIR_IN,
2483a1c49c43SSean Wang 			      reg >> 16, reg & 0xffff,
2484a1c49c43SSean Wang 			      buf, size, USB_CTRL_SET_TIMEOUT);
2485a1c49c43SSean Wang 	if (err < 0)
2486a1c49c43SSean Wang 		goto err_free_buf;
2487a1c49c43SSean Wang 
2488a1c49c43SSean Wang 	*val = get_unaligned_le32(buf);
2489a1c49c43SSean Wang 
2490a1c49c43SSean Wang err_free_buf:
2491a1c49c43SSean Wang 	kfree(buf);
2492a1c49c43SSean Wang 
2493a1c49c43SSean Wang 	return err;
2494a1c49c43SSean Wang }
2495a1c49c43SSean Wang 
249648c13301SMark Chen static int btusb_mtk_id_get(struct btusb_data *data, u32 reg, u32 *id)
2497a1c49c43SSean Wang {
249848c13301SMark Chen 	return btusb_mtk_reg_read(data, reg, id);
2499a1c49c43SSean Wang }
2500a1c49c43SSean Wang 
2501a1c49c43SSean Wang static int btusb_mtk_setup(struct hci_dev *hdev)
2502a1c49c43SSean Wang {
2503a1c49c43SSean Wang 	struct btusb_data *data = hci_get_drvdata(hdev);
2504a1c49c43SSean Wang 	struct btmtk_hci_wmt_params wmt_params;
2505a1c49c43SSean Wang 	ktime_t calltime, delta, rettime;
2506a1c49c43SSean Wang 	struct btmtk_tci_sleep tci_sleep;
2507a1c49c43SSean Wang 	unsigned long long duration;
2508a1c49c43SSean Wang 	struct sk_buff *skb;
2509a1c49c43SSean Wang 	const char *fwname;
2510a1c49c43SSean Wang 	int err, status;
2511a1c49c43SSean Wang 	u32 dev_id;
2512fc342c4dSMark Chen 	char fw_bin_name[64];
2513201cf397Smark-yw.chen 	u32 fw_version = 0;
2514a1c49c43SSean Wang 	u8 param;
2515a1c49c43SSean Wang 
2516a1c49c43SSean Wang 	calltime = ktime_get();
2517a1c49c43SSean Wang 
251848c13301SMark Chen 	err = btusb_mtk_id_get(data, 0x80000008, &dev_id);
2519a1c49c43SSean Wang 	if (err < 0) {
2520a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to get device id (%d)", err);
2521a1c49c43SSean Wang 		return err;
2522a1c49c43SSean Wang 	}
2523a1c49c43SSean Wang 
2524fc342c4dSMark Chen 	if (!dev_id) {
2525fc342c4dSMark Chen 		err = btusb_mtk_id_get(data, 0x70010200, &dev_id);
2526fc342c4dSMark Chen 		if (err < 0) {
2527fc342c4dSMark Chen 			bt_dev_err(hdev, "Failed to get device id (%d)", err);
2528fc342c4dSMark Chen 			return err;
2529fc342c4dSMark Chen 		}
2530fc342c4dSMark Chen 		err = btusb_mtk_id_get(data, 0x80021004, &fw_version);
2531fc342c4dSMark Chen 		if (err < 0) {
2532fc342c4dSMark Chen 			bt_dev_err(hdev, "Failed to get fw version (%d)", err);
2533fc342c4dSMark Chen 			return err;
2534fc342c4dSMark Chen 		}
2535fc342c4dSMark Chen 	}
2536fc342c4dSMark Chen 
2537a1c49c43SSean Wang 	switch (dev_id) {
25389ce67c32SSean Wang 	case 0x7663:
25399ce67c32SSean Wang 		fwname = FIRMWARE_MT7663;
25409ce67c32SSean Wang 		break;
2541a1c49c43SSean Wang 	case 0x7668:
2542a1c49c43SSean Wang 		fwname = FIRMWARE_MT7668;
2543a1c49c43SSean Wang 		break;
254409a19d6dSmark-yw.chen 	case 0x7922:
2545fc342c4dSMark Chen 	case 0x7961:
2546fc342c4dSMark Chen 		snprintf(fw_bin_name, sizeof(fw_bin_name),
2547fc342c4dSMark Chen 			"mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin",
2548fc342c4dSMark Chen 			 dev_id & 0xffff, (fw_version & 0xff) + 1);
25498c0d17b6SSean Wang 		err = btmtk_setup_firmware_79xx(hdev, fw_bin_name,
25508c0d17b6SSean Wang 						btusb_mtk_hci_wmt_sync);
2551fc342c4dSMark Chen 
2552e9478026Smark-yw.chen 		/* It's Device EndPoint Reset Option Register */
2553e9478026Smark-yw.chen 		btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
2554e9478026Smark-yw.chen 
2555fc342c4dSMark Chen 		/* Enable Bluetooth protocol */
2556fc342c4dSMark Chen 		param = 1;
2557fc342c4dSMark Chen 		wmt_params.op = BTMTK_WMT_FUNC_CTRL;
2558fc342c4dSMark Chen 		wmt_params.flag = 0;
2559fc342c4dSMark Chen 		wmt_params.dlen = sizeof(param);
2560fc342c4dSMark Chen 		wmt_params.data = &param;
2561fc342c4dSMark Chen 		wmt_params.status = NULL;
2562fc342c4dSMark Chen 
2563fc342c4dSMark Chen 		err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
2564fc342c4dSMark Chen 		if (err < 0) {
2565fc342c4dSMark Chen 			bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
2566fc342c4dSMark Chen 			return err;
2567fc342c4dSMark Chen 		}
2568654e6f77Smark-yw.chen 
2569654e6f77Smark-yw.chen 		hci_set_msft_opcode(hdev, 0xFD30);
257028491d7eSmark-yw.chen 		hci_set_aosp_capable(hdev);
2571fc342c4dSMark Chen 		goto done;
2572a1c49c43SSean Wang 	default:
2573a297f565SJupeng Zhong 		bt_dev_err(hdev, "Unsupported hardware variant (%08x)",
2574a1c49c43SSean Wang 			   dev_id);
2575a1c49c43SSean Wang 		return -ENODEV;
2576a1c49c43SSean Wang 	}
2577a1c49c43SSean Wang 
2578a1c49c43SSean Wang 	/* Query whether the firmware is already download */
2579a1c49c43SSean Wang 	wmt_params.op = BTMTK_WMT_SEMAPHORE;
2580a1c49c43SSean Wang 	wmt_params.flag = 1;
2581a1c49c43SSean Wang 	wmt_params.dlen = 0;
2582a1c49c43SSean Wang 	wmt_params.data = NULL;
2583a1c49c43SSean Wang 	wmt_params.status = &status;
2584a1c49c43SSean Wang 
2585a1c49c43SSean Wang 	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
2586a1c49c43SSean Wang 	if (err < 0) {
2587a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
2588a1c49c43SSean Wang 		return err;
2589a1c49c43SSean Wang 	}
2590a1c49c43SSean Wang 
2591a1c49c43SSean Wang 	if (status == BTMTK_WMT_PATCH_DONE) {
2592a1c49c43SSean Wang 		bt_dev_info(hdev, "firmware already downloaded");
2593a1c49c43SSean Wang 		goto ignore_setup_fw;
2594a1c49c43SSean Wang 	}
2595a1c49c43SSean Wang 
2596a1c49c43SSean Wang 	/* Setup a firmware which the device definitely requires */
25978c0d17b6SSean Wang 	err = btmtk_setup_firmware(hdev, fwname,
25988c0d17b6SSean Wang 				   btusb_mtk_hci_wmt_sync);
2599a1c49c43SSean Wang 	if (err < 0)
2600a1c49c43SSean Wang 		return err;
2601a1c49c43SSean Wang 
2602a1c49c43SSean Wang ignore_setup_fw:
2603a1c49c43SSean Wang 	err = readx_poll_timeout(btusb_mtk_func_query, hdev, status,
2604a1c49c43SSean Wang 				 status < 0 || status != BTMTK_WMT_ON_PROGRESS,
2605a1c49c43SSean Wang 				 2000, 5000000);
2606a1c49c43SSean Wang 	/* -ETIMEDOUT happens */
2607a1c49c43SSean Wang 	if (err < 0)
2608a1c49c43SSean Wang 		return err;
2609a1c49c43SSean Wang 
2610a1c49c43SSean Wang 	/* The other errors happen in btusb_mtk_func_query */
2611a1c49c43SSean Wang 	if (status < 0)
2612a1c49c43SSean Wang 		return status;
2613a1c49c43SSean Wang 
2614a1c49c43SSean Wang 	if (status == BTMTK_WMT_ON_DONE) {
2615a1c49c43SSean Wang 		bt_dev_info(hdev, "function already on");
2616a1c49c43SSean Wang 		goto ignore_func_on;
2617a1c49c43SSean Wang 	}
2618a1c49c43SSean Wang 
2619a1c49c43SSean Wang 	/* Enable Bluetooth protocol */
2620a1c49c43SSean Wang 	param = 1;
2621a1c49c43SSean Wang 	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
2622a1c49c43SSean Wang 	wmt_params.flag = 0;
2623a1c49c43SSean Wang 	wmt_params.dlen = sizeof(param);
2624a1c49c43SSean Wang 	wmt_params.data = &param;
2625a1c49c43SSean Wang 	wmt_params.status = NULL;
2626a1c49c43SSean Wang 
2627a1c49c43SSean Wang 	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
2628a1c49c43SSean Wang 	if (err < 0) {
2629a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
2630a1c49c43SSean Wang 		return err;
2631a1c49c43SSean Wang 	}
2632a1c49c43SSean Wang 
2633a1c49c43SSean Wang ignore_func_on:
2634a1c49c43SSean Wang 	/* Apply the low power environment setup */
2635a1c49c43SSean Wang 	tci_sleep.mode = 0x5;
2636a1c49c43SSean Wang 	tci_sleep.duration = cpu_to_le16(0x640);
2637a1c49c43SSean Wang 	tci_sleep.host_duration = cpu_to_le16(0x640);
2638a1c49c43SSean Wang 	tci_sleep.host_wakeup_pin = 0;
2639a1c49c43SSean Wang 	tci_sleep.time_compensation = 0;
2640a1c49c43SSean Wang 
2641a1c49c43SSean Wang 	skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep,
2642a1c49c43SSean Wang 			     HCI_INIT_TIMEOUT);
2643a1c49c43SSean Wang 	if (IS_ERR(skb)) {
2644a1c49c43SSean Wang 		err = PTR_ERR(skb);
2645a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to apply low power setting (%d)", err);
2646a1c49c43SSean Wang 		return err;
2647a1c49c43SSean Wang 	}
2648a1c49c43SSean Wang 	kfree_skb(skb);
2649a1c49c43SSean Wang 
2650fc342c4dSMark Chen done:
2651a1c49c43SSean Wang 	rettime = ktime_get();
2652a1c49c43SSean Wang 	delta = ktime_sub(rettime, calltime);
2653a1c49c43SSean Wang 	duration = (unsigned long long)ktime_to_ns(delta) >> 10;
2654a1c49c43SSean Wang 
2655a1c49c43SSean Wang 	bt_dev_info(hdev, "Device setup in %llu usecs", duration);
2656a1c49c43SSean Wang 
2657a1c49c43SSean Wang 	return 0;
2658a1c49c43SSean Wang }
2659a1c49c43SSean Wang 
2660a1c49c43SSean Wang static int btusb_mtk_shutdown(struct hci_dev *hdev)
2661a1c49c43SSean Wang {
2662a1c49c43SSean Wang 	struct btmtk_hci_wmt_params wmt_params;
2663a1c49c43SSean Wang 	u8 param = 0;
2664a1c49c43SSean Wang 	int err;
2665a1c49c43SSean Wang 
2666a1c49c43SSean Wang 	/* Disable the device */
2667a1c49c43SSean Wang 	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
2668a1c49c43SSean Wang 	wmt_params.flag = 0;
2669a1c49c43SSean Wang 	wmt_params.dlen = sizeof(param);
2670a1c49c43SSean Wang 	wmt_params.data = &param;
2671a1c49c43SSean Wang 	wmt_params.status = NULL;
2672a1c49c43SSean Wang 
2673a1c49c43SSean Wang 	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
2674a1c49c43SSean Wang 	if (err < 0) {
2675a1c49c43SSean Wang 		bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
2676a1c49c43SSean Wang 		return err;
2677a1c49c43SSean Wang 	}
2678a1c49c43SSean Wang 
2679a1c49c43SSean Wang 	return 0;
2680a1c49c43SSean Wang }
2681a1c49c43SSean Wang 
2682e9478026Smark-yw.chen static void btusb_mtk_cmd_timeout(struct hci_dev *hdev)
2683e9478026Smark-yw.chen {
2684e9478026Smark-yw.chen 	struct btusb_data *data = hci_get_drvdata(hdev);
2685e9478026Smark-yw.chen 	u32 val;
2686e9478026Smark-yw.chen 	int err, retry = 0;
2687e9478026Smark-yw.chen 
2688e9478026Smark-yw.chen 	/* It's MediaTek specific bluetooth reset mechanism via USB */
2689e9478026Smark-yw.chen 	if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
2690e9478026Smark-yw.chen 		bt_dev_err(hdev, "last reset failed? Not resetting again");
2691e9478026Smark-yw.chen 		return;
2692e9478026Smark-yw.chen 	}
2693e9478026Smark-yw.chen 
2694e9478026Smark-yw.chen 	err = usb_autopm_get_interface(data->intf);
2695e9478026Smark-yw.chen 	if (err < 0)
2696e9478026Smark-yw.chen 		return;
2697e9478026Smark-yw.chen 
2698e9478026Smark-yw.chen 	btusb_stop_traffic(data);
2699e9478026Smark-yw.chen 	usb_kill_anchored_urbs(&data->tx_anchor);
2700e9478026Smark-yw.chen 
2701e9478026Smark-yw.chen 	/* It's Device EndPoint Reset Option Register */
2702e9478026Smark-yw.chen 	bt_dev_dbg(hdev, "Initiating reset mechanism via uhw");
2703e9478026Smark-yw.chen 	btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT);
2704e9478026Smark-yw.chen 	btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val);
2705e9478026Smark-yw.chen 
2706e9478026Smark-yw.chen 	/* Reset the bluetooth chip via USB interface. */
2707e9478026Smark-yw.chen 	btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1);
2708e9478026Smark-yw.chen 	btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF);
2709e9478026Smark-yw.chen 	btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val);
2710e9478026Smark-yw.chen 	btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF);
2711e9478026Smark-yw.chen 	btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val);
2712e9478026Smark-yw.chen 	/* MT7921 need to delay 20ms between toggle reset bit */
2713e9478026Smark-yw.chen 	msleep(20);
2714e9478026Smark-yw.chen 	btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0);
2715e9478026Smark-yw.chen 	btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val);
2716e9478026Smark-yw.chen 
2717e9478026Smark-yw.chen 	/* Poll the register until reset is completed */
2718e9478026Smark-yw.chen 	do {
2719e9478026Smark-yw.chen 		btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val);
2720e9478026Smark-yw.chen 		if (val & MTK_BT_RST_DONE) {
2721e9478026Smark-yw.chen 			bt_dev_dbg(hdev, "Bluetooth Reset Successfully");
2722e9478026Smark-yw.chen 			break;
2723e9478026Smark-yw.chen 		}
2724e9478026Smark-yw.chen 
2725e9478026Smark-yw.chen 		bt_dev_dbg(hdev, "Polling Bluetooth Reset CR");
2726e9478026Smark-yw.chen 		retry++;
2727e9478026Smark-yw.chen 		msleep(MTK_BT_RESET_WAIT_MS);
2728e9478026Smark-yw.chen 	} while (retry < MTK_BT_RESET_NUM_TRIES);
2729e9478026Smark-yw.chen 
2730e9478026Smark-yw.chen 	btusb_mtk_id_get(data, 0x70010200, &val);
2731e9478026Smark-yw.chen 	if (!val)
2732e9478026Smark-yw.chen 		bt_dev_err(hdev, "Can't get device id, subsys reset fail.");
2733e9478026Smark-yw.chen 
2734e9478026Smark-yw.chen 	usb_queue_reset_device(data->intf);
2735e9478026Smark-yw.chen 
2736e9478026Smark-yw.chen 	clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags);
2737e9478026Smark-yw.chen }
2738e9478026Smark-yw.chen 
27390b10c8c8Smark-yw.chen static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
27400b10c8c8Smark-yw.chen {
27410b10c8c8Smark-yw.chen 	struct btusb_data *data = hci_get_drvdata(hdev);
27420b10c8c8Smark-yw.chen 	u16 handle = le16_to_cpu(hci_acl_hdr(skb)->handle);
27430b10c8c8Smark-yw.chen 
27440b10c8c8Smark-yw.chen 	switch (handle) {
27450b10c8c8Smark-yw.chen 	case 0xfc6f:		/* Firmware dump from device */
27460b10c8c8Smark-yw.chen 		/* When the firmware hangs, the device can no longer
27470b10c8c8Smark-yw.chen 		 * suspend and thus disable auto-suspend.
27480b10c8c8Smark-yw.chen 		 */
27490b10c8c8Smark-yw.chen 		usb_disable_autosuspend(data->udev);
2750146af226Smark-yw.chen 		fallthrough;
27510b10c8c8Smark-yw.chen 	case 0x05ff:		/* Firmware debug logging 1 */
27520b10c8c8Smark-yw.chen 	case 0x05fe:		/* Firmware debug logging 2 */
27530b10c8c8Smark-yw.chen 		return hci_recv_diag(hdev, skb);
27540b10c8c8Smark-yw.chen 	}
27550b10c8c8Smark-yw.chen 
27560b10c8c8Smark-yw.chen 	return hci_recv_frame(hdev, skb);
27570b10c8c8Smark-yw.chen }
27580b10c8c8Smark-yw.chen 
2759a4ccc9e3SRajat Jain #ifdef CONFIG_PM
2760a4ccc9e3SRajat Jain /* Configure an out-of-band gpio as wake-up pin, if specified in device tree */
2761a4ccc9e3SRajat Jain static int marvell_config_oob_wake(struct hci_dev *hdev)
2762a4ccc9e3SRajat Jain {
2763a4ccc9e3SRajat Jain 	struct sk_buff *skb;
2764a4ccc9e3SRajat Jain 	struct btusb_data *data = hci_get_drvdata(hdev);
2765a4ccc9e3SRajat Jain 	struct device *dev = &data->udev->dev;
2766a4ccc9e3SRajat Jain 	u16 pin, gap, opcode;
2767a4ccc9e3SRajat Jain 	int ret;
2768a4ccc9e3SRajat Jain 	u8 cmd[5];
2769a4ccc9e3SRajat Jain 
2770a4ccc9e3SRajat Jain 	/* Move on if no wakeup pin specified */
2771a4ccc9e3SRajat Jain 	if (of_property_read_u16(dev->of_node, "marvell,wakeup-pin", &pin) ||
2772a4ccc9e3SRajat Jain 	    of_property_read_u16(dev->of_node, "marvell,wakeup-gap-ms", &gap))
2773a4ccc9e3SRajat Jain 		return 0;
2774a4ccc9e3SRajat Jain 
2775a4ccc9e3SRajat Jain 	/* Vendor specific command to configure a GPIO as wake-up pin */
2776a4ccc9e3SRajat Jain 	opcode = hci_opcode_pack(0x3F, 0x59);
2777a4ccc9e3SRajat Jain 	cmd[0] = opcode & 0xFF;
2778a4ccc9e3SRajat Jain 	cmd[1] = opcode >> 8;
2779a4ccc9e3SRajat Jain 	cmd[2] = 2; /* length of parameters that follow */
2780a4ccc9e3SRajat Jain 	cmd[3] = pin;
2781a4ccc9e3SRajat Jain 	cmd[4] = gap; /* time in ms, for which wakeup pin should be asserted */
2782a4ccc9e3SRajat Jain 
2783a4ccc9e3SRajat Jain 	skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
2784a4ccc9e3SRajat Jain 	if (!skb) {
2785d84fc2c9SJoe Perches 		bt_dev_err(hdev, "%s: No memory", __func__);
2786a4ccc9e3SRajat Jain 		return -ENOMEM;
2787a4ccc9e3SRajat Jain 	}
2788a4ccc9e3SRajat Jain 
278959ae1d12SJohannes Berg 	skb_put_data(skb, cmd, sizeof(cmd));
2790a4ccc9e3SRajat Jain 	hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
2791a4ccc9e3SRajat Jain 
2792a4ccc9e3SRajat Jain 	ret = btusb_send_frame(hdev, skb);
2793a4ccc9e3SRajat Jain 	if (ret) {
2794d84fc2c9SJoe Perches 		bt_dev_err(hdev, "%s: configuration failed", __func__);
2795a4ccc9e3SRajat Jain 		kfree_skb(skb);
2796a4ccc9e3SRajat Jain 		return ret;
2797a4ccc9e3SRajat Jain 	}
2798a4ccc9e3SRajat Jain 
2799a4ccc9e3SRajat Jain 	return 0;
2800a4ccc9e3SRajat Jain }
2801a4ccc9e3SRajat Jain #endif
2802a4ccc9e3SRajat Jain 
2803ae8df494SAmitkumar Karwar static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
2804ae8df494SAmitkumar Karwar 				    const bdaddr_t *bdaddr)
2805ae8df494SAmitkumar Karwar {
2806ae8df494SAmitkumar Karwar 	struct sk_buff *skb;
2807ae8df494SAmitkumar Karwar 	u8 buf[8];
2808ae8df494SAmitkumar Karwar 	long ret;
2809ae8df494SAmitkumar Karwar 
2810ae8df494SAmitkumar Karwar 	buf[0] = 0xfe;
2811ae8df494SAmitkumar Karwar 	buf[1] = sizeof(bdaddr_t);
2812ae8df494SAmitkumar Karwar 	memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
2813ae8df494SAmitkumar Karwar 
2814ae8df494SAmitkumar Karwar 	skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT);
2815ae8df494SAmitkumar Karwar 	if (IS_ERR(skb)) {
2816ae8df494SAmitkumar Karwar 		ret = PTR_ERR(skb);
28172064ee33SMarcel Holtmann 		bt_dev_err(hdev, "changing Marvell device address failed (%ld)",
28182064ee33SMarcel Holtmann 			   ret);
2819ae8df494SAmitkumar Karwar 		return ret;
2820ae8df494SAmitkumar Karwar 	}
2821ae8df494SAmitkumar Karwar 	kfree_skb(skb);
2822ae8df494SAmitkumar Karwar 
2823ae8df494SAmitkumar Karwar 	return 0;
2824ae8df494SAmitkumar Karwar }
2825ae8df494SAmitkumar Karwar 
28265859223eSToshi Kikuchi static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
28275859223eSToshi Kikuchi 				    const bdaddr_t *bdaddr)
28285859223eSToshi Kikuchi {
28295859223eSToshi Kikuchi 	struct sk_buff *skb;
28305859223eSToshi Kikuchi 	u8 buf[10];
28315859223eSToshi Kikuchi 	long ret;
28325859223eSToshi Kikuchi 
28335859223eSToshi Kikuchi 	buf[0] = 0x01;
28345859223eSToshi Kikuchi 	buf[1] = 0x01;
28355859223eSToshi Kikuchi 	buf[2] = 0x00;
28365859223eSToshi Kikuchi 	buf[3] = sizeof(bdaddr_t);
28375859223eSToshi Kikuchi 	memcpy(buf + 4, bdaddr, sizeof(bdaddr_t));
28385859223eSToshi Kikuchi 
28395859223eSToshi Kikuchi 	skb = __hci_cmd_sync(hdev, 0xfc0b, sizeof(buf), buf, HCI_INIT_TIMEOUT);
28405859223eSToshi Kikuchi 	if (IS_ERR(skb)) {
28415859223eSToshi Kikuchi 		ret = PTR_ERR(skb);
28422064ee33SMarcel Holtmann 		bt_dev_err(hdev, "Change address command failed (%ld)", ret);
28435859223eSToshi Kikuchi 		return ret;
28445859223eSToshi Kikuchi 	}
28455859223eSToshi Kikuchi 	kfree_skb(skb);
28465859223eSToshi Kikuchi 
28475859223eSToshi Kikuchi 	return 0;
28485859223eSToshi Kikuchi }
28495859223eSToshi Kikuchi 
2850b40f58b9SRocky Liao static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
2851b40f58b9SRocky Liao 				const bdaddr_t *bdaddr)
2852b40f58b9SRocky Liao {
2853b40f58b9SRocky Liao 	struct sk_buff *skb;
2854b40f58b9SRocky Liao 	u8 buf[6];
2855b40f58b9SRocky Liao 	long ret;
2856b40f58b9SRocky Liao 
2857b40f58b9SRocky Liao 	memcpy(buf, bdaddr, sizeof(bdaddr_t));
2858b40f58b9SRocky Liao 
2859b40f58b9SRocky Liao 	skb = __hci_cmd_sync_ev(hdev, 0xfc14, sizeof(buf), buf,
2860b40f58b9SRocky Liao 				HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
2861b40f58b9SRocky Liao 	if (IS_ERR(skb)) {
2862b40f58b9SRocky Liao 		ret = PTR_ERR(skb);
2863b40f58b9SRocky Liao 		bt_dev_err(hdev, "Change address command failed (%ld)", ret);
2864b40f58b9SRocky Liao 		return ret;
2865b40f58b9SRocky Liao 	}
2866b40f58b9SRocky Liao 	kfree_skb(skb);
2867b40f58b9SRocky Liao 
2868b40f58b9SRocky Liao 	return 0;
2869b40f58b9SRocky Liao }
2870b40f58b9SRocky Liao 
28713267c884SKim, Ben Young Tae #define QCA_DFU_PACKET_LEN	4096
28723267c884SKim, Ben Young Tae 
28733267c884SKim, Ben Young Tae #define QCA_GET_TARGET_VERSION	0x09
28743267c884SKim, Ben Young Tae #define QCA_CHECK_STATUS	0x05
28753267c884SKim, Ben Young Tae #define QCA_DFU_DOWNLOAD	0x01
28763267c884SKim, Ben Young Tae 
28773267c884SKim, Ben Young Tae #define QCA_SYSCFG_UPDATED	0x40
28783267c884SKim, Ben Young Tae #define QCA_PATCH_UPDATED	0x80
28793267c884SKim, Ben Young Tae #define QCA_DFU_TIMEOUT		3000
2880ef2862a1STim Jiang #define QCA_FLAG_MULTI_NVM      0x80
28813267c884SKim, Ben Young Tae 
2882d6cba4e6STim Jiang #define WCN6855_2_0_RAM_VERSION_GF 0x400c1200
2883d6cba4e6STim Jiang #define WCN6855_2_1_RAM_VERSION_GF 0x400c1211
2884d6cba4e6STim Jiang 
28853267c884SKim, Ben Young Tae struct qca_version {
28863267c884SKim, Ben Young Tae 	__le32	rom_version;
28873267c884SKim, Ben Young Tae 	__le32	patch_version;
28883267c884SKim, Ben Young Tae 	__le32	ram_version;
2889ef2862a1STim Jiang 	__le16	board_id;
2890ef2862a1STim Jiang 	__le16	flag;
28913267c884SKim, Ben Young Tae 	__u8	reserved[4];
28923267c884SKim, Ben Young Tae } __packed;
28933267c884SKim, Ben Young Tae 
28943267c884SKim, Ben Young Tae struct qca_rampatch_version {
2895b40f58b9SRocky Liao 	__le16	rom_version_high;
2896b40f58b9SRocky Liao 	__le16  rom_version_low;
28973267c884SKim, Ben Young Tae 	__le16	patch_version;
28983267c884SKim, Ben Young Tae } __packed;
28993267c884SKim, Ben Young Tae 
29003267c884SKim, Ben Young Tae struct qca_device_info {
2901bf906b3dSKim, Ben Young Tae 	u32	rom_version;
2902bf906b3dSKim, Ben Young Tae 	u8	rampatch_hdr;	/* length of header in rampatch */
2903bf906b3dSKim, Ben Young Tae 	u8	nvm_hdr;	/* length of header in NVM */
2904bf906b3dSKim, Ben Young Tae 	u8	ver_offset;	/* offset of version structure in rampatch */
29053267c884SKim, Ben Young Tae };
29063267c884SKim, Ben Young Tae 
29073267c884SKim, Ben Young Tae static const struct qca_device_info qca_devices_table[] = {
2908b40f58b9SRocky Liao 	{ 0x00000100, 20, 4,  8 }, /* Rome 1.0 */
2909b40f58b9SRocky Liao 	{ 0x00000101, 20, 4,  8 }, /* Rome 1.1 */
2910b40f58b9SRocky Liao 	{ 0x00000200, 28, 4, 16 }, /* Rome 2.0 */
2911b40f58b9SRocky Liao 	{ 0x00000201, 28, 4, 16 }, /* Rome 2.1 */
2912b40f58b9SRocky Liao 	{ 0x00000300, 28, 4, 16 }, /* Rome 3.0 */
2913b40f58b9SRocky Liao 	{ 0x00000302, 28, 4, 16 }, /* Rome 3.2 */
2914b40f58b9SRocky Liao 	{ 0x00130100, 40, 4, 16 }, /* WCN6855 1.0 */
2915b40f58b9SRocky Liao 	{ 0x00130200, 40, 4, 16 }, /* WCN6855 2.0 */
2916d6cba4e6STim Jiang 	{ 0x00130201, 40, 4, 16 }, /* WCN6855 2.1 */
29173267c884SKim, Ben Young Tae };
29183267c884SKim, Ben Young Tae 
2919803cdb8cSTakashi Iwai static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
29203267c884SKim, Ben Young Tae 				     void *data, u16 size)
29213267c884SKim, Ben Young Tae {
29223267c884SKim, Ben Young Tae 	int pipe, err;
29233267c884SKim, Ben Young Tae 	u8 *buf;
29243267c884SKim, Ben Young Tae 
29253267c884SKim, Ben Young Tae 	buf = kmalloc(size, GFP_KERNEL);
29263267c884SKim, Ben Young Tae 	if (!buf)
29273267c884SKim, Ben Young Tae 		return -ENOMEM;
29283267c884SKim, Ben Young Tae 
29293267c884SKim, Ben Young Tae 	/* Found some of USB hosts have IOT issues with ours so that we should
29303267c884SKim, Ben Young Tae 	 * not wait until HCI layer is ready.
29313267c884SKim, Ben Young Tae 	 */
29323267c884SKim, Ben Young Tae 	pipe = usb_rcvctrlpipe(udev, 0);
29333267c884SKim, Ben Young Tae 	err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN,
29343267c884SKim, Ben Young Tae 			      0, 0, buf, size, USB_CTRL_SET_TIMEOUT);
29353267c884SKim, Ben Young Tae 	if (err < 0) {
2936803cdb8cSTakashi Iwai 		dev_err(&udev->dev, "Failed to access otp area (%d)", err);
29373267c884SKim, Ben Young Tae 		goto done;
29383267c884SKim, Ben Young Tae 	}
29393267c884SKim, Ben Young Tae 
29403267c884SKim, Ben Young Tae 	memcpy(data, buf, size);
29413267c884SKim, Ben Young Tae 
29423267c884SKim, Ben Young Tae done:
29433267c884SKim, Ben Young Tae 	kfree(buf);
29443267c884SKim, Ben Young Tae 
29453267c884SKim, Ben Young Tae 	return err;
29463267c884SKim, Ben Young Tae }
29473267c884SKim, Ben Young Tae 
29483267c884SKim, Ben Young Tae static int btusb_setup_qca_download_fw(struct hci_dev *hdev,
29493267c884SKim, Ben Young Tae 				       const struct firmware *firmware,
29503267c884SKim, Ben Young Tae 				       size_t hdr_size)
29513267c884SKim, Ben Young Tae {
29523267c884SKim, Ben Young Tae 	struct btusb_data *btdata = hci_get_drvdata(hdev);
29533267c884SKim, Ben Young Tae 	struct usb_device *udev = btdata->udev;
29543267c884SKim, Ben Young Tae 	size_t count, size, sent = 0;
29553267c884SKim, Ben Young Tae 	int pipe, len, err;
29563267c884SKim, Ben Young Tae 	u8 *buf;
29573267c884SKim, Ben Young Tae 
29583267c884SKim, Ben Young Tae 	buf = kmalloc(QCA_DFU_PACKET_LEN, GFP_KERNEL);
29593267c884SKim, Ben Young Tae 	if (!buf)
29603267c884SKim, Ben Young Tae 		return -ENOMEM;
29613267c884SKim, Ben Young Tae 
29623267c884SKim, Ben Young Tae 	count = firmware->size;
29633267c884SKim, Ben Young Tae 
29643267c884SKim, Ben Young Tae 	size = min_t(size_t, count, hdr_size);
29653267c884SKim, Ben Young Tae 	memcpy(buf, firmware->data, size);
29663267c884SKim, Ben Young Tae 
29673267c884SKim, Ben Young Tae 	/* USB patches should go down to controller through USB path
29683267c884SKim, Ben Young Tae 	 * because binary format fits to go down through USB channel.
29693267c884SKim, Ben Young Tae 	 * USB control path is for patching headers and USB bulk is for
29703267c884SKim, Ben Young Tae 	 * patch body.
29713267c884SKim, Ben Young Tae 	 */
29723267c884SKim, Ben Young Tae 	pipe = usb_sndctrlpipe(udev, 0);
29733267c884SKim, Ben Young Tae 	err = usb_control_msg(udev, pipe, QCA_DFU_DOWNLOAD, USB_TYPE_VENDOR,
29743267c884SKim, Ben Young Tae 			      0, 0, buf, size, USB_CTRL_SET_TIMEOUT);
29753267c884SKim, Ben Young Tae 	if (err < 0) {
29762064ee33SMarcel Holtmann 		bt_dev_err(hdev, "Failed to send headers (%d)", err);
29773267c884SKim, Ben Young Tae 		goto done;
29783267c884SKim, Ben Young Tae 	}
29793267c884SKim, Ben Young Tae 
29803267c884SKim, Ben Young Tae 	sent += size;
29813267c884SKim, Ben Young Tae 	count -= size;
29823267c884SKim, Ben Young Tae 
29834f00bfb3STim Jiang 	/* ep2 need time to switch from function acl to function dfu,
29844f00bfb3STim Jiang 	 * so we add 20ms delay here.
29854f00bfb3STim Jiang 	 */
29864f00bfb3STim Jiang 	msleep(20);
29874f00bfb3STim Jiang 
29883267c884SKim, Ben Young Tae 	while (count) {
29893267c884SKim, Ben Young Tae 		size = min_t(size_t, count, QCA_DFU_PACKET_LEN);
29903267c884SKim, Ben Young Tae 
29913267c884SKim, Ben Young Tae 		memcpy(buf, firmware->data + sent, size);
29923267c884SKim, Ben Young Tae 
29933267c884SKim, Ben Young Tae 		pipe = usb_sndbulkpipe(udev, 0x02);
29943267c884SKim, Ben Young Tae 		err = usb_bulk_msg(udev, pipe, buf, size, &len,
29953267c884SKim, Ben Young Tae 				   QCA_DFU_TIMEOUT);
29963267c884SKim, Ben Young Tae 		if (err < 0) {
29972064ee33SMarcel Holtmann 			bt_dev_err(hdev, "Failed to send body at %zd of %zd (%d)",
29982064ee33SMarcel Holtmann 				   sent, firmware->size, err);
29993267c884SKim, Ben Young Tae 			break;
30003267c884SKim, Ben Young Tae 		}
30013267c884SKim, Ben Young Tae 
30023267c884SKim, Ben Young Tae 		if (size != len) {
30032064ee33SMarcel Holtmann 			bt_dev_err(hdev, "Failed to get bulk buffer");
30043267c884SKim, Ben Young Tae 			err = -EILSEQ;
30053267c884SKim, Ben Young Tae 			break;
30063267c884SKim, Ben Young Tae 		}
30073267c884SKim, Ben Young Tae 
30083267c884SKim, Ben Young Tae 		sent  += size;
30093267c884SKim, Ben Young Tae 		count -= size;
30103267c884SKim, Ben Young Tae 	}
30113267c884SKim, Ben Young Tae 
30123267c884SKim, Ben Young Tae done:
30133267c884SKim, Ben Young Tae 	kfree(buf);
30143267c884SKim, Ben Young Tae 	return err;
30153267c884SKim, Ben Young Tae }
30163267c884SKim, Ben Young Tae 
30173267c884SKim, Ben Young Tae static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
30183267c884SKim, Ben Young Tae 					 struct qca_version *ver,
30193267c884SKim, Ben Young Tae 					 const struct qca_device_info *info)
30203267c884SKim, Ben Young Tae {
30213267c884SKim, Ben Young Tae 	struct qca_rampatch_version *rver;
30223267c884SKim, Ben Young Tae 	const struct firmware *fw;
3023b40f58b9SRocky Liao 	u32 ver_rom, ver_patch, rver_rom;
3024b40f58b9SRocky Liao 	u16 rver_rom_low, rver_rom_high, rver_patch;
30253267c884SKim, Ben Young Tae 	char fwname[64];
30263267c884SKim, Ben Young Tae 	int err;
30273267c884SKim, Ben Young Tae 
3028bf906b3dSKim, Ben Young Tae 	ver_rom = le32_to_cpu(ver->rom_version);
3029bf906b3dSKim, Ben Young Tae 	ver_patch = le32_to_cpu(ver->patch_version);
3030bf906b3dSKim, Ben Young Tae 
3031bf906b3dSKim, Ben Young Tae 	snprintf(fwname, sizeof(fwname), "qca/rampatch_usb_%08x.bin", ver_rom);
30323267c884SKim, Ben Young Tae 
30333267c884SKim, Ben Young Tae 	err = request_firmware(&fw, fwname, &hdev->dev);
30343267c884SKim, Ben Young Tae 	if (err) {
30352064ee33SMarcel Holtmann 		bt_dev_err(hdev, "failed to request rampatch file: %s (%d)",
30362064ee33SMarcel Holtmann 			   fwname, err);
30373267c884SKim, Ben Young Tae 		return err;
30383267c884SKim, Ben Young Tae 	}
30393267c884SKim, Ben Young Tae 
30402064ee33SMarcel Holtmann 	bt_dev_info(hdev, "using rampatch file: %s", fwname);
30413267c884SKim, Ben Young Tae 
3042bf906b3dSKim, Ben Young Tae 	rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);
3043b40f58b9SRocky Liao 	rver_rom_low = le16_to_cpu(rver->rom_version_low);
3044bf906b3dSKim, Ben Young Tae 	rver_patch = le16_to_cpu(rver->patch_version);
3045bf906b3dSKim, Ben Young Tae 
3046b40f58b9SRocky Liao 	if (ver_rom & ~0xffffU) {
3047b40f58b9SRocky Liao 		rver_rom_high = le16_to_cpu(rver->rom_version_high);
3048b40f58b9SRocky Liao 		rver_rom = le32_to_cpu(rver_rom_high << 16 | rver_rom_low);
3049b40f58b9SRocky Liao 	} else {
3050b40f58b9SRocky Liao 		rver_rom = rver_rom_low;
3051b40f58b9SRocky Liao 	}
3052b40f58b9SRocky Liao 
30532064ee33SMarcel Holtmann 	bt_dev_info(hdev, "QCA: patch rome 0x%x build 0x%x, "
30542064ee33SMarcel Holtmann 		    "firmware rome 0x%x build 0x%x",
30552064ee33SMarcel Holtmann 		    rver_rom, rver_patch, ver_rom, ver_patch);
3056bf906b3dSKim, Ben Young Tae 
3057bf906b3dSKim, Ben Young Tae 	if (rver_rom != ver_rom || rver_patch <= ver_patch) {
30582064ee33SMarcel Holtmann 		bt_dev_err(hdev, "rampatch file version did not match with firmware");
30593267c884SKim, Ben Young Tae 		err = -EINVAL;
30603267c884SKim, Ben Young Tae 		goto done;
30613267c884SKim, Ben Young Tae 	}
30623267c884SKim, Ben Young Tae 
30633267c884SKim, Ben Young Tae 	err = btusb_setup_qca_download_fw(hdev, fw, info->rampatch_hdr);
30643267c884SKim, Ben Young Tae 
30653267c884SKim, Ben Young Tae done:
30663267c884SKim, Ben Young Tae 	release_firmware(fw);
30673267c884SKim, Ben Young Tae 
30683267c884SKim, Ben Young Tae 	return err;
30693267c884SKim, Ben Young Tae }
30703267c884SKim, Ben Young Tae 
3071d6cba4e6STim Jiang static void btusb_generate_qca_nvm_name(char *fwname, size_t max_size,
3072d6cba4e6STim Jiang 					const struct qca_version *ver)
3073d6cba4e6STim Jiang {
3074d6cba4e6STim Jiang 	u32 rom_version = le32_to_cpu(ver->rom_version);
3075d6cba4e6STim Jiang 	u16 flag = le16_to_cpu(ver->flag);
3076d6cba4e6STim Jiang 
3077d6cba4e6STim Jiang 	if (((flag >> 8) & 0xff) == QCA_FLAG_MULTI_NVM) {
3078d6cba4e6STim Jiang 		u16 board_id = le16_to_cpu(ver->board_id);
3079d6cba4e6STim Jiang 		const char *variant;
3080d6cba4e6STim Jiang 
3081d6cba4e6STim Jiang 		switch (le32_to_cpu(ver->ram_version)) {
3082d6cba4e6STim Jiang 		case WCN6855_2_0_RAM_VERSION_GF:
3083d6cba4e6STim Jiang 		case WCN6855_2_1_RAM_VERSION_GF:
3084d6cba4e6STim Jiang 			variant = "_gf";
3085d6cba4e6STim Jiang 			break;
3086d6cba4e6STim Jiang 		default:
3087d6cba4e6STim Jiang 			variant = "";
3088d6cba4e6STim Jiang 			break;
3089d6cba4e6STim Jiang 		}
3090d6cba4e6STim Jiang 
3091d6cba4e6STim Jiang 		if (board_id == 0) {
3092d6cba4e6STim Jiang 			snprintf(fwname, max_size, "qca/nvm_usb_%08x%s.bin",
3093d6cba4e6STim Jiang 				rom_version, variant);
3094d6cba4e6STim Jiang 		} else {
3095d6cba4e6STim Jiang 			snprintf(fwname, max_size, "qca/nvm_usb_%08x%s_%04x.bin",
3096d6cba4e6STim Jiang 				rom_version, variant, board_id);
3097d6cba4e6STim Jiang 		}
3098d6cba4e6STim Jiang 	} else {
3099d6cba4e6STim Jiang 		snprintf(fwname, max_size, "qca/nvm_usb_%08x.bin",
3100d6cba4e6STim Jiang 			rom_version);
3101d6cba4e6STim Jiang 	}
3102d6cba4e6STim Jiang 
3103d6cba4e6STim Jiang }
3104d6cba4e6STim Jiang 
31053267c884SKim, Ben Young Tae static int btusb_setup_qca_load_nvm(struct hci_dev *hdev,
31063267c884SKim, Ben Young Tae 				    struct qca_version *ver,
31073267c884SKim, Ben Young Tae 				    const struct qca_device_info *info)
31083267c884SKim, Ben Young Tae {
31093267c884SKim, Ben Young Tae 	const struct firmware *fw;
31103267c884SKim, Ben Young Tae 	char fwname[64];
31113267c884SKim, Ben Young Tae 	int err;
31123267c884SKim, Ben Young Tae 
3113d6cba4e6STim Jiang 	btusb_generate_qca_nvm_name(fwname, sizeof(fwname), ver);
31143267c884SKim, Ben Young Tae 
31153267c884SKim, Ben Young Tae 	err = request_firmware(&fw, fwname, &hdev->dev);
31163267c884SKim, Ben Young Tae 	if (err) {
31172064ee33SMarcel Holtmann 		bt_dev_err(hdev, "failed to request NVM file: %s (%d)",
31182064ee33SMarcel Holtmann 			   fwname, err);
31193267c884SKim, Ben Young Tae 		return err;
31203267c884SKim, Ben Young Tae 	}
31213267c884SKim, Ben Young Tae 
31222064ee33SMarcel Holtmann 	bt_dev_info(hdev, "using NVM file: %s", fwname);
31233267c884SKim, Ben Young Tae 
31243267c884SKim, Ben Young Tae 	err = btusb_setup_qca_download_fw(hdev, fw, info->nvm_hdr);
31253267c884SKim, Ben Young Tae 
31263267c884SKim, Ben Young Tae 	release_firmware(fw);
31273267c884SKim, Ben Young Tae 
31283267c884SKim, Ben Young Tae 	return err;
31293267c884SKim, Ben Young Tae }
31303267c884SKim, Ben Young Tae 
3131803cdb8cSTakashi Iwai /* identify the ROM version and check whether patches are needed */
3132803cdb8cSTakashi Iwai static bool btusb_qca_need_patch(struct usb_device *udev)
3133803cdb8cSTakashi Iwai {
3134803cdb8cSTakashi Iwai 	struct qca_version ver;
3135803cdb8cSTakashi Iwai 
3136803cdb8cSTakashi Iwai 	if (btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
3137803cdb8cSTakashi Iwai 				      sizeof(ver)) < 0)
3138803cdb8cSTakashi Iwai 		return false;
3139803cdb8cSTakashi Iwai 	/* only low ROM versions need patches */
3140803cdb8cSTakashi Iwai 	return !(le32_to_cpu(ver.rom_version) & ~0xffffU);
3141803cdb8cSTakashi Iwai }
3142803cdb8cSTakashi Iwai 
31433267c884SKim, Ben Young Tae static int btusb_setup_qca(struct hci_dev *hdev)
31443267c884SKim, Ben Young Tae {
3145803cdb8cSTakashi Iwai 	struct btusb_data *btdata = hci_get_drvdata(hdev);
3146803cdb8cSTakashi Iwai 	struct usb_device *udev = btdata->udev;
31473267c884SKim, Ben Young Tae 	const struct qca_device_info *info = NULL;
31483267c884SKim, Ben Young Tae 	struct qca_version ver;
3149bf906b3dSKim, Ben Young Tae 	u32 ver_rom;
31503267c884SKim, Ben Young Tae 	u8 status;
31513267c884SKim, Ben Young Tae 	int i, err;
31523267c884SKim, Ben Young Tae 
3153803cdb8cSTakashi Iwai 	err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
31543267c884SKim, Ben Young Tae 					sizeof(ver));
31553267c884SKim, Ben Young Tae 	if (err < 0)
31563267c884SKim, Ben Young Tae 		return err;
31573267c884SKim, Ben Young Tae 
3158bf906b3dSKim, Ben Young Tae 	ver_rom = le32_to_cpu(ver.rom_version);
3159803cdb8cSTakashi Iwai 
31603267c884SKim, Ben Young Tae 	for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
3161bf906b3dSKim, Ben Young Tae 		if (ver_rom == qca_devices_table[i].rom_version)
31623267c884SKim, Ben Young Tae 			info = &qca_devices_table[i];
31633267c884SKim, Ben Young Tae 	}
31643267c884SKim, Ben Young Tae 	if (!info) {
3165234f414eSHui Wang 		/* If the rom_version is not matched in the qca_devices_table
3166234f414eSHui Wang 		 * and the high ROM version is not zero, we assume this chip no
3167234f414eSHui Wang 		 * need to load the rampatch and nvm.
3168234f414eSHui Wang 		 */
3169234f414eSHui Wang 		if (ver_rom & ~0xffffU)
3170234f414eSHui Wang 			return 0;
3171234f414eSHui Wang 
31722064ee33SMarcel Holtmann 		bt_dev_err(hdev, "don't support firmware rome 0x%x", ver_rom);
31733267c884SKim, Ben Young Tae 		return -ENODEV;
31743267c884SKim, Ben Young Tae 	}
31753267c884SKim, Ben Young Tae 
3176803cdb8cSTakashi Iwai 	err = btusb_qca_send_vendor_req(udev, QCA_CHECK_STATUS, &status,
31773267c884SKim, Ben Young Tae 					sizeof(status));
31783267c884SKim, Ben Young Tae 	if (err < 0)
31793267c884SKim, Ben Young Tae 		return err;
31803267c884SKim, Ben Young Tae 
31813267c884SKim, Ben Young Tae 	if (!(status & QCA_PATCH_UPDATED)) {
31823267c884SKim, Ben Young Tae 		err = btusb_setup_qca_load_rampatch(hdev, &ver, info);
31833267c884SKim, Ben Young Tae 		if (err < 0)
31843267c884SKim, Ben Young Tae 			return err;
31853267c884SKim, Ben Young Tae 	}
31863267c884SKim, Ben Young Tae 
3187ef2862a1STim Jiang 	err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
3188ef2862a1STim Jiang 					sizeof(ver));
3189ef2862a1STim Jiang 	if (err < 0)
3190ef2862a1STim Jiang 		return err;
3191ef2862a1STim Jiang 
31923267c884SKim, Ben Young Tae 	if (!(status & QCA_SYSCFG_UPDATED)) {
31933267c884SKim, Ben Young Tae 		err = btusb_setup_qca_load_nvm(hdev, &ver, info);
31943267c884SKim, Ben Young Tae 		if (err < 0)
31953267c884SKim, Ben Young Tae 			return err;
31963267c884SKim, Ben Young Tae 	}
31973267c884SKim, Ben Young Tae 
31983267c884SKim, Ben Young Tae 	return 0;
31993267c884SKim, Ben Young Tae }
32003267c884SKim, Ben Young Tae 
32019d08f504SMarcel Holtmann static inline int __set_diag_interface(struct hci_dev *hdev)
32029d08f504SMarcel Holtmann {
32039d08f504SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
32049d08f504SMarcel Holtmann 	struct usb_interface *intf = data->diag;
32059d08f504SMarcel Holtmann 	int i;
32069d08f504SMarcel Holtmann 
32079d08f504SMarcel Holtmann 	if (!data->diag)
32089d08f504SMarcel Holtmann 		return -ENODEV;
32099d08f504SMarcel Holtmann 
32109d08f504SMarcel Holtmann 	data->diag_tx_ep = NULL;
32119d08f504SMarcel Holtmann 	data->diag_rx_ep = NULL;
32129d08f504SMarcel Holtmann 
32139d08f504SMarcel Holtmann 	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
32149d08f504SMarcel Holtmann 		struct usb_endpoint_descriptor *ep_desc;
32159d08f504SMarcel Holtmann 
32169d08f504SMarcel Holtmann 		ep_desc = &intf->cur_altsetting->endpoint[i].desc;
32179d08f504SMarcel Holtmann 
32189d08f504SMarcel Holtmann 		if (!data->diag_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
32199d08f504SMarcel Holtmann 			data->diag_tx_ep = ep_desc;
32209d08f504SMarcel Holtmann 			continue;
32219d08f504SMarcel Holtmann 		}
32229d08f504SMarcel Holtmann 
32239d08f504SMarcel Holtmann 		if (!data->diag_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
32249d08f504SMarcel Holtmann 			data->diag_rx_ep = ep_desc;
32259d08f504SMarcel Holtmann 			continue;
32269d08f504SMarcel Holtmann 		}
32279d08f504SMarcel Holtmann 	}
32289d08f504SMarcel Holtmann 
32299d08f504SMarcel Holtmann 	if (!data->diag_tx_ep || !data->diag_rx_ep) {
32302064ee33SMarcel Holtmann 		bt_dev_err(hdev, "invalid diagnostic descriptors");
32319d08f504SMarcel Holtmann 		return -ENODEV;
32329d08f504SMarcel Holtmann 	}
32339d08f504SMarcel Holtmann 
32349d08f504SMarcel Holtmann 	return 0;
32359d08f504SMarcel Holtmann }
32369d08f504SMarcel Holtmann 
32379d08f504SMarcel Holtmann static struct urb *alloc_diag_urb(struct hci_dev *hdev, bool enable)
32389d08f504SMarcel Holtmann {
32399d08f504SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
32409d08f504SMarcel Holtmann 	struct sk_buff *skb;
32419d08f504SMarcel Holtmann 	struct urb *urb;
32429d08f504SMarcel Holtmann 	unsigned int pipe;
32439d08f504SMarcel Holtmann 
32449d08f504SMarcel Holtmann 	if (!data->diag_tx_ep)
32459d08f504SMarcel Holtmann 		return ERR_PTR(-ENODEV);
32469d08f504SMarcel Holtmann 
32479d08f504SMarcel Holtmann 	urb = usb_alloc_urb(0, GFP_KERNEL);
32489d08f504SMarcel Holtmann 	if (!urb)
32499d08f504SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
32509d08f504SMarcel Holtmann 
32519d08f504SMarcel Holtmann 	skb = bt_skb_alloc(2, GFP_KERNEL);
32529d08f504SMarcel Holtmann 	if (!skb) {
32539d08f504SMarcel Holtmann 		usb_free_urb(urb);
32549d08f504SMarcel Holtmann 		return ERR_PTR(-ENOMEM);
32559d08f504SMarcel Holtmann 	}
32569d08f504SMarcel Holtmann 
3257634fef61SJohannes Berg 	skb_put_u8(skb, 0xf0);
3258634fef61SJohannes Berg 	skb_put_u8(skb, enable);
32599d08f504SMarcel Holtmann 
32609d08f504SMarcel Holtmann 	pipe = usb_sndbulkpipe(data->udev, data->diag_tx_ep->bEndpointAddress);
32619d08f504SMarcel Holtmann 
32629d08f504SMarcel Holtmann 	usb_fill_bulk_urb(urb, data->udev, pipe,
32639d08f504SMarcel Holtmann 			  skb->data, skb->len, btusb_tx_complete, skb);
32649d08f504SMarcel Holtmann 
32659d08f504SMarcel Holtmann 	skb->dev = (void *)hdev;
32669d08f504SMarcel Holtmann 
32679d08f504SMarcel Holtmann 	return urb;
32689d08f504SMarcel Holtmann }
32699d08f504SMarcel Holtmann 
32709d08f504SMarcel Holtmann static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable)
32719d08f504SMarcel Holtmann {
32729d08f504SMarcel Holtmann 	struct btusb_data *data = hci_get_drvdata(hdev);
32739d08f504SMarcel Holtmann 	struct urb *urb;
32749d08f504SMarcel Holtmann 
32759d08f504SMarcel Holtmann 	if (!data->diag)
32769d08f504SMarcel Holtmann 		return -ENODEV;
32779d08f504SMarcel Holtmann 
32789d08f504SMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
32799d08f504SMarcel Holtmann 		return -ENETDOWN;
32809d08f504SMarcel Holtmann 
32819d08f504SMarcel Holtmann 	urb = alloc_diag_urb(hdev, enable);
32829d08f504SMarcel Holtmann 	if (IS_ERR(urb))
32839d08f504SMarcel Holtmann 		return PTR_ERR(urb);
32849d08f504SMarcel Holtmann 
32859d08f504SMarcel Holtmann 	return submit_or_queue_tx_urb(hdev, urb);
32869d08f504SMarcel Holtmann }
32879d08f504SMarcel Holtmann 
3288fd913ef7SRajat Jain #ifdef CONFIG_PM
3289fd913ef7SRajat Jain static irqreturn_t btusb_oob_wake_handler(int irq, void *priv)
3290fd913ef7SRajat Jain {
3291fd913ef7SRajat Jain 	struct btusb_data *data = priv;
3292fd913ef7SRajat Jain 
3293fd913ef7SRajat Jain 	pm_wakeup_event(&data->udev->dev, 0);
3294017789f3SJeffy Chen 	pm_system_wakeup();
3295fd913ef7SRajat Jain 
3296fd913ef7SRajat Jain 	/* Disable only if not already disabled (keep it balanced) */
3297fd913ef7SRajat Jain 	if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) {
3298fd913ef7SRajat Jain 		disable_irq_nosync(irq);
3299fd913ef7SRajat Jain 		disable_irq_wake(irq);
3300fd913ef7SRajat Jain 	}
3301fd913ef7SRajat Jain 	return IRQ_HANDLED;
3302fd913ef7SRajat Jain }
3303fd913ef7SRajat Jain 
3304fd913ef7SRajat Jain static const struct of_device_id btusb_match_table[] = {
3305fd913ef7SRajat Jain 	{ .compatible = "usb1286,204e" },
33064c409af0SBrian Norris 	{ .compatible = "usbcf3,e300" }, /* QCA6174A */
33074c409af0SBrian Norris 	{ .compatible = "usb4ca,301a" }, /* QCA6174A (Lite-On) */
3308fd913ef7SRajat Jain 	{ }
3309fd913ef7SRajat Jain };
3310fd913ef7SRajat Jain MODULE_DEVICE_TABLE(of, btusb_match_table);
3311fd913ef7SRajat Jain 
3312fd913ef7SRajat Jain /* Use an oob wakeup pin? */
3313fd913ef7SRajat Jain static int btusb_config_oob_wake(struct hci_dev *hdev)
3314fd913ef7SRajat Jain {
3315fd913ef7SRajat Jain 	struct btusb_data *data = hci_get_drvdata(hdev);
3316fd913ef7SRajat Jain 	struct device *dev = &data->udev->dev;
3317fd913ef7SRajat Jain 	int irq, ret;
3318fd913ef7SRajat Jain 
3319fd913ef7SRajat Jain 	clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags);
3320fd913ef7SRajat Jain 
3321fd913ef7SRajat Jain 	if (!of_match_device(btusb_match_table, dev))
3322fd913ef7SRajat Jain 		return 0;
3323fd913ef7SRajat Jain 
3324fd913ef7SRajat Jain 	/* Move on if no IRQ specified */
3325fd913ef7SRajat Jain 	irq = of_irq_get_byname(dev->of_node, "wakeup");
3326fd913ef7SRajat Jain 	if (irq <= 0) {
3327fd913ef7SRajat Jain 		bt_dev_dbg(hdev, "%s: no OOB Wakeup IRQ in DT", __func__);
3328fd913ef7SRajat Jain 		return 0;
3329fd913ef7SRajat Jain 	}
3330fd913ef7SRajat Jain 
3331771acc7eSBrian Norris 	irq_set_status_flags(irq, IRQ_NOAUTOEN);
3332fd913ef7SRajat Jain 	ret = devm_request_irq(&hdev->dev, irq, btusb_oob_wake_handler,
3333fd913ef7SRajat Jain 			       0, "OOB Wake-on-BT", data);
3334fd913ef7SRajat Jain 	if (ret) {
3335fd913ef7SRajat Jain 		bt_dev_err(hdev, "%s: IRQ request failed", __func__);
3336fd913ef7SRajat Jain 		return ret;
3337fd913ef7SRajat Jain 	}
3338fd913ef7SRajat Jain 
3339fd913ef7SRajat Jain 	ret = device_init_wakeup(dev, true);
3340fd913ef7SRajat Jain 	if (ret) {
3341fd913ef7SRajat Jain 		bt_dev_err(hdev, "%s: failed to init_wakeup", __func__);
3342fd913ef7SRajat Jain 		return ret;
3343fd913ef7SRajat Jain 	}
3344fd913ef7SRajat Jain 
3345fd913ef7SRajat Jain 	data->oob_wake_irq = irq;
3346fd913ef7SRajat Jain 	bt_dev_info(hdev, "OOB Wake-on-BT configured at IRQ %u", irq);
3347fd913ef7SRajat Jain 	return 0;
3348fd913ef7SRajat Jain }
3349fd913ef7SRajat Jain #endif
3350fd913ef7SRajat Jain 
3351fc549102SHans de Goede static void btusb_check_needs_reset_resume(struct usb_interface *intf)
3352fc549102SHans de Goede {
3353fc549102SHans de Goede 	if (dmi_check_system(btusb_needs_reset_resume_table))
3354fc549102SHans de Goede 		interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
3355fc549102SHans de Goede }
3356fc549102SHans de Goede 
33574539ca67SLuiz Augusto von Dentz static bool btusb_wakeup(struct hci_dev *hdev)
3358b7d0bf11SAbhishek Pandit-Subedi {
3359b7d0bf11SAbhishek Pandit-Subedi 	struct btusb_data *data = hci_get_drvdata(hdev);
3360b7d0bf11SAbhishek Pandit-Subedi 
33614539ca67SLuiz Augusto von Dentz 	return device_may_wakeup(&data->udev->dev);
3362b7d0bf11SAbhishek Pandit-Subedi }
3363b7d0bf11SAbhishek Pandit-Subedi 
33643b0d5250STim Jiang static int btusb_shutdown_qca(struct hci_dev *hdev)
33653b0d5250STim Jiang {
33663b0d5250STim Jiang 	struct sk_buff *skb;
33673b0d5250STim Jiang 
33683b0d5250STim Jiang 	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
33693b0d5250STim Jiang 	if (IS_ERR(skb)) {
33703b0d5250STim Jiang 		bt_dev_err(hdev, "HCI reset during shutdown failed");
33713b0d5250STim Jiang 		return PTR_ERR(skb);
33723b0d5250STim Jiang 	}
33733b0d5250STim Jiang 	kfree_skb(skb);
33743b0d5250STim Jiang 
33753b0d5250STim Jiang 	return 0;
33763b0d5250STim Jiang }
33773b0d5250STim Jiang 
33785e23b923SMarcel Holtmann static int btusb_probe(struct usb_interface *intf,
33795e23b923SMarcel Holtmann 		       const struct usb_device_id *id)
33805e23b923SMarcel Holtmann {
33815e23b923SMarcel Holtmann 	struct usb_endpoint_descriptor *ep_desc;
3382dc786b2cSRajat Jain 	struct gpio_desc *reset_gpio;
33835e23b923SMarcel Holtmann 	struct btusb_data *data;
33845e23b923SMarcel Holtmann 	struct hci_dev *hdev;
338522f8e9dbSMarcel Holtmann 	unsigned ifnum_base;
338653492a66STedd Ho-Jeong An 	int i, err, priv_size;
33875e23b923SMarcel Holtmann 
33885e23b923SMarcel Holtmann 	BT_DBG("intf %p id %p", intf, id);
33895e23b923SMarcel Holtmann 
3390cfeb4145SMarcel Holtmann 	/* interface numbers are hardcoded in the spec */
339122f8e9dbSMarcel Holtmann 	if (intf->cur_altsetting->desc.bInterfaceNumber != 0) {
339222f8e9dbSMarcel Holtmann 		if (!(id->driver_info & BTUSB_IFNUM_2))
33935e23b923SMarcel Holtmann 			return -ENODEV;
339422f8e9dbSMarcel Holtmann 		if (intf->cur_altsetting->desc.bInterfaceNumber != 2)
339522f8e9dbSMarcel Holtmann 			return -ENODEV;
339622f8e9dbSMarcel Holtmann 	}
339722f8e9dbSMarcel Holtmann 
339822f8e9dbSMarcel Holtmann 	ifnum_base = intf->cur_altsetting->desc.bInterfaceNumber;
33995e23b923SMarcel Holtmann 
34005e23b923SMarcel Holtmann 	if (!id->driver_info) {
34015e23b923SMarcel Holtmann 		const struct usb_device_id *match;
340289e7533dSMarcel Holtmann 
34035e23b923SMarcel Holtmann 		match = usb_match_id(intf, blacklist_table);
34045e23b923SMarcel Holtmann 		if (match)
34055e23b923SMarcel Holtmann 			id = match;
34065e23b923SMarcel Holtmann 	}
34075e23b923SMarcel Holtmann 
3408cfeb4145SMarcel Holtmann 	if (id->driver_info == BTUSB_IGNORE)
3409cfeb4145SMarcel Holtmann 		return -ENODEV;
3410cfeb4145SMarcel Holtmann 
34112d25f8b4SSteven.Li 	if (id->driver_info & BTUSB_ATH3012) {
34122d25f8b4SSteven.Li 		struct usb_device *udev = interface_to_usbdev(intf);
34132d25f8b4SSteven.Li 
34142d25f8b4SSteven.Li 		/* Old firmware would otherwise let ath3k driver load
3415d98422cbSDerek Robson 		 * patch and sysconfig files
3416d98422cbSDerek Robson 		 */
3417803cdb8cSTakashi Iwai 		if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001 &&
3418803cdb8cSTakashi Iwai 		    !btusb_qca_need_patch(udev))
34192d25f8b4SSteven.Li 			return -ENODEV;
34202d25f8b4SSteven.Li 	}
34212d25f8b4SSteven.Li 
342298921dbdSSachin Kamat 	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
34235e23b923SMarcel Holtmann 	if (!data)
34245e23b923SMarcel Holtmann 		return -ENOMEM;
34255e23b923SMarcel Holtmann 
34265e23b923SMarcel Holtmann 	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
34275e23b923SMarcel Holtmann 		ep_desc = &intf->cur_altsetting->endpoint[i].desc;
34285e23b923SMarcel Holtmann 
34295e23b923SMarcel Holtmann 		if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) {
34305e23b923SMarcel Holtmann 			data->intr_ep = ep_desc;
34315e23b923SMarcel Holtmann 			continue;
34325e23b923SMarcel Holtmann 		}
34335e23b923SMarcel Holtmann 
34345e23b923SMarcel Holtmann 		if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
34355e23b923SMarcel Holtmann 			data->bulk_tx_ep = ep_desc;
34365e23b923SMarcel Holtmann 			continue;
34375e23b923SMarcel Holtmann 		}
34385e23b923SMarcel Holtmann 
34395e23b923SMarcel Holtmann 		if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
34405e23b923SMarcel Holtmann 			data->bulk_rx_ep = ep_desc;
34415e23b923SMarcel Holtmann 			continue;
34425e23b923SMarcel Holtmann 		}
34435e23b923SMarcel Holtmann 	}
34445e23b923SMarcel Holtmann 
344598921dbdSSachin Kamat 	if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
34465e23b923SMarcel Holtmann 		return -ENODEV;
34475e23b923SMarcel Holtmann 
3448893ba544SMarcel Holtmann 	if (id->driver_info & BTUSB_AMP) {
3449893ba544SMarcel Holtmann 		data->cmdreq_type = USB_TYPE_CLASS | 0x01;
3450893ba544SMarcel Holtmann 		data->cmdreq = 0x2b;
3451893ba544SMarcel Holtmann 	} else {
34527a9d4020SMarcel Holtmann 		data->cmdreq_type = USB_TYPE_CLASS;
3453893ba544SMarcel Holtmann 		data->cmdreq = 0x00;
3454893ba544SMarcel Holtmann 	}
34557a9d4020SMarcel Holtmann 
34565e23b923SMarcel Holtmann 	data->udev = interface_to_usbdev(intf);
34575fbcd260SMarcel Holtmann 	data->intf = intf;
34585e23b923SMarcel Holtmann 
34595e23b923SMarcel Holtmann 	INIT_WORK(&data->work, btusb_work);
34607bee549eSOliver Neukum 	INIT_WORK(&data->waker, btusb_waker);
3461803b5836SMarcel Holtmann 	init_usb_anchor(&data->deferred);
3462803b5836SMarcel Holtmann 	init_usb_anchor(&data->tx_anchor);
34637bee549eSOliver Neukum 	spin_lock_init(&data->txlock);
34645e23b923SMarcel Holtmann 
34655e23b923SMarcel Holtmann 	init_usb_anchor(&data->intr_anchor);
34665e23b923SMarcel Holtmann 	init_usb_anchor(&data->bulk_anchor);
34679bfa35feSMarcel Holtmann 	init_usb_anchor(&data->isoc_anchor);
34689d08f504SMarcel Holtmann 	init_usb_anchor(&data->diag_anchor);
3469a1c49c43SSean Wang 	init_usb_anchor(&data->ctrl_anchor);
3470803b5836SMarcel Holtmann 	spin_lock_init(&data->rxlock);
34715e23b923SMarcel Holtmann 
347253492a66STedd Ho-Jeong An 	priv_size = 0;
347353492a66STedd Ho-Jeong An 
3474019a1caaSTedd Ho-Jeong An 	data->recv_event = hci_recv_frame;
3475019a1caaSTedd Ho-Jeong An 	data->recv_bulk = btusb_recv_bulk;
3476019a1caaSTedd Ho-Jeong An 
347753492a66STedd Ho-Jeong An 	if (id->driver_info & BTUSB_INTEL_COMBINED) {
347853492a66STedd Ho-Jeong An 		/* Allocate extra space for Intel device */
347953492a66STedd Ho-Jeong An 		priv_size += sizeof(struct btintel_data);
348053492a66STedd Ho-Jeong An 
3481019a1caaSTedd Ho-Jeong An 		/* Override the rx handlers */
3482cda0dd78SMarcel Holtmann 		data->recv_event = btusb_recv_event_intel;
3483cda0dd78SMarcel Holtmann 		data->recv_bulk = btusb_recv_bulk_intel;
3484cda0dd78SMarcel Holtmann 	}
34852cbd3f5cSMarcel Holtmann 
34860b10c8c8Smark-yw.chen 	data->recv_acl = hci_recv_frame;
34870b10c8c8Smark-yw.chen 
348853492a66STedd Ho-Jeong An 	hdev = hci_alloc_dev_priv(priv_size);
348998921dbdSSachin Kamat 	if (!hdev)
34905e23b923SMarcel Holtmann 		return -ENOMEM;
34915e23b923SMarcel Holtmann 
3492c13854ceSMarcel Holtmann 	hdev->bus = HCI_USB;
3493155961e8SDavid Herrmann 	hci_set_drvdata(hdev, data);
34945e23b923SMarcel Holtmann 
3495893ba544SMarcel Holtmann 	if (id->driver_info & BTUSB_AMP)
3496893ba544SMarcel Holtmann 		hdev->dev_type = HCI_AMP;
3497893ba544SMarcel Holtmann 	else
3498ca8bee5dSMarcel Holtmann 		hdev->dev_type = HCI_PRIMARY;
3499893ba544SMarcel Holtmann 
35005e23b923SMarcel Holtmann 	data->hdev = hdev;
35015e23b923SMarcel Holtmann 
35025e23b923SMarcel Holtmann 	SET_HCIDEV_DEV(hdev, &intf->dev);
35035e23b923SMarcel Holtmann 
3504dc786b2cSRajat Jain 	reset_gpio = gpiod_get_optional(&data->udev->dev, "reset",
3505dc786b2cSRajat Jain 					GPIOD_OUT_LOW);
3506dc786b2cSRajat Jain 	if (IS_ERR(reset_gpio)) {
3507dc786b2cSRajat Jain 		err = PTR_ERR(reset_gpio);
3508dc786b2cSRajat Jain 		goto out_free_dev;
3509dc786b2cSRajat Jain 	} else if (reset_gpio) {
3510dc786b2cSRajat Jain 		data->reset_gpio = reset_gpio;
3511dc786b2cSRajat Jain 	}
3512dc786b2cSRajat Jain 
35135e23b923SMarcel Holtmann 	hdev->open   = btusb_open;
35145e23b923SMarcel Holtmann 	hdev->close  = btusb_close;
35155e23b923SMarcel Holtmann 	hdev->flush  = btusb_flush;
35165e23b923SMarcel Holtmann 	hdev->send   = btusb_send_frame;
35175e23b923SMarcel Holtmann 	hdev->notify = btusb_notify;
35184539ca67SLuiz Augusto von Dentz 	hdev->wakeup = btusb_wakeup;
35195e23b923SMarcel Holtmann 
3520fd913ef7SRajat Jain #ifdef CONFIG_PM
3521fd913ef7SRajat Jain 	err = btusb_config_oob_wake(hdev);
3522fd913ef7SRajat Jain 	if (err)
3523fd913ef7SRajat Jain 		goto out_free_dev;
3524a4ccc9e3SRajat Jain 
3525a4ccc9e3SRajat Jain 	/* Marvell devices may need a specific chip configuration */
3526a4ccc9e3SRajat Jain 	if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
3527a4ccc9e3SRajat Jain 		err = marvell_config_oob_wake(hdev);
3528a4ccc9e3SRajat Jain 		if (err)
3529a4ccc9e3SRajat Jain 			goto out_free_dev;
3530a4ccc9e3SRajat Jain 	}
3531fd913ef7SRajat Jain #endif
3532418678b0SSzymon Janc 	if (id->driver_info & BTUSB_CW6622)
3533418678b0SSzymon Janc 		set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
3534418678b0SSzymon Janc 
35356c9d435dSMarcel Holtmann 	if (id->driver_info & BTUSB_BCM2045)
35366c9d435dSMarcel Holtmann 		set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
35376c9d435dSMarcel Holtmann 
35389f8f962cSMarcel Holtmann 	if (id->driver_info & BTUSB_BCM92035)
35399f8f962cSMarcel Holtmann 		hdev->setup = btusb_setup_bcm92035;
35409f8f962cSMarcel Holtmann 
3541c0a21a52SMarcel Holtmann 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) &&
3542c0a21a52SMarcel Holtmann 	    (id->driver_info & BTUSB_BCM_PATCHRAM)) {
354349a5f782SMarcel Holtmann 		hdev->manufacturer = 15;
3544c2bfb100SMarcel Holtmann 		hdev->setup = btbcm_setup_patchram;
35459d08f504SMarcel Holtmann 		hdev->set_diag = btusb_bcm_set_diag;
35461df1f591SMarcel Holtmann 		hdev->set_bdaddr = btbcm_set_bdaddr;
35479d08f504SMarcel Holtmann 
35489d08f504SMarcel Holtmann 		/* Broadcom LM_DIAG Interface numbers are hardcoded */
354922f8e9dbSMarcel Holtmann 		data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2);
3550abbaf50eSMarcel Holtmann 	}
355110d4c673SPetri Gynther 
3552c0a21a52SMarcel Holtmann 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) &&
3553c0a21a52SMarcel Holtmann 	    (id->driver_info & BTUSB_BCM_APPLE)) {
355449a5f782SMarcel Holtmann 		hdev->manufacturer = 15;
3555c2bfb100SMarcel Holtmann 		hdev->setup = btbcm_setup_apple;
35569d08f504SMarcel Holtmann 		hdev->set_diag = btusb_bcm_set_diag;
35579d08f504SMarcel Holtmann 
35589d08f504SMarcel Holtmann 		/* Broadcom LM_DIAG Interface numbers are hardcoded */
355922f8e9dbSMarcel Holtmann 		data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2);
35609d08f504SMarcel Holtmann 	}
356117b2772bSMarcel Holtmann 
356283f2dafeSTedd Ho-Jeong An 	/* Combined Intel Device setup to support multiple setup routine */
356383f2dafeSTedd Ho-Jeong An 	if (id->driver_info & BTUSB_INTEL_COMBINED) {
356483f2dafeSTedd Ho-Jeong An 		err = btintel_configure_setup(hdev);
356583f2dafeSTedd Ho-Jeong An 		if (err)
356683f2dafeSTedd Ho-Jeong An 			goto out_free_dev;
356783f2dafeSTedd Ho-Jeong An 
356883f2dafeSTedd Ho-Jeong An 		/* Transport specific configuration */
3569019a1caaSTedd Ho-Jeong An 		hdev->send = btusb_send_frame_intel;
3570dc786b2cSRajat Jain 		hdev->cmd_timeout = btusb_intel_cmd_timeout;
357183f2dafeSTedd Ho-Jeong An 
3572ea7c4c0eSTedd Ho-Jeong An 		if (id->driver_info & BTUSB_INTEL_BROKEN_INITIAL_NCMD)
3573ea7c4c0eSTedd Ho-Jeong An 			btintel_set_flag(hdev, INTEL_BROKEN_INITIAL_NCMD);
3574cb8d6597SMarcel Holtmann 	}
3575dffd30eeSTedd Ho-Jeong An 
3576ae8df494SAmitkumar Karwar 	if (id->driver_info & BTUSB_MARVELL)
3577ae8df494SAmitkumar Karwar 		hdev->set_bdaddr = btusb_set_bdaddr_marvell;
3578ae8df494SAmitkumar Karwar 
3579c0a21a52SMarcel Holtmann 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_MTK) &&
3580c0a21a52SMarcel Holtmann 	    (id->driver_info & BTUSB_MEDIATEK)) {
3581a1c49c43SSean Wang 		hdev->setup = btusb_mtk_setup;
3582a1c49c43SSean Wang 		hdev->shutdown = btusb_mtk_shutdown;
3583a1c49c43SSean Wang 		hdev->manufacturer = 70;
3584e9478026Smark-yw.chen 		hdev->cmd_timeout = btusb_mtk_cmd_timeout;
35858c0d17b6SSean Wang 		hdev->set_bdaddr = btmtk_set_bdaddr;
3586a1c49c43SSean Wang 		set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
35870b10c8c8Smark-yw.chen 		data->recv_acl = btusb_recv_acl_mtk;
3588a1c49c43SSean Wang 	}
3589a1c49c43SSean Wang 
3590661cf88aSMarcel Holtmann 	if (id->driver_info & BTUSB_SWAVE) {
3591661cf88aSMarcel Holtmann 		set_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks);
3592d57dbe77SMarcel Holtmann 		set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks);
3593661cf88aSMarcel Holtmann 	}
3594d57dbe77SMarcel Holtmann 
3595e4c534bbSMarcel Holtmann 	if (id->driver_info & BTUSB_INTEL_BOOT) {
3596e4c534bbSMarcel Holtmann 		hdev->manufacturer = 2;
359740df783dSMarcel Holtmann 		set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
3598e4c534bbSMarcel Holtmann 	}
359940df783dSMarcel Holtmann 
360079f0c87dSJakub Pawlowski 	if (id->driver_info & BTUSB_ATH3012) {
3601803cdb8cSTakashi Iwai 		data->setup_on_usb = btusb_setup_qca;
36025859223eSToshi Kikuchi 		hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
36033d50d51aSJakub Pawlowski 		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
360479f0c87dSJakub Pawlowski 		set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
360579f0c87dSJakub Pawlowski 	}
36065859223eSToshi Kikuchi 
36073267c884SKim, Ben Young Tae 	if (id->driver_info & BTUSB_QCA_ROME) {
36083267c884SKim, Ben Young Tae 		data->setup_on_usb = btusb_setup_qca;
36093267c884SKim, Ben Young Tae 		hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
36106933568aSAbhishek Pandit-Subedi 		hdev->cmd_timeout = btusb_qca_cmd_timeout;
361196e58d36SVic Wei 		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
3612fc549102SHans de Goede 		btusb_check_needs_reset_resume(intf);
36133267c884SKim, Ben Young Tae 	}
36143267c884SKim, Ben Young Tae 
3615b40f58b9SRocky Liao 	if (id->driver_info & BTUSB_QCA_WCN6855) {
3616b40f58b9SRocky Liao 		data->setup_on_usb = btusb_setup_qca;
36173b0d5250STim Jiang 		hdev->shutdown = btusb_shutdown_qca;
3618b40f58b9SRocky Liao 		hdev->set_bdaddr = btusb_set_bdaddr_wcn6855;
3619b40f58b9SRocky Liao 		hdev->cmd_timeout = btusb_qca_cmd_timeout;
3620b40f58b9SRocky Liao 		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
3621cbe6a044SMichael Sun 		hci_set_msft_opcode(hdev, 0xFD70);
3622b40f58b9SRocky Liao 	}
3623b40f58b9SRocky Liao 
3624461f95f0SHilda Wu 	if (id->driver_info & BTUSB_AMP) {
3625461f95f0SHilda Wu 		/* AMP controllers do not support SCO packets */
3626461f95f0SHilda Wu 		data->isoc = NULL;
3627461f95f0SHilda Wu 	} else {
3628461f95f0SHilda Wu 		/* Interface orders are hardcoded in the specification */
3629461f95f0SHilda Wu 		data->isoc = usb_ifnum_to_if(data->udev, ifnum_base + 1);
3630461f95f0SHilda Wu 		data->isoc_ifnum = ifnum_base + 1;
3631461f95f0SHilda Wu 	}
3632461f95f0SHilda Wu 
363342d22098SArnd Bergmann 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_RTL) &&
363442d22098SArnd Bergmann 	    (id->driver_info & BTUSB_REALTEK)) {
3635db33c77dSCarlo Caione 		hdev->setup = btrtl_setup_realtek;
36367af3f558SJian-Hong Pan 		hdev->shutdown = btrtl_shutdown_realtek;
3637d7ef0d1eSAlex Lu 		hdev->cmd_timeout = btusb_rtl_cmd_timeout;
363804b8c814SDaniel Drake 
36398274db07SMax Chou 		/* Realtek devices need to set remote wakeup on auto-suspend */
36408274db07SMax Chou 		set_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags);
364155981d35SPauli Virtanen 		set_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags);
364204b8c814SDaniel Drake 	}
3643a2698a9bSDaniel Drake 
36447a9d4020SMarcel Holtmann 	if (!reset)
3645a6c511c6SSzymon Janc 		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
36465e23b923SMarcel Holtmann 
3647cfeb4145SMarcel Holtmann 	if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
3648cfeb4145SMarcel Holtmann 		if (!disable_scofix)
3649cfeb4145SMarcel Holtmann 			set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
3650cfeb4145SMarcel Holtmann 	}
3651cfeb4145SMarcel Holtmann 
36529bfa35feSMarcel Holtmann 	if (id->driver_info & BTUSB_BROKEN_ISOC)
36539bfa35feSMarcel Holtmann 		data->isoc = NULL;
36549bfa35feSMarcel Holtmann 
36554b127bd5SAlain Michaud 	if (id->driver_info & BTUSB_WIDEBAND_SPEECH)
365600bce3fbSAlain Michaud 		set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
36574b127bd5SAlain Michaud 
3658aff8c489SAlain Michaud 	if (id->driver_info & BTUSB_VALID_LE_STATES)
3659aff8c489SAlain Michaud 		set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
3660aff8c489SAlain Michaud 
36617a9d4020SMarcel Holtmann 	if (id->driver_info & BTUSB_DIGIANSWER) {
36627a9d4020SMarcel Holtmann 		data->cmdreq_type = USB_TYPE_VENDOR;
3663a6c511c6SSzymon Janc 		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
36647a9d4020SMarcel Holtmann 	}
36657a9d4020SMarcel Holtmann 
36667a9d4020SMarcel Holtmann 	if (id->driver_info & BTUSB_CSR) {
36677a9d4020SMarcel Holtmann 		struct usb_device *udev = data->udev;
366881cac64bSMarcel Holtmann 		u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);
36697a9d4020SMarcel Holtmann 
36707a9d4020SMarcel Holtmann 		/* Old firmware would otherwise execute USB reset */
367181cac64bSMarcel Holtmann 		if (bcdDevice < 0x117)
3672a6c511c6SSzymon Janc 			set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
367381cac64bSMarcel Holtmann 
3674cde1a8a9SIsmael Ferreras Morezuelas 		/* This must be set first in case we disable it for fakes */
367549c989a0SJakub Pawlowski 		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
3676cde1a8a9SIsmael Ferreras Morezuelas 
3677cde1a8a9SIsmael Ferreras Morezuelas 		/* Fake CSR devices with broken commands */
3678cde1a8a9SIsmael Ferreras Morezuelas 		if (le16_to_cpu(udev->descriptor.idVendor)  == 0x0a12 &&
3679cde1a8a9SIsmael Ferreras Morezuelas 		    le16_to_cpu(udev->descriptor.idProduct) == 0x0001)
3680cde1a8a9SIsmael Ferreras Morezuelas 			hdev->setup = btusb_setup_csr;
36817a9d4020SMarcel Holtmann 	}
36827a9d4020SMarcel Holtmann 
3683cfeb4145SMarcel Holtmann 	if (id->driver_info & BTUSB_SNIFFER) {
36849bfa35feSMarcel Holtmann 		struct usb_device *udev = data->udev;
3685cfeb4145SMarcel Holtmann 
36867a9d4020SMarcel Holtmann 		/* New sniffer firmware has crippled HCI interface */
3687cfeb4145SMarcel Holtmann 		if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
3688cfeb4145SMarcel Holtmann 			set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
3689cfeb4145SMarcel Holtmann 	}
3690cfeb4145SMarcel Holtmann 
36913a5ef20cSMarcel Holtmann 	if (id->driver_info & BTUSB_INTEL_BOOT) {
36923a5ef20cSMarcel Holtmann 		/* A bug in the bootloader causes that interrupt interface is
36933a5ef20cSMarcel Holtmann 		 * only enabled after receiving SetInterface(0, AltSetting=0).
36943a5ef20cSMarcel Holtmann 		 */
36953a5ef20cSMarcel Holtmann 		err = usb_set_interface(data->udev, 0, 0);
36963a5ef20cSMarcel Holtmann 		if (err < 0) {
36973a5ef20cSMarcel Holtmann 			BT_ERR("failed to set interface 0, alt 0 %d", err);
369810ab133bSRajat Jain 			goto out_free_dev;
36993a5ef20cSMarcel Holtmann 		}
37003a5ef20cSMarcel Holtmann 	}
37013a5ef20cSMarcel Holtmann 
37029bfa35feSMarcel Holtmann 	if (data->isoc) {
37039bfa35feSMarcel Holtmann 		err = usb_driver_claim_interface(&btusb_driver,
37045fbcd260SMarcel Holtmann 						 data->isoc, data);
370510ab133bSRajat Jain 		if (err < 0)
370610ab133bSRajat Jain 			goto out_free_dev;
37079bfa35feSMarcel Holtmann 	}
37089bfa35feSMarcel Holtmann 
3709c0a21a52SMarcel Holtmann 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) && data->diag) {
37109d08f504SMarcel Holtmann 		if (!usb_driver_claim_interface(&btusb_driver,
37119d08f504SMarcel Holtmann 						data->diag, data))
37129d08f504SMarcel Holtmann 			__set_diag_interface(hdev);
37139d08f504SMarcel Holtmann 		else
37149d08f504SMarcel Holtmann 			data->diag = NULL;
37159d08f504SMarcel Holtmann 	}
37169d08f504SMarcel Holtmann 
371789591522SHans de Goede 	if (enable_autosuspend)
371889591522SHans de Goede 		usb_enable_autosuspend(data->udev);
3719eff2d68cSHans de Goede 
37205e23b923SMarcel Holtmann 	err = hci_register_dev(hdev);
372110ab133bSRajat Jain 	if (err < 0)
372210ab133bSRajat Jain 		goto out_free_dev;
37235e23b923SMarcel Holtmann 
37245e23b923SMarcel Holtmann 	usb_set_intfdata(intf, data);
37255e23b923SMarcel Holtmann 
37265e23b923SMarcel Holtmann 	return 0;
372710ab133bSRajat Jain 
372810ab133bSRajat Jain out_free_dev:
3729dc786b2cSRajat Jain 	if (data->reset_gpio)
3730dc786b2cSRajat Jain 		gpiod_put(data->reset_gpio);
373110ab133bSRajat Jain 	hci_free_dev(hdev);
373210ab133bSRajat Jain 	return err;
37335e23b923SMarcel Holtmann }
37345e23b923SMarcel Holtmann 
37355e23b923SMarcel Holtmann static void btusb_disconnect(struct usb_interface *intf)
37365e23b923SMarcel Holtmann {
37375e23b923SMarcel Holtmann 	struct btusb_data *data = usb_get_intfdata(intf);
37385e23b923SMarcel Holtmann 	struct hci_dev *hdev;
37395e23b923SMarcel Holtmann 
37405e23b923SMarcel Holtmann 	BT_DBG("intf %p", intf);
37415e23b923SMarcel Holtmann 
37425e23b923SMarcel Holtmann 	if (!data)
37435e23b923SMarcel Holtmann 		return;
37445e23b923SMarcel Holtmann 
37455e23b923SMarcel Holtmann 	hdev = data->hdev;
37465fbcd260SMarcel Holtmann 	usb_set_intfdata(data->intf, NULL);
37475fbcd260SMarcel Holtmann 
37485fbcd260SMarcel Holtmann 	if (data->isoc)
37495fbcd260SMarcel Holtmann 		usb_set_intfdata(data->isoc, NULL);
37505e23b923SMarcel Holtmann 
37519d08f504SMarcel Holtmann 	if (data->diag)
37529d08f504SMarcel Holtmann 		usb_set_intfdata(data->diag, NULL);
37539d08f504SMarcel Holtmann 
37545e23b923SMarcel Holtmann 	hci_unregister_dev(hdev);
37555e23b923SMarcel Holtmann 
37569d08f504SMarcel Holtmann 	if (intf == data->intf) {
37579d08f504SMarcel Holtmann 		if (data->isoc)
37585fbcd260SMarcel Holtmann 			usb_driver_release_interface(&btusb_driver, data->isoc);
37599d08f504SMarcel Holtmann 		if (data->diag)
37609d08f504SMarcel Holtmann 			usb_driver_release_interface(&btusb_driver, data->diag);
37619d08f504SMarcel Holtmann 	} else if (intf == data->isoc) {
37629d08f504SMarcel Holtmann 		if (data->diag)
37639d08f504SMarcel Holtmann 			usb_driver_release_interface(&btusb_driver, data->diag);
37649d08f504SMarcel Holtmann 		usb_driver_release_interface(&btusb_driver, data->intf);
37659d08f504SMarcel Holtmann 	} else if (intf == data->diag) {
37669d08f504SMarcel Holtmann 		usb_driver_release_interface(&btusb_driver, data->intf);
37679d08f504SMarcel Holtmann 		if (data->isoc)
37689d08f504SMarcel Holtmann 			usb_driver_release_interface(&btusb_driver, data->isoc);
37699d08f504SMarcel Holtmann 	}
37705fbcd260SMarcel Holtmann 
3771fd913ef7SRajat Jain 	if (data->oob_wake_irq)
3772fd913ef7SRajat Jain 		device_init_wakeup(&data->udev->dev, false);
3773fd913ef7SRajat Jain 
3774dc786b2cSRajat Jain 	if (data->reset_gpio)
3775dc786b2cSRajat Jain 		gpiod_put(data->reset_gpio);
3776dc786b2cSRajat Jain 
37775e23b923SMarcel Holtmann 	hci_free_dev(hdev);
37785e23b923SMarcel Holtmann }
37795e23b923SMarcel Holtmann 
37807bee549eSOliver Neukum #ifdef CONFIG_PM
37816a88adf2SMarcel Holtmann static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
37826a88adf2SMarcel Holtmann {
37836a88adf2SMarcel Holtmann 	struct btusb_data *data = usb_get_intfdata(intf);
37846a88adf2SMarcel Holtmann 
37856a88adf2SMarcel Holtmann 	BT_DBG("intf %p", intf);
37866a88adf2SMarcel Holtmann 
37876a88adf2SMarcel Holtmann 	if (data->suspend_count++)
37886a88adf2SMarcel Holtmann 		return 0;
37896a88adf2SMarcel Holtmann 
37907bee549eSOliver Neukum 	spin_lock_irq(&data->txlock);
37915b1b0b81SAlan Stern 	if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) {
37927bee549eSOliver Neukum 		set_bit(BTUSB_SUSPENDING, &data->flags);
37937bee549eSOliver Neukum 		spin_unlock_irq(&data->txlock);
37947bee549eSOliver Neukum 	} else {
37957bee549eSOliver Neukum 		spin_unlock_irq(&data->txlock);
37967bee549eSOliver Neukum 		data->suspend_count--;
37977bee549eSOliver Neukum 		return -EBUSY;
37987bee549eSOliver Neukum 	}
37997bee549eSOliver Neukum 
38006a88adf2SMarcel Holtmann 	cancel_work_sync(&data->work);
38016a88adf2SMarcel Holtmann 
38027bee549eSOliver Neukum 	btusb_stop_traffic(data);
38036a88adf2SMarcel Holtmann 	usb_kill_anchored_urbs(&data->tx_anchor);
38046a88adf2SMarcel Holtmann 
3805fd913ef7SRajat Jain 	if (data->oob_wake_irq && device_may_wakeup(&data->udev->dev)) {
3806fd913ef7SRajat Jain 		set_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags);
3807fd913ef7SRajat Jain 		enable_irq_wake(data->oob_wake_irq);
3808fd913ef7SRajat Jain 		enable_irq(data->oob_wake_irq);
3809fd913ef7SRajat Jain 	}
3810fd913ef7SRajat Jain 
38119e45524aSAlex Lu 	/* For global suspend, Realtek devices lose the loaded fw
38129e45524aSAlex Lu 	 * in them. But for autosuspend, firmware should remain.
38139e45524aSAlex Lu 	 * Actually, it depends on whether the usb host sends
38149e45524aSAlex Lu 	 * set feature (enable wakeup) or not.
38159e45524aSAlex Lu 	 */
38168274db07SMax Chou 	if (test_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags)) {
38179e45524aSAlex Lu 		if (PMSG_IS_AUTO(message) &&
38189e45524aSAlex Lu 		    device_can_wakeup(&data->udev->dev))
38199e45524aSAlex Lu 			data->udev->do_remote_wakeup = 1;
38208274db07SMax Chou 		else if (!PMSG_IS_AUTO(message) &&
38218274db07SMax Chou 			 !device_may_wakeup(&data->udev->dev)) {
38228274db07SMax Chou 			data->udev->do_remote_wakeup = 0;
38239e45524aSAlex Lu 			data->udev->reset_resume = 1;
38249e45524aSAlex Lu 		}
38258274db07SMax Chou 	}
38269e45524aSAlex Lu 
38276a88adf2SMarcel Holtmann 	return 0;
38286a88adf2SMarcel Holtmann }
38296a88adf2SMarcel Holtmann 
38307bee549eSOliver Neukum static void play_deferred(struct btusb_data *data)
38317bee549eSOliver Neukum {
38327bee549eSOliver Neukum 	struct urb *urb;
38337bee549eSOliver Neukum 	int err;
38347bee549eSOliver Neukum 
38357bee549eSOliver Neukum 	while ((urb = usb_get_from_anchor(&data->deferred))) {
383619cfe912SJeffy Chen 		usb_anchor_urb(urb, &data->tx_anchor);
383719cfe912SJeffy Chen 
38387bee549eSOliver Neukum 		err = usb_submit_urb(urb, GFP_ATOMIC);
383919cfe912SJeffy Chen 		if (err < 0) {
384019cfe912SJeffy Chen 			if (err != -EPERM && err != -ENODEV)
384119cfe912SJeffy Chen 				BT_ERR("%s urb %p submission failed (%d)",
384219cfe912SJeffy Chen 				       data->hdev->name, urb, -err);
384319cfe912SJeffy Chen 			kfree(urb->setup_packet);
384419cfe912SJeffy Chen 			usb_unanchor_urb(urb);
384519cfe912SJeffy Chen 			usb_free_urb(urb);
38467bee549eSOliver Neukum 			break;
384719cfe912SJeffy Chen 		}
38487bee549eSOliver Neukum 
38497bee549eSOliver Neukum 		data->tx_in_flight++;
385019cfe912SJeffy Chen 		usb_free_urb(urb);
38517bee549eSOliver Neukum 	}
385219cfe912SJeffy Chen 
385319cfe912SJeffy Chen 	/* Cleanup the rest deferred urbs. */
385419cfe912SJeffy Chen 	while ((urb = usb_get_from_anchor(&data->deferred))) {
385519cfe912SJeffy Chen 		kfree(urb->setup_packet);
385619cfe912SJeffy Chen 		usb_free_urb(urb);
385719cfe912SJeffy Chen 	}
38587bee549eSOliver Neukum }
38597bee549eSOliver Neukum 
38606a88adf2SMarcel Holtmann static int btusb_resume(struct usb_interface *intf)
38616a88adf2SMarcel Holtmann {
38626a88adf2SMarcel Holtmann 	struct btusb_data *data = usb_get_intfdata(intf);
38636a88adf2SMarcel Holtmann 	struct hci_dev *hdev = data->hdev;
38647bee549eSOliver Neukum 	int err = 0;
38656a88adf2SMarcel Holtmann 
38666a88adf2SMarcel Holtmann 	BT_DBG("intf %p", intf);
38676a88adf2SMarcel Holtmann 
38686a88adf2SMarcel Holtmann 	if (--data->suspend_count)
38696a88adf2SMarcel Holtmann 		return 0;
38706a88adf2SMarcel Holtmann 
3871fd913ef7SRajat Jain 	/* Disable only if not already disabled (keep it balanced) */
3872fd913ef7SRajat Jain 	if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) {
3873fd913ef7SRajat Jain 		disable_irq(data->oob_wake_irq);
3874fd913ef7SRajat Jain 		disable_irq_wake(data->oob_wake_irq);
3875fd913ef7SRajat Jain 	}
3876fd913ef7SRajat Jain 
38776a88adf2SMarcel Holtmann 	if (!test_bit(HCI_RUNNING, &hdev->flags))
38787bee549eSOliver Neukum 		goto done;
38796a88adf2SMarcel Holtmann 
38806a88adf2SMarcel Holtmann 	if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) {
38816a88adf2SMarcel Holtmann 		err = btusb_submit_intr_urb(hdev, GFP_NOIO);
38826a88adf2SMarcel Holtmann 		if (err < 0) {
38836a88adf2SMarcel Holtmann 			clear_bit(BTUSB_INTR_RUNNING, &data->flags);
38847bee549eSOliver Neukum 			goto failed;
38856a88adf2SMarcel Holtmann 		}
38866a88adf2SMarcel Holtmann 	}
38876a88adf2SMarcel Holtmann 
38886a88adf2SMarcel Holtmann 	if (test_bit(BTUSB_BULK_RUNNING, &data->flags)) {
388943c2e57fSMarcel Holtmann 		err = btusb_submit_bulk_urb(hdev, GFP_NOIO);
389043c2e57fSMarcel Holtmann 		if (err < 0) {
38916a88adf2SMarcel Holtmann 			clear_bit(BTUSB_BULK_RUNNING, &data->flags);
38927bee549eSOliver Neukum 			goto failed;
38937bee549eSOliver Neukum 		}
38947bee549eSOliver Neukum 
38956a88adf2SMarcel Holtmann 		btusb_submit_bulk_urb(hdev, GFP_NOIO);
38966a88adf2SMarcel Holtmann 	}
38976a88adf2SMarcel Holtmann 
38986a88adf2SMarcel Holtmann 	if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
38996a88adf2SMarcel Holtmann 		if (btusb_submit_isoc_urb(hdev, GFP_NOIO) < 0)
39006a88adf2SMarcel Holtmann 			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
39016a88adf2SMarcel Holtmann 		else
39026a88adf2SMarcel Holtmann 			btusb_submit_isoc_urb(hdev, GFP_NOIO);
39036a88adf2SMarcel Holtmann 	}
39046a88adf2SMarcel Holtmann 
39057bee549eSOliver Neukum 	spin_lock_irq(&data->txlock);
39067bee549eSOliver Neukum 	play_deferred(data);
39077bee549eSOliver Neukum 	clear_bit(BTUSB_SUSPENDING, &data->flags);
39087bee549eSOliver Neukum 	spin_unlock_irq(&data->txlock);
39097bee549eSOliver Neukum 	schedule_work(&data->work);
39107bee549eSOliver Neukum 
39116a88adf2SMarcel Holtmann 	return 0;
39127bee549eSOliver Neukum 
39137bee549eSOliver Neukum failed:
39147bee549eSOliver Neukum 	usb_scuttle_anchored_urbs(&data->deferred);
39157bee549eSOliver Neukum done:
39167bee549eSOliver Neukum 	spin_lock_irq(&data->txlock);
39177bee549eSOliver Neukum 	clear_bit(BTUSB_SUSPENDING, &data->flags);
39187bee549eSOliver Neukum 	spin_unlock_irq(&data->txlock);
39197bee549eSOliver Neukum 
39207bee549eSOliver Neukum 	return err;
39216a88adf2SMarcel Holtmann }
39227bee549eSOliver Neukum #endif
39236a88adf2SMarcel Holtmann 
39245e23b923SMarcel Holtmann static struct usb_driver btusb_driver = {
39255e23b923SMarcel Holtmann 	.name		= "btusb",
39265e23b923SMarcel Holtmann 	.probe		= btusb_probe,
39275e23b923SMarcel Holtmann 	.disconnect	= btusb_disconnect,
39287bee549eSOliver Neukum #ifdef CONFIG_PM
39296a88adf2SMarcel Holtmann 	.suspend	= btusb_suspend,
39306a88adf2SMarcel Holtmann 	.resume		= btusb_resume,
39317bee549eSOliver Neukum #endif
39325e23b923SMarcel Holtmann 	.id_table	= btusb_table,
39337bee549eSOliver Neukum 	.supports_autosuspend = 1,
3934e1f12eb6SSarah Sharp 	.disable_hub_initiated_lpm = 1,
39355e23b923SMarcel Holtmann };
39365e23b923SMarcel Holtmann 
393793f1508cSGreg Kroah-Hartman module_usb_driver(btusb_driver);
39385e23b923SMarcel Holtmann 
3939cfeb4145SMarcel Holtmann module_param(disable_scofix, bool, 0644);
3940cfeb4145SMarcel Holtmann MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
3941cfeb4145SMarcel Holtmann 
3942cfeb4145SMarcel Holtmann module_param(force_scofix, bool, 0644);
3943cfeb4145SMarcel Holtmann MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size");
3944cfeb4145SMarcel Holtmann 
3945eff2d68cSHans de Goede module_param(enable_autosuspend, bool, 0644);
3946eff2d68cSHans de Goede MODULE_PARM_DESC(enable_autosuspend, "Enable USB autosuspend by default");
3947eff2d68cSHans de Goede 
3948cfeb4145SMarcel Holtmann module_param(reset, bool, 0644);
3949cfeb4145SMarcel Holtmann MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
3950cfeb4145SMarcel Holtmann 
39515e23b923SMarcel Holtmann MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
39525e23b923SMarcel Holtmann MODULE_DESCRIPTION("Generic Bluetooth USB driver ver " VERSION);
39535e23b923SMarcel Holtmann MODULE_VERSION(VERSION);
39545e23b923SMarcel Holtmann MODULE_LICENSE("GPL");
3955