diff options
author | David S. Miller <davem@davemloft.net> | 2019-10-26 06:19:44 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-10-26 06:19:44 +0300 |
commit | 8ca12bc36f6b3bbecb929734f2a01991ab957c63 (patch) | |
tree | f2e58659e8856fd1647d9cd222269b1f24bc495d /drivers | |
parent | 480274787d7e3458bc5a7cfbbbe07033984ad711 (diff) | |
parent | 3347a80965b38f096b1d6f995c00c9c9e53d4b8b (diff) | |
download | linux-8ca12bc36f6b3bbecb929734f2a01991ab957c63.tar.xz |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says:
====================
pull request: bluetooth-next 2019-10-23
Here's the main bluetooth-next pull request for the 5.5 kernel:
- Multiple fixes to hci_qca driver
- Fix for HCI_USER_CHANNEL initialization
- btwlink: drop superseded driver
- Add support for Intel FW download error recovery
- Various other smaller fixes & improvements
Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/bluetooth/Kconfig | 11 | ||||
-rw-r--r-- | drivers/bluetooth/Makefile | 1 | ||||
-rw-r--r-- | drivers/bluetooth/btintel.c | 45 | ||||
-rw-r--r-- | drivers/bluetooth/btintel.h | 5 | ||||
-rw-r--r-- | drivers/bluetooth/btrtl.c | 2 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 54 | ||||
-rw-r--r-- | drivers/bluetooth/btwilink.c | 337 | ||||
-rw-r--r-- | drivers/bluetooth/hci_bcm.c | 2 | ||||
-rw-r--r-- | drivers/bluetooth/hci_ll.c | 39 | ||||
-rw-r--r-- | drivers/bluetooth/hci_nokia.c | 2 | ||||
-rw-r--r-- | drivers/bluetooth/hci_qca.c | 135 |
11 files changed, 159 insertions, 474 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index aae665a3a254..f7aa2dc1ff85 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -380,17 +380,6 @@ config BT_ATH3K Say Y here to compile support for "Atheros firmware download driver" into the kernel or say M to compile it as module (ath3k). -config BT_WILINK - tristate "Texas Instruments WiLink7 driver" - depends on TI_ST - help - This enables the Bluetooth driver for Texas Instrument's BT/FM/GPS - combo devices. This makes use of shared transport line discipline - core driver to communicate with the BT core of the combo chip. - - Say Y here to compile support for Texas Instrument's WiLink7 driver - into the kernel or say M to compile it as module (btwilink). - config BT_MTKSDIO tristate "MediaTek HCI SDIO driver" depends on MMC diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 34887b9b3a85..1a58a3ae142c 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_BT_INTEL) += btintel.o obj-$(CONFIG_BT_ATH3K) += ath3k.o obj-$(CONFIG_BT_MRVL) += btmrvl.o obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o -obj-$(CONFIG_BT_WILINK) += btwilink.o obj-$(CONFIG_BT_MTKSDIO) += btmtksdio.o obj-$(CONFIG_BT_MTKUART) += btmtkuart.o obj-$(CONFIG_BT_QCOMSMD) += btqcomsmd.o diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index bb99c8653aab..62e781a18bf0 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -709,6 +709,51 @@ done: } EXPORT_SYMBOL_GPL(btintel_download_firmware); +void btintel_reset_to_bootloader(struct hci_dev *hdev) +{ + struct intel_reset params; + struct sk_buff *skb; + + /* Send Intel Reset command. This will result in + * re-enumeration of BT controller. + * + * Intel Reset parameter description: + * reset_type : 0x00 (Soft reset), + * 0x01 (Hard reset) + * patch_enable : 0x00 (Do not enable), + * 0x01 (Enable) + * ddc_reload : 0x00 (Do not reload), + * 0x01 (Reload) + * boot_option: 0x00 (Current image), + * 0x01 (Specified boot address) + * boot_param: Boot address + * + */ + params.reset_type = 0x01; + params.patch_enable = 0x01; + params.ddc_reload = 0x01; + params.boot_option = 0x00; + params.boot_param = cpu_to_le32(0x00000000); + + skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), + ¶ms, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "FW download error recovery failed (%ld)", + PTR_ERR(skb)); + return; + } + bt_dev_info(hdev, "Intel reset sent to retry FW download"); + kfree_skb(skb); + + /* Current Intel BT controllers(ThP/JfP) hold the USB reset + * lines for 2ms when it receives Intel Reset in bootloader mode. + * Whereas, the upcoming Intel BT controllers will hold USB reset + * for 150ms. To keep the delay generic, 150ms is chosen here. + */ + msleep(150); +} +EXPORT_SYMBOL_GPL(btintel_reset_to_bootloader); + MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); 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 3d846190f2bf..a69ea8a87b9b 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -87,6 +87,7 @@ 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); +void btintel_reset_to_bootloader(struct hci_dev *hdev); #else static inline int btintel_check_bdaddr(struct hci_dev *hdev) @@ -181,4 +182,8 @@ static inline int btintel_download_firmware(struct hci_dev *dev, { return -EOPNOTSUPP; } + +static inline void btintel_reset_to_bootloader(struct hci_dev *hdev) +{ +} #endif diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index bf3c02be6930..ae9a2047f242 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -418,7 +418,7 @@ static int rtl_download_firmware(struct hci_dev *hdev, if (IS_ERR(skb)) { rtl_dev_err(hdev, "download fw command failed (%ld)", PTR_ERR(skb)); - ret = -PTR_ERR(skb); + ret = PTR_ERR(skb); goto out; } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a9c35ebb30f8..04a139e7793f 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2182,8 +2182,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * loaded. */ err = btintel_read_version(hdev, &ver); - if (err) + if (err) { + bt_dev_err(hdev, "Intel Read version failed (%d)", err); + btintel_reset_to_bootloader(hdev); return err; + } /* The hardware platform number has a fixed value of 0x37 and * for now only accept this single value. @@ -2326,9 +2329,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) /* Start firmware downloading and get boot parameter */ err = btintel_download_firmware(hdev, fw, &boot_param); - if (err < 0) + if (err < 0) { + /* When FW download fails, send Intel Reset to retry + * FW download. + */ + btintel_reset_to_bootloader(hdev); goto done; - + } set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); bt_dev_info(hdev, "Waiting for firmware download to complete"); @@ -2355,6 +2362,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) if (err) { bt_dev_err(hdev, "Firmware loading timeout"); err = -ETIMEDOUT; + btintel_reset_to_bootloader(hdev); goto done; } @@ -2381,8 +2389,11 @@ done: set_bit(BTUSB_BOOTING, &data->flags); err = btintel_send_intel_reset(hdev, boot_param); - if (err) + if (err) { + bt_dev_err(hdev, "Intel Soft Reset failed (%d)", err); + btintel_reset_to_bootloader(hdev); return err; + } /* The bootloader will not indicate when the device is ready. This * is done by the operational firmware sending bootup notification. @@ -2404,6 +2415,7 @@ done: if (err) { bt_dev_err(hdev, "Device boot timeout"); + btintel_reset_to_bootloader(hdev); return -ETIMEDOUT; } @@ -2432,6 +2444,13 @@ done: */ btintel_set_event_mask(hdev, false); + /* Read the Intel version information after loading the FW */ + err = btintel_read_version(hdev, &ver); + if (err) + return err; + + btintel_version_info(hdev, &ver); + return 0; } @@ -2489,8 +2508,6 @@ static int btusb_shutdown_intel_new(struct hci_dev *hdev) return 0; } -#ifdef CONFIG_BT_HCIBTUSB_MTK - #define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" #define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" @@ -3051,7 +3068,6 @@ static int btusb_mtk_shutdown(struct hci_dev *hdev) MODULE_FIRMWARE(FIRMWARE_MT7663); MODULE_FIRMWARE(FIRMWARE_MT7668); -#endif #ifdef CONFIG_PM /* Configure an out-of-band gpio as wake-up pin, if specified in device tree */ @@ -3411,7 +3427,6 @@ static int btusb_setup_qca(struct hci_dev *hdev) return 0; } -#ifdef CONFIG_BT_HCIBTUSB_BCM static inline int __set_diag_interface(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); @@ -3498,7 +3513,6 @@ static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable) return submit_or_queue_tx_urb(hdev, urb); } -#endif #ifdef CONFIG_PM static irqreturn_t btusb_oob_wake_handler(int irq, void *priv) @@ -3724,8 +3738,8 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_BCM92035) hdev->setup = btusb_setup_bcm92035; -#ifdef CONFIG_BT_HCIBTUSB_BCM - if (id->driver_info & BTUSB_BCM_PATCHRAM) { + if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) && + (id->driver_info & BTUSB_BCM_PATCHRAM)) { hdev->manufacturer = 15; hdev->setup = btbcm_setup_patchram; hdev->set_diag = btusb_bcm_set_diag; @@ -3735,7 +3749,8 @@ static int btusb_probe(struct usb_interface *intf, data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2); } - if (id->driver_info & BTUSB_BCM_APPLE) { + if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) && + (id->driver_info & BTUSB_BCM_APPLE)) { hdev->manufacturer = 15; hdev->setup = btbcm_setup_apple; hdev->set_diag = btusb_bcm_set_diag; @@ -3743,7 +3758,6 @@ static int btusb_probe(struct usb_interface *intf, /* Broadcom LM_DIAG Interface numbers are hardcoded */ data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2); } -#endif if (id->driver_info & BTUSB_INTEL) { hdev->manufacturer = 2; @@ -3774,14 +3788,13 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_MARVELL) hdev->set_bdaddr = btusb_set_bdaddr_marvell; -#ifdef CONFIG_BT_HCIBTUSB_MTK - if (id->driver_info & BTUSB_MEDIATEK) { + if (IS_ENABLED(CONFIG_BT_HCIBTUSB_MTK) && + (id->driver_info & BTUSB_MEDIATEK)) { hdev->setup = btusb_mtk_setup; hdev->shutdown = btusb_mtk_shutdown; hdev->manufacturer = 70; set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); } -#endif if (id->driver_info & BTUSB_SWAVE) { set_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks); @@ -3807,8 +3820,8 @@ static int btusb_probe(struct usb_interface *intf, btusb_check_needs_reset_resume(intf); } -#ifdef CONFIG_BT_HCIBTUSB_RTL - if (id->driver_info & BTUSB_REALTEK) { + if (IS_ENABLED(CONFIG_BT_HCIBTUSB_RTL) && + (id->driver_info & BTUSB_REALTEK)) { hdev->setup = btrtl_setup_realtek; hdev->shutdown = btrtl_shutdown_realtek; hdev->cmd_timeout = btusb_rtl_cmd_timeout; @@ -3819,7 +3832,6 @@ static int btusb_probe(struct usb_interface *intf, */ set_bit(BTUSB_WAKEUP_DISABLE, &data->flags); } -#endif if (id->driver_info & BTUSB_AMP) { /* AMP controllers do not support SCO packets */ @@ -3887,15 +3899,13 @@ static int btusb_probe(struct usb_interface *intf, goto out_free_dev; } -#ifdef CONFIG_BT_HCIBTUSB_BCM - if (data->diag) { + if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) && data->diag) { if (!usb_driver_claim_interface(&btusb_driver, data->diag, data)) __set_diag_interface(hdev); else data->diag = NULL; } -#endif if (enable_autosuspend) usb_enable_autosuspend(data->udev); diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c deleted file mode 100644 index e55f06e4270f..000000000000 --- a/drivers/bluetooth/btwilink.c +++ /dev/null @@ -1,337 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Texas Instrument's Bluetooth Driver For Shared Transport. - * - * Bluetooth Driver acts as interface between HCI core and - * TI Shared Transport Layer. - * - * Copyright (C) 2009-2010 Texas Instruments - * Author: Raja Mani <raja_mani@ti.com> - * Pavan Savoy <pavan_savoy@ti.com> - */ - -#include <linux/platform_device.h> -#include <net/bluetooth/bluetooth.h> -#include <net/bluetooth/hci_core.h> -#include <net/bluetooth/hci.h> - -#include <linux/ti_wilink_st.h> -#include <linux/module.h> - -/* Bluetooth Driver Version */ -#define VERSION "1.0" -#define MAX_BT_CHNL_IDS 3 - -/* Number of seconds to wait for registration completion - * when ST returns PENDING status. - */ -#define BT_REGISTER_TIMEOUT 6000 /* 6 sec */ - -/** - * struct ti_st - driver operation structure - * @hdev: hci device pointer which binds to bt driver - * @reg_status: ST registration callback status - * @st_write: write function provided by the ST driver - * to be used by the driver during send_frame. - * @wait_reg_completion - completion sync between ti_st_open - * and st_reg_completion_cb. - */ -struct ti_st { - struct hci_dev *hdev; - int reg_status; - long (*st_write) (struct sk_buff *); - struct completion wait_reg_completion; -}; - -/* Increments HCI counters based on pocket ID (cmd,acl,sco) */ -static inline void ti_st_tx_complete(struct ti_st *hst, int pkt_type) -{ - struct hci_dev *hdev = hst->hdev; - - /* Update HCI stat counters */ - switch (pkt_type) { - case HCI_COMMAND_PKT: - hdev->stat.cmd_tx++; - break; - - case HCI_ACLDATA_PKT: - hdev->stat.acl_tx++; - break; - - case HCI_SCODATA_PKT: - hdev->stat.sco_tx++; - break; - } -} - -/* ------- Interfaces to Shared Transport ------ */ - -/* Called by ST layer to indicate protocol registration completion - * status.ti_st_open() function will wait for signal from this - * API when st_register() function returns ST_PENDING. - */ -static void st_reg_completion_cb(void *priv_data, int data) -{ - struct ti_st *lhst = priv_data; - - /* Save registration status for use in ti_st_open() */ - lhst->reg_status = data; - /* complete the wait in ti_st_open() */ - complete(&lhst->wait_reg_completion); -} - -/* Called by Shared Transport layer when receive data is available */ -static long st_receive(void *priv_data, struct sk_buff *skb) -{ - struct ti_st *lhst = priv_data; - int err; - - if (!skb) - return -EFAULT; - - if (!lhst) { - kfree_skb(skb); - return -EFAULT; - } - - /* Forward skb to HCI core layer */ - err = hci_recv_frame(lhst->hdev, skb); - if (err < 0) { - BT_ERR("Unable to push skb to HCI core(%d)", err); - return err; - } - - lhst->hdev->stat.byte_rx += skb->len; - - return 0; -} - -/* ------- Interfaces to HCI layer ------ */ -/* protocol structure registered with shared transport */ -static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = { - { - .chnl_id = HCI_EVENT_PKT, /* HCI Events */ - .hdr_len = sizeof(struct hci_event_hdr), - .offset_len_in_hdr = offsetof(struct hci_event_hdr, plen), - .len_size = 1, /* sizeof(plen) in struct hci_event_hdr */ - .reserve = 8, - }, - { - .chnl_id = HCI_ACLDATA_PKT, /* ACL */ - .hdr_len = sizeof(struct hci_acl_hdr), - .offset_len_in_hdr = offsetof(struct hci_acl_hdr, dlen), - .len_size = 2, /* sizeof(dlen) in struct hci_acl_hdr */ - .reserve = 8, - }, - { - .chnl_id = HCI_SCODATA_PKT, /* SCO */ - .hdr_len = sizeof(struct hci_sco_hdr), - .offset_len_in_hdr = offsetof(struct hci_sco_hdr, dlen), - .len_size = 1, /* sizeof(dlen) in struct hci_sco_hdr */ - .reserve = 8, - }, -}; - -/* Called from HCI core to initialize the device */ -static int ti_st_open(struct hci_dev *hdev) -{ - unsigned long timeleft; - struct ti_st *hst; - int err, i; - - BT_DBG("%s %p", hdev->name, hdev); - - /* provide contexts for callbacks from ST */ - hst = hci_get_drvdata(hdev); - - for (i = 0; i < MAX_BT_CHNL_IDS; i++) { - ti_st_proto[i].priv_data = hst; - ti_st_proto[i].max_frame_size = HCI_MAX_FRAME_SIZE; - ti_st_proto[i].recv = st_receive; - ti_st_proto[i].reg_complete_cb = st_reg_completion_cb; - - /* Prepare wait-for-completion handler */ - init_completion(&hst->wait_reg_completion); - /* Reset ST registration callback status flag, - * this value will be updated in - * st_reg_completion_cb() - * function whenever it called from ST driver. - */ - hst->reg_status = -EINPROGRESS; - - err = st_register(&ti_st_proto[i]); - if (!err) - goto done; - - if (err != -EINPROGRESS) { - BT_ERR("st_register failed %d", err); - return err; - } - - /* ST is busy with either protocol - * registration or firmware download. - */ - BT_DBG("waiting for registration " - "completion signal from ST"); - timeleft = wait_for_completion_timeout - (&hst->wait_reg_completion, - msecs_to_jiffies(BT_REGISTER_TIMEOUT)); - if (!timeleft) { - BT_ERR("Timeout(%d sec),didn't get reg " - "completion signal from ST", - BT_REGISTER_TIMEOUT / 1000); - return -ETIMEDOUT; - } - - /* Is ST registration callback - * called with ERROR status? - */ - if (hst->reg_status != 0) { - BT_ERR("ST registration completed with invalid " - "status %d", hst->reg_status); - return -EAGAIN; - } - -done: - hst->st_write = ti_st_proto[i].write; - if (!hst->st_write) { - BT_ERR("undefined ST write function"); - for (i = 0; i < MAX_BT_CHNL_IDS; i++) { - /* Undo registration with ST */ - err = st_unregister(&ti_st_proto[i]); - if (err) - BT_ERR("st_unregister() failed with " - "error %d", err); - hst->st_write = NULL; - } - return -EIO; - } - } - return 0; -} - -/* Close device */ -static int ti_st_close(struct hci_dev *hdev) -{ - int err, i; - struct ti_st *hst = hci_get_drvdata(hdev); - - for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) { - err = st_unregister(&ti_st_proto[i]); - if (err) - BT_ERR("st_unregister(%d) failed with error %d", - ti_st_proto[i].chnl_id, err); - } - - hst->st_write = NULL; - - return err; -} - -static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb) -{ - struct ti_st *hst; - long len; - int pkt_type; - - hst = hci_get_drvdata(hdev); - - /* Prepend skb with frame type */ - memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); - - BT_DBG("%s: type %d len %d", hdev->name, hci_skb_pkt_type(skb), - skb->len); - - /* Insert skb to shared transport layer's transmit queue. - * Freeing skb memory is taken care in shared transport layer, - * so don't free skb memory here. - */ - pkt_type = hci_skb_pkt_type(skb); - len = hst->st_write(skb); - if (len < 0) { - BT_ERR("ST write failed (%ld)", len); - /* Try Again, would only fail if UART has gone bad */ - return -EAGAIN; - } - - /* ST accepted our skb. So, Go ahead and do rest */ - hdev->stat.byte_tx += len; - ti_st_tx_complete(hst, pkt_type); - - return 0; -} - -static int bt_ti_probe(struct platform_device *pdev) -{ - struct ti_st *hst; - struct hci_dev *hdev; - int err; - - hst = devm_kzalloc(&pdev->dev, sizeof(struct ti_st), GFP_KERNEL); - if (!hst) - return -ENOMEM; - - /* Expose "hciX" device to user space */ - hdev = hci_alloc_dev(); - if (!hdev) - return -ENOMEM; - - BT_DBG("hdev %p", hdev); - - hst->hdev = hdev; - hdev->bus = HCI_UART; - hci_set_drvdata(hdev, hst); - hdev->open = ti_st_open; - hdev->close = ti_st_close; - hdev->flush = NULL; - hdev->send = ti_st_send_frame; - - err = hci_register_dev(hdev); - if (err < 0) { - BT_ERR("Can't register HCI device error %d", err); - hci_free_dev(hdev); - return err; - } - - BT_DBG("HCI device registered (hdev %p)", hdev); - - dev_set_drvdata(&pdev->dev, hst); - return 0; -} - -static int bt_ti_remove(struct platform_device *pdev) -{ - struct hci_dev *hdev; - struct ti_st *hst = dev_get_drvdata(&pdev->dev); - - if (!hst) - return -EFAULT; - - BT_DBG("%s", hst->hdev->name); - - hdev = hst->hdev; - ti_st_close(hdev); - hci_unregister_dev(hdev); - - hci_free_dev(hdev); - - dev_set_drvdata(&pdev->dev, NULL); - return 0; -} - -static struct platform_driver btwilink_driver = { - .probe = bt_ti_probe, - .remove = bt_ti_remove, - .driver = { - .name = "btwilink", - }, -}; - -module_platform_driver(btwilink_driver); - -/* ------ Module Info ------ */ - -MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>"); -MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION); -MODULE_VERSION(VERSION); -MODULE_LICENSE("GPL"); diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 7646636f2d18..0f73f6a686cb 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -445,9 +445,11 @@ static int bcm_open(struct hci_uart *hu) out: if (bcm->dev) { + hci_uart_set_flow_control(hu, true); hu->init_speed = bcm->dev->init_speed; hu->oper_speed = bcm->dev->oper_speed; err = bcm_gpio_set_power(bcm->dev, true); + hci_uart_set_flow_control(hu, false); if (err) goto err_unset_hu; } diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 285706618f8a..d9a4c6c691e0 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -621,13 +621,6 @@ static int ll_setup(struct hci_uart *hu) serdev_device_set_flow_control(serdev, true); - if (hu->oper_speed) - speed = hu->oper_speed; - else if (hu->proto->oper_speed) - speed = hu->proto->oper_speed; - else - speed = 0; - do { /* Reset the Bluetooth device */ gpiod_set_value_cansleep(lldev->enable_gpio, 0); @@ -639,20 +632,6 @@ static int ll_setup(struct hci_uart *hu) return err; } - 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_le), &speed_le, - HCI_INIT_TIMEOUT); - if (!IS_ERR(skb)) { - kfree_skb(skb); - serdev_device_set_baudrate(serdev, speed); - } - } - err = download_firmware(lldev); if (!err) break; @@ -677,7 +656,25 @@ static int ll_setup(struct hci_uart *hu) } /* Operational speed if any */ + if (hu->oper_speed) + speed = hu->oper_speed; + else if (hu->proto->oper_speed) + speed = hu->proto->oper_speed; + else + 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_le), &speed_le, + HCI_INIT_TIMEOUT); + if (!IS_ERR(skb)) { + kfree_skb(skb); + serdev_device_set_baudrate(serdev, speed); + } + } return 0; } diff --git a/drivers/bluetooth/hci_nokia.c b/drivers/bluetooth/hci_nokia.c index 6463350b7977..05f7f6de6863 100644 --- a/drivers/bluetooth/hci_nokia.c +++ b/drivers/bluetooth/hci_nokia.c @@ -520,7 +520,7 @@ static int nokia_enqueue(struct hci_uart *hu, struct sk_buff *skb) err = skb_pad(skb, 1); if (err) return err; - skb_put_u8(skb, 0x00); + skb_put(skb, 1); } skb_queue_tail(&btdev->txq, skb); diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index e3164c200eac..c591a8ba9d93 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -130,8 +130,6 @@ enum qca_speed_type { */ struct qca_vreg { const char *name; - unsigned int min_uV; - unsigned int max_uV; unsigned int load_uA; }; @@ -146,8 +144,8 @@ struct qca_vreg_data { */ struct qca_power { struct device *dev; - const struct qca_vreg_data *vreg_data; struct regulator_bulk_data *vreg_bulk; + int num_vregs; bool vregs_on; }; @@ -162,7 +160,8 @@ struct qca_serdev { const char *firmware_name; }; -static int qca_power_setup(struct hci_uart *hu, bool on); +static int qca_regulator_enable(struct qca_serdev *qcadev); +static void qca_regulator_disable(struct qca_serdev *qcadev); static void qca_power_shutdown(struct hci_uart *hu); static int qca_power_off(struct hci_dev *hdev); @@ -518,7 +517,7 @@ static int qca_open(struct hci_uart *hu) } else { hu->init_speed = qcadev->init_speed; hu->oper_speed = qcadev->oper_speed; - ret = qca_power_setup(hu, true); + ret = qca_regulator_enable(qcadev); if (ret) { destroy_workqueue(qca->workqueue); kfree_skb(qca->rx_skb); @@ -1188,7 +1187,7 @@ static int qca_wcn3990_init(struct hci_uart *hu) qcadev = serdev_device_get_drvdata(hu->serdev); if (!qcadev->bt_power->vregs_on) { serdev_device_close(hu->serdev); - ret = qca_power_setup(hu, true); + ret = qca_regulator_enable(qcadev); if (ret) return ret; @@ -1332,10 +1331,10 @@ static const struct hci_uart_proto qca_proto = { static const struct qca_vreg_data qca_soc_data_wcn3990 = { .soc_type = QCA_WCN3990, .vregs = (struct qca_vreg []) { - { "vddio", 1800000, 1900000, 15000 }, - { "vddxo", 1800000, 1900000, 80000 }, - { "vddrf", 1300000, 1350000, 300000 }, - { "vddch0", 3300000, 3400000, 450000 }, + { "vddio", 15000 }, + { "vddxo", 80000 }, + { "vddrf", 300000 }, + { "vddch0", 450000 }, }, .num_vregs = 4, }; @@ -1343,19 +1342,22 @@ static const struct qca_vreg_data qca_soc_data_wcn3990 = { static const struct qca_vreg_data qca_soc_data_wcn3998 = { .soc_type = QCA_WCN3998, .vregs = (struct qca_vreg []) { - { "vddio", 1800000, 1900000, 10000 }, - { "vddxo", 1800000, 1900000, 80000 }, - { "vddrf", 1300000, 1352000, 300000 }, - { "vddch0", 3300000, 3300000, 450000 }, + { "vddio", 10000 }, + { "vddxo", 80000 }, + { "vddrf", 300000 }, + { "vddch0", 450000 }, }, .num_vregs = 4, }; static void qca_power_shutdown(struct hci_uart *hu) { + struct qca_serdev *qcadev; struct qca_data *qca = hu->priv; unsigned long flags; + qcadev = serdev_device_get_drvdata(hu->serdev); + /* From this point we go into power off state. But serial port is * still open, stop queueing the IBS data and flush all the buffered * data in skb's. @@ -1367,7 +1369,7 @@ static void qca_power_shutdown(struct hci_uart *hu) host_set_baudrate(hu, 2400); qca_send_power_pulse(hu, false); - qca_power_setup(hu, false); + qca_regulator_disable(qcadev); } static int qca_power_off(struct hci_dev *hdev) @@ -1383,97 +1385,71 @@ static int qca_power_off(struct hci_dev *hdev) return 0; } -static int qca_enable_regulator(struct qca_vreg vregs, - struct regulator *regulator) +static int qca_regulator_enable(struct qca_serdev *qcadev) { + struct qca_power *power = qcadev->bt_power; int ret; - ret = regulator_set_voltage(regulator, vregs.min_uV, - vregs.max_uV); - if (ret) - return ret; + /* Already enabled */ + if (power->vregs_on) + return 0; - if (vregs.load_uA) - ret = regulator_set_load(regulator, - vregs.load_uA); + BT_DBG("enabling %d regulators)", power->num_vregs); + ret = regulator_bulk_enable(power->num_vregs, power->vreg_bulk); if (ret) return ret; - return regulator_enable(regulator); - -} - -static void qca_disable_regulator(struct qca_vreg vregs, - struct regulator *regulator) -{ - regulator_disable(regulator); - regulator_set_voltage(regulator, 0, vregs.max_uV); - if (vregs.load_uA) - regulator_set_load(regulator, 0); + power->vregs_on = true; + return 0; } -static int qca_power_setup(struct hci_uart *hu, bool on) +static void qca_regulator_disable(struct qca_serdev *qcadev) { - struct qca_vreg *vregs; - struct regulator_bulk_data *vreg_bulk; - struct qca_serdev *qcadev; - int i, num_vregs, ret = 0; + struct qca_power *power; - qcadev = serdev_device_get_drvdata(hu->serdev); - if (!qcadev || !qcadev->bt_power || !qcadev->bt_power->vreg_data || - !qcadev->bt_power->vreg_bulk) - return -EINVAL; - - vregs = qcadev->bt_power->vreg_data->vregs; - vreg_bulk = qcadev->bt_power->vreg_bulk; - num_vregs = qcadev->bt_power->vreg_data->num_vregs; - BT_DBG("on: %d", on); - if (on && !qcadev->bt_power->vregs_on) { - for (i = 0; i < num_vregs; i++) { - ret = qca_enable_regulator(vregs[i], - vreg_bulk[i].consumer); - if (ret) - break; - } + if (!qcadev) + return; - if (ret) { - BT_ERR("failed to enable regulator:%s", vregs[i].name); - /* turn off regulators which are enabled */ - for (i = i - 1; i >= 0; i--) - qca_disable_regulator(vregs[i], - vreg_bulk[i].consumer); - } else { - qcadev->bt_power->vregs_on = true; - } - } else if (!on && qcadev->bt_power->vregs_on) { - /* turn off regulator in reverse order */ - i = qcadev->bt_power->vreg_data->num_vregs - 1; - for ( ; i >= 0; i--) - qca_disable_regulator(vregs[i], vreg_bulk[i].consumer); + power = qcadev->bt_power; - qcadev->bt_power->vregs_on = false; - } + /* Already disabled? */ + if (!power->vregs_on) + return; - return ret; + regulator_bulk_disable(power->num_vregs, power->vreg_bulk); + power->vregs_on = false; } static int qca_init_regulators(struct qca_power *qca, const struct qca_vreg *vregs, size_t num_vregs) { + struct regulator_bulk_data *bulk; + int ret; int i; - qca->vreg_bulk = devm_kcalloc(qca->dev, num_vregs, - sizeof(struct regulator_bulk_data), - GFP_KERNEL); - if (!qca->vreg_bulk) + bulk = devm_kcalloc(qca->dev, num_vregs, sizeof(*bulk), GFP_KERNEL); + if (!bulk) return -ENOMEM; for (i = 0; i < num_vregs; i++) - qca->vreg_bulk[i].supply = vregs[i].name; + bulk[i].supply = vregs[i].name; + + ret = devm_regulator_bulk_get(qca->dev, num_vregs, bulk); + if (ret < 0) + return ret; - return devm_regulator_bulk_get(qca->dev, num_vregs, qca->vreg_bulk); + for (i = 0; i < num_vregs; i++) { + ret = regulator_set_load(bulk[i].consumer, vregs[i].load_uA); + if (ret) + return ret; + } + + qca->vreg_bulk = bulk; + qca->num_vregs = num_vregs; + + return 0; } static int qca_serdev_probe(struct serdev_device *serdev) @@ -1500,7 +1476,6 @@ static int qca_serdev_probe(struct serdev_device *serdev) return -ENOMEM; qcadev->bt_power->dev = &serdev->dev; - qcadev->bt_power->vreg_data = data; err = qca_init_regulators(qcadev->bt_power, data->vregs, data->num_vregs); if (err) { |