diff options
author | David S. Miller <davem@davemloft.net> | 2015-08-29 13:15:03 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-29 13:15:03 -0700 |
commit | f5004a14fac0a71656340544c48a14c80a3afddf (patch) | |
tree | c92b514ef46049e3050ed95e3065ae2190d3d3fc /drivers | |
parent | 6d74232410a9f3ed0e1fc0f5e538598f21e93982 (diff) | |
parent | 917522aae169ad02010dcee6ae42c16155bcd285 (diff) |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says:
====================
pull request: bluetooth-next 2015-08-28
One more bunch of Bluetooth patches for 4.3:
- Crash fix for hci_bcm driver
- Enhancements to hci_intel driver (e.g. baudrate configuration)
- Fix for SCO link type after multiple connect attempts
- Cleanups & minor fixes in a few other places
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/btintel.c | 2 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 3 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 4 | ||||
-rw-r--r-- | drivers/bluetooth/hci_bcm.c | 40 | ||||
-rw-r--r-- | drivers/bluetooth/hci_h4.c | 9 | ||||
-rw-r--r-- | drivers/bluetooth/hci_intel.c | 321 |
6 files changed, 348 insertions, 31 deletions
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 1ce4ac16c7fa..048423fd83bf 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -173,3 +173,5 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("intel/ibt-11-5.sfi"); +MODULE_FIRMWARE("intel/ibt-11-5.ddc"); diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 7c097629e593..b9978a7ba0cc 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -1376,8 +1376,7 @@ done: /* fw_dump_data will be free in device coredump release function after 5 min*/ - dev_coredumpv(&priv->btmrvl_dev.hcidev->dev, fw_dump_data, - fw_dump_len, GFP_KERNEL); + dev_coredumpv(&card->func->dev, fw_dump_data, fw_dump_len, GFP_KERNEL); BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump end"); } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f759dea7d3ba..b6aceaf82aa8 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1581,7 +1581,7 @@ static int btusb_setup_intel(struct hci_dev *hdev) /* fw_patch_num indicates the version of patch the device currently * have. If there is no patch data in the device, it is always 0x00. - * So, if it is other than 0x00, no need to patch the deivce again. + * So, if it is other than 0x00, no need to patch the device again. */ if (ver->fw_patch_num) { BT_INFO("%s: Intel device is already patched. patch num: %02x", @@ -2100,7 +2100,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) frag_len += sizeof(*cmd) + cmd->plen; - /* The paramter length of the secure send command requires + /* 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. diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 322302b04710..835bfab88ef5 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -66,7 +66,7 @@ struct bcm_data { }; /* List of BCM BT UART devices */ -static DEFINE_SPINLOCK(bcm_device_list_lock); +static DEFINE_SPINLOCK(bcm_device_lock); static LIST_HEAD(bcm_device_list); static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed) @@ -118,7 +118,7 @@ static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed) return 0; } -/* bcm_device_exists should be protected by bcm_device_list_lock */ +/* bcm_device_exists should be protected by bcm_device_lock */ static bool bcm_device_exists(struct bcm_device *device) { struct list_head *p; @@ -138,8 +138,8 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered) if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled) clk_enable(dev->clk); - gpiod_set_value_cansleep(dev->shutdown, powered); - gpiod_set_value_cansleep(dev->device_wakeup, powered); + gpiod_set_value(dev->shutdown, powered); + gpiod_set_value(dev->device_wakeup, powered); if (!powered && !IS_ERR(dev->clk) && dev->clk_enabled) clk_disable(dev->clk); @@ -164,7 +164,7 @@ static int bcm_open(struct hci_uart *hu) hu->priv = bcm; - spin_lock(&bcm_device_list_lock); + spin_lock(&bcm_device_lock); list_for_each(p, &bcm_device_list) { struct bcm_device *dev = list_entry(p, struct bcm_device, list); @@ -185,7 +185,7 @@ static int bcm_open(struct hci_uart *hu) if (bcm->dev) bcm_gpio_set_power(bcm->dev, true); - spin_unlock(&bcm_device_list_lock); + spin_unlock(&bcm_device_lock); return 0; } @@ -197,14 +197,14 @@ static int bcm_close(struct hci_uart *hu) BT_DBG("hu %p", hu); /* Protect bcm->dev against removal of the device or driver */ - spin_lock(&bcm_device_list_lock); + spin_lock(&bcm_device_lock); if (bcm_device_exists(bcm->dev)) { bcm_gpio_set_power(bcm->dev, false); #ifdef CONFIG_PM_SLEEP bcm->dev->hu = NULL; #endif } - spin_unlock(&bcm_device_list_lock); + spin_unlock(&bcm_device_lock); skb_queue_purge(&bcm->txq); kfree_skb(bcm->rx_skb); @@ -338,6 +338,11 @@ static int bcm_suspend(struct device *dev) BT_DBG("suspend (%p): is_suspended %d", bdev, bdev->is_suspended); + spin_lock(&bcm_device_lock); + + if (!bdev->hu) + goto unlock; + if (!bdev->is_suspended) { hci_uart_set_flow_control(bdev->hu, true); @@ -352,6 +357,9 @@ static int bcm_suspend(struct device *dev) mdelay(15); } +unlock: + spin_unlock(&bcm_device_lock); + return 0; } @@ -362,6 +370,11 @@ static int bcm_resume(struct device *dev) BT_DBG("resume (%p): is_suspended %d", bdev, bdev->is_suspended); + spin_lock(&bcm_device_lock); + + if (!bdev->hu) + goto unlock; + if (bdev->device_wakeup) { gpiod_set_value(bdev->device_wakeup, true); BT_DBG("resume, delaying 15 ms"); @@ -375,6 +388,9 @@ static int bcm_resume(struct device *dev) hci_uart_set_flow_control(bdev->hu, false); } +unlock: + spin_unlock(&bcm_device_lock); + return 0; } #endif @@ -488,9 +504,9 @@ static int bcm_probe(struct platform_device *pdev) dev_info(&pdev->dev, "%s device registered.\n", dev->name); /* Place this instance on the device list */ - spin_lock(&bcm_device_list_lock); + spin_lock(&bcm_device_lock); list_add_tail(&dev->list, &bcm_device_list); - spin_unlock(&bcm_device_list_lock); + spin_unlock(&bcm_device_lock); bcm_gpio_set_power(dev, false); @@ -501,9 +517,9 @@ static int bcm_remove(struct platform_device *pdev) { struct bcm_device *dev = platform_get_drvdata(pdev); - spin_lock(&bcm_device_list_lock); + spin_lock(&bcm_device_lock); list_del(&dev->list); - spin_unlock(&bcm_device_list_lock); + spin_unlock(&bcm_device_lock); acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev)); diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index 57faddc53645..eec3f28e4bb9 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -223,8 +223,7 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb, switch ((&pkts[i])->lsize) { case 0: /* No variable data length */ - (&pkts[i])->recv(hdev, skb); - skb = NULL; + dlen = 0; break; case 1: /* Single octet variable length */ @@ -252,6 +251,12 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb, kfree_skb(skb); return ERR_PTR(-EILSEQ); } + + if (!dlen) { + /* No more data, complete frame */ + (&pkts[i])->recv(hdev, skb); + skb = NULL; + } } else { /* Complete frame */ (&pkts[i])->recv(hdev, skb); diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index 21dfa89751df..cf07d1121956 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -25,7 +25,12 @@ #include <linux/errno.h> #include <linux/skbuff.h> #include <linux/firmware.h> +#include <linux/module.h> #include <linux/wait.h> +#include <linux/tty.h> +#include <linux/platform_device.h> +#include <linux/gpio/consumer.h> +#include <linux/acpi.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -39,12 +44,108 @@ #define STATE_FIRMWARE_FAILED 3 #define STATE_BOOTING 4 +struct intel_device { + struct list_head list; + struct platform_device *pdev; + struct gpio_desc *reset; +}; + +static LIST_HEAD(intel_device_list); +static DEFINE_SPINLOCK(intel_device_list_lock); + struct intel_data { struct sk_buff *rx_skb; struct sk_buff_head txq; unsigned long flags; }; +static u8 intel_convert_speed(unsigned int speed) +{ + switch (speed) { + case 9600: + return 0x00; + case 19200: + return 0x01; + case 38400: + return 0x02; + case 57600: + return 0x03; + case 115200: + return 0x04; + case 230400: + return 0x05; + case 460800: + return 0x06; + case 921600: + return 0x07; + case 1843200: + return 0x08; + case 3250000: + return 0x09; + case 2000000: + return 0x0a; + case 3000000: + return 0x0b; + default: + return 0xff; + } +} + +static int intel_wait_booting(struct hci_uart *hu) +{ + struct intel_data *intel = hu->priv; + int err; + + err = wait_on_bit_timeout(&intel->flags, STATE_BOOTING, + TASK_INTERRUPTIBLE, + msecs_to_jiffies(1000)); + + if (err == 1) { + BT_ERR("%s: Device boot interrupted", hu->hdev->name); + return -EINTR; + } + + if (err) { + BT_ERR("%s: Device boot timeout", hu->hdev->name); + return -ETIMEDOUT; + } + + return err; +} + +static int intel_set_power(struct hci_uart *hu, bool powered) +{ + struct list_head *p; + int err = -ENODEV; + + spin_lock(&intel_device_list_lock); + + list_for_each(p, &intel_device_list) { + struct intel_device *idev = list_entry(p, struct intel_device, + list); + + /* tty device and pdev device should share the same parent + * which is the UART port. + */ + if (hu->tty->dev->parent != idev->pdev->dev.parent) + continue; + + if (!idev->reset) { + err = -ENOTSUPP; + break; + } + + BT_INFO("hu %p, Switching compatible pm device (%s) to %u", + hu, dev_name(&idev->pdev->dev), powered); + + gpiod_set_value(idev->reset, powered); + } + + spin_unlock(&intel_device_list_lock); + + return err; +} + static int intel_open(struct hci_uart *hu) { struct intel_data *intel; @@ -58,6 +159,10 @@ static int intel_open(struct hci_uart *hu) skb_queue_head_init(&intel->txq); hu->priv = intel; + + if (!intel_set_power(hu, true)) + set_bit(STATE_BOOTING, &intel->flags); + return 0; } @@ -67,6 +172,8 @@ static int intel_close(struct hci_uart *hu) BT_DBG("hu %p", hu); + intel_set_power(hu, false); + skb_queue_purge(&intel->txq); kfree_skb(intel->rx_skb); kfree(intel); @@ -111,6 +218,68 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode) return hci_recv_frame(hdev, skb); } +static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed) +{ + struct intel_data *intel = hu->priv; + struct hci_dev *hdev = hu->hdev; + u8 speed_cmd[] = { 0x06, 0xfc, 0x01, 0x00 }; + struct sk_buff *skb; + int err; + + /* This can be the first command sent to the chip, check + * that the controller is ready. + */ + err = intel_wait_booting(hu); + + clear_bit(STATE_BOOTING, &intel->flags); + + /* In case of timeout, try to continue anyway */ + if (err && err != ETIMEDOUT) + return err; + + BT_INFO("%s: Change controller speed to %d", hdev->name, speed); + + speed_cmd[3] = intel_convert_speed(speed); + if (speed_cmd[3] == 0xff) { + BT_ERR("%s: Unsupported speed", hdev->name); + return -EINVAL; + } + + /* Device will not accept speed change if Intel version has not been + * previously requested. + */ + skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + BT_ERR("%s: Reading Intel version information failed (%ld)", + hdev->name, PTR_ERR(skb)); + return PTR_ERR(skb); + } + kfree_skb(skb); + + skb = bt_skb_alloc(sizeof(speed_cmd), GFP_KERNEL); + if (!skb) { + BT_ERR("%s: Failed to allocate memory for baudrate packet", + hdev->name); + return -ENOMEM; + } + + memcpy(skb_put(skb, sizeof(speed_cmd)), speed_cmd, sizeof(speed_cmd)); + bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; + + hci_uart_set_flow_control(hu, true); + + skb_queue_tail(&intel->txq, skb); + hci_uart_tx_wakeup(hu); + + /* wait 100ms to change baudrate on controller side */ + msleep(100); + + hci_uart_set_baudrate(hu, speed); + hci_uart_set_flow_control(hu, false); + + return 0; +} + static int intel_setup(struct hci_uart *hu) { static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01, @@ -126,6 +295,8 @@ static int intel_setup(struct hci_uart *hu) u32 frag_len; ktime_t calltime, delta, rettime; unsigned long long duration; + unsigned int init_speed, oper_speed; + int speed_change = 0; int err; BT_DBG("%s", hdev->name); @@ -134,6 +305,28 @@ static int intel_setup(struct hci_uart *hu) calltime = ktime_get(); + if (hu->init_speed) + init_speed = hu->init_speed; + else + init_speed = hu->proto->init_speed; + + if (hu->oper_speed) + oper_speed = hu->oper_speed; + else + oper_speed = hu->proto->oper_speed; + + if (oper_speed && init_speed && oper_speed != init_speed) + speed_change = 1; + + /* Check that the controller is ready */ + err = intel_wait_booting(hu); + + clear_bit(STATE_BOOTING, &intel->flags); + + /* In case of timeout, try to continue anyway */ + if (err && err != ETIMEDOUT) + return err; + set_bit(STATE_BOOTLOADER, &intel->flags); /* Read the Intel version information to determine if the device @@ -416,6 +609,13 @@ done: if (err < 0) return err; + /* We need to restore the default speed before Intel reset */ + if (speed_change) { + err = intel_set_baudrate(hu, init_speed); + if (err) + return err; + } + calltime = ktime_get(); set_bit(STATE_BOOTING, &intel->flags); @@ -436,19 +636,11 @@ done: */ BT_INFO("%s: Waiting for device to boot", hdev->name); - err = wait_on_bit_timeout(&intel->flags, STATE_BOOTING, - TASK_INTERRUPTIBLE, - msecs_to_jiffies(1000)); - - if (err == 1) { - BT_ERR("%s: Device boot interrupted", hdev->name); - return -EINTR; - } + err = intel_wait_booting(hu); + if (err) + return err; - if (err) { - BT_ERR("%s: Device boot timeout", hdev->name); - return -ETIMEDOUT; - } + clear_bit(STATE_BOOTING, &intel->flags); rettime = ktime_get(); delta = ktime_sub(rettime, calltime); @@ -456,6 +648,19 @@ done: BT_INFO("%s: Device booted in %llu usecs", hdev->name, duration); + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) + return PTR_ERR(skb); + kfree_skb(skb); + + if (speed_change) { + err = intel_set_baudrate(hu, oper_speed); + if (err) + return err; + } + + BT_INFO("%s: Setup complete", hdev->name); + clear_bit(STATE_BOOTLOADER, &intel->flags); return 0; @@ -467,7 +672,8 @@ static int intel_recv_event(struct hci_dev *hdev, struct sk_buff *skb) struct intel_data *intel = hu->priv; struct hci_event_hdr *hdr; - if (!test_bit(STATE_BOOTLOADER, &intel->flags)) + if (!test_bit(STATE_BOOTLOADER, &intel->flags) && + !test_bit(STATE_BOOTING, &intel->flags)) goto recv; hdr = (void *)skb->data; @@ -572,21 +778,110 @@ static const struct hci_uart_proto intel_proto = { .id = HCI_UART_INTEL, .name = "Intel", .init_speed = 115200, + .oper_speed = 3000000, .open = intel_open, .close = intel_close, .flush = intel_flush, .setup = intel_setup, + .set_baudrate = intel_set_baudrate, .recv = intel_recv, .enqueue = intel_enqueue, .dequeue = intel_dequeue, }; +#ifdef CONFIG_ACPI +static const struct acpi_device_id intel_acpi_match[] = { + { "INT33E1", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, intel_acpi_match); + +static int intel_acpi_probe(struct intel_device *idev) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(intel_acpi_match, &idev->pdev->dev); + if (!id) + return -ENODEV; + + return 0; +} +#else +static int intel_acpi_probe(struct intel_device *idev) +{ + return -ENODEV; +} +#endif + +static int intel_probe(struct platform_device *pdev) +{ + struct intel_device *idev; + + idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL); + if (!idev) + return -ENOMEM; + + idev->pdev = pdev; + + if (ACPI_HANDLE(&pdev->dev)) { + int err = intel_acpi_probe(idev); + if (err) + return err; + } else { + return -ENODEV; + } + + idev->reset = devm_gpiod_get_optional(&pdev->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(idev->reset)) { + dev_err(&pdev->dev, "Unable to retrieve gpio\n"); + return PTR_ERR(idev->reset); + } + + platform_set_drvdata(pdev, idev); + + /* Place this instance on the device list */ + spin_lock(&intel_device_list_lock); + list_add_tail(&idev->list, &intel_device_list); + spin_unlock(&intel_device_list_lock); + + dev_info(&pdev->dev, "registered.\n"); + + return 0; +} + +static int intel_remove(struct platform_device *pdev) +{ + struct intel_device *idev = platform_get_drvdata(pdev); + + spin_lock(&intel_device_list_lock); + list_del(&idev->list); + spin_unlock(&intel_device_list_lock); + + dev_info(&pdev->dev, "unregistered.\n"); + + return 0; +} + +static struct platform_driver intel_driver = { + .probe = intel_probe, + .remove = intel_remove, + .driver = { + .name = "hci_intel", + .acpi_match_table = ACPI_PTR(intel_acpi_match), + }, +}; + int __init intel_init(void) { + platform_driver_register(&intel_driver); + return hci_uart_register_proto(&intel_proto); } int __exit intel_deinit(void) { + platform_driver_unregister(&intel_driver); + return hci_uart_unregister_proto(&intel_proto); } |