From 1ce0cec1c14cda7e514fa21b36c0f035203b447d Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Mon, 5 Feb 2018 14:20:36 -0800 Subject: Bluetooth: btusb: Add support for Intel Bluetooth device 22560 [8087:0026] The Intel Bluetooth device 22560 family (HarrisonPeak, QnJ, and IcyPeak) use the same firmware loading mechanism as previous generation, so include new USB product ID and whitelist the hardware variant. T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 16 Spd=12 MxCh= 0 D: Ver= 2.01 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=8087 ProdID=0026 Rev= 0.01 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2a55380ad730..098967cb3fc9 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -339,6 +339,7 @@ static const struct usb_device_id blacklist_table[] = { /* Intel Bluetooth devices */ { USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW }, + { USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_NEW }, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, @@ -2057,6 +2058,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) case 0x0c: /* WsP */ case 0x11: /* JfP */ case 0x12: /* ThP */ + case 0x13: /* HrP */ + case 0x14: /* QnJ, IcP */ break; default: BT_ERR("%s: Unsupported Intel hardware variant (%u)", @@ -2149,6 +2152,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) break; case 0x11: /* JfP */ case 0x12: /* ThP */ + case 0x13: /* HrP */ + case 0x14: /* QnJ, IcP */ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi", le16_to_cpu(ver.hw_variant), le16_to_cpu(ver.hw_revision), @@ -2180,6 +2185,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) break; case 0x11: /* JfP */ case 0x12: /* ThP */ + case 0x13: /* HrP */ + case 0x14: /* QnJ, IcP */ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc", le16_to_cpu(ver.hw_variant), le16_to_cpu(ver.hw_revision), -- cgit v1.2.3 From 8b077bdba66d1d606eb1bdce3db87ff605aa7f1c Mon Sep 17 00:00:00 2001 From: Maxim Zhukov Date: Mon, 5 Feb 2018 00:09:43 +0300 Subject: Bluetooth: ath3k: replace hardcode numbers with define Replaced the numbers with a readable define. Signed-off-by: Maxim Zhukov Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 204afe66de92..0a5cfea44529 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -227,15 +227,16 @@ static int ath3k_load_firmware(struct usb_device *udev, return -ENOMEM; } - memcpy(send_buf, firmware->data, 20); + memcpy(send_buf, firmware->data, FW_HDR_SIZE); err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR, - 0, 0, send_buf, 20, USB_CTRL_SET_TIMEOUT); + 0, 0, send_buf, FW_HDR_SIZE, + USB_CTRL_SET_TIMEOUT); if (err < 0) { BT_ERR("Can't change to loading configuration err"); goto error; } - sent += 20; - count -= 20; + sent += FW_HDR_SIZE; + count -= FW_HDR_SIZE; pipe = usb_sndbulkpipe(udev, 0x02); -- cgit v1.2.3 From b3baa2428dece073f7158b2eb616dc69a759ea8e Mon Sep 17 00:00:00 2001 From: Maxim Zhukov Date: Mon, 5 Feb 2018 00:09:44 +0300 Subject: Bluetooth: ath3k: do not init variables Do not need to initialize variables, because further on the code they fall into the snprintf. Signed-off-by: Maxim Zhukov Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 0a5cfea44529..b16c01a0b6d4 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -399,7 +399,7 @@ static int ath3k_set_normal_mode(struct usb_device *udev) static int ath3k_load_patch(struct usb_device *udev) { unsigned char fw_state; - char filename[ATH3K_NAME_LEN] = {0}; + char filename[ATH3K_NAME_LEN]; const struct firmware *firmware; struct ath3k_version fw_version; __u32 pt_rom_version, pt_build_version; @@ -452,7 +452,7 @@ static int ath3k_load_patch(struct usb_device *udev) static int ath3k_load_syscfg(struct usb_device *udev) { unsigned char fw_state; - char filename[ATH3K_NAME_LEN] = {0}; + char filename[ATH3K_NAME_LEN]; const struct firmware *firmware; struct ath3k_version fw_version; int clk_value, ret; -- cgit v1.2.3 From f13b3d7e81bd8b40a42c2fe5304b2fc53d638378 Mon Sep 17 00:00:00 2001 From: Maxim Zhukov Date: Mon, 5 Feb 2018 00:09:45 +0300 Subject: Bluetooth: ath3k: remove blank line after if Removed blank line after if. Signed-off-by: Maxim Zhukov Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index b16c01a0b6d4..4df5b953a40d 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -523,7 +523,6 @@ static int ath3k_probe(struct usb_interface *intf, /* load patch and sysconfig files for AR3012 */ if (id->driver_info & BTUSB_ATH3012) { - /* New firmware with patch and sysconfig files already loaded */ if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001) return -ENODEV; -- cgit v1.2.3 From 3d08f43c73c4144517e31f3cf7564f98e81fd28f Mon Sep 17 00:00:00 2001 From: Maxim Zhukov Date: Mon, 5 Feb 2018 00:09:46 +0300 Subject: Bluetooth: ath3k: Fix warning: quoted string split across lines This patch avoided the warning: WARNING: quoted string split across lines #355: FILE: drivers/bluetooth/ath3k.c:355: + BT_ERR("Error in firmware loading err = %d," + "len = %d, size = %d", err, len, size); This patch fix this issue. Signed-off-by: Maxim Zhukov Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 4df5b953a40d..8fe5ec4bb342 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -203,6 +203,12 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { } /* Terminating entry */ }; +static inline void ath3k_log_failed_loading(int err, int len, int size) +{ + BT_ERR("Error in firmware loading err = %d, len = %d, size = %d", + err, len, size); +} + #define USB_REQ_DFU_DNLOAD 1 #define BULK_SIZE 4096 #define FW_HDR_SIZE 20 @@ -251,8 +257,7 @@ static int ath3k_load_firmware(struct usb_device *udev, &len, 3000); if (err || (len != size)) { - BT_ERR("Error in firmware loading err = %d," - "len = %d, size = %d", err, len, size); + ath3k_log_failed_loading(err, len, size); goto error; } @@ -351,8 +356,7 @@ static int ath3k_load_fwfile(struct usb_device *udev, err = usb_bulk_msg(udev, pipe, send_buf, size, &len, 3000); if (err || (len != size)) { - BT_ERR("Error in firmware loading err = %d," - "len = %d, size = %d", err, len, size); + ath3k_log_failed_loading(err, len, size); kfree(send_buf); return err; } -- cgit v1.2.3 From 0a21963aacfe88fdbfe6166781d4ccd159197bd6 Mon Sep 17 00:00:00 2001 From: Maxim Zhukov Date: Mon, 5 Feb 2018 00:09:47 +0300 Subject: Bluetooth: ath3k: fix checkpatch warning This patch fixed warning: WARNING: Prefer using '"%s...", __func__' to using 'ath3k_disconnect', this function's name, in a string #568: FILE: drivers/bluetooth/ath3k.c:568: + BT_DBG("ath3k_disconnect intf %p", intf); Signed-off-by: Maxim Zhukov Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 8fe5ec4bb342..3d7a5c149af3 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -569,7 +569,7 @@ static int ath3k_probe(struct usb_interface *intf, static void ath3k_disconnect(struct usb_interface *intf) { - BT_DBG("ath3k_disconnect intf %p", intf); + BT_DBG("%s intf %p", __func__, intf); } static struct usb_driver ath3k_driver = { -- cgit v1.2.3 From 688d6240e0646a56ff8bdffb2310dcdeca354814 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Sat, 27 Jan 2018 18:17:38 +0800 Subject: Bluetooth: hci_ath: Replace mdelay with msleep in ath_wakeup_ar3k ath_wakeup_ar3k() is never called from atomic context. It is only called by ath_hci_uart_work() that is only called in ath_open() via INIT_WORK(). All of the above functions do not enter atomic context along the way. Despite never getting called from atomic context, ath_wakeup_ar3k() calls mdelay() for busy wait. That is not necessary and can be replaced with msleep to avoid busy wait. This is found by a static analysis tool named DCNS written by myself. Signed-off-by: Jia-Ju Bai Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ath.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c index 14ae7ee88acb..d568fbd94d6c 100644 --- a/drivers/bluetooth/hci_ath.c +++ b/drivers/bluetooth/hci_ath.c @@ -71,12 +71,12 @@ static int ath_wakeup_ar3k(struct tty_struct *tty) /* Clear RTS first */ tty->driver->ops->tiocmget(tty); tty->driver->ops->tiocmset(tty, 0x00, TIOCM_RTS); - mdelay(20); + msleep(20); /* Set RTS, wake up board */ tty->driver->ops->tiocmget(tty); tty->driver->ops->tiocmset(tty, TIOCM_RTS, 0x00); - mdelay(20); + msleep(20); status = tty->driver->ops->tiocmget(tty); return status; -- cgit v1.2.3 From 1ebbf046273e50cf3cbf2ec13d520dc74ab454d4 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 26 Jan 2018 23:57:01 +0800 Subject: Bluetooth: btmrvl_main: Replace GFP_ATOMIC with GFP_KERNEL in btmrvl_send_sync_cmd After checking all possible call chains to btmrvl_send_sync_cmd(), my tool finds that this function is never called in atomic context, namely never in an interrupt handler or holding a spinlock. And it calls wait_event_interruptible_timeout() after bt_skb_alloc(), so it indicates that btmrvl_send_sync_cmd() can call function which can sleep. Thus GFP_ATOMIC is not necessary, and it can be replaced with GFP_KERNEL. This is found by a static analysis tool named DCNS written by myself. Signed-off-by: Jia-Ju Bai Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index b280d466f05b..f6c694a1b9b0 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -183,7 +183,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode, return -EFAULT; } - skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC); + skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_KERNEL); if (!skb) { BT_ERR("No free skb"); return -ENOMEM; -- cgit v1.2.3 From 06633ee14d5c9bff3b46be67be2824138c75594a Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Sat, 27 Jan 2018 18:03:52 +0800 Subject: Bluetooth: hci_ll: Replace mdelay with msleep in download_firmware download_firmware() is never called from atomic context. It is only called by ll_setup() that is called only via function pointer "->setup" used in hci_uart_setup() in drivers/bluetooth/hci_serdev.c and drivers/bluetooth/hci_ldisc.c. hci_uart_setup() is called only via function pointer "->setup" used in hci_dev_do_open() in net/bluetooth/hci_core.c. All of the above functions do not enter atomic context. Besides, ll_setup() calls msleep() and hci_dev_do_open calls mutex_lock(). So it indicates that all the above functions call functions that can sleep. Despite never getting called from atomic context, download_firmware() calls mdelay() for busy wait. That is not necessary and can be replaced with msleep to avoid busy wait. This is found by a static analysis tool named DCNS written by myself. Signed-off-by: Jia-Ju Bai Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 1b4417a623a4..2f30dcad96bd 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -650,7 +650,7 @@ static int download_firmware(struct ll_device *lldev) break; case ACTION_DELAY: /* sleep */ bt_dev_info(lldev->hu.hdev, "sleep command in scr"); - mdelay(((struct bts_action_delay *)action_ptr)->msec); + msleep(((struct bts_action_delay *)action_ptr)->msec); break; } len -= (sizeof(struct bts_action) + -- cgit v1.2.3 From fed03fe7e55b7dc16077f672bd9d7bbe92b3a691 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 11 Feb 2018 12:24:32 -0600 Subject: Bluetooth: btusb: Add device ID for RTL8822BE The Asus Z370-I contains a Realtek RTL8822BE device with an associated BT chip using a USB ID of 0b05:185c. This device is added to the driver. Signed-off-by: Hon Weng Chong Signed-off-by: Larry Finger Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 098967cb3fc9..c8e9ae6b99e1 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -374,6 +374,9 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK }, + /* Additional Realtek 8822BE Bluetooth devices */ + { USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK }, + /* Silicon Wave based devices */ { USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE }, -- cgit v1.2.3 From 907f84990924bf3a8d248c040dabeb5127ae6938 Mon Sep 17 00:00:00 2001 From: Alex Lu Date: Sun, 11 Feb 2018 12:24:33 -0600 Subject: Bluetooth: btrtl: Add RTL8723D and RTL8821C devices The Bluetooth parts of RTL8723D and RTL8723B share the same lmp subversion, thus we need to check both lmp subversion and hci revision to distinguish the two. The same situation is true for RTL8821A and RTL8821C. Accordingly, the selection code is revised. To improve maintainability, a new id_table struct is defined, and an array of such structs is constructed. Adding a new device can thus be as simple as adding another value to the table. Signed-off-by: Alex Lu Signed-off-by: Larry Finger Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 119 +++++++++++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 34 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 6e2ad748abba..437f080deaab 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -35,6 +35,60 @@ #define RTL_ROM_LMP_8761A 0x8761 #define RTL_ROM_LMP_8822B 0x8822 +#define IC_MATCH_FL_LMPSUBV (1 << 0) +#define IC_MATCH_FL_HCIREV (1 << 1) +#define IC_INFO(lmps, hcir) \ + .match_flags = IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_HCIREV, \ + .lmp_subver = (lmps), \ + .hci_rev = (hcir) + +struct id_table { + __u16 match_flags; + __u16 lmp_subver; + __u16 hci_rev; + bool config_needed; + char *fw_name; + char *cfg_name; +}; + +static const struct id_table ic_id_table[] = { + /* 8723B */ + { IC_INFO(RTL_ROM_LMP_8723B, 0xb), + .config_needed = false, + .fw_name = "rtl_bt/rtl8723b_fw.bin", + .cfg_name = "rtl_bt/rtl8723b_config.bin" }, + + /* 8723D */ + { IC_INFO(RTL_ROM_LMP_8723B, 0xd), + .config_needed = true, + .fw_name = "rtl_bt/rtl8723d_fw.bin", + .cfg_name = "rtl_bt/rtl8723d_config.bin" }, + + /* 8821A */ + { IC_INFO(RTL_ROM_LMP_8821A, 0xa), + .config_needed = false, + .fw_name = "rtl_bt/rtl8821a_fw.bin", + .cfg_name = "rtl_bt/rtl8821a_config.bin" }, + + /* 8821C */ + { IC_INFO(RTL_ROM_LMP_8821A, 0xc), + .config_needed = false, + .fw_name = "rtl_bt/rtl8821c_fw.bin", + .cfg_name = "rtl_bt/rtl8821c_config.bin" }, + + /* 8761A */ + { IC_MATCH_FL_LMPSUBV, RTL_ROM_LMP_8761A, 0x0, + .config_needed = false, + .fw_name = "rtl_bt/rtl8761a_fw.bin", + .cfg_name = "rtl_bt/rtl8761a_config.bin" }, + + /* 8822B */ + { IC_INFO(RTL_ROM_LMP_8822B, 0xb), + .config_needed = true, + .fw_name = "rtl_bt/rtl8822b_fw.bin", + .cfg_name = "rtl_bt/rtl8822b_config.bin" }, + }; + static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version) { struct rtl_rom_version_evt *rom_version; @@ -64,9 +118,9 @@ static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version) return 0; } -static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver, - const struct firmware *fw, - unsigned char **_buf) +static int rtlbt_parse_firmware(struct hci_dev *hdev, u16 lmp_subver, + const struct firmware *fw, + unsigned char **_buf) { const u8 extension_sig[] = { 0x51, 0x04, 0xfd, 0x77 }; struct rtl_epatch_header *epatch_info; @@ -88,6 +142,8 @@ static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver, { RTL_ROM_LMP_8821A, 2 }, { RTL_ROM_LMP_8761A, 3 }, { RTL_ROM_LMP_8822B, 8 }, + { RTL_ROM_LMP_8723B, 9 }, /* 8723D */ + { RTL_ROM_LMP_8821A, 10 }, /* 8821C */ }; ret = rtl_read_rom_version(hdev, &rom_version); @@ -320,8 +376,8 @@ out: return ret; } -static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver, - const char *fw_name) +static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 hci_rev, + u16 lmp_subver) { unsigned char *fw_data = NULL; const struct firmware *fw; @@ -330,39 +386,40 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver, u8 *cfg_buff = NULL; u8 *tbuff; char *cfg_name = NULL; - bool config_needed = false; + char *fw_name = NULL; + int i; + + for (i = 0; i < ARRAY_SIZE(ic_id_table); i++) { + if ((ic_id_table[i].match_flags & IC_MATCH_FL_LMPSUBV) && + (ic_id_table[i].lmp_subver != lmp_subver)) + continue; + if ((ic_id_table[i].match_flags & IC_MATCH_FL_HCIREV) && + (ic_id_table[i].hci_rev != hci_rev)) + continue; - switch (lmp_subver) { - case RTL_ROM_LMP_8723B: - cfg_name = "rtl_bt/rtl8723b_config.bin"; - break; - case RTL_ROM_LMP_8821A: - cfg_name = "rtl_bt/rtl8821a_config.bin"; - break; - case RTL_ROM_LMP_8761A: - cfg_name = "rtl_bt/rtl8761a_config.bin"; - break; - case RTL_ROM_LMP_8822B: - cfg_name = "rtl_bt/rtl8822b_config.bin"; - config_needed = true; - break; - default: - BT_ERR("%s: rtl: no config according to lmp_subver %04x", - hdev->name, lmp_subver); break; } + if (i >= ARRAY_SIZE(ic_id_table)) { + BT_ERR("%s: unknown IC info, lmp subver %04x, hci rev %04x", + hdev->name, lmp_subver, hci_rev); + return -EINVAL; + } + + cfg_name = ic_id_table[i].cfg_name; + if (cfg_name) { cfg_sz = rtl_load_config(hdev, cfg_name, &cfg_buff); if (cfg_sz < 0) { cfg_sz = 0; - if (config_needed) + if (ic_id_table[i].config_needed) BT_ERR("Necessary config file %s not found\n", cfg_name); } } else cfg_sz = 0; + fw_name = ic_id_table[i].fw_name; bt_dev_info(hdev, "rtl: loading %s", fw_name); ret = request_firmware(&fw, fw_name, &hdev->dev); if (ret < 0) { @@ -370,7 +427,7 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver, goto err_req_fw; } - ret = rtl8723b_parse_firmware(hdev, lmp_subver, fw, &fw_data); + ret = rtlbt_parse_firmware(hdev, lmp_subver, fw, &fw_data); if (ret < 0) goto out; @@ -429,7 +486,7 @@ int btrtl_setup_realtek(struct hci_dev *hdev) { struct sk_buff *skb; struct hci_rp_read_local_version *resp; - u16 lmp_subver; + u16 hci_rev, lmp_subver; skb = btrtl_read_local_version(hdev); if (IS_ERR(skb)) @@ -441,6 +498,7 @@ int btrtl_setup_realtek(struct hci_dev *hdev) resp->hci_ver, resp->hci_rev, resp->lmp_ver, resp->lmp_subver); + hci_rev = le16_to_cpu(resp->hci_rev); lmp_subver = le16_to_cpu(resp->lmp_subver); kfree_skb(skb); @@ -455,17 +513,10 @@ int btrtl_setup_realtek(struct hci_dev *hdev) case RTL_ROM_LMP_3499: return btrtl_setup_rtl8723a(hdev); case RTL_ROM_LMP_8723B: - return btrtl_setup_rtl8723b(hdev, lmp_subver, - "rtl_bt/rtl8723b_fw.bin"); case RTL_ROM_LMP_8821A: - return btrtl_setup_rtl8723b(hdev, lmp_subver, - "rtl_bt/rtl8821a_fw.bin"); case RTL_ROM_LMP_8761A: - return btrtl_setup_rtl8723b(hdev, lmp_subver, - "rtl_bt/rtl8761a_fw.bin"); case RTL_ROM_LMP_8822B: - return btrtl_setup_rtl8723b(hdev, lmp_subver, - "rtl_bt/rtl8822b_fw.bin"); + return btrtl_setup_rtl8723b(hdev, hci_rev, lmp_subver); default: bt_dev_info(hdev, "rtl: assuming no firmware upload needed"); return 0; -- cgit v1.2.3 From 38aa4da504837ba8b9c04941e843642f129661eb Mon Sep 17 00:00:00 2001 From: Prameela Rani Garnepudi Date: Tue, 27 Feb 2018 19:56:15 +0530 Subject: Bluetooth: btrsi: add new rsi bluetooth driver Redpine bluetooth driver is a thin driver which depends on 'rsi_91x' driver for transmitting and receiving packets to/from device. It creates hci interface when attach() is called from 'rsi_91x' module. Signed-off-by: Prameela Rani Garnepudi Signed-off-by: Siva Rebbagondla Acked-by: Marcel Holtmann Reviewed-by: Marcel Holtmann Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/bluetooth/Kconfig | 12 +++ drivers/bluetooth/Makefile | 2 + drivers/bluetooth/btrsi.c | 188 +++++++++++++++++++++++++++++++++++++++++++++ include/net/rsi_91x.h | 4 +- 4 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 drivers/bluetooth/btrsi.c (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 07e55cd8f8c8..d8bbd661dbdb 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -392,4 +392,16 @@ config BT_QCOMSMD Say Y here to compile support for HCI over Qualcomm SMD into the kernel or say M to compile as a module. +config BT_HCIRSI + tristate "Redpine HCI support" + default n + select RSI_COEX + help + Redpine BT driver. + This driver handles BT traffic from upper layers and pass + to the RSI_91x coex module for further scheduling to device + + Say Y here to compile support for HCI over Redpine into the + kernel or say M to compile as a module. + endmenu diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 4e4e44d09796..03cfc1b20c4a 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile @@ -28,6 +28,8 @@ obj-$(CONFIG_BT_QCA) += btqca.o obj-$(CONFIG_BT_HCIUART_NOKIA) += hci_nokia.o +obj-$(CONFIG_BT_HCIRSI) += btrsi.o + btmrvl-y := btmrvl_main.o btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c new file mode 100644 index 000000000000..5034325e417c --- /dev/null +++ b/drivers/bluetooth/btrsi.c @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2017 Redpine Signals Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define RSI_HEADROOM_FOR_BT_HAL 16 +#define RSI_FRAME_DESC_SIZE 16 + +struct rsi_hci_adapter { + void *priv; + struct rsi_proto_ops *proto_ops; + struct hci_dev *hdev; +}; + +static int rsi_hci_open(struct hci_dev *hdev) +{ + return 0; +} + +static int rsi_hci_close(struct hci_dev *hdev) +{ + return 0; +} + +static int rsi_hci_flush(struct hci_dev *hdev) +{ + return 0; +} + +static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct rsi_hci_adapter *h_adapter = hci_get_drvdata(hdev); + struct sk_buff *new_skb = NULL; + + switch (hci_skb_pkt_type(skb)) { + case HCI_COMMAND_PKT: + hdev->stat.cmd_tx++; + break; + case HCI_ACLDATA_PKT: + hdev->stat.acl_tx++; + break; + case HCI_SCODATA_PKT: + hdev->stat.sco_tx++; + break; + } + + if (skb_headroom(skb) < RSI_HEADROOM_FOR_BT_HAL) { + /* Insufficient skb headroom - allocate a new skb */ + new_skb = skb_realloc_headroom(skb, RSI_HEADROOM_FOR_BT_HAL); + if (unlikely(!new_skb)) + return -ENOMEM; + bt_cb(new_skb)->pkt_type = hci_skb_pkt_type(skb); + kfree_skb(skb); + skb = new_skb; + } + + return h_adapter->proto_ops->coex_send_pkt(h_adapter->priv, skb, + RSI_BT_Q); +} + +static int rsi_hci_recv_pkt(void *priv, const u8 *pkt) +{ + struct rsi_hci_adapter *h_adapter = priv; + struct hci_dev *hdev = h_adapter->hdev; + struct sk_buff *skb; + int pkt_len = get_unaligned_le16(pkt) & 0x0fff; + + skb = dev_alloc_skb(pkt_len); + if (!skb) + return -ENOMEM; + + memcpy(skb->data, pkt + RSI_FRAME_DESC_SIZE, pkt_len); + skb_put(skb, pkt_len); + h_adapter->hdev->stat.byte_rx += skb->len; + + hci_skb_pkt_type(skb) = pkt[14]; + + return hci_recv_frame(hdev, skb); +} + +static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops) +{ + struct rsi_hci_adapter *h_adapter = NULL; + struct hci_dev *hdev; + int err = 0; + + h_adapter = kzalloc(sizeof(*h_adapter), GFP_KERNEL); + if (!h_adapter) + return -ENOMEM; + + h_adapter->priv = priv; + ops->set_bt_context(priv, h_adapter); + h_adapter->proto_ops = ops; + + hdev = hci_alloc_dev(); + if (!hdev) { + BT_ERR("Failed to alloc HCI device"); + goto err; + } + + h_adapter->hdev = hdev; + + if (ops->get_host_intf(priv) == RSI_HOST_INTF_SDIO) + hdev->bus = HCI_SDIO; + else + hdev->bus = HCI_USB; + + hci_set_drvdata(hdev, h_adapter); + hdev->dev_type = HCI_PRIMARY; + hdev->open = rsi_hci_open; + hdev->close = rsi_hci_close; + hdev->flush = rsi_hci_flush; + hdev->send = rsi_hci_send_pkt; + + err = hci_register_dev(hdev); + if (err < 0) { + BT_ERR("HCI registration failed with errcode %d", err); + hci_free_dev(hdev); + goto err; + } + + return 0; +err: + h_adapter->hdev = NULL; + kfree(h_adapter); + return -EINVAL; +} + +static void rsi_hci_detach(void *priv) +{ + struct rsi_hci_adapter *h_adapter = priv; + struct hci_dev *hdev; + + if (!h_adapter) + return; + + hdev = h_adapter->hdev; + if (hdev) { + hci_unregister_dev(hdev); + hci_free_dev(hdev); + h_adapter->hdev = NULL; + } + + kfree(h_adapter); +} + +const struct rsi_mod_ops rsi_bt_ops = { + .attach = rsi_hci_attach, + .detach = rsi_hci_detach, + .recv_pkt = rsi_hci_recv_pkt, +}; +EXPORT_SYMBOL(rsi_bt_ops); + +static int rsi_91x_bt_module_init(void) +{ + return 0; +} + +static void rsi_91x_bt_module_exit(void) +{ + return; +} + +module_init(rsi_91x_bt_module_init); +module_exit(rsi_91x_bt_module_exit); +MODULE_AUTHOR("Redpine Signals Inc"); +MODULE_DESCRIPTION("RSI BT driver"); +MODULE_SUPPORTED_DEVICE("RSI-BT"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/include/net/rsi_91x.h b/include/net/rsi_91x.h index 737ab4e01e3b..040f07b47f1f 100644 --- a/include/net/rsi_91x.h +++ b/include/net/rsi_91x.h @@ -49,6 +49,8 @@ struct rsi_proto_ops { struct rsi_mod_ops { int (*attach)(void *priv, struct rsi_proto_ops *ops); void (*detach)(void *priv); - int (*recv_pkt)(void *priv, u8 *msg); + int (*recv_pkt)(void *priv, const u8 *msg); }; + +extern const struct rsi_mod_ops rsi_bt_ops; #endif -- cgit v1.2.3 From 255dd5b79d5474dad3ecebe99be7818684921abd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 15 Mar 2018 22:18:24 +0100 Subject: Bluetooth: btrsi: rework dependencies The linkage between the bluetooth driver and the wireless driver is not defined properly, leading to build problems such as: warning: (BT_HCIRSI) selects RSI_COEX which has unmet direct dependencies (NETDEVICES && WLAN && WLAN_VENDOR_RSI && BT_HCIRSI && RSI_91X) drivers/net/wireless/rsi/rsi_91x_main.o: In function `rsi_read_pkt': (.text+0x205): undefined reference to `rsi_bt_ops' As the dependency is actually the reverse (RSI_91X uses the BT_RSI driver, not the other way round), this changes the dependency to match, and enables the bluetooth driver from the RSI_COEX symbol. Fixes: 38aa4da50483 ("Bluetooth: btrsi: add new rsi bluetooth driver") Acked-by; Marcel Holtmann Signed-off-by: Arnd Bergmann Signed-off-by: Kalle Valo --- drivers/bluetooth/Kconfig | 4 +--- drivers/net/wireless/rsi/Kconfig | 4 +++- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index d8bbd661dbdb..149a38ee1fce 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -393,9 +393,7 @@ config BT_QCOMSMD kernel or say M to compile as a module. config BT_HCIRSI - tristate "Redpine HCI support" - default n - select RSI_COEX + tristate help Redpine BT driver. This driver handles BT traffic from upper layers and pass diff --git a/drivers/net/wireless/rsi/Kconfig b/drivers/net/wireless/rsi/Kconfig index f004be33fcfa..976c21866230 100644 --- a/drivers/net/wireless/rsi/Kconfig +++ b/drivers/net/wireless/rsi/Kconfig @@ -13,6 +13,7 @@ if WLAN_VENDOR_RSI config RSI_91X tristate "Redpine Signals Inc 91x WLAN driver support" + select BT_HCIRSI if RSI_COEX depends on MAC80211 ---help--- This option enabes support for RSI 1x1 devices. @@ -44,7 +45,8 @@ config RSI_USB config RSI_COEX bool "Redpine Signals WLAN BT Coexistence support" - depends on BT_HCIRSI && RSI_91X + depends on BT && RSI_91X + depends on !(BT=m && RSI_91X=y) default y ---help--- This option enables the WLAN BT coex support in rsi drivers. -- cgit v1.2.3 From fb2d466be9b336e9c801978e6a75d06059ac124a Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 5 Mar 2018 19:02:35 +0100 Subject: Bluetooth: hci_bcm: use gpiod cansleep version Some GPIO controller drivers request sleepable context and so can't be accessed from IRQ context. Using gpiod_set/get_value accessors with such controller leads to a kernel warning since they are reserved for atomic context (according to the documentation). Use the postfixed _cansleep version instead, indicating that context is safe for sleeping if necessary. Note that this is the case here since we never toggle the gpio neither from IRQ nor from a spinlocked section. Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 40b9fb247010..467e2f5cb7e3 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -908,13 +908,13 @@ static inline int bcm_apple_get_resources(struct bcm_device *dev) static int bcm_gpio_set_device_wakeup(struct bcm_device *dev, bool awake) { - gpiod_set_value(dev->device_wakeup, awake); + gpiod_set_value_cansleep(dev->device_wakeup, awake); return 0; } static int bcm_gpio_set_shutdown(struct bcm_device *dev, bool powered) { - gpiod_set_value(dev->shutdown, powered); + gpiod_set_value_cansleep(dev->shutdown, powered); return 0; } -- cgit v1.2.3 From f3863f1d7a579a8d8d7741a777ef863674a4d0c8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 7 Mar 2018 22:39:03 +0100 Subject: Bluetooth: hci_bcm: Use default baud rate if missing shutdown GPIO In case the shutdown GPIO is not wired up, it is impossible to reset the Bluetooth controller to its original state. This include the initial default baud rate which leads to issues when reloading the module or when something unexpected happens. To avoid any kind of runtime deadlocks, stick with the initial default baud rate. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/hci_bcm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 467e2f5cb7e3..ff7535e85dea 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -1146,6 +1146,12 @@ static int bcm_serdev_probe(struct serdev_device *serdev) if (err) return err; + if (!bcmdev->shutdown) { + dev_warn(&serdev->dev, + "No reset resource, using default baud rate\n"); + bcmdev->oper_speed = bcmdev->init_speed; + } + err = bcm_gpio_set_power(bcmdev, false); if (err) dev_err(&serdev->dev, "Failed to power down\n"); -- cgit v1.2.3 From a5c2f4c1c5292362c8f78e63f82c527cea955bbd Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 12 Mar 2018 10:20:04 +0100 Subject: Bluetooth: btmrvl: Delete an unnecessary variable initialisation in btmrvl_sdio_register_dev() The local variable "ret" will be set to an appropriate value a bit later. Thus omit the explicit initialisation at the beginning. Signed-off-by: Markus Elfring Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 7dbb4463b539..cd27d2f48bf2 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -920,7 +920,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card) { struct sdio_func *func; u8 reg; - int ret = 0; + int ret; if (!card || !card->func) { BT_ERR("Error: card or function is NULL!"); -- cgit v1.2.3 From 9376e4a5a318e1dbf1c53a31cfbe919e0ba926b0 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 12 Mar 2018 11:15:59 +0100 Subject: Bluetooth: btmrvl: Delete an unnecessary variable initialisation in btmrvl_sdio_card_to_host() The variable "payload" will eventually be set to an appropriate pointer a bit later. Thus omit the explicit initialisation at the beginning. Signed-off-by: Markus Elfring Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index cd27d2f48bf2..6f99b9f3d57f 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -689,7 +689,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) int ret, num_blocks, blksz; struct sk_buff *skb = NULL; u32 type; - u8 *payload = NULL; + u8 *payload; struct hci_dev *hdev = priv->btmrvl_dev.hcidev; struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; -- cgit v1.2.3 From 9bef22fb00cbfc6400c52c265c6c5ebcb6bfc1d1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 20 Mar 2018 09:31:04 +0100 Subject: Bluetooth: hci_ll: Use skb_put_u8 instead of struct hcill_cmd The struct hcill_cmd to create an skb with a single u8 is pointless. So just use skb_put_u8 instead. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/hci_ll.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 2f30dcad96bd..7c55a9f77808 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -82,10 +82,6 @@ enum hcill_states_e { HCILL_AWAKE_TO_ASLEEP }; -struct hcill_cmd { - u8 cmd; -} __packed; - struct ll_device { struct hci_uart hu; struct serdev_device *serdev; @@ -113,7 +109,6 @@ static int send_hcill_cmd(u8 cmd, struct hci_uart *hu) int err = 0; struct sk_buff *skb = NULL; struct ll_struct *ll = hu->priv; - struct hcill_cmd *hcill_packet; BT_DBG("hu %p cmd 0x%x", hu, cmd); @@ -126,8 +121,7 @@ static int send_hcill_cmd(u8 cmd, struct hci_uart *hu) } /* prepare packet */ - hcill_packet = skb_put(skb, 1); - hcill_packet->cmd = cmd; + skb_put_u8(skb, cmd); /* send packet */ skb_queue_tail(&ll->txq, skb); -- cgit v1.2.3 From a41e0796396eeceff673af4a38feaee149c6ff86 Mon Sep 17 00:00:00 2001 From: Vicente Bergas Date: Tue, 20 Mar 2018 19:41:10 +0100 Subject: Bluetooth: btusb: Add USB ID 7392:a611 for Edimax EW-7611ULB This WiFi/Bluetooth USB dongle uses a Realtek chipset, so, use btrtl for it. Product information: https://wikidevi.com/wiki/Edimax_EW-7611ULB From /sys/kernel/debug/usb/devices T: Bus=02 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=7392 ProdID=a611 Rev= 2.00 S: Manufacturer=Realtek S: Product=Edimax Wi-Fi N150 Bluetooth4.0 USB Adapter S: SerialNumber=00e04c000001 C:* #Ifs= 3 Cfg#= 1 Atr=e0 MxPwr=500mA A: FirstIf#= 0 IfCount= 2 Cls=e0(wlcon) Sub=01 Prot=01 I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms I:* If#= 2 Alt= 0 #EPs= 6 Cls=ff(vend.) Sub=ff Prot=ff Driver=rtl8723bu E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=03(Int.) MxPS= 64 Ivl=500us E: Ad=08(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=09(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms Tested-by: Vicente Bergas Signed-off-by: Vicente Bergas Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 5cd868ea28ed..c701443de3e7 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -368,6 +368,9 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK }, + /* Additional Realtek 8723BU Bluetooth devices */ + { USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK }, + /* Additional Realtek 8821AE Bluetooth devices */ { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK }, -- cgit v1.2.3 From e09070c51b280567695022237e57c428e548b355 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 16 Mar 2018 21:28:07 +0100 Subject: Bluetooth: hci_bcm: Add irq_polarity module option Add irq_polarity module option for easier troubleshooting of irq-polarity issues. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index ff7535e85dea..50c8523f8653 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -126,6 +126,10 @@ struct bcm_data { static DEFINE_MUTEX(bcm_device_lock); static LIST_HEAD(bcm_device_list); +static int irq_polarity = -1; +module_param(irq_polarity, int, 0444); +MODULE_PARM_DESC(irq_polarity, "IRQ polarity 0: active-high 1: active-low"); + static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed) { if (hu->serdev) @@ -989,11 +993,17 @@ static int bcm_acpi_probe(struct bcm_device *dev) } acpi_dev_free_resource_list(&resources); - dmi_id = dmi_first_match(bcm_active_low_irq_dmi_table); - if (dmi_id) { - dev_warn(dev->dev, "%s: Overwriting IRQ polarity to active low", - dmi_id->ident); - dev->irq_active_low = true; + if (irq_polarity != -1) { + dev->irq_active_low = irq_polarity; + dev_warn(dev->dev, "Overwriting IRQ polarity to active %s by module-param\n", + dev->irq_active_low ? "low" : "high"); + } else { + dmi_id = dmi_first_match(bcm_active_low_irq_dmi_table); + if (dmi_id) { + dev_warn(dev->dev, "%s: Overwriting IRQ polarity to active low", + dmi_id->ident); + dev->irq_active_low = true; + } } return 0; -- cgit v1.2.3 From bb5208b314c5127b716b2ee4f55803a8bb73b750 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 16 Mar 2018 21:28:08 +0100 Subject: Bluetooth: hci_bcm: Treat Interrupt ACPI resources as always being active-low Older devices with a serdev attached bcm bt hci, use an Interrupt ACPI resource to describe the IRQ (rather then a GpioInt resource). These device seem to all claim the IRQ is active-high and seem to all need a DMI quirk to treat it as active-low. Instead simply always assume that Interrupt resource specified IRQs are always active-low. This fixes the bt device not being able to wake the host from runtime- suspend on the: Asus T100TAM, Asus T200TA, Lenovo Yoga2 and the Toshiba Encore, without the need to add 4 new DMI quirks for these models. This also allows us to remove 2 DMI quirks for the Asus T100TA and Asus T100CHI series. Likely the 2 remaining quirks can also be removed but I could not find a DSDT of these devices to verify this. Cc: stable@vger.kernel.org Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=198953 Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1554835 Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 50c8523f8653..ce8c629c0eac 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -799,22 +799,6 @@ static const struct acpi_gpio_mapping acpi_bcm_int_first_gpios[] = { #ifdef CONFIG_ACPI /* IRQ polarity of some chipsets are not defined correctly in ACPI table. */ static const struct dmi_system_id bcm_active_low_irq_dmi_table[] = { - { - .ident = "Asus T100TA", - .matches = { - DMI_EXACT_MATCH(DMI_SYS_VENDOR, - "ASUSTeK COMPUTER INC."), - DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), - }, - }, - { - .ident = "Asus T100CHI", - .matches = { - DMI_EXACT_MATCH(DMI_SYS_VENDOR, - "ASUSTeK COMPUTER INC."), - DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100CHI"), - }, - }, { /* Handle ThinkPad 8 tablets with BCM2E55 chipset ACPI ID */ .ident = "Lenovo ThinkPad 8", .matches = { @@ -842,7 +826,9 @@ static int bcm_resource(struct acpi_resource *ares, void *data) switch (ares->type) { case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: irq = &ares->data.extended_irq; - dev->irq_active_low = irq->polarity == ACPI_ACTIVE_LOW; + if (irq->polarity != ACPI_ACTIVE_LOW) + dev_info(dev->dev, "ACPI Interrupt resource is active-high, this is usually wrong, treating the IRQ as active-low\n"); + dev->irq_active_low = true; break; case ACPI_RESOURCE_TYPE_GPIO: -- cgit v1.2.3 From 4063cafa3b24ff04635bdedc97cd3e4320415065 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 16 Mar 2018 21:28:09 +0100 Subject: Bluetooth: hci_bcm: Add 6 new ACPI HIDs Add 6 new ACPI HIDs to enable bluetooth on devices using these HIDs, I've tested the following HIDs / devices: BCM2E74: Jumper ezPad mini 3 BCM2E83: Acer Iconia Tab8 w1-810 BCM2E90: Meegopad T08 BCM2EAA: Chuwi Vi8 plus (CWI519) The reporter of Red Hat bugzilla 1554835 has tested: BCM2E84: Lenovo Yoga2 The reporter of kernel bugzilla 274481 has tested: BCM2E38: Toshiba Encore Note the Lenovo Yoga2 and Toshiba Encore also needs the earlier patch to treat all Interrupt ACPI resources as active low. Cc: stable@vger.kernel.org Buglink: https://bugzilla.kernel.org/attachment.cgi?id=274481 Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1554835 Reported-and-tested-by: Robert R. Howell Reported-and-tested-by: Christian Herzog Tested-by: Hans de Goede Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index ce8c629c0eac..fe45b8869cc1 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -1076,6 +1076,7 @@ static const struct hci_uart_proto bcm_proto = { #ifdef CONFIG_ACPI static const struct acpi_device_id bcm_acpi_match[] = { { "BCM2E1A", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, + { "BCM2E38", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E39", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E3A", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E3D", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, @@ -1088,12 +1089,17 @@ static const struct acpi_device_id bcm_acpi_match[] = { { "BCM2E67", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E71", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E72", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, + { "BCM2E74", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E7B", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E7C", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E7E", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, + { "BCM2E83", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, + { "BCM2E84", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, + { "BCM2E90", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, { "BCM2E95", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, { "BCM2E96", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, { "BCM2EA4", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, + { "BCM2EAA", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, { }, }; MODULE_DEVICE_TABLE(acpi, bcm_acpi_match); -- cgit v1.2.3 From 9644e6b98cda0485d12b6b1cf72658855e57c878 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 16 Mar 2018 21:28:10 +0100 Subject: Bluetooth: hci_bcm: Remove duplication in gpio-mappings declaration We declare the same set of const acpi_gpio_params twice with different names, besides the needless duplication this naming leads to a sortof double indirection which also makes it harder to see how the mapping is actually setup. This commit renames the first set to have generic names, which better describe the contents of the mapping and drops the second set. Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index fe45b8869cc1..e4371d0edbcf 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -774,25 +774,21 @@ unlock: } #endif -static const struct acpi_gpio_params int_last_device_wakeup_gpios = { 0, 0, false }; -static const struct acpi_gpio_params int_last_shutdown_gpios = { 1, 0, false }; -static const struct acpi_gpio_params int_last_host_wakeup_gpios = { 2, 0, false }; +static const struct acpi_gpio_params first_gpio = { 0, 0, false }; +static const struct acpi_gpio_params second_gpio = { 1, 0, false }; +static const struct acpi_gpio_params third_gpio = { 2, 0, false }; static const struct acpi_gpio_mapping acpi_bcm_int_last_gpios[] = { - { "device-wakeup-gpios", &int_last_device_wakeup_gpios, 1 }, - { "shutdown-gpios", &int_last_shutdown_gpios, 1 }, - { "host-wakeup-gpios", &int_last_host_wakeup_gpios, 1 }, + { "device-wakeup-gpios", &first_gpio, 1 }, + { "shutdown-gpios", &second_gpio, 1 }, + { "host-wakeup-gpios", &third_gpio, 1 }, { }, }; -static const struct acpi_gpio_params int_first_host_wakeup_gpios = { 0, 0, false }; -static const struct acpi_gpio_params int_first_device_wakeup_gpios = { 1, 0, false }; -static const struct acpi_gpio_params int_first_shutdown_gpios = { 2, 0, false }; - static const struct acpi_gpio_mapping acpi_bcm_int_first_gpios[] = { - { "device-wakeup-gpios", &int_first_device_wakeup_gpios, 1 }, - { "shutdown-gpios", &int_first_shutdown_gpios, 1 }, - { "host-wakeup-gpios", &int_first_host_wakeup_gpios, 1 }, + { "host-wakeup-gpios", &first_gpio, 1 }, + { "device-wakeup-gpios", &second_gpio, 1 }, + { "shutdown-gpios", &third_gpio, 1 }, { }, }; -- cgit v1.2.3 From a4de1567be322f4fca75e47bb7bd4cd8e3d79657 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 16 Mar 2018 21:28:11 +0100 Subject: Bluetooth: hci_bcm: Do not tie GPIO pin order to a specific ACPI HID Since I've been doing a lot of work on Linux Bay Trail / Cherry Trail support, I've gathered a collection of ACPI DSDTs from about 50 such machines. Looking at these DSTDs many have an ACPI device entry describing a bcm bluetooth device (often disabled in the DSDT), quite a few of these ACPI device entries have a resource-table where the order does not match with the order currently associated with the HID of that entry in the bcm_acpi_match table. Looking at the Windows .inf files, there is nothing indicating a specific order there, so I believe that there is no 1:1 mapping between the ACPI HID and the order in which the resources are listed. Therefor this commit replaces the hardcoded mapping based on ACPI HID, with code which actually checks in which order the resources are listed and bases the gpio-mapping on that. This should ensure that we always pick the right mapping and this will make adding new ACPI HIDs to the driver easier. This has been tested on the following devices: -Asus T100CHI BCM2E39 / brcmfmac43241b4-sdio / BCM4324B3-37.4M.hcd -Asus T100TA BCM2E39 / brcmfmac43241b4-sdio / BCM4324B3-37.4M.hcd -Asus T200TA BCM2E65 / brcmfmac43340-sdio / BCM43341B0-37.4M.hcd -Jumper ezPad mini 3 BCM2E74 / brcmfmac43430a0-sdio / BCM4343A0-26M.hcd -Acer Iconia Tab8 w1-8 BCM2E83 / brcmfmac4330-sdio / BCM4330B1-26M.hcd -Chuwi Vi8 plus(CWI519) BCM2EAA / brcmfmac43430-sdio / BCM43430A1-26M.hcd Which together cover all 3 combinations of using an Interrupt resource / GpioInt resource as first resource / GpioInt resource as last resource. Tested-by: Hans de Goede Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 91 +++++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 36 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index e4371d0edbcf..79a0ec57d485 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -98,6 +98,8 @@ struct bcm_device { int (*set_shutdown)(struct bcm_device *, bool); #ifdef CONFIG_ACPI acpi_handle btlp, btpu, btpd; + int gpio_count; + int gpio_int_idx; #endif struct clk *clk; @@ -829,8 +831,11 @@ static int bcm_resource(struct acpi_resource *ares, void *data) case ACPI_RESOURCE_TYPE_GPIO: gpio = &ares->data.gpio; - if (gpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT) + if (gpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT) { + dev->gpio_int_idx = dev->gpio_count; dev->irq_active_low = gpio->polarity == ACPI_ACTIVE_LOW; + } + dev->gpio_count++; break; case ACPI_RESOURCE_TYPE_SERIAL_BUS: @@ -948,20 +953,11 @@ static int bcm_acpi_probe(struct bcm_device *dev) LIST_HEAD(resources); const struct dmi_system_id *dmi_id; const struct acpi_gpio_mapping *gpio_mapping = acpi_bcm_int_last_gpios; - const struct acpi_device_id *id; struct resource_entry *entry; int ret; - /* Retrieve GPIO data */ - id = acpi_match_device(dev->dev->driver->acpi_match_table, dev->dev); - if (id) - gpio_mapping = (const struct acpi_gpio_mapping *) id->driver_data; - - ret = devm_acpi_dev_add_driver_gpios(dev->dev, gpio_mapping); - if (ret) - return ret; - /* Retrieve UART ACPI info */ + dev->gpio_int_idx = -1; ret = acpi_dev_get_resources(ACPI_COMPANION(dev->dev), &resources, bcm_resource, dev); if (ret < 0) @@ -975,6 +971,29 @@ static int bcm_acpi_probe(struct bcm_device *dev) } acpi_dev_free_resource_list(&resources); + /* If the DSDT uses an Interrupt resource for the IRQ, then there are + * only 2 GPIO resources, we use the irq-last mapping for this, since + * we already have an irq the 3th / last mapping will not be used. + */ + if (dev->irq) + gpio_mapping = acpi_bcm_int_last_gpios; + else if (dev->gpio_int_idx == 0) + gpio_mapping = acpi_bcm_int_first_gpios; + else if (dev->gpio_int_idx == 2) + gpio_mapping = acpi_bcm_int_last_gpios; + else + dev_warn(dev->dev, "Unexpected ACPI gpio_int_idx: %d\n", + dev->gpio_int_idx); + + /* Warn if our expectations are not met. */ + if (dev->gpio_count != (dev->irq ? 2 : 3)) + dev_warn(dev->dev, "Unexpected number of ACPI GPIOs: %d\n", + dev->gpio_count); + + ret = devm_acpi_dev_add_driver_gpios(dev->dev, gpio_mapping); + if (ret) + return ret; + if (irq_polarity != -1) { dev->irq_active_low = irq_polarity; dev_warn(dev->dev, "Overwriting IRQ polarity to active %s by module-param\n", @@ -1071,31 +1090,31 @@ static const struct hci_uart_proto bcm_proto = { #ifdef CONFIG_ACPI static const struct acpi_device_id bcm_acpi_match[] = { - { "BCM2E1A", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E38", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E39", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E3A", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E3D", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E3F", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E40", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E54", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E55", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E64", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E65", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E67", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E71", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E72", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E74", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E7B", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E7C", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E7E", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, - { "BCM2E83", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, - { "BCM2E84", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E90", (kernel_ulong_t)&acpi_bcm_int_last_gpios }, - { "BCM2E95", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, - { "BCM2E96", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, - { "BCM2EA4", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, - { "BCM2EAA", (kernel_ulong_t)&acpi_bcm_int_first_gpios }, + { "BCM2E1A" }, + { "BCM2E38" }, + { "BCM2E39" }, + { "BCM2E3A" }, + { "BCM2E3D" }, + { "BCM2E3F" }, + { "BCM2E40" }, + { "BCM2E54" }, + { "BCM2E55" }, + { "BCM2E64" }, + { "BCM2E65" }, + { "BCM2E67" }, + { "BCM2E71" }, + { "BCM2E72" }, + { "BCM2E74" }, + { "BCM2E7B" }, + { "BCM2E7C" }, + { "BCM2E7E" }, + { "BCM2E83" }, + { "BCM2E84" }, + { "BCM2E90" }, + { "BCM2E95" }, + { "BCM2E96" }, + { "BCM2EA4" }, + { "BCM2EAA" }, { }, }; MODULE_DEVICE_TABLE(acpi, bcm_acpi_match); -- cgit v1.2.3 From 6112150261247d9a7d85dda476143985f44f8859 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 21 Mar 2018 13:53:18 +0100 Subject: Bluetooth: hci_bcm: Add ACPI HIDs found in Windows .inf files and DSTDs Now that we need just an ACPI HID in the table, and the driver auto- configures itself otherwise, we can easily add a bunch of known ACPI HIDs. This avoids having to add these 1 by 1 as devices with one are encountered by users. This commit may seem as if it simply adds all IDs between BCM2E00-BCM2EAC, but that is not true, all these IDs were found in actual .inf files and the range is not entirely continuous, the following IDs are not added: BCM2E6A, BCM2E6C, BCM2E8F and BCM2E91 because I did not see these in any .inf files. As for the large amount of IDs this seems to be caused by Broadcom using a separate ID for every bluetooth module using their chips. E.g. BCM2EA6 seems to be specifically for the Raspberry Pi 3. Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 141 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 79a0ec57d485..4ceaf1f4a4e7 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -1090,31 +1090,172 @@ static const struct hci_uart_proto bcm_proto = { #ifdef CONFIG_ACPI static const struct acpi_device_id bcm_acpi_match[] = { + { "BCM2E00" }, + { "BCM2E01" }, + { "BCM2E02" }, + { "BCM2E03" }, + { "BCM2E04" }, + { "BCM2E05" }, + { "BCM2E06" }, + { "BCM2E07" }, + { "BCM2E08" }, + { "BCM2E09" }, + { "BCM2E0A" }, + { "BCM2E0B" }, + { "BCM2E0C" }, + { "BCM2E0D" }, + { "BCM2E0E" }, + { "BCM2E0F" }, + { "BCM2E10" }, + { "BCM2E11" }, + { "BCM2E12" }, + { "BCM2E13" }, + { "BCM2E14" }, + { "BCM2E15" }, + { "BCM2E16" }, + { "BCM2E17" }, + { "BCM2E18" }, + { "BCM2E19" }, { "BCM2E1A" }, + { "BCM2E1B" }, + { "BCM2E1C" }, + { "BCM2E1D" }, + { "BCM2E1F" }, + { "BCM2E20" }, + { "BCM2E21" }, + { "BCM2E22" }, + { "BCM2E23" }, + { "BCM2E24" }, + { "BCM2E25" }, + { "BCM2E26" }, + { "BCM2E27" }, + { "BCM2E28" }, + { "BCM2E29" }, + { "BCM2E2A" }, + { "BCM2E2B" }, + { "BCM2E2C" }, + { "BCM2E2D" }, + { "BCM2E2E" }, + { "BCM2E2F" }, + { "BCM2E30" }, + { "BCM2E31" }, + { "BCM2E32" }, + { "BCM2E33" }, + { "BCM2E34" }, + { "BCM2E35" }, + { "BCM2E36" }, + { "BCM2E37" }, { "BCM2E38" }, { "BCM2E39" }, { "BCM2E3A" }, + { "BCM2E3B" }, + { "BCM2E3C" }, { "BCM2E3D" }, + { "BCM2E3E" }, { "BCM2E3F" }, { "BCM2E40" }, + { "BCM2E41" }, + { "BCM2E42" }, + { "BCM2E43" }, + { "BCM2E44" }, + { "BCM2E45" }, + { "BCM2E46" }, + { "BCM2E47" }, + { "BCM2E48" }, + { "BCM2E49" }, + { "BCM2E4A" }, + { "BCM2E4B" }, + { "BCM2E4C" }, + { "BCM2E4D" }, + { "BCM2E4E" }, + { "BCM2E4F" }, + { "BCM2E50" }, + { "BCM2E51" }, + { "BCM2E52" }, + { "BCM2E53" }, { "BCM2E54" }, { "BCM2E55" }, + { "BCM2E56" }, + { "BCM2E57" }, + { "BCM2E58" }, + { "BCM2E59" }, + { "BCM2E5A" }, + { "BCM2E5B" }, + { "BCM2E5C" }, + { "BCM2E5D" }, + { "BCM2E5E" }, + { "BCM2E5F" }, + { "BCM2E60" }, + { "BCM2E61" }, + { "BCM2E62" }, + { "BCM2E63" }, { "BCM2E64" }, { "BCM2E65" }, + { "BCM2E66" }, { "BCM2E67" }, + { "BCM2E68" }, + { "BCM2E69" }, + { "BCM2E6B" }, + { "BCM2E6D" }, + { "BCM2E6E" }, + { "BCM2E6F" }, + { "BCM2E70" }, { "BCM2E71" }, { "BCM2E72" }, + { "BCM2E73" }, { "BCM2E74" }, + { "BCM2E75" }, + { "BCM2E76" }, + { "BCM2E77" }, + { "BCM2E78" }, + { "BCM2E79" }, + { "BCM2E7A" }, { "BCM2E7B" }, { "BCM2E7C" }, + { "BCM2E7D" }, { "BCM2E7E" }, + { "BCM2E7F" }, + { "BCM2E80" }, + { "BCM2E81" }, + { "BCM2E82" }, { "BCM2E83" }, { "BCM2E84" }, + { "BCM2E85" }, + { "BCM2E86" }, + { "BCM2E87" }, + { "BCM2E88" }, + { "BCM2E89" }, + { "BCM2E8A" }, + { "BCM2E8B" }, + { "BCM2E8C" }, + { "BCM2E8D" }, + { "BCM2E8E" }, { "BCM2E90" }, + { "BCM2E92" }, + { "BCM2E93" }, + { "BCM2E94" }, { "BCM2E95" }, { "BCM2E96" }, + { "BCM2E97" }, + { "BCM2E98" }, + { "BCM2E99" }, + { "BCM2E9A" }, + { "BCM2E9B" }, + { "BCM2E9C" }, + { "BCM2E9D" }, + { "BCM2EA0" }, + { "BCM2EA1" }, + { "BCM2EA2" }, + { "BCM2EA3" }, { "BCM2EA4" }, + { "BCM2EA5" }, + { "BCM2EA6" }, + { "BCM2EA7" }, + { "BCM2EA8" }, + { "BCM2EA9" }, { "BCM2EAA" }, + { "BCM2EAB" }, + { "BCM2EAC" }, { }, }; MODULE_DEVICE_TABLE(acpi, bcm_acpi_match); -- cgit v1.2.3 From f9d7c8fd2630d1d15dbc23e6ff6f9f0b54194ee4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 24 Mar 2018 10:19:52 +0100 Subject: Bluetooth: hci_ll: Convert to use h4_recv_buf helper The HCILL or eHCILL protocol from TI is actually an H:4 protocol with a few extra events and thus can also use the h4_recv_buf helper. Instead of open coding the same funtionality add the extra events to the packet description table and use h4_recv_buf. Signed-off-by: Marcel Holtmann Tested-by: Tony Lindgren Signed-off-by: Johan Hedberg --- drivers/bluetooth/Kconfig | 1 + drivers/bluetooth/hci_ll.c | 214 +++++++++++++++------------------------------ 2 files changed, 70 insertions(+), 145 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 149a38ee1fce..b83d12ac378e 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -147,6 +147,7 @@ config BT_HCIUART_ATH3K config BT_HCIUART_LL bool "HCILL protocol support" depends on BT_HCIUART_SERDEV + select BT_HCIUART_H4 help HCILL (HCI Low Level) is a serial protocol for communication between Bluetooth device and host. This protocol is required for diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 7c55a9f77808..27e414b4e3a2 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -67,13 +67,6 @@ #define HCILL_WAKE_UP_IND 0x32 #define HCILL_WAKE_UP_ACK 0x33 -/* HCILL receiver States */ -#define HCILL_W4_PACKET_TYPE 0 -#define HCILL_W4_EVENT_HDR 1 -#define HCILL_W4_ACL_HDR 2 -#define HCILL_W4_SCO_HDR 3 -#define HCILL_W4_DATA 4 - /* HCILL states */ enum hcill_states_e { HCILL_ASLEEP, @@ -91,8 +84,6 @@ struct ll_device { }; struct ll_struct { - unsigned long rx_state; - unsigned long rx_count; struct sk_buff *rx_skb; struct sk_buff_head txq; spinlock_t hcill_lock; /* HCILL state lock */ @@ -373,155 +364,88 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb) return 0; } -static inline int ll_check_data_len(struct hci_dev *hdev, struct ll_struct *ll, int len) +static int ll_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) { - int room = skb_tailroom(ll->rx_skb); - - BT_DBG("len %d room %d", len, room); + struct hci_uart *hu = hci_get_drvdata(hdev); + struct ll_struct *ll = hu->priv; - if (!len) { - hci_recv_frame(hdev, ll->rx_skb); - } else if (len > room) { - BT_ERR("Data length is too large"); - kfree_skb(ll->rx_skb); - } else { - ll->rx_state = HCILL_W4_DATA; - ll->rx_count = len; - return len; + switch (hci_skb_pkt_type(skb)) { + case HCILL_GO_TO_SLEEP_IND: + BT_DBG("HCILL_GO_TO_SLEEP_IND packet"); + ll_device_want_to_sleep(hu); + break; + case HCILL_GO_TO_SLEEP_ACK: + /* shouldn't happen */ + bt_dev_err(hdev, "received HCILL_GO_TO_SLEEP_ACK in state %ld", + ll->hcill_state); + break; + case HCILL_WAKE_UP_IND: + BT_DBG("HCILL_WAKE_UP_IND packet"); + ll_device_want_to_wakeup(hu); + break; + case HCILL_WAKE_UP_ACK: + BT_DBG("HCILL_WAKE_UP_ACK packet"); + ll_device_woke_up(hu); + break; } - ll->rx_state = HCILL_W4_PACKET_TYPE; - ll->rx_skb = NULL; - ll->rx_count = 0; - + kfree_skb(skb); return 0; } +#define LL_RECV_SLEEP_IND \ + .type = HCILL_GO_TO_SLEEP_IND, \ + .hlen = 0, \ + .loff = 0, \ + .lsize = 0, \ + .maxlen = 0 + +#define LL_RECV_SLEEP_ACK \ + .type = HCILL_GO_TO_SLEEP_ACK, \ + .hlen = 0, \ + .loff = 0, \ + .lsize = 0, \ + .maxlen = 0 + +#define LL_RECV_WAKE_IND \ + .type = HCILL_WAKE_UP_IND, \ + .hlen = 0, \ + .loff = 0, \ + .lsize = 0, \ + .maxlen = 0 + +#define LL_RECV_WAKE_ACK \ + .type = HCILL_WAKE_UP_ACK, \ + .hlen = 0, \ + .loff = 0, \ + .lsize = 0, \ + .maxlen = 0 + +static const struct h4_recv_pkt ll_recv_pkts[] = { + { H4_RECV_ACL, .recv = hci_recv_frame }, + { H4_RECV_SCO, .recv = hci_recv_frame }, + { H4_RECV_EVENT, .recv = hci_recv_frame }, + { LL_RECV_SLEEP_IND, .recv = ll_recv_frame }, + { LL_RECV_SLEEP_ACK, .recv = ll_recv_frame }, + { LL_RECV_WAKE_IND, .recv = ll_recv_frame }, + { LL_RECV_WAKE_ACK, .recv = ll_recv_frame }, +}; + /* Recv data */ static int ll_recv(struct hci_uart *hu, const void *data, int count) { struct ll_struct *ll = hu->priv; - const char *ptr; - struct hci_event_hdr *eh; - struct hci_acl_hdr *ah; - struct hci_sco_hdr *sh; - int len, type, dlen; - - BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count); - - ptr = data; - while (count) { - if (ll->rx_count) { - len = min_t(unsigned int, ll->rx_count, count); - skb_put_data(ll->rx_skb, ptr, len); - ll->rx_count -= len; count -= len; ptr += len; - - if (ll->rx_count) - continue; - - switch (ll->rx_state) { - case HCILL_W4_DATA: - BT_DBG("Complete data"); - hci_recv_frame(hu->hdev, ll->rx_skb); - - ll->rx_state = HCILL_W4_PACKET_TYPE; - ll->rx_skb = NULL; - continue; - - case HCILL_W4_EVENT_HDR: - eh = hci_event_hdr(ll->rx_skb); - - BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); - - ll_check_data_len(hu->hdev, ll, eh->plen); - continue; - case HCILL_W4_ACL_HDR: - ah = hci_acl_hdr(ll->rx_skb); - dlen = __le16_to_cpu(ah->dlen); + if (!test_bit(HCI_UART_REGISTERED, &hu->flags)) + return -EUNATCH; - BT_DBG("ACL header: dlen %d", dlen); - - ll_check_data_len(hu->hdev, ll, dlen); - continue; - - case HCILL_W4_SCO_HDR: - sh = hci_sco_hdr(ll->rx_skb); - - BT_DBG("SCO header: dlen %d", sh->dlen); - - ll_check_data_len(hu->hdev, ll, sh->dlen); - continue; - } - } - - /* HCILL_W4_PACKET_TYPE */ - switch (*ptr) { - case HCI_EVENT_PKT: - BT_DBG("Event packet"); - ll->rx_state = HCILL_W4_EVENT_HDR; - ll->rx_count = HCI_EVENT_HDR_SIZE; - type = HCI_EVENT_PKT; - break; - - case HCI_ACLDATA_PKT: - BT_DBG("ACL packet"); - ll->rx_state = HCILL_W4_ACL_HDR; - ll->rx_count = HCI_ACL_HDR_SIZE; - type = HCI_ACLDATA_PKT; - break; - - case HCI_SCODATA_PKT: - BT_DBG("SCO packet"); - ll->rx_state = HCILL_W4_SCO_HDR; - ll->rx_count = HCI_SCO_HDR_SIZE; - type = HCI_SCODATA_PKT; - break; - - /* HCILL signals */ - case HCILL_GO_TO_SLEEP_IND: - BT_DBG("HCILL_GO_TO_SLEEP_IND packet"); - ll_device_want_to_sleep(hu); - ptr++; count--; - continue; - - case HCILL_GO_TO_SLEEP_ACK: - /* shouldn't happen */ - BT_ERR("received HCILL_GO_TO_SLEEP_ACK (in state %ld)", ll->hcill_state); - ptr++; count--; - continue; - - case HCILL_WAKE_UP_IND: - BT_DBG("HCILL_WAKE_UP_IND packet"); - ll_device_want_to_wakeup(hu); - ptr++; count--; - continue; - - case HCILL_WAKE_UP_ACK: - BT_DBG("HCILL_WAKE_UP_ACK packet"); - ll_device_woke_up(hu); - ptr++; count--; - continue; - - default: - BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr); - hu->hdev->stat.err_rx++; - ptr++; count--; - continue; - } - - ptr++; count--; - - /* Allocate packet */ - ll->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); - if (!ll->rx_skb) { - BT_ERR("Can't allocate mem for new packet"); - ll->rx_state = HCILL_W4_PACKET_TYPE; - ll->rx_count = 0; - return -ENOMEM; - } - - hci_skb_pkt_type(ll->rx_skb) = type; + ll->rx_skb = h4_recv_buf(hu->hdev, ll->rx_skb, data, count, + ll_recv_pkts, ARRAY_SIZE(ll_recv_pkts)); + if (IS_ERR(ll->rx_skb)) { + int err = PTR_ERR(ll->rx_skb); + bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err); + ll->rx_skb = NULL; + return err; } return count; -- cgit v1.2.3 From 07eb96a5a7b083c988a2c7b0663e958e392f18c7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 24 Mar 2018 10:19:53 +0100 Subject: Bluetooth: bpa10x: Use separate h4_recv_buf helper When adding the alignment and padding support for H:4 packet processing for the Nokia driver, it broke the h4_recv_buf usage within bpa10x driver. To fix this use a separate helper function and placing it into a dedicated h4_recv.h header file. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/Kconfig | 3 +- drivers/bluetooth/bpa10x.c | 2 +- drivers/bluetooth/h4_recv.h | 160 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 drivers/bluetooth/h4_recv.h (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index b83d12ac378e..4e7594f3d072 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -243,8 +243,7 @@ config BT_HCIBCM203X config BT_HCIBPA10X tristate "HCI BPA10x USB driver" - depends on USB && BT_HCIUART - select BT_HCIUART_H4 + depends on USB help Bluetooth HCI BPA10x USB driver. This driver provides support for the Digianswer BPA 100/105 Bluetooth diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 801ea4ca65e4..c6f7cc57db14 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -35,7 +35,7 @@ #include #include -#include "hci_uart.h" +#include "h4_recv.h" #define VERSION "0.11" diff --git a/drivers/bluetooth/h4_recv.h b/drivers/bluetooth/h4_recv.h new file mode 100644 index 000000000000..b432651f8236 --- /dev/null +++ b/drivers/bluetooth/h4_recv.h @@ -0,0 +1,160 @@ +/* + * + * Generic Bluetooth HCI UART driver + * + * Copyright (C) 2015-2018 Intel Corporation + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include + +struct h4_recv_pkt { + u8 type; /* Packet type */ + u8 hlen; /* Header length */ + u8 loff; /* Data length offset in header */ + u8 lsize; /* Data length field size */ + u16 maxlen; /* Max overall packet length */ + int (*recv)(struct hci_dev *hdev, struct sk_buff *skb); +}; + +#define H4_RECV_ACL \ + .type = HCI_ACLDATA_PKT, \ + .hlen = HCI_ACL_HDR_SIZE, \ + .loff = 2, \ + .lsize = 2, \ + .maxlen = HCI_MAX_FRAME_SIZE \ + +#define H4_RECV_SCO \ + .type = HCI_SCODATA_PKT, \ + .hlen = HCI_SCO_HDR_SIZE, \ + .loff = 2, \ + .lsize = 1, \ + .maxlen = HCI_MAX_SCO_SIZE + +#define H4_RECV_EVENT \ + .type = HCI_EVENT_PKT, \ + .hlen = HCI_EVENT_HDR_SIZE, \ + .loff = 1, \ + .lsize = 1, \ + .maxlen = HCI_MAX_EVENT_SIZE + +static inline struct sk_buff *h4_recv_buf(struct hci_dev *hdev, + struct sk_buff *skb, + const unsigned char *buffer, + int count, + const struct h4_recv_pkt *pkts, + int pkts_count) +{ + while (count) { + int i, len; + + if (!count) + break; + + if (!skb) { + for (i = 0; i < pkts_count; i++) { + if (buffer[0] != (&pkts[i])->type) + continue; + + skb = bt_skb_alloc((&pkts[i])->maxlen, + GFP_ATOMIC); + if (!skb) + return ERR_PTR(-ENOMEM); + + hci_skb_pkt_type(skb) = (&pkts[i])->type; + hci_skb_expect(skb) = (&pkts[i])->hlen; + break; + } + + /* Check for invalid packet type */ + if (!skb) + return ERR_PTR(-EILSEQ); + + count -= 1; + buffer += 1; + } + + len = min_t(uint, hci_skb_expect(skb) - skb->len, count); + skb_put_data(skb, buffer, len); + + count -= len; + buffer += len; + + /* Check for partial packet */ + if (skb->len < hci_skb_expect(skb)) + continue; + + for (i = 0; i < pkts_count; i++) { + if (hci_skb_pkt_type(skb) == (&pkts[i])->type) + break; + } + + if (i >= pkts_count) { + kfree_skb(skb); + return ERR_PTR(-EILSEQ); + } + + if (skb->len == (&pkts[i])->hlen) { + u16 dlen; + + switch ((&pkts[i])->lsize) { + case 0: + /* No variable data length */ + dlen = 0; + break; + case 1: + /* Single octet variable length */ + dlen = skb->data[(&pkts[i])->loff]; + hci_skb_expect(skb) += dlen; + + if (skb_tailroom(skb) < dlen) { + kfree_skb(skb); + return ERR_PTR(-EMSGSIZE); + } + break; + case 2: + /* Double octet variable length */ + dlen = get_unaligned_le16(skb->data + + (&pkts[i])->loff); + hci_skb_expect(skb) += dlen; + + if (skb_tailroom(skb) < dlen) { + kfree_skb(skb); + return ERR_PTR(-EMSGSIZE); + } + break; + default: + /* Unsupported variable length */ + kfree_skb(skb); + return ERR_PTR(-EILSEQ); + } + + if (!dlen) { + /* No more data, complete frame */ + (&pkts[i])->recv(hdev, skb); + skb = NULL; + } + } else { + /* Complete frame */ + (&pkts[i])->recv(hdev, skb); + skb = NULL; + } + } + + return skb; +} -- cgit v1.2.3 From 6f6f1eced8c325d5ef64451556947f606f9fac7a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 24 Mar 2018 10:19:54 +0100 Subject: Bluetooth: Remove unused btuart_cs driver With patch 279c936153199 the btuart_cs driver has been deprecated in favor of serial_cs + hci_uart combination. static struct pcmcia_device_id btuart_ids[] = { /* don't use this driver. Use serial_cs + hci_uart instead */ PCMCIA_DEVICE_NULL }; Intead of keeping it around, just remove it since it is not even assigned to any PCMCIA identifiers anymore. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/Kconfig | 16 - drivers/bluetooth/Makefile | 1 - drivers/bluetooth/btuart_cs.c | 675 ------------------------------------------ 3 files changed, 692 deletions(-) delete mode 100644 drivers/bluetooth/btuart_cs.c (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 4e7594f3d072..010f5f579e68 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -305,22 +305,6 @@ config BT_HCIBLUECARD Say Y here to compile support for HCI BlueCard devices into the kernel or say M to compile it as module (bluecard_cs). -config BT_HCIBTUART - tristate "HCI UART (PC Card) device driver" - depends on PCMCIA - help - Bluetooth HCI UART (PC Card) driver. - This driver provides support for Bluetooth PCMCIA devices with - an UART interface: - Xircom CreditCard Bluetooth Adapter - Xircom RealPort2 Bluetooth Adapter - Sphinx PICO Card - H-Soft blue+Card - Cyber-blue Compact Flash Card - - Say Y here to compile support for HCI UART devices into the - kernel or say M to compile it as module (btuart_cs). - config BT_HCIVHCI tristate "HCI VHCI (Virtual HCI device) driver" help diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 03cfc1b20c4a..ec16c55eb6e9 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_BT_HCIBFUSB) += bfusb.o obj-$(CONFIG_BT_HCIDTL1) += dtl1_cs.o obj-$(CONFIG_BT_HCIBT3C) += bt3c_cs.o obj-$(CONFIG_BT_HCIBLUECARD) += bluecard_cs.o -obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o obj-$(CONFIG_BT_HCIBTUSB) += btusb.o obj-$(CONFIG_BT_HCIBTSDIO) += btsdio.o diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c deleted file mode 100644 index 310e9c2e09b6..000000000000 --- a/drivers/bluetooth/btuart_cs.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * - * Driver for Bluetooth PCMCIA cards with HCI UART interface - * - * Copyright (C) 2001-2002 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - - - -/* ======================== Module parameters ======================== */ - - -MODULE_AUTHOR("Marcel Holtmann "); -MODULE_DESCRIPTION("Bluetooth driver for Bluetooth PCMCIA cards with HCI UART interface"); -MODULE_LICENSE("GPL"); - - - -/* ======================== Local structures ======================== */ - - -struct btuart_info { - struct pcmcia_device *p_dev; - - struct hci_dev *hdev; - - spinlock_t lock; /* For serializing operations */ - - struct sk_buff_head txq; - unsigned long tx_state; - - unsigned long rx_state; - unsigned long rx_count; - struct sk_buff *rx_skb; -}; - - -static int btuart_config(struct pcmcia_device *link); -static void btuart_release(struct pcmcia_device *link); - -static void btuart_detach(struct pcmcia_device *p_dev); - - -/* Maximum baud rate */ -#define SPEED_MAX 115200 - -/* Default baud rate: 57600, 115200, 230400 or 460800 */ -#define DEFAULT_BAUD_RATE 115200 - - -/* Transmit states */ -#define XMIT_SENDING 1 -#define XMIT_WAKEUP 2 -#define XMIT_WAITING 8 - -/* Receiver states */ -#define RECV_WAIT_PACKET_TYPE 0 -#define RECV_WAIT_EVENT_HEADER 1 -#define RECV_WAIT_ACL_HEADER 2 -#define RECV_WAIT_SCO_HEADER 3 -#define RECV_WAIT_DATA 4 - - - -/* ======================== Interrupt handling ======================== */ - - -static int btuart_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) -{ - int actual = 0; - - /* Tx FIFO should be empty */ - if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) - return 0; - - /* Fill FIFO with current frame */ - while ((fifo_size-- > 0) && (actual < len)) { - /* Transmit next byte */ - outb(buf[actual], iobase + UART_TX); - actual++; - } - - return actual; -} - - -static void btuart_write_wakeup(struct btuart_info *info) -{ - if (!info) { - BT_ERR("Unknown device"); - return; - } - - if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { - set_bit(XMIT_WAKEUP, &(info->tx_state)); - return; - } - - do { - unsigned int iobase = info->p_dev->resource[0]->start; - register struct sk_buff *skb; - int len; - - clear_bit(XMIT_WAKEUP, &(info->tx_state)); - - if (!pcmcia_dev_present(info->p_dev)) - return; - - skb = skb_dequeue(&(info->txq)); - if (!skb) - break; - - /* Send frame */ - len = btuart_write(iobase, 16, skb->data, skb->len); - set_bit(XMIT_WAKEUP, &(info->tx_state)); - - if (len == skb->len) { - kfree_skb(skb); - } else { - skb_pull(skb, len); - skb_queue_head(&(info->txq), skb); - } - - info->hdev->stat.byte_tx += len; - - } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); - - clear_bit(XMIT_SENDING, &(info->tx_state)); -} - - -static void btuart_receive(struct btuart_info *info) -{ - unsigned int iobase; - int boguscount = 0; - - if (!info) { - BT_ERR("Unknown device"); - return; - } - - iobase = info->p_dev->resource[0]->start; - - do { - info->hdev->stat.byte_rx++; - - /* Allocate packet */ - if (!info->rx_skb) { - info->rx_state = RECV_WAIT_PACKET_TYPE; - info->rx_count = 0; - info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); - if (!info->rx_skb) { - BT_ERR("Can't allocate mem for new packet"); - return; - } - } - - if (info->rx_state == RECV_WAIT_PACKET_TYPE) { - - hci_skb_pkt_type(info->rx_skb) = inb(iobase + UART_RX); - - switch (hci_skb_pkt_type(info->rx_skb)) { - - case HCI_EVENT_PKT: - info->rx_state = RECV_WAIT_EVENT_HEADER; - info->rx_count = HCI_EVENT_HDR_SIZE; - break; - - case HCI_ACLDATA_PKT: - info->rx_state = RECV_WAIT_ACL_HEADER; - info->rx_count = HCI_ACL_HDR_SIZE; - break; - - case HCI_SCODATA_PKT: - info->rx_state = RECV_WAIT_SCO_HEADER; - info->rx_count = HCI_SCO_HDR_SIZE; - break; - - default: - /* Unknown packet */ - BT_ERR("Unknown HCI packet with type 0x%02x received", - hci_skb_pkt_type(info->rx_skb)); - info->hdev->stat.err_rx++; - - kfree_skb(info->rx_skb); - info->rx_skb = NULL; - break; - - } - - } else { - - skb_put_u8(info->rx_skb, inb(iobase + UART_RX)); - info->rx_count--; - - if (info->rx_count == 0) { - - int dlen; - struct hci_event_hdr *eh; - struct hci_acl_hdr *ah; - struct hci_sco_hdr *sh; - - - switch (info->rx_state) { - - case RECV_WAIT_EVENT_HEADER: - eh = hci_event_hdr(info->rx_skb); - info->rx_state = RECV_WAIT_DATA; - info->rx_count = eh->plen; - break; - - case RECV_WAIT_ACL_HEADER: - ah = hci_acl_hdr(info->rx_skb); - dlen = __le16_to_cpu(ah->dlen); - info->rx_state = RECV_WAIT_DATA; - info->rx_count = dlen; - break; - - case RECV_WAIT_SCO_HEADER: - sh = hci_sco_hdr(info->rx_skb); - info->rx_state = RECV_WAIT_DATA; - info->rx_count = sh->dlen; - break; - - case RECV_WAIT_DATA: - hci_recv_frame(info->hdev, info->rx_skb); - info->rx_skb = NULL; - break; - - } - - } - - } - - /* Make sure we don't stay here too long */ - if (boguscount++ > 16) - break; - - } while (inb(iobase + UART_LSR) & UART_LSR_DR); -} - - -static irqreturn_t btuart_interrupt(int irq, void *dev_inst) -{ - struct btuart_info *info = dev_inst; - unsigned int iobase; - int boguscount = 0; - int iir, lsr; - irqreturn_t r = IRQ_NONE; - - if (!info || !info->hdev) - /* our irq handler is shared */ - return IRQ_NONE; - - iobase = info->p_dev->resource[0]->start; - - spin_lock(&(info->lock)); - - iir = inb(iobase + UART_IIR) & UART_IIR_ID; - while (iir) { - r = IRQ_HANDLED; - - /* Clear interrupt */ - lsr = inb(iobase + UART_LSR); - - switch (iir) { - case UART_IIR_RLSI: - BT_ERR("RLSI"); - break; - case UART_IIR_RDI: - /* Receive interrupt */ - btuart_receive(info); - break; - case UART_IIR_THRI: - if (lsr & UART_LSR_THRE) { - /* Transmitter ready for data */ - btuart_write_wakeup(info); - } - break; - default: - BT_ERR("Unhandled IIR=%#x", iir); - break; - } - - /* Make sure we don't stay here too long */ - if (boguscount++ > 100) - break; - - iir = inb(iobase + UART_IIR) & UART_IIR_ID; - - } - - spin_unlock(&(info->lock)); - - return r; -} - - -static void btuart_change_speed(struct btuart_info *info, - unsigned int speed) -{ - unsigned long flags; - unsigned int iobase; - int fcr; /* FIFO control reg */ - int lcr; /* Line control reg */ - int divisor; - - if (!info) { - BT_ERR("Unknown device"); - return; - } - - iobase = info->p_dev->resource[0]->start; - - spin_lock_irqsave(&(info->lock), flags); - - /* Turn off interrupts */ - outb(0, iobase + UART_IER); - - divisor = SPEED_MAX / speed; - - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT; - - /* - * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and - * almost 1,7 ms at 19200 bps. At speeds above that we can just forget - * about this timeout since it will always be fast enough. - */ - - if (speed < 38400) - fcr |= UART_FCR_TRIGGER_1; - else - fcr |= UART_FCR_TRIGGER_14; - - /* Bluetooth cards use 8N1 */ - lcr = UART_LCR_WLEN8; - - outb(UART_LCR_DLAB | lcr, iobase + UART_LCR); /* Set DLAB */ - outb(divisor & 0xff, iobase + UART_DLL); /* Set speed */ - outb(divisor >> 8, iobase + UART_DLM); - outb(lcr, iobase + UART_LCR); /* Set 8N1 */ - outb(fcr, iobase + UART_FCR); /* Enable FIFO's */ - - /* Turn on interrupts */ - outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); - - spin_unlock_irqrestore(&(info->lock), flags); -} - - - -/* ======================== HCI interface ======================== */ - - -static int btuart_hci_flush(struct hci_dev *hdev) -{ - struct btuart_info *info = hci_get_drvdata(hdev); - - /* Drop TX queue */ - skb_queue_purge(&(info->txq)); - - return 0; -} - - -static int btuart_hci_open(struct hci_dev *hdev) -{ - return 0; -} - - -static int btuart_hci_close(struct hci_dev *hdev) -{ - btuart_hci_flush(hdev); - - return 0; -} - - -static int btuart_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) -{ - struct btuart_info *info = hci_get_drvdata(hdev); - - switch (hci_skb_pkt_type(skb)) { - case HCI_COMMAND_PKT: - hdev->stat.cmd_tx++; - break; - case HCI_ACLDATA_PKT: - hdev->stat.acl_tx++; - break; - case HCI_SCODATA_PKT: - hdev->stat.sco_tx++; - break; - } - - /* Prepend skb with frame type */ - memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); - skb_queue_tail(&(info->txq), skb); - - btuart_write_wakeup(info); - - return 0; -} - - - -/* ======================== Card services HCI interaction ======================== */ - - -static int btuart_open(struct btuart_info *info) -{ - unsigned long flags; - unsigned int iobase = info->p_dev->resource[0]->start; - struct hci_dev *hdev; - - spin_lock_init(&(info->lock)); - - skb_queue_head_init(&(info->txq)); - - info->rx_state = RECV_WAIT_PACKET_TYPE; - info->rx_count = 0; - info->rx_skb = NULL; - - /* Initialize HCI device */ - hdev = hci_alloc_dev(); - if (!hdev) { - BT_ERR("Can't allocate HCI device"); - return -ENOMEM; - } - - info->hdev = hdev; - - hdev->bus = HCI_PCCARD; - hci_set_drvdata(hdev, info); - SET_HCIDEV_DEV(hdev, &info->p_dev->dev); - - hdev->open = btuart_hci_open; - hdev->close = btuart_hci_close; - hdev->flush = btuart_hci_flush; - hdev->send = btuart_hci_send_frame; - - spin_lock_irqsave(&(info->lock), flags); - - /* Reset UART */ - outb(0, iobase + UART_MCR); - - /* Turn off interrupts */ - outb(0, iobase + UART_IER); - - /* Initialize UART */ - outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */ - outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR); - - /* Turn on interrupts */ - // outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); - - spin_unlock_irqrestore(&(info->lock), flags); - - btuart_change_speed(info, DEFAULT_BAUD_RATE); - - /* Timeout before it is safe to send the first HCI packet */ - msleep(1000); - - /* Register HCI device */ - if (hci_register_dev(hdev) < 0) { - BT_ERR("Can't register HCI device"); - info->hdev = NULL; - hci_free_dev(hdev); - return -ENODEV; - } - - return 0; -} - - -static int btuart_close(struct btuart_info *info) -{ - unsigned long flags; - unsigned int iobase = info->p_dev->resource[0]->start; - struct hci_dev *hdev = info->hdev; - - if (!hdev) - return -ENODEV; - - btuart_hci_close(hdev); - - spin_lock_irqsave(&(info->lock), flags); - - /* Reset UART */ - outb(0, iobase + UART_MCR); - - /* Turn off interrupts */ - outb(0, iobase + UART_IER); - - spin_unlock_irqrestore(&(info->lock), flags); - - hci_unregister_dev(hdev); - hci_free_dev(hdev); - - return 0; -} - -static int btuart_probe(struct pcmcia_device *link) -{ - struct btuart_info *info; - - /* Create new info device */ - info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->p_dev = link; - link->priv = info; - - link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP | - CONF_AUTO_SET_IO; - - return btuart_config(link); -} - - -static void btuart_detach(struct pcmcia_device *link) -{ - btuart_release(link); -} - -static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data) -{ - int *try = priv_data; - - if (!try) - p_dev->io_lines = 16; - - if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0)) - return -EINVAL; - - p_dev->resource[0]->end = 8; - p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - - return pcmcia_request_io(p_dev); -} - -static int btuart_check_config_notpicky(struct pcmcia_device *p_dev, - void *priv_data) -{ - static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; - int j; - - if (p_dev->io_lines > 3) - return -ENODEV; - - p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - p_dev->resource[0]->end = 8; - - for (j = 0; j < 5; j++) { - p_dev->resource[0]->start = base[j]; - p_dev->io_lines = base[j] ? 16 : 3; - if (!pcmcia_request_io(p_dev)) - return 0; - } - return -ENODEV; -} - -static int btuart_config(struct pcmcia_device *link) -{ - struct btuart_info *info = link->priv; - int i; - int try; - - /* First pass: look for a config entry that looks normal. - * Two tries: without IO aliases, then with aliases - */ - for (try = 0; try < 2; try++) - if (!pcmcia_loop_config(link, btuart_check_config, &try)) - goto found_port; - - /* Second pass: try to find an entry that isn't picky about - * its base address, then try to grab any standard serial port - * address, and finally try to get any free port. - */ - if (!pcmcia_loop_config(link, btuart_check_config_notpicky, NULL)) - goto found_port; - - BT_ERR("No usable port range found"); - goto failed; - -found_port: - i = pcmcia_request_irq(link, btuart_interrupt); - if (i != 0) - goto failed; - - i = pcmcia_enable_device(link); - if (i != 0) - goto failed; - - if (btuart_open(info) != 0) - goto failed; - - return 0; - -failed: - btuart_release(link); - return -ENODEV; -} - - -static void btuart_release(struct pcmcia_device *link) -{ - struct btuart_info *info = link->priv; - - btuart_close(info); - - pcmcia_disable_device(link); -} - -static const struct pcmcia_device_id btuart_ids[] = { - /* don't use this driver. Use serial_cs + hci_uart instead */ - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, btuart_ids); - -static struct pcmcia_driver btuart_driver = { - .owner = THIS_MODULE, - .name = "btuart_cs", - .probe = btuart_probe, - .remove = btuart_detach, - .id_table = btuart_ids, -}; -module_pcmcia_driver(btuart_driver); -- cgit v1.2.3 From 45a42bc9cc65b9ab33411bee454b55bd8a00c977 Mon Sep 17 00:00:00 2001 From: Ian W MORRISON Date: Tue, 27 Mar 2018 09:09:28 +1100 Subject: Bluetooth: hci_bcm: Remove DMI quirk for the MINIX Z83-4 As Interrupt resource specified IRQs are now assumed to be always active-low the DMI quirk for the MINIX Z83-4 is no longer required. Signed-off-by: Ian W MORRISON Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 4ceaf1f4a4e7..441f5e1deb11 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -804,13 +804,6 @@ static const struct dmi_system_id bcm_active_low_irq_dmi_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 8"), }, }, - { - .ident = "MINIX Z83-4", - .matches = { - DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MINIX"), - DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"), - }, - }, { } }; -- cgit v1.2.3 From f9b95db0165ae81c99fe1893e586aab34751ee51 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 28 Mar 2018 13:22:14 +0000 Subject: Bluetooth: btrsi: remove unused including Remove including that don't need it. Signed-off-by: Wei Yongjun Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrsi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c index 5034325e417c..60d1419590ba 100644 --- a/drivers/bluetooth/btrsi.c +++ b/drivers/bluetooth/btrsi.c @@ -13,7 +13,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include #include -- cgit v1.2.3 From 96e58d368fa6c9419fa1fd724a50b7ed900a78d2 Mon Sep 17 00:00:00 2001 From: Vic Wei Date: Wed, 28 Mar 2018 08:28:47 -0700 Subject: Bluetooth: Set HCI_QUIRK_SIMULTANEOUS_DISCOVERY for BTUSB_QCA_ROME QCA Rome controllers can do both LE scan and BR/EDR inquiry at once. Signed-off-by: Vic Wei Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c701443de3e7..c8c8b0b8d333 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3063,6 +3063,7 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_QCA_ROME) { data->setup_on_usb = btusb_setup_qca; hdev->set_bdaddr = btusb_set_bdaddr_ath3012; + set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); } #ifdef CONFIG_BT_HCIBTUSB_RTL -- cgit v1.2.3