hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/bluetooth/hci_serdev.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Bluetooth HCI serdev driver lib
34 *
....@@ -8,17 +9,6 @@
89 * Copyright (C) 2000-2001 Qualcomm Incorporated
910 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
1011 * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
11
- *
12
- * This program is free software; you can redistribute it and/or modify
13
- * it under the terms of the GNU General Public License as published by
14
- * the Free Software Foundation; either version 2 of the License, or
15
- * (at your option) any later version.
16
- *
17
- * This program is distributed in the hope that it will be useful,
18
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
- * GNU General Public License for more details.
21
- *
2212 */
2313
2414 #include <linux/kernel.h>
....@@ -30,8 +20,6 @@
3020 #include <net/bluetooth/hci_core.h>
3121
3222 #include "hci_uart.h"
33
-
34
-static struct serdev_device_ops hci_serdev_client_ops;
3523
3624 static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
3725 {
....@@ -57,9 +45,10 @@
5745 {
5846 struct sk_buff *skb = hu->tx_skb;
5947
60
- if (!skb)
61
- skb = hu->proto->dequeue(hu);
62
- else
48
+ if (!skb) {
49
+ if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
50
+ skb = hu->proto->dequeue(hu);
51
+ } else
6352 hu->tx_skb = NULL;
6453
6554 return skb;
....@@ -94,9 +83,9 @@
9483 hci_uart_tx_complete(hu, hci_skb_pkt_type(skb));
9584 kfree_skb(skb);
9685 }
97
- } while(test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state));
9886
99
- clear_bit(HCI_UART_SENDING, &hu->tx_state);
87
+ clear_bit(HCI_UART_SENDING, &hu->tx_state);
88
+ } while (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state));
10089 }
10190
10291 /* ------- Interface to HCI layer ------ */
....@@ -124,7 +113,21 @@
124113 /* Initialize device */
125114 static int hci_uart_open(struct hci_dev *hdev)
126115 {
116
+ struct hci_uart *hu = hci_get_drvdata(hdev);
117
+ int err;
118
+
127119 BT_DBG("%s %p", hdev->name, hdev);
120
+
121
+ /* When Quirk HCI_QUIRK_NON_PERSISTENT_SETUP is set by
122
+ * driver, BT SoC is completely turned OFF during
123
+ * BT OFF. Upon next BT ON UART port should be opened.
124
+ */
125
+ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
126
+ err = serdev_device_open(hu->serdev);
127
+ if (err)
128
+ return err;
129
+ set_bit(HCI_UART_PROTO_READY, &hu->flags);
130
+ }
128131
129132 /* Undo clearing this from hci_uart_close() */
130133 hdev->flush = hci_uart_flush;
....@@ -135,10 +138,24 @@
135138 /* Close device */
136139 static int hci_uart_close(struct hci_dev *hdev)
137140 {
141
+ struct hci_uart *hu = hci_get_drvdata(hdev);
142
+
138143 BT_DBG("hdev %p", hdev);
144
+
145
+ if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
146
+ return 0;
139147
140148 hci_uart_flush(hdev);
141149 hdev->flush = NULL;
150
+
151
+ /* When QUIRK HCI_QUIRK_NON_PERSISTENT_SETUP is set by driver,
152
+ * BT SOC is completely powered OFF during BT OFF, holding port
153
+ * open may drain the battery.
154
+ */
155
+ if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) {
156
+ clear_bit(HCI_UART_PROTO_READY, &hu->flags);
157
+ serdev_device_close(hu->serdev);
158
+ }
142159
143160 return 0;
144161 }
....@@ -269,7 +286,7 @@
269286 return count;
270287 }
271288
272
-static struct serdev_device_ops hci_serdev_client_ops = {
289
+static const struct serdev_device_ops hci_serdev_client_ops = {
273290 .receive_buf = hci_uart_receive_buf,
274291 .write_wakeup = hci_uart_write_wakeup,
275292 };
....@@ -284,9 +301,12 @@
284301
285302 serdev_device_set_client_ops(hu->serdev, &hci_serdev_client_ops);
286303
304
+ if (percpu_init_rwsem(&hu->proto_lock))
305
+ return -ENOMEM;
306
+
287307 err = serdev_device_open(hu->serdev);
288308 if (err)
289
- return err;
309
+ goto err_rwsem;
290310
291311 err = p->open(hu);
292312 if (err)
....@@ -310,7 +330,6 @@
310330
311331 INIT_WORK(&hu->init_ready, hci_uart_init_work);
312332 INIT_WORK(&hu->write_work, hci_uart_write_work);
313
- percpu_init_rwsem(&hu->proto_lock);
314333
315334 /* Only when vendor specific setup callback is provided, consider
316335 * the manufacturer information valid. This avoids filling in the
....@@ -331,9 +350,6 @@
331350
332351 if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags))
333352 set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
334
-
335
- if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
336
- set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
337353
338354 if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags))
339355 hdev->dev_type = HCI_AMP;
....@@ -360,6 +376,8 @@
360376 p->close(hu);
361377 err_open:
362378 serdev_device_close(hu->serdev);
379
+err_rwsem:
380
+ percpu_free_rwsem(&hu->proto_lock);
363381 return err;
364382 }
365383 EXPORT_SYMBOL_GPL(hci_uart_register_device);
....@@ -367,8 +385,6 @@
367385 void hci_uart_unregister_device(struct hci_uart *hu)
368386 {
369387 struct hci_dev *hdev = hu->hdev;
370
-
371
- clear_bit(HCI_UART_PROTO_READY, &hu->flags);
372388
373389 cancel_work_sync(&hu->init_ready);
374390 if (test_bit(HCI_UART_REGISTERED, &hu->flags))
....@@ -378,6 +394,11 @@
378394 cancel_work_sync(&hu->write_work);
379395
380396 hu->proto->close(hu);
381
- serdev_device_close(hu->serdev);
397
+
398
+ if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
399
+ clear_bit(HCI_UART_PROTO_READY, &hu->flags);
400
+ serdev_device_close(hu->serdev);
401
+ }
402
+ percpu_free_rwsem(&hu->proto_lock);
382403 }
383404 EXPORT_SYMBOL_GPL(hci_uart_unregister_device);