aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/bluetooth/hci_h5.c52
1 files changed, 48 insertions, 4 deletions
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
index 6a8d0d06aba7..672f63623bf7 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -23,6 +23,7 @@
23 23
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/errno.h> 25#include <linux/errno.h>
26#include <linux/serdev.h>
26#include <linux/skbuff.h> 27#include <linux/skbuff.h>
27 28
28#include <net/bluetooth/bluetooth.h> 29#include <net/bluetooth/bluetooth.h>
@@ -65,6 +66,9 @@ enum {
65}; 66};
66 67
67struct h5 { 68struct h5 {
69 /* Must be the first member, hci_serdev.c expects this. */
70 struct hci_uart serdev_hu;
71
68 struct sk_buff_head unack; /* Unack'ed packets queue */ 72 struct sk_buff_head unack; /* Unack'ed packets queue */
69 struct sk_buff_head rel; /* Reliable packets queue */ 73 struct sk_buff_head rel; /* Reliable packets queue */
70 struct sk_buff_head unrel; /* Unreliable packets queue */ 74 struct sk_buff_head unrel; /* Unreliable packets queue */
@@ -193,9 +197,13 @@ static int h5_open(struct hci_uart *hu)
193 197
194 BT_DBG("hu %p", hu); 198 BT_DBG("hu %p", hu);
195 199
196 h5 = kzalloc(sizeof(*h5), GFP_KERNEL); 200 if (hu->serdev) {
197 if (!h5) 201 h5 = serdev_device_get_drvdata(hu->serdev);
198 return -ENOMEM; 202 } else {
203 h5 = kzalloc(sizeof(*h5), GFP_KERNEL);
204 if (!h5)
205 return -ENOMEM;
206 }
199 207
200 hu->priv = h5; 208 hu->priv = h5;
201 h5->hu = hu; 209 h5->hu = hu;
@@ -229,7 +237,8 @@ static int h5_close(struct hci_uart *hu)
229 skb_queue_purge(&h5->rel); 237 skb_queue_purge(&h5->rel);
230 skb_queue_purge(&h5->unrel); 238 skb_queue_purge(&h5->unrel);
231 239
232 kfree(h5); 240 if (!hu->serdev)
241 kfree(h5);
233 242
234 return 0; 243 return 0;
235} 244}
@@ -750,12 +759,47 @@ static const struct hci_uart_proto h5p = {
750 .flush = h5_flush, 759 .flush = h5_flush,
751}; 760};
752 761
762static int h5_serdev_probe(struct serdev_device *serdev)
763{
764 struct device *dev = &serdev->dev;
765 struct h5 *h5;
766
767 h5 = devm_kzalloc(dev, sizeof(*h5), GFP_KERNEL);
768 if (!h5)
769 return -ENOMEM;
770
771 set_bit(HCI_UART_RESET_ON_INIT, &h5->serdev_hu.flags);
772
773 h5->hu = &h5->serdev_hu;
774 h5->serdev_hu.serdev = serdev;
775 serdev_device_set_drvdata(serdev, h5);
776
777 return hci_uart_register_device(&h5->serdev_hu, &h5p);
778}
779
780static void h5_serdev_remove(struct serdev_device *serdev)
781{
782 struct h5 *h5 = serdev_device_get_drvdata(serdev);
783
784 hci_uart_unregister_device(&h5->serdev_hu);
785}
786
787static struct serdev_device_driver h5_serdev_driver = {
788 .probe = h5_serdev_probe,
789 .remove = h5_serdev_remove,
790 .driver = {
791 .name = "hci_uart_h5",
792 },
793};
794
753int __init h5_init(void) 795int __init h5_init(void)
754{ 796{
797 serdev_device_driver_register(&h5_serdev_driver);
755 return hci_uart_register_proto(&h5p); 798 return hci_uart_register_proto(&h5p);
756} 799}
757 800
758int __exit h5_deinit(void) 801int __exit h5_deinit(void)
759{ 802{
803 serdev_device_driver_unregister(&h5_serdev_driver);
760 return hci_uart_unregister_proto(&h5p); 804 return hci_uart_unregister_proto(&h5p);
761} 805}