Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / bluetooth / hci_bcm.c
1 /*
2  *
3  *  Bluetooth HCI UART driver for Broadcom devices
4  *
5  *  Copyright (C) 2015  Intel Corporation
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/skbuff.h>
27
28 #include <net/bluetooth/bluetooth.h>
29 #include <net/bluetooth/hci_core.h>
30
31 #include "btbcm.h"
32 #include "hci_uart.h"
33
34 struct bcm_data {
35         struct sk_buff *rx_skb;
36         struct sk_buff_head txq;
37 };
38
39 static int bcm_open(struct hci_uart *hu)
40 {
41         struct bcm_data *bcm;
42
43         BT_DBG("hu %p", hu);
44
45         bcm = kzalloc(sizeof(*bcm), GFP_KERNEL);
46         if (!bcm)
47                 return -ENOMEM;
48
49         skb_queue_head_init(&bcm->txq);
50
51         hu->priv = bcm;
52         return 0;
53 }
54
55 static int bcm_close(struct hci_uart *hu)
56 {
57         struct bcm_data *bcm = hu->priv;
58
59         BT_DBG("hu %p", hu);
60
61         skb_queue_purge(&bcm->txq);
62         kfree_skb(bcm->rx_skb);
63         kfree(bcm);
64
65         hu->priv = NULL;
66         return 0;
67 }
68
69 static int bcm_flush(struct hci_uart *hu)
70 {
71         struct bcm_data *bcm = hu->priv;
72
73         BT_DBG("hu %p", hu);
74
75         skb_queue_purge(&bcm->txq);
76
77         return 0;
78 }
79
80 static int bcm_setup(struct hci_uart *hu)
81 {
82         BT_DBG("hu %p", hu);
83
84         hu->hdev->set_bdaddr = btbcm_set_bdaddr;
85
86         return btbcm_setup_patchram(hu->hdev);
87 }
88
89 static const struct h4_recv_pkt bcm_recv_pkts[] = {
90         { H4_RECV_ACL,   .recv = hci_recv_frame },
91         { H4_RECV_SCO,   .recv = hci_recv_frame },
92         { H4_RECV_EVENT, .recv = hci_recv_frame },
93 };
94
95 static int bcm_recv(struct hci_uart *hu, const void *data, int count)
96 {
97         struct bcm_data *bcm = hu->priv;
98
99         if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
100                 return -EUNATCH;
101
102         bcm->rx_skb = h4_recv_buf(hu->hdev, bcm->rx_skb, data, count,
103                                   bcm_recv_pkts, ARRAY_SIZE(bcm_recv_pkts));
104         if (IS_ERR(bcm->rx_skb)) {
105                 int err = PTR_ERR(bcm->rx_skb);
106                 BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err);
107                 return err;
108         }
109
110         return count;
111 }
112
113 static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
114 {
115         struct bcm_data *bcm = hu->priv;
116
117         BT_DBG("hu %p skb %p", hu, skb);
118
119         /* Prepend skb with frame type */
120         memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
121         skb_queue_tail(&bcm->txq, skb);
122
123         return 0;
124 }
125
126 static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
127 {
128         struct bcm_data *bcm = hu->priv;
129
130         return skb_dequeue(&bcm->txq);
131 }
132
133 static const struct hci_uart_proto bcm_proto = {
134         .id             = HCI_UART_BCM,
135         .name           = "BCM",
136         .open           = bcm_open,
137         .close          = bcm_close,
138         .flush          = bcm_flush,
139         .setup          = bcm_setup,
140         .recv           = bcm_recv,
141         .enqueue        = bcm_enqueue,
142         .dequeue        = bcm_dequeue,
143 };
144
145 int __init bcm_init(void)
146 {
147         return hci_uart_register_proto(&bcm_proto);
148 }
149
150 int __exit bcm_deinit(void)
151 {
152         return hci_uart_unregister_proto(&bcm_proto);
153 }