From ba8f3597900291a93604643017fff66a14546015 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 6 Nov 2017 12:16:56 +0100 Subject: Bluetooth: hci_qca: Avoid setup failure on missing rampatch Assuming that the original code idea was to enable in-band sleeping only if the setup_rome method returns succes and run in 'standard' mode otherwise, we should not return setup_rome return value which makes qca_setup fail if no rampatch/nvm file found. This fixes BT issue on the dragonboard-820C p4 which includes the following QCA controller: hci0: Product:0x00000008 hci0: Patch :0x00000111 hci0: ROM :0x00000302 hci0: SOC :0x00000044 Since there is no rampatch for this controller revision, just make it work as is. Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index bbd7db7384e6..05ec530b8a3a 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -932,6 +932,9 @@ static int qca_setup(struct hci_uart *hu) if (!ret) { set_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); qca_debugfs_init(hdev); + } else if (ret == -ENOENT) { + /* No patch/nvm-config found, run with original fw/config */ + ret = 0; } /* Setup bdaddr */ -- cgit v1.2.3 From eff2d68ca7388ee1c08811c6bbf4d8587cba01da Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 13 Nov 2017 14:44:16 +0100 Subject: Bluetooth: btusb: Add a Kconfig option to enable USB autosuspend by default On many laptops the btusb device is the only USB device not having USB autosuspend enabled, this causes not only the HCI but also the USB controller to stay awake, together using aprox. 0.4W of power. Modern ultrabooks idle around 6W (at 50% screen brightness), 3.5W for Apollo Lake devices. 0.4W is a significant chunk of this (7 / 11%). The btusb driver already contains code to allow enabling USB autosuspend, but currently leaves it up to the user / userspace to enable it. This means that for most people it will not be enabled, leading to an unnecessarily high power consumption. Since enabling it is not entirely without risk of regressions, this commit adds a Kconfig option so that Linux distributions can choose to enable it by default. This commit also adds a module option so that when distros receive bugs they can easily ask the user to disable it again for easy debugging. Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/Kconfig | 10 ++++++++++ drivers/bluetooth/btusb.c | 7 +++++++ 2 files changed, 17 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 60e1c7d6986d..eb4101aee787 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -31,6 +31,16 @@ config BT_HCIBTUSB Say Y here to compile support for Bluetooth USB devices into the kernel or say M to compile it as module (btusb). +config BT_HCIBTUSB_AUTOSUSPEND + bool "Enable USB autosuspend for Bluetooth USB devices by default. + depends on BT_HCIBTUSB + help + Say Y here to enable USB autosuspend for Bluetooth USB devices by + default. + + This can be overridden by passing btusb.enable_autosuspend=[y|n] + on the kernel commandline. + config BT_HCIBTUSB_BCM bool "Broadcom protocol support" depends on BT_HCIBTUSB diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f7120c9eb9bd..808c249845db 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -40,6 +40,7 @@ static bool disable_scofix; static bool force_scofix; +static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND); static bool reset = true; @@ -3213,6 +3214,9 @@ static int btusb_probe(struct usb_interface *intf, } #endif + if (enable_autosuspend) + usb_enable_autosuspend(data->udev); + err = hci_register_dev(hdev); if (err < 0) goto out_free_dev; @@ -3425,6 +3429,9 @@ MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size"); module_param(force_scofix, bool, 0644); MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size"); +module_param(enable_autosuspend, bool, 0644); +MODULE_PARM_DESC(enable_autosuspend, "Enable USB autosuspend by default"); + module_param(reset, bool, 0644); MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); -- cgit v1.2.3 From e7232d184c7da04006bbc1e3de3c6565c4ef15a1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 14 Nov 2017 10:15:23 +0100 Subject: Bluetooth: btusb: Fix BT_HCIBTUSB_AUTOSUSPEND Kconfig option name Fix: drivers/bluetooth/Kconfig:35:warning: multi-line strings not supported warning. Reported-by: Stephen Rothwell Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index eb4101aee787..45a2f59cd935 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -32,7 +32,7 @@ config BT_HCIBTUSB kernel or say M to compile it as module (btusb). config BT_HCIBTUSB_AUTOSUSPEND - bool "Enable USB autosuspend for Bluetooth USB devices by default. + bool "Enable USB autosuspend for Bluetooth USB devices by default" depends on BT_HCIBTUSB help Say Y here to enable USB autosuspend for Bluetooth USB devices by -- cgit v1.2.3 From d73e172816652772114827abaa2dbc053eecbbd7 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Fri, 17 Nov 2017 00:54:53 +0100 Subject: Bluetooth: hci_serdev: Init hci_uart proto_lock to avoid oops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit John Stultz reports a boot time crash with the HiKey board (which uses hci_serdev) occurring in hci_uart_tx_wakeup(). That function is contained in hci_ldisc.c, but also called from the newer hci_serdev.c. It acquires the proto_lock in struct hci_uart and it turns out that we forgot to init the lock in the serdev code path, thus causing the crash. John bisected the crash to commit 67d2f8781b9f ("Bluetooth: hci_ldisc: Allow sleeping while proto locks are held"), but the issue was present before and the commit merely exposed it. (Perhaps by luck, the crash did not occur with rwlocks.) Init the proto_lock in the serdev code path to avoid the oops. Stack trace for posterity: Unable to handle kernel read from unreadable memory at 406f127000 [000000406f127000] user address but active_mm is swapper Internal error: Oops: 96000005 [#1] PREEMPT SMP Hardware name: HiKey Development Board (DT) Call trace: hci_uart_tx_wakeup+0x38/0x148 hci_uart_send_frame+0x28/0x38 hci_send_frame+0x64/0xc0 hci_cmd_work+0x98/0x110 process_one_work+0x134/0x330 worker_thread+0x130/0x468 kthread+0xf8/0x128 ret_from_fork+0x10/0x18 Link: https://lkml.org/lkml/2017/11/15/908 Reported-and-tested-by: John Stultz Cc: Ronald Tschalär Cc: Rob Herring Cc: Sumit Semwal Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_serdev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 71664b22ec9d..e0e6461b9200 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -303,6 +303,7 @@ int hci_uart_register_device(struct hci_uart *hu, hci_set_drvdata(hdev, hu); INIT_WORK(&hu->write_work, hci_uart_write_work); + percpu_init_rwsem(&hu->proto_lock); /* Only when vendor specific setup callback is provided, consider * the manufacturer information valid. This avoids filling in the -- cgit v1.2.3 From 67b8fbead4685b36d290a0ef91c6ddffc4920ec9 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Wed, 22 Nov 2017 15:03:17 +0100 Subject: Bluetooth: btqcomsmd: Fix skb double free corruption In case of hci send frame failure, skb is still owned by the caller (hci_core) and then should not be freed. This fixes crash on dragonboard-410c when sending SCO packet. skb is freed by both btqcomsmd and hci_core. Fixes: 1511cc750c3d ("Bluetooth: Introduce Qualcomm WCNSS SMD based HCI driver") Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqcomsmd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c index 663bed63b871..2c9a5fc9137d 100644 --- a/drivers/bluetooth/btqcomsmd.c +++ b/drivers/bluetooth/btqcomsmd.c @@ -88,7 +88,8 @@ static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb) break; } - kfree_skb(skb); + if (!ret) + kfree_skb(skb); return ret; } -- cgit v1.2.3 From c23fae11111f4d682dfc5b4dfcdbafc4a096a4b6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Nov 2017 14:37:28 +0100 Subject: Bluetooth: hci_bcm: Add support for BCM2E72 The Asus T100HA laptop uses an ACPI HID of BCM2E72 for the bluetooth part of the SDIO bcm43340 wifi/bt combo chip. Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 707c2d1b84c7..47fc58c9eb49 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -939,6 +939,7 @@ static const struct acpi_device_id bcm_acpi_match[] = { { "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 }, { "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 }, -- cgit v1.2.3 From b4cdaba274247c9c841c6a682c08fa91fb3aa549 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 29 Nov 2017 20:29:07 +0100 Subject: Bluetooth: btsdio: Do not bind to non-removable BCM43341 BCM43341 devices soldered onto the PCB (non-removable) always (AFAICT) use an UART connection for bluetooth. But they also advertise btsdio support on their 3th sdio function, this causes 2 problems: 1) A non functioning BT HCI getting registered 2) Since the btsdio driver does not have suspend/resume callbacks, mmc_sdio_pre_suspend will return -ENOSYS, causing mmc_pm_notify() to react as if the SDIO-card is removed and since the slot is marked as non-removable it will never get detected as inserted again. Which results in wifi no longer working after a suspend/resume. This commit fixes both by making btsdio ignore BCM43341 devices when connected to a slot which is marked non-removable. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btsdio.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index c8e945d19ffe..20142bc77554 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -292,6 +293,14 @@ static int btsdio_probe(struct sdio_func *func, tuple = tuple->next; } + /* BCM43341 devices soldered onto the PCB (non-removable) use an + * uart connection for bluetooth, ignore the BT SDIO interface. + */ + if (func->vendor == SDIO_VENDOR_ID_BROADCOM && + func->device == SDIO_DEVICE_ID_BROADCOM_43341 && + !mmc_card_is_removable(func->card->host)) + return -ENODEV; + data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; -- cgit v1.2.3 From 059fb8230732d101950ae1d435238d78545cf46b Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Dec 2017 21:01:58 -0600 Subject: Bluetooth: hci_ll: remove \n from kernel messages The bt_* printk macros include a \n already, so we don't need extra ones here. Signed-off-by: David Lechner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index e2c078d61730..ce0dd2f164c7 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -628,11 +628,11 @@ static int download_firmware(struct ll_device *lldev) break; } if (cmd->prefix != 1) - bt_dev_dbg(lldev->hu.hdev, "command type %d\n", cmd->prefix); + bt_dev_dbg(lldev->hu.hdev, "command type %d", cmd->prefix); skb = __hci_cmd_sync(lldev->hu.hdev, cmd->opcode, cmd->plen, &cmd->speed, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { - bt_dev_err(lldev->hu.hdev, "send command failed\n"); + bt_dev_err(lldev->hu.hdev, "send command failed"); err = PTR_ERR(skb); goto out_rel_fw; } -- cgit v1.2.3 From d54fdcf9244ceca3e2768878b7512f12725437d1 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Dec 2017 20:43:55 -0600 Subject: Bluetooth: serdev: hci_ll: Wait for CTS instead of using msleep When a TI Bluetooth chip is reset, it takes about 100ms for the RTS line of the chip to deassert. For my use case with a TI CC2560A chip, this delay was not long enough and caused the local UART to never transmit at all (TI AM1808 SoC UART2). We can wait for the CTS signal using serdev_device_wait_for_cts() instead of trying to guess using msleep(). Also changed the comment to be more informative while we are touching this code. Signed-off-by: David Lechner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ll.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index ce0dd2f164c7..447abea2fa04 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -674,11 +674,15 @@ static int ll_setup(struct hci_uart *hu) serdev_device_set_flow_control(serdev, true); do { - /* Configure BT_EN to HIGH state */ + /* Reset the Bluetooth device */ gpiod_set_value_cansleep(lldev->enable_gpio, 0); msleep(5); gpiod_set_value_cansleep(lldev->enable_gpio, 1); - msleep(100); + err = serdev_device_wait_for_cts(serdev, true, 200); + if (err) { + bt_dev_err(hu->hdev, "Failed to get CTS"); + return err; + } err = download_firmware(lldev); if (!err) -- cgit v1.2.3 From 7c6ca1201e5e87513b27196138f06df9cbd09a7a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 3 Dec 2017 21:21:21 -0600 Subject: Bluetooth: hci_ll: add constant for vendor-specific command This adds a #define for the vendor-specific HCI command to set the baudrate instead of using the bare 0xff36 multiple times. Signed-off-by: David Lechner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ll.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 447abea2fa04..974a78879d20 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -56,6 +56,9 @@ #include "hci_uart.h" +/* Vendor-specific HCI commands */ +#define HCI_VS_UPDATE_UART_HCI_BAUDRATE 0xff36 + /* HCILL commands */ #define HCILL_GO_TO_SLEEP_IND 0x30 #define HCILL_GO_TO_SLEEP_ACK 0x31 @@ -620,7 +623,7 @@ static int download_firmware(struct ll_device *lldev) case ACTION_SEND_COMMAND: /* action send */ bt_dev_dbg(lldev->hu.hdev, "S"); cmd = (struct hci_command *)action_ptr; - if (cmd->opcode == 0xff36) { + if (cmd->opcode == HCI_VS_UPDATE_UART_HCI_BAUDRATE) { /* ignore remote change * baud rate HCI VS command */ @@ -704,7 +707,10 @@ static int ll_setup(struct hci_uart *hu) speed = 0; if (speed) { - struct sk_buff *skb = __hci_cmd_sync(hu->hdev, 0xff36, sizeof(speed), &speed, HCI_INIT_TIMEOUT); + struct sk_buff *skb; + + skb = __hci_cmd_sync(hu->hdev, HCI_VS_UPDATE_UART_HCI_BAUDRATE, + sizeof(speed), &speed, HCI_INIT_TIMEOUT); if (!IS_ERR(skb)) { kfree_skb(skb); serdev_device_set_baudrate(serdev, speed); -- cgit v1.2.3 From c30b93eade2ad1d77695669f25ddeb3833588d3b Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 7 Dec 2017 20:22:19 -0600 Subject: Bluetooth: hci_ll: Add endianness conversion when setting baudrate This adds an endianness conversion when setting the baudrate using a vendor-specific command. Otherwise, bad things might happen on a big- endian system. Suggested-by: Marcel Holtmann Signed-off-by: David Lechner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ll.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 974a78879d20..efcfbe9aac21 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -707,10 +707,12 @@ static int ll_setup(struct hci_uart *hu) speed = 0; if (speed) { + __le32 speed_le = cpu_to_le32(speed); struct sk_buff *skb; skb = __hci_cmd_sync(hu->hdev, HCI_VS_UPDATE_UART_HCI_BAUDRATE, - sizeof(speed), &speed, HCI_INIT_TIMEOUT); + sizeof(speed_le), &speed_le, + HCI_INIT_TIMEOUT); if (!IS_ERR(skb)) { kfree_skb(skb); serdev_device_set_baudrate(serdev, speed); -- cgit v1.2.3 From aa0993986932fe0ac7694b22c26c84e67abec53d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 12 Dec 2017 15:59:16 -0600 Subject: Bluetooth: hci_ll: add support for setting public address This adds support for setting the public address on Texas Instruments Bluetooth chips using a vendor-specific command. This has been tested on a CC2560A chip. The TI wiki also indicates that this command should work on TI WL17xx/WL18xx Bluetooth chips. During review, there was some question as to the correctness of the byte swapping since TI's documentation is not clear on this matter. This can be tested with the btmgmt utility from bluez. The adapter must be powered off to change the address. If the baswap() is omitted, address is reversed. In case there is a issue in the future, here is the output of btmon during the command `btmgmt public-addr 00:11:22:33:44:55`: Bluetooth monitor ver 5.43 = Note: Linux version 4.15.0-rc2-08561-gcb132a1-dirty (armv5tejl) 0.707043 = Note: Bluetooth subsystem version 2.22 0.707091 = New Index: 00:17:E7:BD:1C:8E (Primary,UART,hci0) [hci0] 0.707106 @ MGMT Open: btmgmt (privileged) version 1.14 {0x0002} 0.707124 @ MGMT Open: bluetoothd (privileged) version 1.14 {0x0001} 0.707137 @ MGMT Open: btmon (privileged) version 1.14 {0x0003} 0.707540 @ MGMT Command: Set Public Address (0x0039) plen 6 {0x0002} [hci0] 11.167991 Address: 00:11:22:33:44:55 (CIMSYS Inc) @ MGMT Event: Command Complete (0x0001) plen 7 {0x0002} [hci0] 11.175681 Set Public Address (0x0039) plen 4 Status: Success (0x00) Missing options: 0x00000000 @ MGMT Event: Index Removed (0x0005) plen 0 {0x0003} [hci0] 11.175757 @ MGMT Event: Index Removed (0x0005) plen 0 {0x0002} [hci0] 11.175757 @ MGMT Event: Index Removed (0x0005) plen 0 {0x0001} [hci0] 11.175757 = Open Index: 00:17:E7:BD:1C:8E [hci0] 11.176807 < HCI Command: Vendor (0x3f|0x0006) plen 6 [hci0] 11.176975 00 11 22 33 44 55 .."3DU > HCI Event: Command Complete (0x0e) plen 4 [hci0] 11.188260 Vendor (0x3f|0x0006) ncmd 1 Status: Success (0x00) ... < HCI Command: Read Local Version Info.. (0x04|0x0001) plen 0 [hci0] 11.189859 > HCI Event: Command Complete (0x0e) plen 12 [hci0] 11.190732 Read Local Version Information (0x04|0x0001) ncmd 1 Status: Success (0x00) HCI version: Bluetooth 2.1 (0x04) - Revision 0 (0x0000) LMP version: Bluetooth 2.1 (0x04) - Subversion 6431 (0x191f) Manufacturer: Texas Instruments Inc. (13) < HCI Command: Read BD ADDR (0x04|0x0009) plen 0 [hci0] 11.191027 > HCI Event: Command Complete (0x0e) plen 10 [hci0] 11.192101 Read BD ADDR (0x04|0x0009) ncmd 1 Status: Success (0x00) Address: 00:11:22:33:44:55 (CIMSYS Inc) ... Signed-off-by: David Lechner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ll.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index efcfbe9aac21..c948e8dcc553 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -57,6 +57,7 @@ #include "hci_uart.h" /* Vendor-specific HCI commands */ +#define HCI_VS_WRITE_BD_ADDR 0xfc06 #define HCI_VS_UPDATE_UART_HCI_BAUDRATE 0xff36 /* HCILL commands */ @@ -662,6 +663,24 @@ out_rel_fw: return err; } +static int ll_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) +{ + bdaddr_t bdaddr_swapped; + struct sk_buff *skb; + + /* HCI_VS_WRITE_BD_ADDR (at least on a CC2560A chip) expects the BD + * address to be MSB first, but bdaddr_t has the convention of being + * LSB first. + */ + baswap(&bdaddr_swapped, bdaddr); + skb = __hci_cmd_sync(hdev, HCI_VS_WRITE_BD_ADDR, sizeof(bdaddr_t), + &bdaddr_swapped, HCI_INIT_TIMEOUT); + if (!IS_ERR(skb)) + kfree_skb(skb); + + return PTR_ERR_OR_ZERO(skb); +} + static int ll_setup(struct hci_uart *hu) { int err, retry = 3; @@ -674,6 +693,8 @@ static int ll_setup(struct hci_uart *hu) lldev = serdev_device_get_drvdata(serdev); + hu->hdev->set_bdaddr = ll_set_bdaddr; + serdev_device_set_flow_control(serdev, true); do { -- cgit v1.2.3 From 0e58d0cdb3eb6e06416bcc1af3605993c6a07656 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 12 Dec 2017 17:54:12 -0600 Subject: Bluetooth: hci_ll: Add optional nvmem BD address source This adds an optional nvmem consumer to get a BD address from an external source. The BD address is then set in the Bluetooth chip after the firmware has been loaded. This has been tested working with a TI CC2560A chip (in a LEGO MINDSTORMS EV3). Signed-off-by: David Lechner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ll.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index c948e8dcc553..9de106f6b8e1 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "hci_uart.h" @@ -90,6 +91,7 @@ struct ll_device { struct serdev_device *serdev; struct gpio_desc *enable_gpio; struct clk *ext_clk; + bdaddr_t bdaddr; }; struct ll_struct { @@ -719,6 +721,18 @@ static int ll_setup(struct hci_uart *hu) if (err) return err; + /* Set BD address if one was specified at probe */ + if (!bacmp(&lldev->bdaddr, BDADDR_NONE)) { + /* This means that there was an error getting the BD address + * during probe, so mark the device as having a bad address. + */ + set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks); + } else if (bacmp(&lldev->bdaddr, BDADDR_ANY)) { + err = ll_set_bdaddr(hu->hdev, &lldev->bdaddr); + if (err) + set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks); + } + /* Operational speed if any */ if (hu->oper_speed) speed = hu->oper_speed; @@ -749,6 +763,7 @@ static int hci_ti_probe(struct serdev_device *serdev) { struct hci_uart *hu; struct ll_device *lldev; + struct nvmem_cell *bdaddr_cell; u32 max_speed = 3000000; lldev = devm_kzalloc(&serdev->dev, sizeof(struct ll_device), GFP_KERNEL); @@ -770,6 +785,52 @@ static int hci_ti_probe(struct serdev_device *serdev) of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed); hci_uart_set_speeds(hu, 115200, max_speed); + /* optional BD address from nvram */ + bdaddr_cell = nvmem_cell_get(&serdev->dev, "bd-address"); + if (IS_ERR(bdaddr_cell)) { + int err = PTR_ERR(bdaddr_cell); + + if (err == -EPROBE_DEFER) + return err; + + /* ENOENT means there is no matching nvmem cell and ENOSYS + * means that nvmem is not enabled in the kernel configuration. + */ + if (err != -ENOENT && err != -ENOSYS) { + /* If there was some other error, give userspace a + * chance to fix the problem instead of failing to load + * the driver. Using BDADDR_NONE as a flag that is + * tested later in the setup function. + */ + dev_warn(&serdev->dev, + "Failed to get \"bd-address\" nvmem cell (%d)\n", + err); + bacpy(&lldev->bdaddr, BDADDR_NONE); + } + } else { + bdaddr_t *bdaddr; + size_t len; + + bdaddr = nvmem_cell_read(bdaddr_cell, &len); + nvmem_cell_put(bdaddr_cell); + if (IS_ERR(bdaddr)) { + dev_err(&serdev->dev, "Failed to read nvmem bd-address\n"); + return PTR_ERR(bdaddr); + } + if (len != sizeof(bdaddr_t)) { + dev_err(&serdev->dev, "Invalid nvmem bd-address length\n"); + kfree(bdaddr); + return -EINVAL; + } + + /* As per the device tree bindings, the value from nvmem is + * expected to be MSB first, but in the kernel it is expected + * that bdaddr_t is LSB first. + */ + baswap(&lldev->bdaddr, bdaddr); + kfree(bdaddr); + } + return hci_uart_register_device(hu, &llp); } -- cgit v1.2.3 From 4166493c97c0c70e8d7678422c2214dc5ec6e9d3 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 12 Dec 2017 18:29:31 -0600 Subject: Bluetooth: hci_ll: add "ti,cc2560" compatible string This adds the "ti,cc2560" compatible string for a TI CC2560 chip. Signed-off-by: David Lechner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ll.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 9de106f6b8e1..1b4417a623a4 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -842,6 +842,7 @@ static void hci_ti_remove(struct serdev_device *serdev) } static const struct of_device_id hci_ti_of_match[] = { + { .compatible = "ti,cc2560" }, { .compatible = "ti,wl1271-st" }, { .compatible = "ti,wl1273-st" }, { .compatible = "ti,wl1281-st" }, -- cgit v1.2.3 From 479f335c1b24b98fd1daae024d2f5d7cc355f1fc Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Wed, 13 Dec 2017 17:28:04 +0800 Subject: Bluetooth: Fix a possible sleep-in-atomic bug in bluecard_write_wakeup The driver may sleep in the interrupt handler. The function call path is: bluecard_interrupt (interrupt handler) bluecard_write_wakeup schedule_timeout --> may sleep To fix it, schedule_timeout is replaced with mdelay. This bug is found by my static analysis tool(DSAC) and checked by my code review. Signed-off-by: Jia-Ju Bai Signed-off-by: Marcel Holtmann --- drivers/bluetooth/bluecard_cs.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index d513ef4743dc..82437a69f99c 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -302,9 +302,7 @@ static void bluecard_write_wakeup(struct bluecard_info *info) } /* Wait until the command reaches the baseband */ - prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); - finish_wait(&wq, &wait); + mdelay(100); /* Set baud on baseband */ info->ctrl_reg &= ~0x03; @@ -316,9 +314,7 @@ static void bluecard_write_wakeup(struct bluecard_info *info) outb(info->ctrl_reg, iobase + REG_CONTROL); /* Wait before the next HCI packet can be send */ - prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - finish_wait(&wq, &wait); + mdelay(1000); } if (len == skb->len) { -- cgit v1.2.3 From 0a03f98b98c201191e3ba15a0e33f46d8660e1fd Mon Sep 17 00:00:00 2001 From: Ioan Moldovan Date: Mon, 28 Aug 2017 18:09:39 +0300 Subject: Bluetooth: Add a new 04ca:3015 QCA_ROME device This patch adds the 04ca:3015 (from a QCA9377 board) Bluetooth device to the btusb blacklist and makes the kernel use the btqca module instead of btusb. The patch is necessary because, without it the 04ca:3015 device defaults to using the btusb driver, which makes the WIFI side of the QCA9377 board unusable (obtains 0 MBps in speedtest, when the 04ca:3015 bluetooth is used with an audio headset). /sys/kernel/debug/usb/devices: T: Bus=01 Lev=01 Prnt=01 Port=04 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 2.01 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=04ca ProdID=3015 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= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) 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=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) 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=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) 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=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) 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=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=03(O) 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=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=03(O) 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=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms Signed-off-by: Ioan Moldovan Signed-off-by: Johan Hedberg --- 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 808c249845db..d1512fbf820d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -271,6 +271,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0489, 0xe09f), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME }, + { USB_DEVICE(0x04ca, 0x3015), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME }, /* Broadcom BCM2035 */ -- cgit v1.2.3 From 27378f4c1b92fe275236c69d2f7f2c27090e7b53 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Tue, 26 Dec 2017 17:07:34 +0200 Subject: Bluetooth: Avoid WARN splat due to missing GPIOLIB Loading hci_bcm with CONFIG_GPIOLIB=n results in the following splat when calling gpiod_to_irq() from bcm_get_resources(): WARNING: CPU: 0 PID: 1006 at ./include/linux/gpio/consumer.h:450 bcm_get_resources+0x50/0x80 CPU: 0 PID: 1006 Comm: kworker/u8:4 Tainted: G A 4.15.0-rc4custom+ #4 Hardware name: Apple Inc. MacBook8,1/Mac-BE0E8AC46FE800CC, BIOS MB81.88Z.0168.B00.1708080033 08/08/2017 Call Trace: bcm_serdev_probe+0x8b/0xc0 driver_probe_device+0x202/0x310 __driver_attach+0x85/0x90 ? driver_probe_device+0x310/0x310 bus_for_each_dev+0x57/0x80 async_run_entry_fn+0x2c/0xd0 process_one_work+0x1d2/0x3d0 worker_thread+0x26/0x3c0 ? process_one_work+0x3d0/0x3d0 kthread+0x10c/0x130 ? kthread_create_on_node+0x40/0x40 ret_from_fork+0x1f/0x30 We could call gpiod_to_irq() only if IS_ENABLED(CONFIG_GPIOLIB) but without GPIOLIB, the driver's power saving features can't be used, so selecting GPIOLIB seems more appropriate. The same issue is present in hci_intel.c and hci_nokia.c, fix those up as well. Reported-by: Max Shavrick Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/Kconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 45a2f59cd935..41932f0e68d0 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -110,6 +110,7 @@ config BT_HCIUART_NOKIA depends on PM select BT_HCIUART_H4 select BT_BCM + select GPIOLIB help Nokia H4+ is serial protocol for communication between Bluetooth device and host. This protocol is required for Bluetooth devices @@ -170,6 +171,7 @@ config BT_HCIUART_INTEL depends on BT_HCIUART select BT_HCIUART_H4 select BT_INTEL + select GPIOLIB help The Intel protocol support enables Bluetooth HCI over serial port interface for Intel Bluetooth controllers. @@ -183,6 +185,7 @@ config BT_HCIUART_BCM depends on (!ACPI || SERIAL_DEV_CTRL_TTYPORT) select BT_HCIUART_H4 select BT_BCM + select GPIOLIB help The Broadcom protocol support enables Bluetooth HCI over serial port interface for Broadcom Bluetooth controllers. -- cgit v1.2.3 From 43fff768346810042836df325d736bd2c2a634a7 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Tue, 26 Dec 2017 17:07:34 +0200 Subject: Bluetooth: hci_bcm: Streamline runtime PM code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver seeks to force the Bluetooth device on for the duration of 5 seconds when the Bluetooth device has woken the host and after a complete packet has been received. It does that by calling: pm_runtime_get(); pm_runtime_mark_last_busy(); pm_runtime_put_autosuspend(); The same can be achieved more succinctly with: pm_request_resume(); That's because after runtime resuming the device, rpm_resume() invokes pm_runtime_mark_last_busy() followed by rpm_idle(), which will cause the device to be suspended after expiration of the autosuspend_delay. No functional change intended. Cc: Frédéric Danis Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 47fc58c9eb49..1fc604a0d870 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -191,9 +191,7 @@ static irqreturn_t bcm_host_wake(int irq, void *data) bt_dev_dbg(bdev, "Host wake IRQ"); - pm_runtime_get(bdev->dev); - pm_runtime_mark_last_busy(bdev->dev); - pm_runtime_put_autosuspend(bdev->dev); + pm_request_resume(bdev->dev); return IRQ_HANDLED; } @@ -512,11 +510,8 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count) } else if (!bcm->rx_skb) { /* Delay auto-suspend when receiving completed packet */ mutex_lock(&bcm_device_lock); - if (bcm->dev && bcm_device_exists(bcm->dev)) { - pm_runtime_get(bcm->dev->dev); - pm_runtime_mark_last_busy(bcm->dev->dev); - pm_runtime_put_autosuspend(bcm->dev->dev); - } + if (bcm->dev && bcm_device_exists(bcm->dev)) + pm_request_resume(bcm->dev->dev); mutex_unlock(&bcm_device_lock); } -- cgit v1.2.3 From 7d06d5895c159f64c46560dc258e553ad8670fe0 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 20 Dec 2017 19:00:07 +0800 Subject: Revert "Bluetooth: btusb: fix QCA Rome suspend/resume" This reverts commit fd865802c66bc451dc515ed89360f84376ce1a56. This commit causes a regression on some QCA ROME chips. The USB device reset happens in btusb_open(), hence firmware loading gets interrupted. Furthermore, this commit stops working after commit ("a0085f2510e8976614ad8f766b209448b385492f Bluetooth: btusb: driver to enable the usb-wakeup feature"). Reset-resume quirk only gets enabled in btusb_suspend() when it's not a wakeup source. If we really want to reset the USB device, we need to do it before btusb_open(). Let's handle it in drivers/usb/core/quirks.c. Cc: stable@vger.kernel.org Cc: Leif Liddy Cc: Matthias Kaehlcke Cc: Brian Norris Cc: Daniel Drake Signed-off-by: Kai-Heng Feng Reviewed-by: Brian Norris Tested-by: Brian Norris Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d1512fbf820d..d6fcb4d31548 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3119,12 +3119,6 @@ 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; - - /* QCA Rome devices lose their updated firmware over suspend, - * but the USB hub doesn't notice any status change. - * Explicitly request a device reset on resume. - */ - set_bit(BTUSB_RESET_RESUME, &data->flags); } #ifdef CONFIG_BT_HCIBTUSB_RTL -- cgit v1.2.3 From e5a49ee98191eedf208ea169455667deb80fe646 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Tue, 2 Jan 2018 10:41:11 +0800 Subject: Bluetooth: btusb: Add support for 0cf3:e010 Device 0cf3:e010 is one of the QCA ROME family. T: Bus=01 Lev=01 Prnt=01 Port=13 Cnt=03 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 2.01 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0cf3 ProdID=e010 Rev=00.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 I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb Signed-off-by: AceLan Kao 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 d6fcb4d31548..dcd2f9861d8e 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -264,6 +264,7 @@ static const struct usb_device_id blacklist_table[] = { /* QCA ROME chipset */ { USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME }, + { USB_DEVICE(0x0cf3, 0xe010), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME }, -- cgit v1.2.3 From b71b25fed1c3fa7fdeba4bbda2d17fb384a80508 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 2 Jan 2018 11:50:30 +0100 Subject: Bluetooth: hciuart: add nvmem dependency When the hci support is built-in, but mvmem is a loadable module, we get a link failure: drivers/bluetooth/hci_ll.o: In function `hci_ti_probe': hci_ll.c:(.text+0x226): undefined reference to `nvmem_cell_get' hci_ll.c:(.text+0x238): undefined reference to `nvmem_cell_read' hci_ll.c:(.text+0x244): undefined reference to `nvmem_cell_put' This adds another Kconfig dependency to enforce valid configurations. Fixes: 0e58d0cdb3eb ("Bluetooth: hci_ll: Add optional nvmem BD address source") Signed-off-by: Arnd Bergmann Signed-off-by: Marcel Holtmann --- drivers/bluetooth/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 41932f0e68d0..d816ce9e23a7 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -77,6 +77,7 @@ config BT_HCIBTSDIO config BT_HCIUART tristate "HCI UART driver" depends on SERIAL_DEV_BUS || !SERIAL_DEV_BUS + depends on NVMEM || !NVMEM depends on TTY help Bluetooth HCI UART driver. -- cgit v1.2.3 From a3a446c7c0e643f740990a7bc2950e75856beb3c Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Tue, 2 Jan 2018 20:08:40 +0100 Subject: Bluetooth: Depend on rather than select GPIOLIB Commit 27378f4c1b92 ("Bluetooth: Avoid WARN splat due to missing GPIOLIB") amended Kconfig to select GPIOLIB if BT_HCIUART_NOKIA, BT_HCIUART_INTEL or BT_HCIUART_BCM is enabled since all three drivers require it to function. The diagnosis was correct but the treatment was not. As stated in Documentation/gpio/consumer.txt: Guidelines for GPIOs consumers ============================== Drivers that can't work without standard GPIO calls should have Kconfig entries that depend on GPIOLIB. ^^^^^^^^^ Fix it. Reported-by: Andy Shevchenko Signed-off-by: Lukas Wunner Reviewed-by: Linus Walleij Signed-off-by: Marcel Holtmann --- drivers/bluetooth/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index d816ce9e23a7..07e55cd8f8c8 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -108,10 +108,10 @@ config BT_HCIUART_NOKIA tristate "UART Nokia H4+ protocol support" depends on BT_HCIUART depends on BT_HCIUART_SERDEV + depends on GPIOLIB depends on PM select BT_HCIUART_H4 select BT_BCM - select GPIOLIB help Nokia H4+ is serial protocol for communication between Bluetooth device and host. This protocol is required for Bluetooth devices @@ -170,9 +170,9 @@ config BT_HCIUART_3WIRE config BT_HCIUART_INTEL bool "Intel protocol support" depends on BT_HCIUART + depends on GPIOLIB select BT_HCIUART_H4 select BT_INTEL - select GPIOLIB help The Intel protocol support enables Bluetooth HCI over serial port interface for Intel Bluetooth controllers. @@ -184,9 +184,9 @@ config BT_HCIUART_BCM depends on BT_HCIUART depends on BT_HCIUART_SERDEV depends on (!ACPI || SERIAL_DEV_CTRL_TTYPORT) + depends on GPIOLIB select BT_HCIUART_H4 select BT_BCM - select GPIOLIB help The Broadcom protocol support enables Bluetooth HCI over serial port interface for Broadcom Bluetooth controllers. -- cgit v1.2.3 From cca32837f0f5fb794d0d486bc76ed0bfb703de7b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 6 Jan 2018 16:15:14 +0000 Subject: Bluetooth: bpa10x: make array 'req' static, shrinks object size Don't populate the const read-only array 'req' on the stack but instead make it static. Makes the object code smaller by over 40 bytes: Before: text data bss dec hex filename 8497 3408 128 12033 2f01 linux/drivers/bluetooth/bpa10x.o After: text data bss dec hex filename 8366 3496 128 11990 2ed6 linux/drivers/bluetooth/bpa10x.o (gcc version 7.2.0 x86_64) Signed-off-by: Colin Ian King Signed-off-by: Marcel Holtmann --- drivers/bluetooth/bpa10x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 7971bfbd4321..801ea4ca65e4 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -259,7 +259,7 @@ static int bpa10x_flush(struct hci_dev *hdev) static int bpa10x_setup(struct hci_dev *hdev) { - const u8 req[] = { 0x07 }; + static const u8 req[] = { 0x07 }; struct sk_buff *skb; BT_DBG("%s", hdev->name); -- cgit v1.2.3 From 948c7ca03c14d9dd5ece5866dc1ab49f95613ad6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 6 Jan 2018 16:23:28 +0000 Subject: Bluetooth: btintel: make array 'param' static, shrinks object size Don't populate the const read-only array 'param' on the stack but instead make it static. Makes the object code smaller by nearly 20 bytes: Before: text data bss dec hex filename 11605 2629 64 14298 37da linux/drivers/bluetooth/btintel.o After: text data bss dec hex filename 11531 2685 64 14280 37c8 linux/drivers/bluetooth/btintel.o (gcc version 7.2.0 x86_64) Signed-off-by: Colin Ian King Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btintel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 4459555c9d88..07f00e422e85 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -75,7 +75,7 @@ EXPORT_SYMBOL_GPL(btintel_check_bdaddr); int btintel_enter_mfg(struct hci_dev *hdev) { - const u8 param[] = { 0x01, 0x00 }; + static const u8 param[] = { 0x01, 0x00 }; struct sk_buff *skb; skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT); -- cgit v1.2.3 From 61f5acea8737d9b717fcc22bb6679924f3c82b98 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 8 Jan 2018 10:44:16 +0100 Subject: Bluetooth: btusb: Restore QCA Rome suspend/resume fix with a "rewritten" version Commit 7d06d5895c15 ("Revert "Bluetooth: btusb: fix QCA...suspend/resume"") removed the setting of the BTUSB_RESET_RESUME quirk for QCA Rome devices, instead favoring adding USB_QUIRK_RESET_RESUME quirks in usb/core/quirks.c. This was done because the DIY BTUSB_RESET_RESUME reset-resume handling has several issues (see the original commit message). An added advantage of moving over to the USB-core reset-resume handling is that it also disables autosuspend for these devices, which is similarly broken on these. But there are 2 issues with this approach: 1) It leaves the broken DIY BTUSB_RESET_RESUME code in place for Realtek devices. 2) Sofar only 2 of the 10 QCA devices known to the btusb code have been added to usb/core/quirks.c and if we fix the Realtek case the same way we need to add an additional 14 entries. So in essence we need to duplicate a large part of the usb_device_id table in btusb.c in usb/core/quirks.c and manually keep them in sync. This commit instead restores setting a reset-resume quirk for QCA devices in the btusb.c code, avoiding the duplicate usb_device_id table problem. This commit avoids the problems with the original DIY BTUSB_RESET_RESUME code by simply setting the USB_QUIRK_RESET_RESUME quirk directly on the usb_device. This commit also moves the BTUSB_REALTEK case over to directly setting the USB_QUIRK_RESET_RESUME on the usb_device and removes the now unused BTUSB_RESET_RESUME code. BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1514836 Fixes: 7d06d5895c15 ("Revert "Bluetooth: btusb: fix QCA...suspend/resume"") Cc: stable@vger.kernel.org Cc: Leif Liddy Cc: Matthias Kaehlcke Cc: Brian Norris Cc: Daniel Drake Cc: Kai-Heng Feng Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index dcd2f9861d8e..29977ebfd031 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -390,9 +391,8 @@ static const struct usb_device_id blacklist_table[] = { #define BTUSB_FIRMWARE_LOADED 7 #define BTUSB_FIRMWARE_FAILED 8 #define BTUSB_BOOTING 9 -#define BTUSB_RESET_RESUME 10 -#define BTUSB_DIAG_RUNNING 11 -#define BTUSB_OOB_WAKE_ENABLED 12 +#define BTUSB_DIAG_RUNNING 10 +#define BTUSB_OOB_WAKE_ENABLED 11 struct btusb_data { struct hci_dev *hdev; @@ -3120,6 +3120,12 @@ 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; + + /* QCA Rome devices lose their updated firmware over suspend, + * but the USB hub doesn't notice any status change. + * explicitly request a device reset on resume. + */ + interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; } #ifdef CONFIG_BT_HCIBTUSB_RTL @@ -3130,7 +3136,7 @@ static int btusb_probe(struct usb_interface *intf, * but the USB hub doesn't notice any status change. * Explicitly request a device reset on resume. */ - set_bit(BTUSB_RESET_RESUME, &data->flags); + interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; } #endif @@ -3299,14 +3305,6 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) enable_irq(data->oob_wake_irq); } - /* Optionally request a device reset on resume, but only when - * wakeups are disabled. If wakeups are enabled we assume the - * device will stay powered up throughout suspend. - */ - if (test_bit(BTUSB_RESET_RESUME, &data->flags) && - !device_may_wakeup(&data->udev->dev)) - data->udev->reset_resume = 1; - return 0; } -- cgit v1.2.3 From 3e81a4ca51a1172253078ca7abd6a91040b8fcf4 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Mandate presence of shutdown and device wake GPIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 0395ffc1ee05 ("Bluetooth: hci_bcm: Add PM for BCM devices") amended this driver to request a shutdown and device wake GPIO on probe, but mandated that only one of them need to be present: /* Make sure at-least one of the GPIO is defined and that * a name is specified for this instance */ if ((!dev->device_wakeup && !dev->shutdown) || !dev->name) { dev_err(&pdev->dev, "invalid platform data\n"); return -EINVAL; } However the same commit added a call to bcm_gpio_set_power() to the ->probe hook, which unconditionally accesses *both* GPIOs. Luckily, the resulting NULL pointer deref was never reported, suggesting there's no machine where either GPIO is missing. Commit 8a92056837fd ("Bluetooth: hci_bcm: Add (runtime)pm support to the serdev driver") removed the check whether at least one of the GPIOs is present without specifying a reason. Because commit 62aaefa7d038 ("Bluetooth: hci_bcm: improve use of gpios API") refactored the driver to use devm_gpiod_get_optional() instead of devm_gpiod_get(), one is now tempted to believe that the driver doesn't require *any* of the two GPIOs. Which is wrong, the driver still requires both GPIOs to avoid a NULL pointer deref. To this end, establish the status quo ante and request the GPIOs with devm_gpiod_get() again. Bail out of ->probe if either of them is missing. Oddly enough, whereas bcm_gpio_set_power() accesses the device wake pin unconditionally, bcm_suspend_device() and bcm_resume_device() do check for its presence before accessing it. Those checks are superfluous, so remove them. Cc: Frédéric Danis Cc: Loic Poulain Cc: Hans de Goede Cc: Uwe Kleine-König Cc: Linus Walleij Reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 1fc604a0d870..7d059b35c63a 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -572,11 +572,9 @@ static int bcm_suspend_device(struct device *dev) } /* Suspend the device */ - if (bdev->device_wakeup) { - gpiod_set_value(bdev->device_wakeup, false); - bt_dev_dbg(bdev, "suspend, delaying 15 ms"); - mdelay(15); - } + gpiod_set_value(bdev->device_wakeup, false); + bt_dev_dbg(bdev, "suspend, delaying 15 ms"); + mdelay(15); return 0; } @@ -587,11 +585,9 @@ static int bcm_resume_device(struct device *dev) bt_dev_dbg(bdev, ""); - if (bdev->device_wakeup) { - gpiod_set_value(bdev->device_wakeup, true); - bt_dev_dbg(bdev, "resume, delaying 15 ms"); - mdelay(15); - } + gpiod_set_value(bdev->device_wakeup, true); + bt_dev_dbg(bdev, "resume, delaying 15 ms"); + mdelay(15); /* When this executes, the device has woken up already */ if (bdev->is_suspended && bdev->hu) { @@ -774,14 +770,12 @@ static int bcm_get_resources(struct bcm_device *dev) dev->clk = devm_clk_get(dev->dev, NULL); - dev->device_wakeup = devm_gpiod_get_optional(dev->dev, - "device-wakeup", - GPIOD_OUT_LOW); + dev->device_wakeup = devm_gpiod_get(dev->dev, "device-wakeup", + GPIOD_OUT_LOW); if (IS_ERR(dev->device_wakeup)) return PTR_ERR(dev->device_wakeup); - dev->shutdown = devm_gpiod_get_optional(dev->dev, "shutdown", - GPIOD_OUT_LOW); + dev->shutdown = devm_gpiod_get(dev->dev, "shutdown", GPIOD_OUT_LOW); if (IS_ERR(dev->shutdown)) return PTR_ERR(dev->shutdown); -- cgit v1.2.3 From 4a59f1fab91e9445e34c69d8e4401a0d6bdbe914 Mon Sep 17 00:00:00 2001 From: Ronald Tschalär Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Validate IRQ before using it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ->close, ->suspend and ->resume hooks assume presence of a valid IRQ if the device is wakeup capable. However it's entirely possible that wakeup was enabled by some other entity besides this driver and in this case the user will get a WARN splat if no valid IRQ was found. Avoid by checking if the IRQ is valid, i.e. > 0. Case in point: On recent MacBook Pros, the Bluetooth device lacks an IRQ (because host wakeup is handled by the SMC, independently of the operating system), but it does possess a _PRW method (which specifies the SMC's GPE as wake event). The ACPI core therefore automatically marks the physical Bluetooth device wakeup capable upon binding it to its ACPI companion: device_set_wakeup_capable+0x96/0xb0 acpi_bind_one+0x28a/0x310 acpi_platform_notify+0x20/0xa0 device_add+0x215/0x690 serdev_device_add+0x57/0xf0 acpi_serdev_add_device+0xc9/0x110 acpi_ns_walk_namespace+0x131/0x280 acpi_walk_namespace+0xf5/0x13d serdev_controller_add+0x6f/0x110 serdev_tty_port_register+0x98/0xf0 tty_port_register_device_attr_serdev+0x3a/0x70 uart_add_one_port+0x268/0x500 serial8250_register_8250_port+0x32e/0x490 dw8250_probe+0x46c/0x720 platform_drv_probe+0x35/0x90 driver_probe_device+0x300/0x450 bus_for_each_drv+0x67/0xb0 __device_attach+0xde/0x160 bus_probe_device+0x9c/0xb0 device_add+0x448/0x690 platform_device_add+0x10e/0x260 mfd_add_device+0x392/0x4c0 mfd_add_devices+0xb1/0x110 intel_lpss_probe+0x2a9/0x610 [intel_lpss] intel_lpss_pci_probe+0x7a/0xa8 [intel_lpss_pci] Reviewed-by: Andy Shevchenko Signed-off-by: Ronald Tschalär [lukas: fix up ->suspend and ->resume as well, add commit message] Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 7d059b35c63a..d9f71ed26667 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -377,7 +377,7 @@ static int bcm_close(struct hci_uart *hu) pm_runtime_disable(bdev->dev); pm_runtime_set_suspended(bdev->dev); - if (device_can_wakeup(bdev->dev)) { + if (bdev->irq > 0) { devm_free_irq(bdev->dev, bdev->irq, bdev); device_init_wakeup(bdev->dev, false); } @@ -623,7 +623,7 @@ static int bcm_suspend(struct device *dev) if (pm_runtime_active(dev)) bcm_suspend_device(dev); - if (device_may_wakeup(dev)) { + if (device_may_wakeup(dev) && bdev->irq > 0) { error = enable_irq_wake(bdev->irq); if (!error) bt_dev_dbg(bdev, "BCM irq: enabled"); @@ -653,7 +653,7 @@ static int bcm_resume(struct device *dev) if (!bdev->hu) goto unlock; - if (device_may_wakeup(dev)) { + if (device_may_wakeup(dev) && bdev->irq > 0) { disable_irq_wake(bdev->irq); bt_dev_dbg(bdev, "BCM irq: disabled"); } -- cgit v1.2.3 From 6d83f1ee88a47d81f29d3aa4d17ad68d73473d40 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Clean up unnecessary #ifdef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pm_runtime_disable() and pm_runtime_set_suspended() are replaced with empty inlines if CONFIG_PM is disabled, so there's no need to #ifdef them. device_init_wakeup() is likewise replaced with an inline, though it's not empty, but it and devm_free_irq() can be made conditional on IS_ENABLED(CONFIG_PM), which is preferable to #ifdef as per section 20 of Documentation/process/coding-style.rst. Cc: Frédéric Danis Reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index d9f71ed26667..c551ef4c350f 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -373,15 +373,13 @@ static int bcm_close(struct hci_uart *hu) if (bdev) { bcm_gpio_set_power(bdev, false); -#ifdef CONFIG_PM pm_runtime_disable(bdev->dev); pm_runtime_set_suspended(bdev->dev); - if (bdev->irq > 0) { + if (IS_ENABLED(CONFIG_PM) && bdev->irq > 0) { devm_free_irq(bdev->dev, bdev->irq, bdev); device_init_wakeup(bdev->dev, false); } -#endif } mutex_unlock(&bcm_device_lock); -- cgit v1.2.3 From 54ba69f9e7304e15e07713b4bb0eb1a405d271f0 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Fix race on close MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upon ->close, the driver powers the Bluetooth controller down, deasserts the device wake pin, updates the runtime PM status to "suspended" and finally frees the IRQ. Because the IRQ is freed last, a runtime resume can take place after the controller was powered down. The impact is not grave, the worst thing that can happen is that the device wake pin is reasserted (should have no effect while the regulator is off) and that setting the runtime PM status to "suspended" does not reflect reality. Still, it's wrong, so free the IRQ first. Cc: Frédéric Danis Reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index c551ef4c350f..6144a3f9c37a 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -372,14 +372,14 @@ static int bcm_close(struct hci_uart *hu) } if (bdev) { - bcm_gpio_set_power(bdev, false); - pm_runtime_disable(bdev->dev); - pm_runtime_set_suspended(bdev->dev); - if (IS_ENABLED(CONFIG_PM) && bdev->irq > 0) { devm_free_irq(bdev->dev, bdev->irq, bdev); device_init_wakeup(bdev->dev, false); } + + bcm_gpio_set_power(bdev, false); + pm_runtime_disable(bdev->dev); + pm_runtime_set_suspended(bdev->dev); } mutex_unlock(&bcm_device_lock); -- cgit v1.2.3 From f4cf6b7e3b8704d3dabfb8427a61d4c03ce48d80 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Fix unbalanced pm_runtime_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On ->setup, pm_runtime_enable() is only called if a valid IRQ was found, but on ->close(), pm_runtime_disable() is called unconditionally. Disablement of runtime PM is recorded in a counter, so every pm_runtime_disable() needs to be balanced. Fix it. Cc: Frédéric Danis Reported-and-reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 6144a3f9c37a..140c7e5bf812 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -375,10 +375,10 @@ static int bcm_close(struct hci_uart *hu) if (IS_ENABLED(CONFIG_PM) && bdev->irq > 0) { devm_free_irq(bdev->dev, bdev->irq, bdev); device_init_wakeup(bdev->dev, false); + pm_runtime_disable(bdev->dev); } bcm_gpio_set_power(bdev, false); - pm_runtime_disable(bdev->dev); pm_runtime_set_suspended(bdev->dev); } mutex_unlock(&bcm_device_lock); -- cgit v1.2.3 From 4dc273306c16b04f696e8ab0e8bb4f6e238fe61b Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Invalidate IRQ on request failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If devm_request_irq() fails, the driver bails out of bcm_request_irq() but continues to ->setup the device (because the IRQ is optional). The driver subsequently calls devm_free_irq(), enable_irq_wake() and disable_irq_wake() on the IRQ even though requesting it failed. Avoid by invalidating the IRQ on request failure. Cc: Frédéric Danis Reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 140c7e5bf812..c893c597fead 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -216,8 +216,10 @@ static int bcm_request_irq(struct bcm_data *bcm) bdev->irq_active_low ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING, "host_wake", bdev); - if (err) + if (err) { + bdev->irq = err; goto unlock; + } device_init_wakeup(bdev->dev, true); -- cgit v1.2.3 From b7c2abac14e1fdf6136a8b54c6151ffe300b961b Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Document struct bcm_device Reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index c893c597fead..3c1282a9fcd4 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -52,7 +52,30 @@ #define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */ -/* device driver resources */ +/** + * struct bcm_device - device driver resources + * @serdev_hu: HCI UART controller struct + * @list: bcm_device_list node + * @dev: physical UART slave + * @name: device name logged by bt_dev_*() functions + * @device_wakeup: BT_WAKE pin, + * assert = Bluetooth device must wake up or remain awake, + * deassert = Bluetooth device may sleep when sleep criteria are met + * @shutdown: BT_REG_ON pin, + * power up or power down Bluetooth device internal regulators + * @clk: clock used by Bluetooth device + * @clk_enabled: whether @clk is prepared and enabled + * @init_speed: default baudrate of Bluetooth device; + * the host UART is initially set to this baudrate so that + * it can configure the Bluetooth device for @oper_speed + * @oper_speed: preferred baudrate of Bluetooth device; + * set to 0 if @init_speed is already the preferred baudrate + * @irq: interrupt triggered by HOST_WAKE_BT pin + * @irq_active_low: whether @irq is active low + * @hu: pointer to HCI UART controller struct, + * used to disable flow control during runtime suspend and system sleep + * @is_suspended: whether flow control is currently disabled + */ struct bcm_device { /* Must be the first member, hci_serdev.c expects this. */ struct hci_uart serdev_hu; @@ -74,7 +97,7 @@ struct bcm_device { #ifdef CONFIG_PM struct hci_uart *hu; - bool is_suspended; /* suspend/resume flag */ + bool is_suspended; #endif }; -- cgit v1.2.3 From 8353b4a636f2c83de748656acc6b6a8757d7a0ff Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Add callbacks to toggle GPIOs MacBooks provides custom ACPI methods to toggle the GPIOs for device wake and shutdown instead of accessing the pins directly. Prepare for their support by adding callbacks to toggle the GPIOs, which on non-Macs do nothing more but call gpiod_set_value(). No functional change intended. Suggested-and-reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 3c1282a9fcd4..8741e302e6fd 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -63,6 +63,8 @@ * deassert = Bluetooth device may sleep when sleep criteria are met * @shutdown: BT_REG_ON pin, * power up or power down Bluetooth device internal regulators + * @set_device_wakeup: callback to toggle BT_WAKE pin + * @set_shutdown: callback to toggle BT_REG_ON pin * @clk: clock used by Bluetooth device * @clk_enabled: whether @clk is prepared and enabled * @init_speed: default baudrate of Bluetooth device; @@ -86,6 +88,8 @@ struct bcm_device { const char *name; struct gpio_desc *device_wakeup; struct gpio_desc *shutdown; + int (*set_device_wakeup)(struct bcm_device *, bool); + int (*set_shutdown)(struct bcm_device *, bool); struct clk *clk; bool clk_enabled; @@ -196,8 +200,8 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered) if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled) clk_prepare_enable(dev->clk); - gpiod_set_value(dev->shutdown, powered); - gpiod_set_value(dev->device_wakeup, powered); + dev->set_shutdown(dev, powered); + dev->set_device_wakeup(dev, powered); if (!powered && !IS_ERR(dev->clk) && dev->clk_enabled) clk_disable_unprepare(dev->clk); @@ -595,7 +599,7 @@ static int bcm_suspend_device(struct device *dev) } /* Suspend the device */ - gpiod_set_value(bdev->device_wakeup, false); + bdev->set_device_wakeup(bdev, false); bt_dev_dbg(bdev, "suspend, delaying 15 ms"); mdelay(15); @@ -608,7 +612,7 @@ static int bcm_resume_device(struct device *dev) bt_dev_dbg(bdev, ""); - gpiod_set_value(bdev->device_wakeup, true); + bdev->set_device_wakeup(bdev, true); bt_dev_dbg(bdev, "resume, delaying 15 ms"); mdelay(15); @@ -787,6 +791,18 @@ static int bcm_resource(struct acpi_resource *ares, void *data) } #endif /* CONFIG_ACPI */ +static int bcm_gpio_set_device_wakeup(struct bcm_device *dev, bool awake) +{ + gpiod_set_value(dev->device_wakeup, awake); + return 0; +} + +static int bcm_gpio_set_shutdown(struct bcm_device *dev, bool powered) +{ + gpiod_set_value(dev->shutdown, powered); + return 0; +} + static int bcm_get_resources(struct bcm_device *dev) { dev->name = dev_name(dev->dev); @@ -802,6 +818,9 @@ static int bcm_get_resources(struct bcm_device *dev) if (IS_ERR(dev->shutdown)) return PTR_ERR(dev->shutdown); + dev->set_device_wakeup = bcm_gpio_set_device_wakeup; + dev->set_shutdown = bcm_gpio_set_shutdown; + /* IRQ can be declared in ACPI table as Interrupt or GpioInt */ if (dev->irq <= 0) { struct gpio_desc *gpio; -- cgit v1.2.3 From 8bfa7e1e03aca3626b82857850a1e18ae0ed291d Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Handle errors properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A significant portion of this driver lacks error handling. As a first step, add error paths to bcm_gpio_set_power(), bcm_open(), bcm_close(), bcm_suspend_device(), bcm_resume_device(), bcm_resume(), bcm_probe() and bcm_serdev_probe(). (I've also scrutinized bcm_suspend() but think it's fine as is.) Those are all the functions accessing the device wake and shutdown GPIO. On Apple Macs the pins are accessed through ACPI methods, which may fail for various reasons, hence proper error handling is necessary. Non-Macs access the pins directly, which may fail as well but the GPIO core does not yet pass back errors to consumers. Cc: Frédéric Danis Cc: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 91 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 16 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 8741e302e6fd..03a365148184 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -197,11 +197,21 @@ static bool bcm_device_exists(struct bcm_device *device) static int bcm_gpio_set_power(struct bcm_device *dev, bool powered) { - if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled) - clk_prepare_enable(dev->clk); + int err; - dev->set_shutdown(dev, powered); - dev->set_device_wakeup(dev, powered); + if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled) { + err = clk_prepare_enable(dev->clk); + if (err) + return err; + } + + err = dev->set_shutdown(dev, powered); + if (err) + goto err_clk_disable; + + err = dev->set_device_wakeup(dev, powered); + if (err) + goto err_revert_shutdown; if (!powered && !IS_ERR(dev->clk) && dev->clk_enabled) clk_disable_unprepare(dev->clk); @@ -209,6 +219,13 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered) dev->clk_enabled = powered; return 0; + +err_revert_shutdown: + dev->set_shutdown(dev, !powered); +err_clk_disable: + if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled) + clk_disable_unprepare(dev->clk); + return err; } #ifdef CONFIG_PM @@ -331,6 +348,7 @@ static int bcm_open(struct hci_uart *hu) { struct bcm_data *bcm; struct list_head *p; + int err; bt_dev_dbg(hu->hdev, "hu %p", hu); @@ -345,7 +363,10 @@ static int bcm_open(struct hci_uart *hu) mutex_lock(&bcm_device_lock); if (hu->serdev) { - serdev_device_open(hu->serdev); + err = serdev_device_open(hu->serdev); + if (err) + goto err_free; + bcm->dev = serdev_device_get_drvdata(hu->serdev); goto out; } @@ -373,17 +394,30 @@ out: if (bcm->dev) { hu->init_speed = bcm->dev->init_speed; hu->oper_speed = bcm->dev->oper_speed; - bcm_gpio_set_power(bcm->dev, true); + err = bcm_gpio_set_power(bcm->dev, true); + if (err) + goto err_unset_hu; } mutex_unlock(&bcm_device_lock); return 0; + +err_unset_hu: +#ifdef CONFIG_PM + bcm->dev->hu = NULL; +#endif +err_free: + mutex_unlock(&bcm_device_lock); + hu->priv = NULL; + kfree(bcm); + return err; } static int bcm_close(struct hci_uart *hu) { struct bcm_data *bcm = hu->priv; struct bcm_device *bdev = NULL; + int err; bt_dev_dbg(hu->hdev, "hu %p", hu); @@ -407,8 +441,11 @@ static int bcm_close(struct hci_uart *hu) pm_runtime_disable(bdev->dev); } - bcm_gpio_set_power(bdev, false); - pm_runtime_set_suspended(bdev->dev); + err = bcm_gpio_set_power(bdev, false); + if (err) + bt_dev_err(hu->hdev, "Failed to power down"); + else + pm_runtime_set_suspended(bdev->dev); } mutex_unlock(&bcm_device_lock); @@ -588,6 +625,7 @@ static struct sk_buff *bcm_dequeue(struct hci_uart *hu) static int bcm_suspend_device(struct device *dev) { struct bcm_device *bdev = dev_get_drvdata(dev); + int err; bt_dev_dbg(bdev, ""); @@ -599,7 +637,15 @@ static int bcm_suspend_device(struct device *dev) } /* Suspend the device */ - bdev->set_device_wakeup(bdev, false); + err = bdev->set_device_wakeup(bdev, false); + if (err) { + if (bdev->is_suspended && bdev->hu) { + bdev->is_suspended = false; + hci_uart_set_flow_control(bdev->hu, false); + } + return -EBUSY; + } + bt_dev_dbg(bdev, "suspend, delaying 15 ms"); mdelay(15); @@ -609,10 +655,16 @@ static int bcm_suspend_device(struct device *dev) static int bcm_resume_device(struct device *dev) { struct bcm_device *bdev = dev_get_drvdata(dev); + int err; bt_dev_dbg(bdev, ""); - bdev->set_device_wakeup(bdev, true); + err = bdev->set_device_wakeup(bdev, true); + if (err) { + dev_err(dev, "Failed to power up\n"); + return err; + } + bt_dev_dbg(bdev, "resume, delaying 15 ms"); mdelay(15); @@ -666,6 +718,7 @@ unlock: static int bcm_resume(struct device *dev) { struct bcm_device *bdev = dev_get_drvdata(dev); + int err = 0; bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended); @@ -685,14 +738,16 @@ static int bcm_resume(struct device *dev) bt_dev_dbg(bdev, "BCM irq: disabled"); } - bcm_resume_device(dev); + err = bcm_resume_device(dev); unlock: mutex_unlock(&bcm_device_lock); - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); + if (!err) { + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + } return 0; } @@ -923,7 +978,9 @@ static int bcm_probe(struct platform_device *pdev) list_add_tail(&dev->list, &bcm_device_list); mutex_unlock(&bcm_device_lock); - bcm_gpio_set_power(dev, false); + ret = bcm_gpio_set_power(dev, false); + if (ret) + dev_err(&pdev->dev, "Failed to power down\n"); return 0; } @@ -1025,7 +1082,9 @@ static int bcm_serdev_probe(struct serdev_device *serdev) if (err) return err; - bcm_gpio_set_power(bcmdev, false); + err = bcm_gpio_set_power(bcmdev, false); + if (err) + dev_err(&serdev->dev, "Failed to power down\n"); return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto); } -- cgit v1.2.3 From 4c33162c1ad0d3524455d6c10de2a05847ad5617 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Support Apple GPIO handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable Bluetooth on the following Macs which provide custom ACPI methods to toggle the GPIOs for device wake and shutdown instead of accessing the pins directly: MacBook8,1 2015 12" MacBook9,1 2016 12" MacBook10,1 2017 12" MacBookPro13,1 2016 13" MacBookPro13,2 2016 13" with Touch Bar MacBookPro13,3 2016 15" with Touch Bar MacBookPro14,1 2017 13" MacBookPro14,2 2017 13" with Touch Bar MacBookPro14,3 2017 15" with Touch Bar On the MacBook8,1 Bluetooth is muxed with a second device (a debug port on the SSD) under the control of PCH GPIO 36. Because serdev cannot deal with multiple slaves yet, it is currently necessary to patch the DSDT and remove the SSDC device. The custom ACPI methods are called: BTLP (Low Power) takes one argument, toggles device wake GPIO BTPU (Power Up) tells SMC to drive shutdown GPIO high BTPD (Power Down) tells SMC to drive shutdown GPIO low BTRS (Reset) calls BTPD followed by BTPU BTRB unknown, not present on all MacBooks Search for the BTLP, BTPU and BTPD methods on ->probe and cache them in struct bcm_device if the machine is a Mac. Additionally, set the init_speed based on a custom device property provided by Apple in lieu of _CRS resources. The Broadcom UART's speed is fixed on Apple Macs: Any attempt to change it results in Bluetooth status code 0x0c and bcm_set_baudrate() thus always returns -EBUSY. By setting only the init_speed and leaving oper_speed at zero, we can achieve that the host UART's speed is adjusted but the Broadcom UART's speed is left as is. The host wake pin goes into the SMC which handles it independently of the OS, so there's no IRQ for it. Thanks to Ronald Tschalär who did extensive debugging and testing of this patch and contributed fixes. ACPI snippet containing the custom methods and device properties (taken from a MacBook8,1): Method (BTLP, 1, Serialized) { If (LEqual (Arg0, 0x00)) { Store (0x01, GD54) /* set PCH GPIO 54 direction to input */ } If (LEqual (Arg0, 0x01)) { Store (0x00, GD54) /* set PCH GPIO 54 direction to output */ Store (0x00, GP54) /* set PCH GPIO 54 value to low */ } } Method (BTPU, 0, Serialized) { Store (0x01, \_SB.PCI0.LPCB.EC.BTPC) Sleep (0x0A) } Method (BTPD, 0, Serialized) { Store (0x00, \_SB.PCI0.LPCB.EC.BTPC) Sleep (0x0A) } Method (BTRS, 0, Serialized) { BTPD () BTPU () } Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method { If (LEqual (Arg0, ToUUID ("a0b5b7c6-1318-441c-b0c9-fe695eaf949b"))) { Store (Package (0x08) { "baud", Buffer (0x08) { 0xC0, 0xC6, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00 }, "parity", Buffer (0x08) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, "dataBits", Buffer (0x08) { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, "stopBits", Buffer (0x08) { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, Local0) DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0)) Return (Local0) } Return (0x00) } Link: https://github.com/Dunedan/mbp-2016-linux/issues/29 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=110901 Reported-by: Leif Liddy Cc: Mika Westerberg Cc: Frédéric Danis Cc: Loic Poulain Cc: Hans de Goede Tested-by: Max Shavrick [MacBook8,1] Tested-by: Leif Liddy [MacBook9,1] Tested-by: Daniel Roschka [MacBookPro13,2] Tested-by: Ronald Tschalär [MacBookPro13,3] Tested-by: Peter Y. Chuang [MacBookPro14,1] Reviewed-by: Andy Shevchenko Signed-off-by: Ronald Tschalär Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 03a365148184..3e818a429fc5 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -64,7 +65,12 @@ * @shutdown: BT_REG_ON pin, * power up or power down Bluetooth device internal regulators * @set_device_wakeup: callback to toggle BT_WAKE pin + * either by accessing @device_wakeup or by calling @btlp * @set_shutdown: callback to toggle BT_REG_ON pin + * either by accessing @shutdown or by calling @btpu/@btpd + * @btlp: Apple ACPI method to toggle BT_WAKE pin ("Bluetooth Low Power") + * @btpu: Apple ACPI method to drive BT_REG_ON pin high ("Bluetooth Power Up") + * @btpd: Apple ACPI method to drive BT_REG_ON pin low ("Bluetooth Power Down") * @clk: clock used by Bluetooth device * @clk_enabled: whether @clk is prepared and enabled * @init_speed: default baudrate of Bluetooth device; @@ -90,6 +96,9 @@ struct bcm_device { struct gpio_desc *shutdown; int (*set_device_wakeup)(struct bcm_device *, bool); int (*set_shutdown)(struct bcm_device *, bool); +#ifdef CONFIG_ACPI + acpi_handle btlp, btpu, btpd; +#endif struct clk *clk; bool clk_enabled; @@ -844,6 +853,49 @@ static int bcm_resource(struct acpi_resource *ares, void *data) return 0; } + +static int bcm_apple_set_device_wakeup(struct bcm_device *dev, bool awake) +{ + if (ACPI_FAILURE(acpi_execute_simple_method(dev->btlp, NULL, !awake))) + return -EIO; + + return 0; +} + +static int bcm_apple_set_shutdown(struct bcm_device *dev, bool powered) +{ + if (ACPI_FAILURE(acpi_evaluate_object(powered ? dev->btpu : dev->btpd, + NULL, NULL, NULL))) + return -EIO; + + return 0; +} + +static int bcm_apple_get_resources(struct bcm_device *dev) +{ + struct acpi_device *adev = ACPI_COMPANION(dev->dev); + const union acpi_object *obj; + + if (!adev || + ACPI_FAILURE(acpi_get_handle(adev->handle, "BTLP", &dev->btlp)) || + ACPI_FAILURE(acpi_get_handle(adev->handle, "BTPU", &dev->btpu)) || + ACPI_FAILURE(acpi_get_handle(adev->handle, "BTPD", &dev->btpd))) + return -ENODEV; + + if (!acpi_dev_get_property(adev, "baud", ACPI_TYPE_BUFFER, &obj) && + obj->buffer.length == 8) + dev->init_speed = *(u64 *)obj->buffer.pointer; + + dev->set_device_wakeup = bcm_apple_set_device_wakeup; + dev->set_shutdown = bcm_apple_set_shutdown; + + return 0; +} +#else +static inline int bcm_apple_get_resources(struct bcm_device *dev) +{ + return -EOPNOTSUPP; +} #endif /* CONFIG_ACPI */ static int bcm_gpio_set_device_wakeup(struct bcm_device *dev, bool awake) @@ -862,6 +914,9 @@ static int bcm_get_resources(struct bcm_device *dev) { dev->name = dev_name(dev->dev); + if (x86_apple_machine && !bcm_apple_get_resources(dev)) + return 0; + dev->clk = devm_clk_get(dev->dev, NULL); dev->device_wakeup = devm_gpiod_get(dev->dev, "device-wakeup", -- cgit v1.2.3 From 5954cdf1793a0e1296e495884669c79f9ef2b2b3 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Silence IRQ printk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The host wake IRQ is optional, but if none is found, "BCM irq: -22" is logged which may irritate users. This is really a debug message, so use dev_dbg() instead of dev_info(). If users are interested in the IRQ, they can always consult /proc/interrupts. Cc: Frédéric Danis Reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 3e818a429fc5..0929a264bffa 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -943,7 +943,7 @@ static int bcm_get_resources(struct bcm_device *dev) dev->irq = gpiod_to_irq(gpio); } - dev_info(dev->dev, "BCM irq: %d\n", dev->irq); + dev_dbg(dev->dev, "BCM irq: %d\n", dev->irq); return 0; } -- cgit v1.2.3 From e4b9e5b8618dc59f5de5cecf4e0188a3cdcd5648 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: hci_bcm: Sleep instead of spinning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver calls mdelay(15) in the ->suspend, ->resume, ->runtime_suspend and ->runtime_resume hook, however spinning for such a long period of time is discouraged as per Documentation/timers/timers-howto.txt. The use of mdelay() seems unnecessary, it is allowed to sleep in the system sleep and runtime PM hooks (with the exception of ->suspend_noirq and ->resume_noirq) and the driver itself also does not rely on a non-sleeping ->runtime_resume as the only place where a synchronous resume is performed, in bcm_dequeue(), is called from a work item in hci_ldisc.c and hci_serdev.c. So replace the mdelay(15) with msleep(15). Note that the delay is inserted after asserting or deasserting the device wake pin, but in bcm_gpio_set_power() that pin is asserted or deasserted *without* observing a delay. It is thus unclear if the delay is necessary at all. It is likewise unclear why it is exactly 15 ms, the commit introducing it, 118612fb9165 ("Bluetooth: hci_bcm: Add suspend/resume PM functions"), does not provide a rationale. Cc: Frédéric Danis Suggested-and-reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner 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 0929a264bffa..461364a00b20 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -656,7 +656,7 @@ static int bcm_suspend_device(struct device *dev) } bt_dev_dbg(bdev, "suspend, delaying 15 ms"); - mdelay(15); + msleep(15); return 0; } @@ -675,7 +675,7 @@ static int bcm_resume_device(struct device *dev) } bt_dev_dbg(bdev, "resume, delaying 15 ms"); - mdelay(15); + msleep(15); /* When this executes, the device has woken up already */ if (bdev->is_suspended && bdev->hu) { -- cgit v1.2.3 From ff8759609d021c0e85945fcc4a148a0e55ace70f Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 10 Jan 2018 16:32:10 +0100 Subject: Bluetooth: btbcm: Fix sleep mode struct ordering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the documentation for Laird SD40 radio modules (which use the BCM4329 chipset), the order of the Enable_BREAK_To_Host and Pulsed_HOST_WAKE parameters in the sleep mode struct is reversed vis-à-vis our struct declaration. See page 46 of this PDF: http://cdn.lairdtech.com/home/brandworld/files/Application%20Note%20-%2040%20Series%20Bluetooth.pdf The documentation is dated Oct 2015, so fairly recent, making it appear more likely that the documentation is correct and our code is wrong. Amend our code to be in congruence with the documentation. Cc: Sue White Reviewed-by: Andy Shevchenko Signed-off-by: Lukas Wunner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.h | 2 +- drivers/bluetooth/hci_bcm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.h b/drivers/bluetooth/btbcm.h index d9e6b41658e5..cfe6ad4cc621 100644 --- a/drivers/bluetooth/btbcm.h +++ b/drivers/bluetooth/btbcm.h @@ -44,8 +44,8 @@ struct bcm_set_sleep_mode { __u8 tristate_control; __u8 usb_auto_sleep; __u8 usb_resume_timeout; - __u8 pulsed_host_wake; __u8 break_to_host; + __u8 pulsed_host_wake; } __packed; struct bcm_set_pcm_int_params { diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 461364a00b20..64800cd2796c 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -300,8 +300,8 @@ static const struct bcm_set_sleep_mode default_sleep_params = { /* Irrelevant USB flags */ .usb_auto_sleep = 0, .usb_resume_timeout = 0, + .break_to_host = 0, .pulsed_host_wake = 0, - .break_to_host = 0 }; static int bcm_setup_sleep(struct hci_uart *hu) -- cgit v1.2.3 From d456f678a074b5d7cf14c4043f9294edadc2aef8 Mon Sep 17 00:00:00 2001 From: Jörg Krause Date: Thu, 18 Jan 2018 10:21:55 +0100 Subject: Bluetooth: btbcm: Add entry for BCM4343A0 UART bluetooth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the device ID for the bluetooth chip used in the AMPAK AP6212 WiFi+Bluetooth module. The AP6212 is used on several BananaPi boards, e.g. M2-Ultra. The AP6212 is a combo module, where the WiFi chip is identified as BCM43430A0 whereas the Bluetooth chip identifies itself as 4343A0. Note, the missing '0' before the 'A0'. The AP6212 needs a firmware blob. Loading the provided firmware file from the BananaPi vendor, the adapter name is printed as 'BCM4343A0 26MHz AP6212_CL1-0061': ''' hci0: Type: Primary Bus: UART BD Address: 43:43:A0:12:1F:AC ACL MTU: 1021:8 SCO MTU: 64:1 UP RUNNING RX bytes:3076 acl:0 sco:0 events:278 errors:0 TX bytes:39726 acl:0 sco:0 commands:279 errors:0 Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 Link policy: RSWITCH SNIFF Link mode: SLAVE ACCEPT Name: 'BCM4343A0 26MHz AP6212_CL1-0061' Class: 0x000000 Service Classes: Unspecified Device Class: Miscellaneous, HCI Version: 4.1 (0x7) Revision: 0xf2 LMP Version: 4.1 (0x7) Subversion: 0x2122 Manufacturer: Broadcom Corporation (15) ''' Signed-off-by: Jörg Krause Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index afa4cb3b16e3..6659f113042c 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -323,6 +323,7 @@ static const struct { { 0x410e, "BCM43341B0" }, /* 002.001.014 */ { 0x4406, "BCM4324B3" }, /* 002.004.006 */ { 0x610c, "BCM4354" }, /* 003.001.012 */ + { 0x2122, "BCM4343A0" }, /* 001.001.034 */ { 0x2209, "BCM43430A1" }, /* 001.002.009 */ { 0x6119, "BCM4345C0" }, /* 003.001.025 */ { 0x230f, "BCM4356A2" }, /* 001.003.015 */ -- cgit v1.2.3 From 8c6b8eda7294775097e0d0eb64cb6f86d460d7c2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 22 Jan 2018 12:53:24 +0100 Subject: Bluetooth: hci_bcm: For serdev case close serdev on failure to set power Commit 8bfa7e1e03ac ("Bluetooth: hci_bcm: Handle errors properly") introduced error checking for the bcm_gpio_set_power() call in bcm_open() but the error-path it introduces unsets dev->hu, which is correct for platform_device instantiated bcm_dev-s but not for serdev instantiated devs. For serdev instantiated devs serdev_device_close() should be called instead (and dev->hu should be left set). Cc: Lukas Wunner Fixes: 8bfa7e1e03ac ("Bluetooth: hci_bcm: Handle errors properly") Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 64800cd2796c..0438a64b8185 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -412,8 +412,11 @@ out: return 0; err_unset_hu: + if (hu->serdev) + serdev_device_close(hu->serdev); #ifdef CONFIG_PM - bcm->dev->hu = NULL; + else + bcm->dev->hu = NULL; #endif err_free: mutex_unlock(&bcm_device_lock); -- cgit v1.2.3 From 965651c16b9e6212f781d5b619ab78bd82bf54ce Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Wed, 24 Jan 2018 09:19:17 -0800 Subject: Bluetooth: hci_intel: Update firmware filename for Intel 9x60 and later The format of Intel Bluetooth firmware for bootloader product is ibt--.sfi and .ddc. But for the 9x60 SKU, there are three variants of FW, which cannot be differenticate just with hw_variant and device_revision_id. So, to pick the appropriate FW file for 9x60 SKU, three fields, hw_variant, hw_revision, and fw_revision, needs to be used rather than hw_variant and device_revision_id. Format will be like this: ibt---.sfi and .ddc Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_intel.c | 56 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 7 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index aad07e40ea4f..97586848ec97 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -708,16 +708,43 @@ static int intel_setup(struct hci_uart *hu) } /* With this Intel bootloader only the hardware variant and device - * revision information are used to select the right firmware. + * revision information are used to select the right firmware for SfP + * and WsP. * * The firmware filename is ibt--.sfi. * * Currently the supported hardware variants are: * 11 (0x0b) for iBT 3.0 (LnP/SfP) + * 12 (0x0c) for iBT 3.5 (WsP) + * + * For ThP/JfP and for future SKU's, the FW name varies based on HW + * variant, HW revision and FW revision, as these are dependent on CNVi + * and RF Combination. + * + * 18 (0x12) for iBT3.5 (ThP/JfP) + * + * The firmware file name for these will be + * ibt---.sfi. + * */ - snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi", - le16_to_cpu(ver.hw_variant), - le16_to_cpu(params->dev_revid)); + switch (ver.hw_variant) { + case 0x0b: /* SfP */ + case 0x0c: /* WsP */ + snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi", + le16_to_cpu(ver.hw_variant), + le16_to_cpu(params->dev_revid)); + break; + case 0x12: /* ThP */ + snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi", + le16_to_cpu(ver.hw_variant), + le16_to_cpu(ver.hw_revision), + le16_to_cpu(ver.fw_revision)); + break; + default: + bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)", + ver.hw_variant); + return -EINVAL; + } err = request_firmware(&fw, fwname, &hdev->dev); if (err < 0) { @@ -730,9 +757,24 @@ static int intel_setup(struct hci_uart *hu) bt_dev_info(hdev, "Found device firmware: %s", fwname); /* Save the DDC file name for later */ - snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc", - le16_to_cpu(ver.hw_variant), - le16_to_cpu(params->dev_revid)); + switch (ver.hw_variant) { + case 0x0b: /* SfP */ + case 0x0c: /* WsP */ + snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc", + le16_to_cpu(ver.hw_variant), + le16_to_cpu(params->dev_revid)); + break; + case 0x12: /* ThP */ + snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc", + le16_to_cpu(ver.hw_variant), + le16_to_cpu(ver.hw_revision), + le16_to_cpu(ver.fw_revision)); + break; + default: + bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)", + ver.hw_variant); + return -EINVAL; + } kfree_skb(skb); -- cgit v1.2.3 From e5889af62fce081dbd2e5d087683b9b7135bc731 Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Wed, 24 Jan 2018 09:19:18 -0800 Subject: Bluetooth: btintel: Create common function for Intel Reset The Intel_Reset command is used to reset the device after downloading the firmware and this is Intel generic command used in both USB and UART. Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btintel.c | 20 ++++++++++++++++++++ drivers/bluetooth/btintel.h | 15 +++++++++++++++ drivers/bluetooth/btusb.c | 15 +++++++-------- drivers/bluetooth/hci_intel.c | 15 +++++++-------- 4 files changed, 49 insertions(+), 16 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 07f00e422e85..c8aaed16f858 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -569,6 +569,26 @@ struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, } EXPORT_SYMBOL_GPL(btintel_regmap_init); +int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param) +{ + struct intel_reset params = { 0x00, 0x01, 0x00, 0x01, 0x00000000 }; + struct sk_buff *skb; + + params.boot_param = cpu_to_le32(boot_param); + + skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), ¶ms, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Failed to send Intel Reset command"); + return PTR_ERR(skb); + } + + kfree_skb(skb); + + return 0; +} +EXPORT_SYMBOL_GPL(btintel_send_intel_reset); + MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 1e8955aaafed..2235705c2ef2 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -69,6 +69,14 @@ struct intel_secure_send_result { __u8 status; } __packed; +struct intel_reset { + __u8 reset_type; + __u8 patch_enable; + __u8 ddc_reload; + __u8 boot_option; + __le32 boot_param; +} __packed; + #if IS_ENABLED(CONFIG_BT_INTEL) int btintel_check_bdaddr(struct hci_dev *hdev); @@ -89,6 +97,7 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver); struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, u16 opcode_write); +int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param); #else @@ -165,4 +174,10 @@ static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev, { return ERR_PTR(-EINVAL); } + +static inline int btintel_send_intel_reset(struct hci_dev *hdev, + u32 reset_param) +{ + return -EOPNOTSUPP; +} #endif diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 29977ebfd031..93db5b9f5376 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2009,8 +2009,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) static int btusb_setup_intel_new(struct hci_dev *hdev) { - static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01, - 0x00, 0x08, 0x04, 0x00 }; struct btusb_data *data = hci_get_drvdata(hdev); struct sk_buff *skb; struct intel_version ver; @@ -2018,6 +2016,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) const struct firmware *fw; const u8 *fw_ptr; u32 frag_len; + u32 boot_param; char fwname[64]; ktime_t calltime, delta, rettime; unsigned long long duration; @@ -2025,6 +2024,9 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) BT_DBG("%s", hdev->name); + /* The default boot parameter */ + boot_param = 0x00040800; + calltime = ktime_get(); /* Read the Intel version information to determine if the device @@ -2341,12 +2343,9 @@ done: set_bit(BTUSB_BOOTING, &data->flags); - skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param, - HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - kfree_skb(skb); + err = btintel_send_intel_reset(hdev, boot_param); + if (err) + return err; /* The bootloader will not indicate when the device is ready. This * is done by the operational firmware sending bootup notification. diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index 97586848ec97..acac48d0c79c 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -540,8 +540,6 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed) static int intel_setup(struct hci_uart *hu) { - static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01, - 0x00, 0x08, 0x04, 0x00 }; struct intel_data *intel = hu->priv; struct hci_dev *hdev = hu->hdev; struct sk_buff *skb; @@ -552,6 +550,7 @@ static int intel_setup(struct hci_uart *hu) const u8 *fw_ptr; char fwname[64]; u32 frag_len; + u32 boot_param; ktime_t calltime, delta, rettime; unsigned long long duration; unsigned int init_speed, oper_speed; @@ -563,6 +562,9 @@ static int intel_setup(struct hci_uart *hu) hu->hdev->set_diag = btintel_set_diag; hu->hdev->set_bdaddr = btintel_set_bdaddr; + /* Default boot parameter */ + boot_param = 0x00040800; + calltime = ktime_get(); if (hu->init_speed) @@ -911,12 +913,9 @@ done: set_bit(STATE_BOOTING, &intel->flags); - skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param, - HCI_CMD_TIMEOUT); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - kfree_skb(skb); + err = btintel_send_intel_reset(hdev, boot_param); + if (err) + return err; /* The bootloader will not indicate when the device is ready. This * is done by the operational firmware sending bootup notification. -- cgit v1.2.3 From 04d729b8a56304698c2eec6b93f2319b38851f6e Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Wed, 24 Jan 2018 09:19:19 -0800 Subject: Bluetooth: btintel: Use boot parameter from firmware file Each RAM SKU has a different boot parameter which is used in HCI_Intel_Reset command after downloading the firmware. The boot parameter is embedded in the firmware data and to support multiple SKUs, driver reads the boot parameter while downloading the firmware instead of using static values per SKU. Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 21 +++++++++++++++++++-- drivers/bluetooth/hci_intel.c | 22 ++++++++++++++++++++-- 2 files changed, 39 insertions(+), 4 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 93db5b9f5376..2a7d69072e36 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2024,8 +2024,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) BT_DBG("%s", hdev->name); - /* The default boot parameter */ - boot_param = 0x00040800; + /* Set the default boot parameter to 0x0 and it is updated to + * SKU specific boot parameter after reading Intel_Write_Boot_Params + * command while downloading the firmware. + */ + boot_param = 0x00000000; calltime = ktime_get(); @@ -2269,6 +2272,20 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) while (fw_ptr - fw->data < fw->size) { struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len); + /* Each SKU has a different reset parameter to use in the + * HCI_Intel_Reset command and it is embedded in the firmware + * data. So, instead of using static value per SKU, check + * the firmware data and save it for later use. + */ + if (cmd->opcode == 0xfc0e) { + /* The boot parameter is the first 32-bit value + * and rest of 3 octets are reserved. + */ + boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd)); + + bt_dev_dbg(hdev, "boot_param=0x%x", boot_param); + } + frag_len += sizeof(*cmd) + cmd->plen; /* The parameter length of the secure send command requires diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index acac48d0c79c..6f02f65820a3 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -562,8 +563,11 @@ static int intel_setup(struct hci_uart *hu) hu->hdev->set_diag = btintel_set_diag; hu->hdev->set_bdaddr = btintel_set_bdaddr; - /* Default boot parameter */ - boot_param = 0x00040800; + /* Set the default boot parameter to 0x0 and it is updated to + * SKU specific boot parameter after reading Intel_Write_Boot_Params + * command while downloading the firmware. + */ + boot_param = 0x00000000; calltime = ktime_get(); @@ -824,6 +828,20 @@ static int intel_setup(struct hci_uart *hu) while (fw_ptr - fw->data < fw->size) { struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len); + /* Each SKU has a different reset parameter to use in the + * HCI_Intel_Reset command and it is embedded in the firmware + * data. So, instead of using static value per SKU, check + * the firmware data and save it for later use. + */ + if (cmd->opcode == 0xfc0e) { + /* The boot parameter is the first 32-bit value + * and rest of 3 octets are reserved. + */ + boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd)); + + bt_dev_dbg(hdev, "boot_param=0x%x", boot_param); + } + frag_len += sizeof(*cmd) + cmd->plen; bt_dev_dbg(hdev, "Patching %td/%zu", (fw_ptr - fw->data), -- cgit v1.2.3 From faf174d297134ad071f528a9db787b4c95734b40 Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Wed, 24 Jan 2018 09:19:20 -0800 Subject: Bluetooth: btintel: Create common Intel Read Boot Params function The Intel_Read_Boot_Params command is used to read boot parameters from the bootloader and this is Intel generic command used in USB and UART drivers. Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btintel.c | 51 +++++++++++++++++++++++++++++++++++++++++ drivers/bluetooth/btintel.h | 8 +++++++ drivers/bluetooth/btusb.c | 53 ++++++++----------------------------------- drivers/bluetooth/hci_intel.c | 48 +++++++-------------------------------- 4 files changed, 76 insertions(+), 84 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index c8aaed16f858..da47f6dccd38 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -589,6 +589,57 @@ int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param) } EXPORT_SYMBOL_GPL(btintel_send_intel_reset); +int btintel_read_boot_params(struct hci_dev *hdev, + struct intel_boot_params *params) +{ + struct sk_buff *skb; + + skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)", + PTR_ERR(skb)); + return PTR_ERR(skb); + } + + if (skb->len != sizeof(*params)) { + bt_dev_err(hdev, "Intel boot parameters size mismatch"); + kfree_skb(skb); + return -EILSEQ; + } + + memcpy(params, skb->data, sizeof(*params)); + + kfree_skb(skb); + + if (params->status) { + bt_dev_err(hdev, "Intel boot parameters command failed (%02x)", + params->status); + return -bt_to_errno(params->status); + } + + bt_dev_info(hdev, "Device revision is %u", + le16_to_cpu(params->dev_revid)); + + bt_dev_info(hdev, "Secure boot is %s", + params->secure_boot ? "enabled" : "disabled"); + + bt_dev_info(hdev, "OTP lock is %s", + params->otp_lock ? "enabled" : "disabled"); + + bt_dev_info(hdev, "API lock is %s", + params->api_lock ? "enabled" : "disabled"); + + bt_dev_info(hdev, "Debug lock is %s", + params->debug_lock ? "enabled" : "disabled"); + + bt_dev_info(hdev, "Minimum firmware build %u week %u %u", + params->min_fw_build_nn, params->min_fw_build_cw, + 2000 + params->min_fw_build_yy); + + return 0; +} +EXPORT_SYMBOL_GPL(btintel_read_boot_params); + MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 2235705c2ef2..0391e7aba03b 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -98,6 +98,8 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver); struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, u16 opcode_write); int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param); +int btintel_read_boot_params(struct hci_dev *hdev, + struct intel_boot_params *params); #else @@ -180,4 +182,10 @@ static inline int btintel_send_intel_reset(struct hci_dev *hdev, { return -EOPNOTSUPP; } + +static inline int btintel_read_boot_params(struct hci_dev *hdev, + struct intel_boot_params *params) +{ + return -EOPNOTSUPP; +} #endif diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2a7d69072e36..6ea21d503eaf 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2010,9 +2010,8 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) static int btusb_setup_intel_new(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); - struct sk_buff *skb; struct intel_version ver; - struct intel_boot_params *params; + struct intel_boot_params params; const struct firmware *fw; const u8 *fw_ptr; u32 frag_len; @@ -2100,55 +2099,24 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) /* Read the secure boot parameters to identify the operating * details of the bootloader. */ - skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - BT_ERR("%s: Reading Intel boot parameters failed (%ld)", - hdev->name, PTR_ERR(skb)); - return PTR_ERR(skb); - } - - if (skb->len != sizeof(*params)) { - BT_ERR("%s: Intel boot parameters size mismatch", hdev->name); - kfree_skb(skb); - return -EILSEQ; - } - - params = (struct intel_boot_params *)skb->data; - - bt_dev_info(hdev, "Device revision is %u", - le16_to_cpu(params->dev_revid)); - - bt_dev_info(hdev, "Secure boot is %s", - params->secure_boot ? "enabled" : "disabled"); - - bt_dev_info(hdev, "OTP lock is %s", - params->otp_lock ? "enabled" : "disabled"); - - bt_dev_info(hdev, "API lock is %s", - params->api_lock ? "enabled" : "disabled"); - - bt_dev_info(hdev, "Debug lock is %s", - params->debug_lock ? "enabled" : "disabled"); - - bt_dev_info(hdev, "Minimum firmware build %u week %u %u", - params->min_fw_build_nn, params->min_fw_build_cw, - 2000 + params->min_fw_build_yy); + err = btintel_read_boot_params(hdev, ¶ms); + if (err) + return err; /* It is required that every single firmware fragment is acknowledged * with a command complete event. If the boot parameters indicate * that this bootloader does not send them, then abort the setup. */ - if (params->limited_cce != 0x00) { + if (params.limited_cce != 0x00) { BT_ERR("%s: Unsupported Intel firmware loading method (%u)", - hdev->name, params->limited_cce); - kfree_skb(skb); + hdev->name, params.limited_cce); return -EINVAL; } /* If the OTP has no valid Bluetooth device address, then there will * also be no valid address for the operational firmware. */ - if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) { + if (!bacmp(¶ms.otp_bdaddr, BDADDR_ANY)) { bt_dev_info(hdev, "No device address configured"); set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); } @@ -2179,7 +2147,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) case 0x0c: /* WsP */ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi", le16_to_cpu(ver.hw_variant), - le16_to_cpu(params->dev_revid)); + le16_to_cpu(params.dev_revid)); break; case 0x11: /* JfP */ case 0x12: /* ThP */ @@ -2197,7 +2165,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) if (err < 0) { BT_ERR("%s: Failed to load Intel firmware file (%d)", hdev->name, err); - kfree_skb(skb); return err; } @@ -2211,7 +2178,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) case 0x0c: /* WsP */ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc", le16_to_cpu(ver.hw_variant), - le16_to_cpu(params->dev_revid)); + le16_to_cpu(params.dev_revid)); break; case 0x11: /* JfP */ case 0x12: /* ThP */ @@ -2225,8 +2192,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) return -EINVAL; } - kfree_skb(skb); - if (fw->size < 644) { BT_ERR("%s: Invalid size of firmware file (%zu)", hdev->name, fw->size); diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index 6f02f65820a3..cf7438512d21 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -545,7 +545,7 @@ static int intel_setup(struct hci_uart *hu) struct hci_dev *hdev = hu->hdev; struct sk_buff *skb; struct intel_version ver; - struct intel_boot_params *params; + struct intel_boot_params params; struct list_head *p; const struct firmware *fw; const u8 *fw_ptr; @@ -662,53 +662,24 @@ static int intel_setup(struct hci_uart *hu) /* Read the secure boot parameters to identify the operating * details of the bootloader. */ - skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_CMD_TIMEOUT); - if (IS_ERR(skb)) { - bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)", - PTR_ERR(skb)); - return PTR_ERR(skb); - } - - if (skb->len != sizeof(*params)) { - bt_dev_err(hdev, "Intel boot parameters size mismatch"); - kfree_skb(skb); - return -EILSEQ; - } - - params = (struct intel_boot_params *)skb->data; - if (params->status) { - bt_dev_err(hdev, "Intel boot parameters command failure (%02x)", - params->status); - err = -bt_to_errno(params->status); - kfree_skb(skb); + err = btintel_read_boot_params(hdev, ¶ms); + if (err) return err; - } - - bt_dev_info(hdev, "Device revision is %u", - le16_to_cpu(params->dev_revid)); - - bt_dev_info(hdev, "Secure boot is %s", - params->secure_boot ? "enabled" : "disabled"); - - bt_dev_info(hdev, "Minimum firmware build %u week %u %u", - params->min_fw_build_nn, params->min_fw_build_cw, - 2000 + params->min_fw_build_yy); /* It is required that every single firmware fragment is acknowledged * with a command complete event. If the boot parameters indicate * that this bootloader does not send them, then abort the setup. */ - if (params->limited_cce != 0x00) { + if (params.limited_cce != 0x00) { bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)", - params->limited_cce); - kfree_skb(skb); + params.limited_cce); return -EINVAL; } /* If the OTP has no valid Bluetooth device address, then there will * also be no valid address for the operational firmware. */ - if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) { + if (!bacmp(¶ms.otp_bdaddr, BDADDR_ANY)) { bt_dev_info(hdev, "No device address configured"); set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); } @@ -738,7 +709,7 @@ static int intel_setup(struct hci_uart *hu) case 0x0c: /* WsP */ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi", le16_to_cpu(ver.hw_variant), - le16_to_cpu(params->dev_revid)); + le16_to_cpu(params.dev_revid)); break; case 0x12: /* ThP */ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi", @@ -756,7 +727,6 @@ static int intel_setup(struct hci_uart *hu) if (err < 0) { bt_dev_err(hdev, "Failed to load Intel firmware file (%d)", err); - kfree_skb(skb); return err; } @@ -768,7 +738,7 @@ static int intel_setup(struct hci_uart *hu) case 0x0c: /* WsP */ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc", le16_to_cpu(ver.hw_variant), - le16_to_cpu(params->dev_revid)); + le16_to_cpu(params.dev_revid)); break; case 0x12: /* ThP */ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc", @@ -782,8 +752,6 @@ static int intel_setup(struct hci_uart *hu) return -EINVAL; } - kfree_skb(skb); - if (fw->size < 644) { bt_dev_err(hdev, "Invalid size of firmware file (%zu)", fw->size); -- cgit v1.2.3 From fbbe83c52bc0d52398de72d7df1857cc9b36244e Mon Sep 17 00:00:00 2001 From: Tedd Ho-Jeong An Date: Wed, 24 Jan 2018 09:19:21 -0800 Subject: Bluetooth: btintel: Create common function for firmware download The firmware download flow for RAM SKU is same for both USB and UART and this patch creates a common function for both driver. Signed-off-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btintel.c | 84 +++++++++++++++++++++++++++++++++++++++++++ drivers/bluetooth/btintel.h | 10 +++++- drivers/bluetooth/btusb.c | 76 ++------------------------------------- drivers/bluetooth/hci_intel.c | 83 ++---------------------------------------- 4 files changed, 99 insertions(+), 154 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index da47f6dccd38..5270d5513201 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -640,6 +641,89 @@ int btintel_read_boot_params(struct hci_dev *hdev, } EXPORT_SYMBOL_GPL(btintel_read_boot_params); +int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw, + u32 *boot_param) +{ + int err; + const u8 *fw_ptr; + u32 frag_len; + + /* Start the firmware download transaction with the Init fragment + * represented by the 128 bytes of CSS header. + */ + err = btintel_secure_send(hdev, 0x00, 128, fw->data); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware header (%d)", err); + goto done; + } + + /* Send the 256 bytes of public key information from the firmware + * as the PKey fragment. + */ + err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err); + goto done; + } + + /* Send the 256 bytes of signature information from the firmware + * as the Sign fragment. + */ + err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware signature (%d)", err); + goto done; + } + + fw_ptr = fw->data + 644; + frag_len = 0; + + while (fw_ptr - fw->data < fw->size) { + struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len); + + /* Each SKU has a different reset parameter to use in the + * HCI_Intel_Reset command and it is embedded in the firmware + * data. So, instead of using static value per SKU, check + * the firmware data and save it for later use. + */ + if (le16_to_cpu(cmd->opcode) == 0xfc0e) { + /* The boot parameter is the first 32-bit value + * and rest of 3 octets are reserved. + */ + *boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd)); + + bt_dev_dbg(hdev, "boot_param=0x%x", *boot_param); + } + + frag_len += sizeof(*cmd) + cmd->plen; + + /* The parameter length of the secure send command requires + * a 4 byte alignment. It happens so that the firmware file + * contains proper Intel_NOP commands to align the fragments + * as needed. + * + * Send set of commands with 4 byte alignment from the + * firmware data buffer as a single Data fragement. + */ + if (!(frag_len % 4)) { + err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr); + if (err < 0) { + bt_dev_err(hdev, + "Failed to send firmware data (%d)", + err); + goto done; + } + + fw_ptr += frag_len; + frag_len = 0; + } + } + +done: + return err; +} +EXPORT_SYMBOL_GPL(btintel_download_firmware); + MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 0391e7aba03b..41c642cc523f 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -100,7 +100,8 @@ struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param); int btintel_read_boot_params(struct hci_dev *hdev, struct intel_boot_params *params); - +int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw, + u32 *boot_param); #else static inline int btintel_check_bdaddr(struct hci_dev *hdev) @@ -188,4 +189,11 @@ static inline int btintel_read_boot_params(struct hci_dev *hdev, { return -EOPNOTSUPP; } + +static inline int btintel_download_firmware(struct hci_dev *dev, + const struct firmware *fw, + u32 *boot_param) +{ + return -EOPNOTSUPP; +} #endif diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 6ea21d503eaf..2a55380ad730 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2013,8 +2013,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) struct intel_version ver; struct intel_boot_params params; const struct firmware *fw; - const u8 *fw_ptr; - u32 frag_len; u32 boot_param; char fwname[64]; ktime_t calltime, delta, rettime; @@ -2201,78 +2199,10 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) set_bit(BTUSB_DOWNLOADING, &data->flags); - /* Start the firmware download transaction with the Init fragment - * represented by the 128 bytes of CSS header. - */ - err = btintel_secure_send(hdev, 0x00, 128, fw->data); - if (err < 0) { - BT_ERR("%s: Failed to send firmware header (%d)", - hdev->name, err); - goto done; - } - - /* Send the 256 bytes of public key information from the firmware - * as the PKey fragment. - */ - err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128); - if (err < 0) { - BT_ERR("%s: Failed to send firmware public key (%d)", - hdev->name, err); - goto done; - } - - /* Send the 256 bytes of signature information from the firmware - * as the Sign fragment. - */ - err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388); - if (err < 0) { - BT_ERR("%s: Failed to send firmware signature (%d)", - hdev->name, err); + /* Start firmware downloading and get boot parameter */ + err = btintel_download_firmware(hdev, fw, &boot_param); + if (err < 0) goto done; - } - - fw_ptr = fw->data + 644; - frag_len = 0; - - while (fw_ptr - fw->data < fw->size) { - struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len); - - /* Each SKU has a different reset parameter to use in the - * HCI_Intel_Reset command and it is embedded in the firmware - * data. So, instead of using static value per SKU, check - * the firmware data and save it for later use. - */ - if (cmd->opcode == 0xfc0e) { - /* The boot parameter is the first 32-bit value - * and rest of 3 octets are reserved. - */ - boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd)); - - bt_dev_dbg(hdev, "boot_param=0x%x", boot_param); - } - - frag_len += sizeof(*cmd) + cmd->plen; - - /* The parameter length of the secure send command requires - * a 4 byte alignment. It happens so that the firmware file - * contains proper Intel_NOP commands to align the fragments - * as needed. - * - * Send set of commands with 4 byte alignment from the - * firmware data buffer as a single Data fragement. - */ - if (!(frag_len % 4)) { - err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr); - if (err < 0) { - BT_ERR("%s: Failed to send firmware data (%d)", - hdev->name, err); - goto done; - } - - fw_ptr += frag_len; - frag_len = 0; - } - } set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index cf7438512d21..7c166e3b308b 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -548,9 +547,7 @@ static int intel_setup(struct hci_uart *hu) struct intel_boot_params params; struct list_head *p; const struct firmware *fw; - const u8 *fw_ptr; char fwname[64]; - u32 frag_len; u32 boot_param; ktime_t calltime, delta, rettime; unsigned long long duration; @@ -761,84 +758,10 @@ static int intel_setup(struct hci_uart *hu) set_bit(STATE_DOWNLOADING, &intel->flags); - /* Start the firmware download transaction with the Init fragment - * represented by the 128 bytes of CSS header. - */ - err = btintel_secure_send(hdev, 0x00, 128, fw->data); - if (err < 0) { - bt_dev_err(hdev, "Failed to send firmware header (%d)", err); - goto done; - } - - /* Send the 256 bytes of public key information from the firmware - * as the PKey fragment. - */ - err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128); - if (err < 0) { - bt_dev_err(hdev, "Failed to send firmware public key (%d)", - err); - goto done; - } - - /* Send the 256 bytes of signature information from the firmware - * as the Sign fragment. - */ - err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388); - if (err < 0) { - bt_dev_err(hdev, "Failed to send firmware signature (%d)", - err); + /* Start firmware downloading and get boot parameter */ + err = btintel_download_firmware(hdev, fw, &boot_param); + if (err < 0) goto done; - } - - fw_ptr = fw->data + 644; - frag_len = 0; - - while (fw_ptr - fw->data < fw->size) { - struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len); - - /* Each SKU has a different reset parameter to use in the - * HCI_Intel_Reset command and it is embedded in the firmware - * data. So, instead of using static value per SKU, check - * the firmware data and save it for later use. - */ - if (cmd->opcode == 0xfc0e) { - /* The boot parameter is the first 32-bit value - * and rest of 3 octets are reserved. - */ - boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd)); - - bt_dev_dbg(hdev, "boot_param=0x%x", boot_param); - } - - frag_len += sizeof(*cmd) + cmd->plen; - - bt_dev_dbg(hdev, "Patching %td/%zu", (fw_ptr - fw->data), - fw->size); - - /* The parameter length of the secure send command requires - * a 4 byte alignment. It happens so that the firmware file - * contains proper Intel_NOP commands to align the fragments - * as needed. - * - * Send set of commands with 4 byte alignment from the - * firmware data buffer as a single Data fragement. - */ - if (frag_len % 4) - continue; - - /* Send each command from the firmware data buffer as - * a single Data fragment. - */ - err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr); - if (err < 0) { - bt_dev_err(hdev, "Failed to send firmware data (%d)", - err); - goto done; - } - - fw_ptr += frag_len; - frag_len = 0; - } set_bit(STATE_FIRMWARE_LOADED, &intel->flags); -- cgit v1.2.3