From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 03 Jan 2024 09:43:39 +0000 Subject: [PATCH] update kernel to 5.10.198 --- kernel/drivers/bluetooth/hci_serdev.c | 75 ++++++++++++++++++++++++------------- 1 files changed, 48 insertions(+), 27 deletions(-) diff --git a/kernel/drivers/bluetooth/hci_serdev.c b/kernel/drivers/bluetooth/hci_serdev.c index 7b3aade..f2e2e55 100644 --- a/kernel/drivers/bluetooth/hci_serdev.c +++ b/kernel/drivers/bluetooth/hci_serdev.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Bluetooth HCI serdev driver lib * @@ -8,17 +9,6 @@ * Copyright (C) 2000-2001 Qualcomm Incorporated * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <linux/kernel.h> @@ -30,8 +20,6 @@ #include <net/bluetooth/hci_core.h> #include "hci_uart.h" - -static struct serdev_device_ops hci_serdev_client_ops; static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) { @@ -57,9 +45,10 @@ { struct sk_buff *skb = hu->tx_skb; - if (!skb) - skb = hu->proto->dequeue(hu); - else + if (!skb) { + if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) + skb = hu->proto->dequeue(hu); + } else hu->tx_skb = NULL; return skb; @@ -94,9 +83,9 @@ hci_uart_tx_complete(hu, hci_skb_pkt_type(skb)); kfree_skb(skb); } - } while(test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)); - clear_bit(HCI_UART_SENDING, &hu->tx_state); + clear_bit(HCI_UART_SENDING, &hu->tx_state); + } while (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)); } /* ------- Interface to HCI layer ------ */ @@ -124,7 +113,21 @@ /* Initialize device */ static int hci_uart_open(struct hci_dev *hdev) { + struct hci_uart *hu = hci_get_drvdata(hdev); + int err; + BT_DBG("%s %p", hdev->name, hdev); + + /* When Quirk HCI_QUIRK_NON_PERSISTENT_SETUP is set by + * driver, BT SoC is completely turned OFF during + * BT OFF. Upon next BT ON UART port should be opened. + */ + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { + err = serdev_device_open(hu->serdev); + if (err) + return err; + set_bit(HCI_UART_PROTO_READY, &hu->flags); + } /* Undo clearing this from hci_uart_close() */ hdev->flush = hci_uart_flush; @@ -135,10 +138,24 @@ /* Close device */ static int hci_uart_close(struct hci_dev *hdev) { + struct hci_uart *hu = hci_get_drvdata(hdev); + BT_DBG("hdev %p", hdev); + + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) + return 0; hci_uart_flush(hdev); hdev->flush = NULL; + + /* When QUIRK HCI_QUIRK_NON_PERSISTENT_SETUP is set by driver, + * BT SOC is completely powered OFF during BT OFF, holding port + * open may drain the battery. + */ + if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) { + clear_bit(HCI_UART_PROTO_READY, &hu->flags); + serdev_device_close(hu->serdev); + } return 0; } @@ -269,7 +286,7 @@ return count; } -static struct serdev_device_ops hci_serdev_client_ops = { +static const struct serdev_device_ops hci_serdev_client_ops = { .receive_buf = hci_uart_receive_buf, .write_wakeup = hci_uart_write_wakeup, }; @@ -284,9 +301,12 @@ serdev_device_set_client_ops(hu->serdev, &hci_serdev_client_ops); + if (percpu_init_rwsem(&hu->proto_lock)) + return -ENOMEM; + err = serdev_device_open(hu->serdev); if (err) - return err; + goto err_rwsem; err = p->open(hu); if (err) @@ -310,7 +330,6 @@ INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->write_work, hci_uart_write_work); - percpu_init_rwsem(&hu->proto_lock); /* Only when vendor specific setup callback is provided, consider * the manufacturer information valid. This avoids filling in the @@ -331,9 +350,6 @@ if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags)) set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); - - if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags)) - set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags)) hdev->dev_type = HCI_AMP; @@ -360,6 +376,8 @@ p->close(hu); err_open: serdev_device_close(hu->serdev); +err_rwsem: + percpu_free_rwsem(&hu->proto_lock); return err; } EXPORT_SYMBOL_GPL(hci_uart_register_device); @@ -367,8 +385,6 @@ void hci_uart_unregister_device(struct hci_uart *hu) { struct hci_dev *hdev = hu->hdev; - - clear_bit(HCI_UART_PROTO_READY, &hu->flags); cancel_work_sync(&hu->init_ready); if (test_bit(HCI_UART_REGISTERED, &hu->flags)) @@ -378,6 +394,11 @@ cancel_work_sync(&hu->write_work); hu->proto->close(hu); - serdev_device_close(hu->serdev); + + if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) { + clear_bit(HCI_UART_PROTO_READY, &hu->flags); + serdev_device_close(hu->serdev); + } + percpu_free_rwsem(&hu->proto_lock); } EXPORT_SYMBOL_GPL(hci_uart_unregister_device); -- Gitblit v1.6.2