From 2af0a709134f842b67151d6b97d512184fcc4ad6 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 17 Aug 2015 16:00:21 +0200 Subject: [PATCH 01/11] Bluetooth: hci_bcm: Use non-sleep version of gpio_set_value We should not sleep while holding a spinlock. bcm_gpio_set_power is called while holding the bcm_device_list lock. Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 322302b04710..33ec09752ea8 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -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); From d4902632ffe5d6958bd267a6712575e3a312a6e2 Mon Sep 17 00:00:00 2001 From: Shengzhen Li Date: Wed, 19 Aug 2015 03:12:19 -0700 Subject: [PATCH 02/11] Bluetooth: btmrvl: change device pointer passed to dev_coredumpv This change ensures we will get driver name as 'btmrvl_sdio' in udev event. Signed-off-by: Shengzhen Li Signed-off-by: Amitkumar Karwar Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_sdio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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"); } From df945360ce07ca592464e44fdd2ce61ee1536e1e Mon Sep 17 00:00:00 2001 From: Nicholas Krause Date: Tue, 18 Aug 2015 21:23:01 -0400 Subject: [PATCH 03/11] Bluetooth: Make the function sco_conn_del have a return type of void This makes the function sco_conn_del have a return type of void now due to this function always running successfully and thus never needing to signal its caller when a non recoverable internal failure occurs by returning a error code to its respective caller. Signed-off-by: Nicholas Krause Signed-off-by: Marcel Holtmann --- net/bluetooth/sco.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 688a040c5626..f315c8d0e43b 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -154,13 +154,13 @@ static void sco_chan_del(struct sock *sk, int err) sock_set_flag(sk, SOCK_ZAPPED); } -static int sco_conn_del(struct hci_conn *hcon, int err) +static void sco_conn_del(struct hci_conn *hcon, int err) { struct sco_conn *conn = hcon->sco_data; struct sock *sk; if (!conn) - return 0; + return; BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); @@ -179,7 +179,6 @@ static int sco_conn_del(struct hci_conn *hcon, int err) hcon->sco_data = NULL; kfree(conn); - return 0; } static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) From 4e1795de10903ae561872c54a72fa1bcf78f49cd Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Thu, 20 Aug 2015 12:09:47 +0200 Subject: [PATCH 04/11] nl802154: stricter input checking for boolean inputs So far we handled boolean input by forcing them with !! and assigning them into a bool. This allowed userspace to send values > 1 which were used as 1. We should be stricter here and return -EINVAL for all but 0 or 1. Signed-off-by: Stefan Schmidt Acked-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/ieee802154/nl802154.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 1b00a14850cb..3f89c0abdab1 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1034,7 +1034,7 @@ static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info) struct cfg802154_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; struct wpan_dev *wpan_dev = dev->ieee802154_ptr; - bool mode; + int mode; if (netif_running(dev)) return -EBUSY; @@ -1042,7 +1042,11 @@ static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[NL802154_ATTR_LBT_MODE]) return -EINVAL; - mode = !!nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]); + mode = nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]); + + if (mode != 0 && mode != 1) + return -EINVAL; + if (!wpan_phy_supported_bool(mode, rdev->wpan_phy.supported.lbt)) return -EINVAL; @@ -1055,7 +1059,7 @@ nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info) struct cfg802154_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; struct wpan_dev *wpan_dev = dev->ieee802154_ptr; - bool ackreq; + int ackreq; if (netif_running(dev)) return -EBUSY; @@ -1063,7 +1067,11 @@ nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]) return -EINVAL; - ackreq = !!nla_get_u8(info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]); + ackreq = nla_get_u8(info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]); + + if (ackreq != 0 && ackreq != 1) + return -EINVAL; + return rdev_set_ackreq_default(rdev, wpan_dev, ackreq); } From e54991677e1c8060ba5642472cbd9a0954298d01 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 24 Aug 2015 18:57:57 +0200 Subject: [PATCH 05/11] Bluetooth: hci_uart: Fix zero len data packet reception issue Packets with a variable length value equal to zero were not received. Since no more data expected (and input buffer entirely consumed), we need to complete/forward the packet immediately instead of waiting for more data. Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_h4.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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); From ff2895592f0fccc59332d5c7d4917ccbecd7468e Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Tue, 25 Aug 2015 17:55:44 +0200 Subject: [PATCH 06/11] Bluetooth: hci_intel: Add Intel baudrate configuration support Implement the set_baudrate callback for hci_intel. - Controller requires a read Intel version command before updating its baudrate. - The operation consists in an async cmd since the controller does not respond at the same speed. - Wait 100ms to let the controller change its baudrate. - Clear RTS until we change our own UART speed Manage speed change in the setup function, we need to restore the oper speed once chip has booted on patched firmware. Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_intel.c | 119 ++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index 21dfa89751df..da3192aee5e1 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -45,6 +45,38 @@ struct intel_data { 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_open(struct hci_uart *hu) { struct intel_data *intel; @@ -111,6 +143,56 @@ 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; + + 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 +208,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 +218,19 @@ 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; + set_bit(STATE_BOOTLOADER, &intel->flags); /* Read the Intel version information to determine if the device @@ -416,6 +513,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); @@ -456,6 +560,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; @@ -572,10 +689,12 @@ 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, From 5075edae086ff1c09e66699b7a27e1589ca75a3f Mon Sep 17 00:00:00 2001 From: Minjune Kim Date: Thu, 27 Aug 2015 13:21:52 +0900 Subject: [PATCH 07/11] Bluetooth: btusb: Correct typos based on checkpatch.pl Signed-off-by: Minjune Kim Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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. From 0ed97e829458496cc41ff8c39eb330d5a2247191 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 27 Aug 2015 08:57:39 +0200 Subject: [PATCH 08/11] Bluetooth: btintel: Add MODULE_FIRMWARE entries for iBT 3.0 controllers The iBT 3.0 controllers need intel/ibt-11-5.sfi and intel/ibt-11-5.ddc firmware files from linux-firmware repository. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btintel.c | 2 ++ 1 file changed, 2 insertions(+) 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 "); 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"); From 1ab1f239bf17e91b183a0f18fbb22722ff16d164 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Thu, 27 Aug 2015 07:21:51 +0200 Subject: [PATCH 09/11] Bluetooth: hci_intel: Add support for platform driver A platform device can be used to provide some specific resources in order to manage the controller. In this first patch we retrieve the reset gpio which is used to power on/off the controller. The main issue is to match the current tty with the correct pdev. In case of ACPI, we can easily find the right tty/pdev pair because they are both child of the same UART port. If controller is powered-on from the driver, we need to wait for a HCI boot event before being able to send any command. Signed-off-by: Loic Poulain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_intel.c | 202 +++++++++++++++++++++++++++++++--- 1 file changed, 189 insertions(+), 13 deletions(-) diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index da3192aee5e1..cf07d1121956 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -25,7 +25,12 @@ #include #include #include +#include #include +#include +#include +#include +#include #include #include @@ -39,6 +44,15 @@ #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; @@ -77,6 +91,61 @@ static u8 intel_convert_speed(unsigned int speed) } } +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; @@ -90,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; } @@ -99,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); @@ -149,6 +224,18 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed) 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); @@ -231,6 +318,15 @@ static int intel_setup(struct hci_uart *hu) 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 @@ -540,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)); + err = intel_wait_booting(hu); + if (err) + return err; - if (err == 1) { - BT_ERR("%s: Device boot interrupted", hdev->name); - return -EINTR; - } - - 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); @@ -584,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; @@ -700,12 +789,99 @@ static const struct hci_uart_proto intel_proto = { .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); } From 618353b1f34947b3a399d6f51934f10df40e42ff Mon Sep 17 00:00:00 2001 From: Kuba Pawlak Date: Fri, 28 Aug 2015 13:05:22 +0100 Subject: [PATCH 10/11] Bluetooth: Fix SCO link type handling on connection complete Synchronous connections are initially created with type eSCO. Link manager may reject proposed link parameters, which triggers connection setup retry with a different set. Link type embedded in responses should be disregarded until Synchronous Connect Complete returns Success (0x00). Current code updates link type every time which creates an issue when link type changes to SCO and back to eSCO on further attepts. Issue happens with BlackBerry 9100 and 9700 with Intel WilkinsPeak on third connection setup attept 2015-05-18 01:27:57.332242 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x0380 2015-05-18 01:27:57.333604 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 2015-05-18 01:27:57.334614 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x1a handle 0 bdaddr 30:7C:30:B3:A8:86 type SCO Error: Unsupported Remote Feature / Unsupported LMP Feature 2015-05-18 01:27:57.334895 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x0380 2015-05-18 01:27:57.335601 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 2015-05-18 01:27:57.336610 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x1a handle 0 bdaddr 30:7C:30:B3:A8:86 type SCO Error: Unsupported Remote Feature / Unsupported LMP Feature 2015-05-18 01:27:57.336685 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x03c8 2015-05-18 01:27:57.337603 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 2015-05-18 01:27:57.342608 > HCI Event: Max Slots Change (0x1b) plen 3 handle 256 slots 1 2015-05-18 01:27:57.377631 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x00 handle 257 bdaddr 30:7C:30:B3:A8:86 type eSCO Air mode: CVSD Signed-off-by: Kuba Pawlak Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 7ba35a9ba6b7..186041866315 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3726,17 +3726,25 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, if (ev->link_type == ESCO_LINK) goto unlock; + /* When the link type in the event indicates SCO connection + * and lookup of the connection object fails, then check + * if an eSCO connection object exists. + * + * The core limits the synchronous connections to either + * SCO or eSCO. The eSCO connection is preferred and tried + * to be setup first and until successfully established, + * the link type will be hinted as eSCO. + */ conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); if (!conn) goto unlock; - - conn->type = SCO_LINK; } switch (ev->status) { case 0x00: conn->handle = __le16_to_cpu(ev->handle); conn->state = BT_CONNECTED; + conn->type = ev->link_type; hci_debugfs_create_conn(conn); hci_conn_add_sysfs(conn); From 917522aae169ad02010dcee6ae42c16155bcd285 Mon Sep 17 00:00:00 2001 From: Frederic Danis Date: Fri, 28 Aug 2015 15:44:00 +0200 Subject: [PATCH 11/11] Bluetooth: hci_bcm: Fix crash on suspend If bcm_suspend is called whithout device opened there is a crash as it tries to use bdev->hu which is NULL. Rename bcm_device_list_lock to bcm_device_lock as it does not only apply to bcm_device_list. Signed-off-by: Frederic Danis Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 33ec09752ea8..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; @@ -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));