lkml.org 
[lkml]   [2019]   [Sep]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.2 37/45] Bluetooth: btrtl: HCI reset on close for Realtek BT chip
    Date
    From: Jian-Hong Pan <jian-hong@endlessm.com>

    [ Upstream commit 7af3f558aca74f2ee47b173f1c27f6bb9a5b5561 ]

    Realtek RTL8822BE BT chip on ASUS X420FA cannot be turned on correctly
    after on-off several times. Bluetooth daemon sets BT mode failed when
    this issue happens. Scanning must be active while turning off for this
    bug to be hit.

    bluetoothd[1576]: Failed to set mode: Failed (0x03)

    If BT is turned off, then turned on again, it works correctly again.

    According to the vendor driver, the HCI_QUIRK_RESET_ON_CLOSE flag is set
    during probing. So, this patch makes Realtek's BT reset on close to fix
    this issue.

    Link: https://bugzilla.kernel.org/show_bug.cgi?id=203429
    Signed-off-by: Jian-Hong Pan <jian-hong@endlessm.com>
    Reviewed-by: Daniel Drake <drake@endlessm.com>
    Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/bluetooth/btrtl.c | 20 ++++++++++++++++++++
    drivers/bluetooth/btrtl.h | 6 ++++++
    drivers/bluetooth/btusb.c | 1 +
    3 files changed, 27 insertions(+)

    diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
    index 208feef63de40..d04b443cad1f2 100644
    --- a/drivers/bluetooth/btrtl.c
    +++ b/drivers/bluetooth/btrtl.c
    @@ -637,6 +637,26 @@ int btrtl_setup_realtek(struct hci_dev *hdev)
    }
    EXPORT_SYMBOL_GPL(btrtl_setup_realtek);

    +int btrtl_shutdown_realtek(struct hci_dev *hdev)
    +{
    + struct sk_buff *skb;
    + int ret;
    +
    + /* According to the vendor driver, BT must be reset on close to avoid
    + * firmware crash.
    + */
    + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
    + if (IS_ERR(skb)) {
    + ret = PTR_ERR(skb);
    + bt_dev_err(hdev, "HCI reset during shutdown failed");
    + return ret;
    + }
    + kfree_skb(skb);
    +
    + return 0;
    +}
    +EXPORT_SYMBOL_GPL(btrtl_shutdown_realtek);
    +
    static unsigned int btrtl_convert_baudrate(u32 device_baudrate)
    {
    switch (device_baudrate) {
    diff --git a/drivers/bluetooth/btrtl.h b/drivers/bluetooth/btrtl.h
    index f1676144fce81..10ad40c3e42c2 100644
    --- a/drivers/bluetooth/btrtl.h
    +++ b/drivers/bluetooth/btrtl.h
    @@ -55,6 +55,7 @@ void btrtl_free(struct btrtl_device_info *btrtl_dev);
    int btrtl_download_firmware(struct hci_dev *hdev,
    struct btrtl_device_info *btrtl_dev);
    int btrtl_setup_realtek(struct hci_dev *hdev);
    +int btrtl_shutdown_realtek(struct hci_dev *hdev);
    int btrtl_get_uart_settings(struct hci_dev *hdev,
    struct btrtl_device_info *btrtl_dev,
    unsigned int *controller_baudrate,
    @@ -83,6 +84,11 @@ static inline int btrtl_setup_realtek(struct hci_dev *hdev)
    return -EOPNOTSUPP;
    }

    +static inline int btrtl_shutdown_realtek(struct hci_dev *hdev)
    +{
    + return -EOPNOTSUPP;
    +}
    +
    static inline int btrtl_get_uart_settings(struct hci_dev *hdev,
    struct btrtl_device_info *btrtl_dev,
    unsigned int *controller_baudrate,
    diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
    index 7954a79249235..0f4750322864a 100644
    --- a/drivers/bluetooth/btusb.c
    +++ b/drivers/bluetooth/btusb.c
    @@ -3181,6 +3181,7 @@ static int btusb_probe(struct usb_interface *intf,
    #ifdef CONFIG_BT_HCIBTUSB_RTL
    if (id->driver_info & BTUSB_REALTEK) {
    hdev->setup = btrtl_setup_realtek;
    + hdev->shutdown = btrtl_shutdown_realtek;

    /* Realtek devices lose their updated firmware over suspend,
    * but the USB hub doesn't notice any status change.
    --
    2.20.1


    \
     
     \ /
      Last update: 2019-09-29 16:03    [W:4.834 / U:0.936 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site