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