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