diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2018-04-04 16:11:49 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2018-04-04 16:11:49 -0700 |
commit | 664b0bae0b87f69bc9deb098f5e0158b9cf18e04 (patch) | |
tree | d5841492b396ff483723b9339c7c11dc33b67688 /drivers/bluetooth/btqcomsmd.c | |
parent | Input: ALPS - fix TrackStick detection on Thinkpad L570 and Latitude 7370 (diff) | |
parent | Input: i8042 - enable MUX on Sony VAIO VGN-CS series to fix touchpad (diff) | |
download | linux-dev-664b0bae0b87f69bc9deb098f5e0158b9cf18e04.tar.xz linux-dev-664b0bae0b87f69bc9deb098f5e0158b9cf18e04.zip |
Merge branch 'next' into for-linus
Prepare input updates for 4.17 merge window.
Diffstat (limited to 'drivers/bluetooth/btqcomsmd.c')
-rw-r--r-- | drivers/bluetooth/btqcomsmd.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c index d00c4fdae924..2c9a5fc9137d 100644 --- a/drivers/bluetooth/btqcomsmd.c +++ b/drivers/bluetooth/btqcomsmd.c @@ -15,6 +15,8 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/rpmsg.h> +#include <linux/of.h> + #include <linux/soc/qcom/wcnss_ctrl.h> #include <linux/platform_device.h> @@ -26,6 +28,7 @@ struct btqcomsmd { struct hci_dev *hdev; + bdaddr_t bdaddr; struct rpmsg_endpoint *acl_channel; struct rpmsg_endpoint *cmd_channel; }; @@ -85,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; } @@ -100,6 +104,38 @@ static int btqcomsmd_close(struct hci_dev *hdev) return 0; } +static int btqcomsmd_setup(struct hci_dev *hdev) +{ + struct btqcomsmd *btq = hci_get_drvdata(hdev); + struct sk_buff *skb; + int err; + + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) + return PTR_ERR(skb); + kfree_skb(skb); + + /* Devices do not have persistent storage for BD address. If no + * BD address has been retrieved during probe, mark the device + * as having an invalid BD address. + */ + if (!bacmp(&btq->bdaddr, BDADDR_ANY)) { + set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); + return 0; + } + + /* When setting a configured BD address fails, mark the device + * as having an invalid BD address. + */ + err = qca_set_bdaddr_rome(hdev, &btq->bdaddr); + if (err) { + set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); + return 0; + } + + return 0; +} + static int btqcomsmd_probe(struct platform_device *pdev) { struct btqcomsmd *btq; @@ -123,6 +159,15 @@ static int btqcomsmd_probe(struct platform_device *pdev) if (IS_ERR(btq->cmd_channel)) return PTR_ERR(btq->cmd_channel); + /* The local-bd-address property is usually injected by the + * bootloader which has access to the allocated BD address. + */ + if (!of_property_read_u8_array(pdev->dev.of_node, "local-bd-address", + (u8 *)&btq->bdaddr, sizeof(bdaddr_t))) { + dev_info(&pdev->dev, "BD address %pMR retrieved from device-tree", + &btq->bdaddr); + } + hdev = hci_alloc_dev(); if (!hdev) return -ENOMEM; @@ -135,6 +180,7 @@ static int btqcomsmd_probe(struct platform_device *pdev) hdev->open = btqcomsmd_open; hdev->close = btqcomsmd_close; hdev->send = btqcomsmd_send; + hdev->setup = btqcomsmd_setup; hdev->set_bdaddr = qca_set_bdaddr_rome; ret = hci_register_dev(hdev); |