diff --git a/Documentation/devicetree/bindings/net/ti,wilink-st.txt b/Documentation/devicetree/bindings/net/ti,wilink-st.txt index cbad73a84ac43250865fd6e47dc47a388e082342..1649c1f66b079a74c5b218caf6196692c2104b14 100644 --- a/Documentation/devicetree/bindings/net/ti,wilink-st.txt +++ b/Documentation/devicetree/bindings/net/ti,wilink-st.txt @@ -14,6 +14,12 @@ Required properties: - compatible: should be one of the following: "ti,wl1271-st" "ti,wl1273-st" + "ti,wl1281-st" + "ti,wl1283-st" + "ti,wl1285-st" + "ti,wl1801-st" + "ti,wl1805-st" + "ti,wl1807-st" "ti,wl1831-st" "ti,wl1835-st" "ti,wl1837-st" @@ -22,6 +28,10 @@ Optional properties: - enable-gpios : GPIO signal controlling enabling of BT. Active high. - vio-supply : Vio input supply (1.8V) - vbat-supply : Vbat input supply (2.9-4.8V) + - clocks : Must contain an entry, for each entry in clock-names. + See ../clocks/clock-bindings.txt for details. + - clock-names : Must include the following entry: + "ext_clock" (External clock provided to the TI combo chip). Example: @@ -31,5 +41,7 @@ Example: bluetooth { compatible = "ti,wl1835-st"; enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; + clocks = <&clk32k_wl18xx>; + clock-names = "ext_clock"; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index 49f6a6242cf9fa3d9cd64d4ef22f8abf74e8e885..5cdfe732df38e4b9b6226c2f6b5174c5e6539b71 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -141,6 +141,8 @@ bluetooth { compatible = "ti,wl1835-st"; enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; + clocks = <&pmic>; + clock-names = "ext_clock"; }; }; diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index ba3dd2eafc0954a344337fe64013d986cfad15b3..24f8c4e93f4eb7ce34e5280781dab25ea5ffaf40 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -246,6 +246,27 @@ static struct sk_buff *btbcm_read_verbose_config(struct hci_dev *hdev) return skb; } +static struct sk_buff *btbcm_read_controller_features(struct hci_dev *hdev) +{ + struct sk_buff *skb; + + skb = __hci_cmd_sync(hdev, 0xfc6e, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + BT_ERR("%s: BCM: Read controller features failed (%ld)", + hdev->name, PTR_ERR(skb)); + return skb; + } + + if (skb->len != 9) { + BT_ERR("%s: BCM: Controller features length mismatch", + hdev->name); + kfree_skb(skb); + return ERR_PTR(-EIO); + } + + return skb; +} + static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev) { struct sk_buff *skb; @@ -417,6 +438,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev) BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]); kfree_skb(skb); + /* Read Controller Features */ + skb = btbcm_read_controller_features(hdev); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]); + kfree_skb(skb); + /* Read Local Name */ skb = btbcm_read_local_name(hdev); if (IS_ERR(skb)) @@ -540,6 +569,13 @@ int btbcm_setup_apple(struct hci_dev *hdev) kfree_skb(skb); } + /* Read Controller Features */ + skb = btbcm_read_controller_features(hdev); + if (!IS_ERR(skb)) { + BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]); + kfree_skb(skb); + } + /* Read Local Name */ skb = btbcm_read_local_name(hdev); if (!IS_ERR(skb)) { diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 278e811861503681ea25f95cf8fd9d2316f6b063..bfd5f4bdec806c2c093793ccd268045279cb3fe1 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -266,6 +266,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME }, + { USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME }, /* Broadcom BCM2035 */ diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index f87bfdfee4ff5adab798167929650f14f978931a..e2096c7803b36c9d6f43fd32c3829c3414566659 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -762,8 +762,7 @@ static int bcm_acpi_probe(struct bcm_device *dev) if (id) gpio_mapping = (const struct acpi_gpio_mapping *) id->driver_data; - ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev), - gpio_mapping); + ret = devm_acpi_dev_add_driver_gpios(&pdev->dev, gpio_mapping); if (ret) return ret; @@ -834,8 +833,6 @@ static int bcm_remove(struct platform_device *pdev) list_del(&dev->list); mutex_unlock(&bcm_device_lock); - acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev)); - dev_info(&pdev->dev, "%s device unregistered.\n", dev->name); return 0; diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index fa5099986f1b3ca50c14745990a0fe682963b737..851bee82df2ac3a3d9a169596234a709d072beb0 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -1205,9 +1205,19 @@ static const struct dev_pm_ops intel_pm_ops = { SET_RUNTIME_PM_OPS(intel_suspend_device, intel_resume_device, NULL) }; +static const struct acpi_gpio_params reset_gpios = { 0, 0, false }; +static const struct acpi_gpio_params host_wake_gpios = { 1, 0, false }; + +static const struct acpi_gpio_mapping acpi_hci_intel_gpios[] = { + { "reset-gpios", &reset_gpios, 1 }, + { "host-wake-gpios", &host_wake_gpios, 1 }, + { }, +}; + static int intel_probe(struct platform_device *pdev) { struct intel_device *idev; + int ret; idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL); if (!idev) @@ -1217,6 +1227,10 @@ static int intel_probe(struct platform_device *pdev) idev->pdev = pdev; + ret = devm_acpi_dev_add_driver_gpios(&pdev->dev, acpi_hci_intel_gpios); + if (ret) + dev_dbg(&pdev->dev, "Unable to add GPIO mapping table\n"); + idev->reset = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(idev->reset)) { dev_err(&pdev->dev, "Unable to retrieve gpio\n"); diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 200288c87fc431ae623c116f14115e1d607733f4..2b16d48d82ee94ed7cf43610b2f3024d43888fa0 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -84,6 +85,7 @@ struct ll_device { struct hci_uart hu; struct serdev_device *serdev; struct gpio_desc *enable_gpio; + struct clk *ext_clk; }; struct ll_struct { @@ -146,8 +148,12 @@ static int ll_open(struct hci_uart *hu) hu->priv = ll; - if (hu->serdev) + if (hu->serdev) { + struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev); serdev_device_open(hu->serdev); + if (!IS_ERR(lldev->ext_clk)) + clk_prepare_enable(lldev->ext_clk); + } return 0; } @@ -181,6 +187,8 @@ static int ll_close(struct hci_uart *hu) struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev); gpiod_set_value_cansleep(lldev->enable_gpio, 0); + clk_disable_unprepare(lldev->ext_clk); + serdev_device_close(hu->serdev); } @@ -721,6 +729,10 @@ static int hci_ti_probe(struct serdev_device *serdev) if (IS_ERR(lldev->enable_gpio)) return PTR_ERR(lldev->enable_gpio); + lldev->ext_clk = devm_clk_get(&serdev->dev, "ext_clock"); + if (IS_ERR(lldev->ext_clk) && PTR_ERR(lldev->ext_clk) != -ENOENT) + return PTR_ERR(lldev->ext_clk); + of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed); hci_uart_set_speeds(hu, 115200, max_speed); @@ -741,6 +753,14 @@ static void hci_ti_remove(struct serdev_device *serdev) } static const struct of_device_id hci_ti_of_match[] = { + { .compatible = "ti,wl1271-st" }, + { .compatible = "ti,wl1273-st" }, + { .compatible = "ti,wl1281-st" }, + { .compatible = "ti,wl1283-st" }, + { .compatible = "ti,wl1285-st" }, + { .compatible = "ti,wl1801-st" }, + { .compatible = "ti,wl1805-st" }, + { .compatible = "ti,wl1807-st" }, { .compatible = "ti,wl1831-st" }, { .compatible = "ti,wl1835-st" }, { .compatible = "ti,wl1837-st" }, diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 7655b4005dfbfaecfae8c5d6d0956cb117ee7262..93806b959039c7185ad29123c3ba0ad281d04be7 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -548,6 +548,7 @@ static void hci_set_event_mask_page_2(struct hci_request *req) { struct hci_dev *hdev = req->hdev; u8 events[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + bool changed = false; /* If Connectionless Slave Broadcast master role is supported * enable all necessary events for it. @@ -557,6 +558,7 @@ static void hci_set_event_mask_page_2(struct hci_request *req) events[1] |= 0x80; /* Synchronization Train Complete */ events[2] |= 0x10; /* Slave Page Response Timeout */ events[2] |= 0x20; /* CSB Channel Map Change */ + changed = true; } /* If Connectionless Slave Broadcast slave role is supported @@ -567,13 +569,24 @@ static void hci_set_event_mask_page_2(struct hci_request *req) events[2] |= 0x02; /* CSB Receive */ events[2] |= 0x04; /* CSB Timeout */ events[2] |= 0x08; /* Truncated Page Complete */ + changed = true; } /* Enable Authenticated Payload Timeout Expired event if supported */ - if (lmp_ping_capable(hdev) || hdev->le_features[0] & HCI_LE_PING) + if (lmp_ping_capable(hdev) || hdev->le_features[0] & HCI_LE_PING) { events[2] |= 0x80; + changed = true; + } - hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events); + /* Some Broadcom based controllers indicate support for Set Event + * Mask Page 2 command, but then actually do not support it. Since + * the default value is all bits set to zero, the command is only + * required if the event mask has to be changed. In case no change + * to the event mask is needed, skip this command. + */ + if (changed) + hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, + sizeof(events), events); } static int hci_init3_req(struct hci_request *req, unsigned long opt) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 14585edc94397c6f42e5f5fcee2f7f471019819e..a0ef89772c366c53097c3a18760e48d302d00656 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -523,7 +524,7 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16], if (err) return false; - return !memcmp(bdaddr->b, hash, 3); + return !crypto_memneq(bdaddr->b, hash, 3); } int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa) @@ -579,7 +580,7 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]) /* This is unlikely, but we need to check that * we didn't accidentially generate a debug key. */ - if (memcmp(smp->local_sk, debug_sk, 32)) + if (crypto_memneq(smp->local_sk, debug_sk, 32)) break; } smp->debug_key = false; @@ -993,7 +994,7 @@ static u8 smp_random(struct smp_chan *smp) if (ret) return SMP_UNSPECIFIED; - if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { + if (crypto_memneq(smp->pcnf, confirm, sizeof(smp->pcnf))) { BT_ERR("Pairing failed (confirmation values mismatch)"); return SMP_CONFIRM_FAILED; } @@ -1512,7 +1513,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) smp->rrnd, r, cfm)) return SMP_UNSPECIFIED; - if (memcmp(smp->pcnf, cfm, 16)) + if (crypto_memneq(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED; smp->passkey_round++; @@ -1908,7 +1909,7 @@ static u8 sc_send_public_key(struct smp_chan *smp) /* This is unlikely, but we need to check that * we didn't accidentially generate a debug key. */ - if (memcmp(smp->local_sk, debug_sk, 32)) + if (crypto_memneq(smp->local_sk, debug_sk, 32)) break; } } @@ -2176,7 +2177,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (memcmp(smp->pcnf, cfm, 16)) + if (crypto_memneq(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED; } else { smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), @@ -2660,7 +2661,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (memcmp(cfm.confirm_val, smp->pcnf, 16)) + if (crypto_memneq(cfm.confirm_val, smp->pcnf, 16)) return SMP_CONFIRM_FAILED; } @@ -2693,7 +2694,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) else hcon->pending_sec_level = BT_SECURITY_FIPS; - if (!memcmp(debug_pk, smp->remote_pk, 64)) + if (!crypto_memneq(debug_pk, smp->remote_pk, 64)) set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); if (smp->method == DSP_PASSKEY) { @@ -2792,7 +2793,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (memcmp(check->e, e, 16)) + if (crypto_memneq(check->e, e, 16)) return SMP_DHKEY_CHECK_FAILED; if (!hcon->out) { @@ -3506,10 +3507,10 @@ static int __init test_debug_key(void) if (!generate_ecdh_keys(pk, sk)) return -EINVAL; - if (memcmp(sk, debug_sk, 32)) + if (crypto_memneq(sk, debug_sk, 32)) return -EINVAL; - if (memcmp(pk, debug_pk, 64)) + if (crypto_memneq(pk, debug_pk, 64)) return -EINVAL; return 0; @@ -3529,7 +3530,7 @@ static int __init test_ah(struct crypto_cipher *tfm_aes) if (err) return err; - if (memcmp(res, exp, 3)) + if (crypto_memneq(res, exp, 3)) return -EINVAL; return 0; @@ -3559,7 +3560,7 @@ static int __init test_c1(struct crypto_cipher *tfm_aes) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3584,7 +3585,7 @@ static int __init test_s1(struct crypto_cipher *tfm_aes) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3616,7 +3617,7 @@ static int __init test_f4(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3650,10 +3651,10 @@ static int __init test_f5(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(mackey, exp_mackey, 16)) + if (crypto_memneq(mackey, exp_mackey, 16)) return -EINVAL; - if (memcmp(ltk, exp_ltk, 16)) + if (crypto_memneq(ltk, exp_ltk, 16)) return -EINVAL; return 0; @@ -3686,7 +3687,7 @@ static int __init test_f6(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3740,7 +3741,7 @@ static int __init test_h6(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0;