ARM64: DTS: Add rk3399-firefly uart4 device, node as /dev/ttyS1
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rkwifi / bcmdhd / dhd_bta.c
1 /*
2  * BT-AMP support routines
3  *
4  * Copyright (C) 1999-2016, Broadcom Corporation
5  * 
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  * 
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions of
16  * the license of that module.  An independent module is a module which is not
17  * derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  * 
20  *      Notwithstanding the above, under no circumstances may you combine this
21  * software in any way with any other Broadcom software provided under a license
22  * other than the GPL, without Broadcom's express prior written consent.
23  *
24  *
25  * <<Broadcom-WL-IPTag/Open:>>
26  *
27  * $Id: dhd_bta.c 514727 2014-11-12 03:02:48Z $
28  */
29 #error "WLBTAMP is not defined"
30
31 #include <typedefs.h>
32 #include <osl.h>
33 #include <bcmcdc.h>
34 #include <bcmutils.h>
35 #include <bcmendian.h>
36 #include <proto/802.11.h>
37 #include <proto/802.11_bta.h>
38 #include <proto/bt_amp_hci.h>
39 #include <dngl_stats.h>
40 #include <dhd.h>
41 #include <dhd_bus.h>
42 #include <dhd_proto.h>
43 #include <dhdioctl.h>
44 #include <dhd_dbg.h>
45
46 #include <dhd_bta.h>
47
48
49 #ifdef SEND_HCI_CMD_VIA_IOCTL
50 #define BTA_HCI_CMD_MAX_LEN HCI_CMD_PREAMBLE_SIZE + HCI_CMD_DATA_SIZE
51
52 /* Send HCI cmd via wl iovar HCI_cmd to the dongle. */
53 int
54 dhd_bta_docmd(dhd_pub_t *pub, void *cmd_buf, uint cmd_len)
55 {
56         amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)cmd_buf;
57         uint8 buf[BTA_HCI_CMD_MAX_LEN + 16];
58         uint len = sizeof(buf);
59         wl_ioctl_t ioc;
60
61         if (cmd_len < HCI_CMD_PREAMBLE_SIZE)
62                 return BCME_BADLEN;
63
64         if ((uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE > cmd_len)
65                 return BCME_BADLEN;
66
67         len = bcm_mkiovar("HCI_cmd",
68                 (char *)cmd, (uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE, (char *)buf, len);
69
70
71         memset(&ioc, 0, sizeof(ioc));
72
73         ioc.cmd = WLC_SET_VAR;
74         ioc.buf = buf;
75         ioc.len = len;
76         ioc.set = TRUE;
77
78         return dhd_wl_ioctl(pub, &ioc, ioc.buf, ioc.len);
79 }
80 #else /* !SEND_HCI_CMD_VIA_IOCTL */
81
82 static void
83 dhd_bta_flush_hcidata(dhd_pub_t *pub, uint16 llh)
84 {
85         int prec;
86         struct pktq *q;
87         uint count = 0;
88
89         q = dhd_bus_txq(pub->bus);
90         if (q == NULL)
91                 return;
92
93         DHD_BTA(("dhd: flushing HCI ACL data for logical link %u...\n", llh));
94
95         dhd_os_sdlock_txq(pub);
96
97         /* Walk through the txq and toss all HCI ACL data packets */
98         PKTQ_PREC_ITER(q, prec) {
99                 void *head_pkt = NULL;
100
101                 while (pktq_ppeek(q, prec) != head_pkt) {
102                         void *pkt = pktq_pdeq(q, prec);
103                         int ifidx;
104
105                         dhd_prot_hdrpull(pub, &ifidx, pkt, NULL, NULL);
106
107                         if (PKTLEN(pub->osh, pkt) >= RFC1042_HDR_LEN) {
108                                 struct ether_header *eh =
109                                         (struct ether_header *)PKTDATA(pub->osh, pkt);
110
111                                 if (ntoh16(eh->ether_type) < ETHER_TYPE_MIN) {
112                                         struct dot11_llc_snap_header *lsh =
113                                                 (struct dot11_llc_snap_header *)&eh[1];
114
115                                         if (bcmp(lsh, BT_SIG_SNAP_MPROT,
116                                                  DOT11_LLC_SNAP_HDR_LEN - 2) == 0 &&
117                                             ntoh16(lsh->type) == BTA_PROT_L2CAP) {
118                                                 amp_hci_ACL_data_t *ACL_data =
119                                                         (amp_hci_ACL_data_t *)&lsh[1];
120                                                 uint16 handle = ltoh16(ACL_data->handle);
121
122                                                 if (HCI_ACL_DATA_HANDLE(handle) == llh) {
123                                                         PKTFREE(pub->osh, pkt, TRUE);
124                                                         count ++;
125                                                         continue;
126                                                 }
127                                         }
128                                 }
129                         }
130
131                         dhd_prot_hdrpush(pub, ifidx, pkt);
132
133                         if (head_pkt == NULL)
134                                 head_pkt = pkt;
135                         pktq_penq(q, prec, pkt);
136                 }
137         }
138
139         dhd_os_sdunlock_txq(pub);
140
141         DHD_BTA(("dhd: flushed %u packet(s) for logical link %u...\n", count, llh));
142 }
143
144 /* Handle HCI cmd locally.
145  * Return 0: continue to send the cmd across SDIO
146  *        < 0: stop, fail
147  *        > 0: stop, succuess
148  */
149 static int
150 _dhd_bta_docmd(dhd_pub_t *pub, amp_hci_cmd_t *cmd)
151 {
152         int status = 0;
153
154         switch (ltoh16_ua((uint8 *)&cmd->opcode)) {
155         case HCI_Enhanced_Flush: {
156                 eflush_cmd_parms_t *cmdparms = (eflush_cmd_parms_t *)cmd->parms;
157                 dhd_bta_flush_hcidata(pub, ltoh16_ua(cmdparms->llh));
158                 break;
159         }
160         default:
161                 break;
162         }
163
164         return status;
165 }
166
167 /* Send HCI cmd encapsulated in BT-SIG frame via data channel to the dongle. */
168 int
169 dhd_bta_docmd(dhd_pub_t *pub, void *cmd_buf, uint cmd_len)
170 {
171         amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)cmd_buf;
172         struct ether_header *eh;
173         struct dot11_llc_snap_header *lsh;
174         osl_t *osh = pub->osh;
175         uint len;
176         void *p;
177         int status;
178
179         if (cmd_len < HCI_CMD_PREAMBLE_SIZE) {
180                 DHD_ERROR(("dhd_bta_docmd: short command, cmd_len %u\n", cmd_len));
181                 return BCME_BADLEN;
182         }
183
184         if ((len = (uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE) > cmd_len) {
185                 DHD_ERROR(("dhd_bta_docmd: malformed command, len %u cmd_len %u\n",
186                            len, cmd_len));
187                 /* return BCME_BADLEN; */
188         }
189
190         p = PKTGET(osh, pub->hdrlen + RFC1042_HDR_LEN + len, TRUE);
191         if (p == NULL) {
192                 DHD_ERROR(("dhd_bta_docmd: out of memory\n"));
193                 return BCME_NOMEM;
194         }
195
196
197         /* intercept and handle the HCI cmd locally */
198         if ((status = _dhd_bta_docmd(pub, cmd)) > 0)
199                 return 0;
200         else if (status < 0)
201                 return status;
202
203         /* copy in HCI cmd */
204         PKTPULL(osh, p, pub->hdrlen + RFC1042_HDR_LEN);
205         bcopy(cmd, PKTDATA(osh, p), len);
206
207         /* copy in partial Ethernet header with BT-SIG LLC/SNAP header */
208         PKTPUSH(osh, p, RFC1042_HDR_LEN);
209         eh = (struct ether_header *)PKTDATA(osh, p);
210         bzero(eh->ether_dhost, ETHER_ADDR_LEN);
211         ETHER_SET_LOCALADDR(eh->ether_dhost);
212         bcopy(&pub->mac, eh->ether_shost, ETHER_ADDR_LEN);
213         eh->ether_type = hton16(len + DOT11_LLC_SNAP_HDR_LEN);
214         lsh = (struct dot11_llc_snap_header *)&eh[1];
215         bcopy(BT_SIG_SNAP_MPROT, lsh, DOT11_LLC_SNAP_HDR_LEN - 2);
216         lsh->type = 0;
217
218         return dhd_sendpkt(pub, 0, p);
219 }
220 #endif /* !SEND_HCI_CMD_VIA_IOCTL */
221
222 /* Send HCI ACL data to dongle via data channel */
223 int
224 dhd_bta_tx_hcidata(dhd_pub_t *pub, void *data_buf, uint data_len)
225 {
226         amp_hci_ACL_data_t *data = (amp_hci_ACL_data_t *)data_buf;
227         struct ether_header *eh;
228         struct dot11_llc_snap_header *lsh;
229         osl_t *osh = pub->osh;
230         uint len;
231         void *p;
232
233         if (data_len < HCI_ACL_DATA_PREAMBLE_SIZE) {
234                 DHD_ERROR(("dhd_bta_tx_hcidata: short data_buf, data_len %u\n", data_len));
235                 return BCME_BADLEN;
236         }
237
238         if ((len = (uint)ltoh16(data->dlen) + HCI_ACL_DATA_PREAMBLE_SIZE) > data_len) {
239                 DHD_ERROR(("dhd_bta_tx_hcidata: malformed hci data, len %u data_len %u\n",
240                            len, data_len));
241                 /* return BCME_BADLEN; */
242         }
243
244         p = PKTGET(osh, pub->hdrlen + RFC1042_HDR_LEN + len, TRUE);
245         if (p == NULL) {
246                 DHD_ERROR(("dhd_bta_tx_hcidata: out of memory\n"));
247                 return BCME_NOMEM;
248         }
249
250
251         /* copy in HCI ACL data header and HCI ACL data */
252         PKTPULL(osh, p, pub->hdrlen + RFC1042_HDR_LEN);
253         bcopy(data, PKTDATA(osh, p), len);
254
255         /* copy in partial Ethernet header with BT-SIG LLC/SNAP header */
256         PKTPUSH(osh, p, RFC1042_HDR_LEN);
257         eh = (struct ether_header *)PKTDATA(osh, p);
258         bzero(eh->ether_dhost, ETHER_ADDR_LEN);
259         bcopy(&pub->mac, eh->ether_shost, ETHER_ADDR_LEN);
260         eh->ether_type = hton16(len + DOT11_LLC_SNAP_HDR_LEN);
261         lsh = (struct dot11_llc_snap_header *)&eh[1];
262         bcopy(BT_SIG_SNAP_MPROT, lsh, DOT11_LLC_SNAP_HDR_LEN - 2);
263         lsh->type = HTON16(BTA_PROT_L2CAP);
264
265         return dhd_sendpkt(pub, 0, p);
266 }
267
268 /* txcomplete callback */
269 void
270 dhd_bta_tx_hcidata_complete(dhd_pub_t *dhdp, void *txp, bool success)
271 {
272         uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, txp);
273         amp_hci_ACL_data_t *ACL_data = (amp_hci_ACL_data_t *)(pktdata + RFC1042_HDR_LEN);
274         uint16 handle = ltoh16(ACL_data->handle);
275         uint16 llh = HCI_ACL_DATA_HANDLE(handle);
276
277         wl_event_msg_t event;
278         uint8 data[HCI_EVT_PREAMBLE_SIZE + sizeof(num_completed_data_blocks_evt_parms_t)];
279         amp_hci_event_t *evt;
280         num_completed_data_blocks_evt_parms_t *parms;
281
282         uint16 len = HCI_EVT_PREAMBLE_SIZE + sizeof(num_completed_data_blocks_evt_parms_t);
283
284         /* update the event struct */
285         memset(&event, 0, sizeof(event));
286         event.version = hton16(BCM_EVENT_MSG_VERSION);
287         event.event_type = hton32(WLC_E_BTA_HCI_EVENT);
288         event.status = 0;
289         event.reason = 0;
290         event.auth_type = 0;
291         event.datalen = hton32(len);
292         event.flags = 0;
293
294         /* generate Number of Completed Blocks event */
295         evt = (amp_hci_event_t *)data;
296         evt->ecode = HCI_Number_of_Completed_Data_Blocks;
297         evt->plen = sizeof(num_completed_data_blocks_evt_parms_t);
298
299         parms = (num_completed_data_blocks_evt_parms_t *)evt->parms;
300         htol16_ua_store(dhdp->maxdatablks, (uint8 *)&parms->num_blocks);
301         parms->num_handles = 1;
302         htol16_ua_store(llh, (uint8 *)&parms->completed[0].handle);
303         parms->completed[0].pkts = 1;
304         parms->completed[0].blocks = 1;
305
306         dhd_sendup_event_common(dhdp, &event, data);
307 }
308
309 /* event callback */
310 void
311 dhd_bta_doevt(dhd_pub_t *dhdp, void *data_buf, uint data_len)
312 {
313         amp_hci_event_t *evt = (amp_hci_event_t *)data_buf;
314
315         ASSERT(dhdp);
316         ASSERT(evt);
317
318         switch (evt->ecode) {
319         case HCI_Command_Complete: {
320                 cmd_complete_parms_t *parms = (cmd_complete_parms_t *)evt->parms;
321                 switch (ltoh16_ua((uint8 *)&parms->opcode)) {
322                 case HCI_Read_Data_Block_Size: {
323                         read_data_block_size_evt_parms_t *parms2 =
324                                 (read_data_block_size_evt_parms_t *)parms->parms;
325                         dhdp->maxdatablks = ltoh16_ua((uint8 *)&parms2->data_block_num);
326                         break;
327                 }
328                 }
329                 break;
330         }
331
332         case HCI_Flush_Occurred: {
333                 flush_occurred_evt_parms_t *evt_parms = (flush_occurred_evt_parms_t *)evt->parms;
334                 dhd_bta_flush_hcidata(dhdp, ltoh16_ua((uint8 *)&evt_parms->handle));
335                 break;
336         }
337         default:
338                 break;
339         }
340 }