1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Shared Transport Line discipline driver Core |
4 | * This hooks up ST KIM driver and ST LL driver |
5 | * Copyright (C) 2009-2010 Texas Instruments |
6 | * Author: Pavan Savoy <pavan_savoy@ti.com> |
7 | */ |
8 | |
9 | #define pr_fmt(fmt) "(stc): " fmt |
10 | #include <linux/module.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/tty.h> |
13 | |
14 | #include <linux/seq_file.h> |
15 | #include <linux/skbuff.h> |
16 | |
17 | #include <linux/ti_wilink_st.h> |
18 | #include <linux/netdevice.h> |
19 | |
20 | /* |
21 | * function pointer pointing to either, |
22 | * st_kim_recv during registration to receive fw download responses |
23 | * st_int_recv after registration to receive proto stack responses |
24 | */ |
25 | static void (*st_recv)(void *disc_data, const u8 *ptr, size_t count); |
26 | |
27 | /********************************************************************/ |
28 | static void add_channel_to_table(struct st_data_s *st_gdata, |
29 | struct st_proto_s *new_proto) |
30 | { |
31 | pr_info("%s: id %d\n" , __func__, new_proto->chnl_id); |
32 | /* list now has the channel id as index itself */ |
33 | st_gdata->list[new_proto->chnl_id] = new_proto; |
34 | st_gdata->is_registered[new_proto->chnl_id] = true; |
35 | } |
36 | |
37 | static void remove_channel_from_table(struct st_data_s *st_gdata, |
38 | struct st_proto_s *proto) |
39 | { |
40 | pr_info("%s: id %d\n" , __func__, proto->chnl_id); |
41 | /* st_gdata->list[proto->chnl_id] = NULL; */ |
42 | st_gdata->is_registered[proto->chnl_id] = false; |
43 | } |
44 | |
45 | /* |
46 | * called from KIM during firmware download. |
47 | * |
48 | * This is a wrapper function to tty->ops->write_room. |
49 | * It returns number of free space available in |
50 | * uart tx buffer. |
51 | */ |
52 | int st_get_uart_wr_room(struct st_data_s *st_gdata) |
53 | { |
54 | if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) { |
55 | pr_err("tty unavailable to perform write" ); |
56 | return -1; |
57 | } |
58 | |
59 | return tty_write_room(tty: st_gdata->tty); |
60 | } |
61 | |
62 | /* |
63 | * can be called in from |
64 | * -- KIM (during fw download) |
65 | * -- ST Core (during st_write) |
66 | * |
67 | * This is the internal write function - a wrapper |
68 | * to tty->ops->write |
69 | */ |
70 | int st_int_write(struct st_data_s *st_gdata, |
71 | const unsigned char *data, int count) |
72 | { |
73 | struct tty_struct *tty; |
74 | if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) { |
75 | pr_err("tty unavailable to perform write" ); |
76 | return -EINVAL; |
77 | } |
78 | tty = st_gdata->tty; |
79 | #ifdef VERBOSE |
80 | print_hex_dump(KERN_DEBUG, "<out<" , DUMP_PREFIX_NONE, |
81 | 16, 1, data, count, 0); |
82 | #endif |
83 | return tty->ops->write(tty, data, count); |
84 | |
85 | } |
86 | |
87 | /* |
88 | * push the skb received to relevant |
89 | * protocol stacks |
90 | */ |
91 | static void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata) |
92 | { |
93 | pr_debug(" %s(prot:%d) " , __func__, chnl_id); |
94 | |
95 | if (unlikely |
96 | (st_gdata == NULL || st_gdata->rx_skb == NULL |
97 | || st_gdata->is_registered[chnl_id] == false)) { |
98 | pr_err("chnl_id %d not registered, no data to send?" , |
99 | chnl_id); |
100 | kfree_skb(skb: st_gdata->rx_skb); |
101 | return; |
102 | } |
103 | /* |
104 | * this cannot fail |
105 | * this shouldn't take long |
106 | * - should be just skb_queue_tail for the |
107 | * protocol stack driver |
108 | */ |
109 | if (likely(st_gdata->list[chnl_id]->recv != NULL)) { |
110 | if (unlikely |
111 | (st_gdata->list[chnl_id]->recv |
112 | (st_gdata->list[chnl_id]->priv_data, st_gdata->rx_skb) |
113 | != 0)) { |
114 | pr_err(" proto stack %d's ->recv failed" , chnl_id); |
115 | kfree_skb(skb: st_gdata->rx_skb); |
116 | return; |
117 | } |
118 | } else { |
119 | pr_err(" proto stack %d's ->recv null" , chnl_id); |
120 | kfree_skb(skb: st_gdata->rx_skb); |
121 | } |
122 | return; |
123 | } |
124 | |
125 | /* |
126 | * st_reg_complete - to call registration complete callbacks |
127 | * of all protocol stack drivers |
128 | * This function is being called with spin lock held, protocol drivers are |
129 | * only expected to complete their waits and do nothing more than that. |
130 | */ |
131 | static void st_reg_complete(struct st_data_s *st_gdata, int err) |
132 | { |
133 | unsigned char i = 0; |
134 | pr_info(" %s " , __func__); |
135 | for (i = 0; i < ST_MAX_CHANNELS; i++) { |
136 | if (likely(st_gdata != NULL && |
137 | st_gdata->is_registered[i] == true && |
138 | st_gdata->list[i]->reg_complete_cb != NULL)) { |
139 | st_gdata->list[i]->reg_complete_cb |
140 | (st_gdata->list[i]->priv_data, err); |
141 | pr_info("protocol %d's cb sent %d\n" , i, err); |
142 | if (err) { /* cleanup registered protocol */ |
143 | st_gdata->is_registered[i] = false; |
144 | if (st_gdata->protos_registered) |
145 | st_gdata->protos_registered--; |
146 | } |
147 | } |
148 | } |
149 | } |
150 | |
151 | static inline int st_check_data_len(struct st_data_s *st_gdata, |
152 | unsigned char chnl_id, int len) |
153 | { |
154 | int room = skb_tailroom(skb: st_gdata->rx_skb); |
155 | |
156 | pr_debug("len %d room %d" , len, room); |
157 | |
158 | if (!len) { |
159 | /* |
160 | * Received packet has only packet header and |
161 | * has zero length payload. So, ask ST CORE to |
162 | * forward the packet to protocol driver (BT/FM/GPS) |
163 | */ |
164 | st_send_frame(chnl_id, st_gdata); |
165 | |
166 | } else if (len > room) { |
167 | /* |
168 | * Received packet's payload length is larger. |
169 | * We can't accommodate it in created skb. |
170 | */ |
171 | pr_err("Data length is too large len %d room %d" , len, |
172 | room); |
173 | kfree_skb(skb: st_gdata->rx_skb); |
174 | } else { |
175 | /* |
176 | * Packet header has non-zero payload length and |
177 | * we have enough space in created skb. Lets read |
178 | * payload data */ |
179 | st_gdata->rx_state = ST_W4_DATA; |
180 | st_gdata->rx_count = len; |
181 | return len; |
182 | } |
183 | |
184 | /* Change ST state to continue to process next packet */ |
185 | st_gdata->rx_state = ST_W4_PACKET_TYPE; |
186 | st_gdata->rx_skb = NULL; |
187 | st_gdata->rx_count = 0; |
188 | st_gdata->rx_chnl = 0; |
189 | |
190 | return 0; |
191 | } |
192 | |
193 | /* |
194 | * st_wakeup_ack - internal function for action when wake-up ack |
195 | * received |
196 | */ |
197 | static inline void st_wakeup_ack(struct st_data_s *st_gdata, |
198 | unsigned char cmd) |
199 | { |
200 | struct sk_buff *waiting_skb; |
201 | unsigned long flags = 0; |
202 | |
203 | spin_lock_irqsave(&st_gdata->lock, flags); |
204 | /* |
205 | * de-Q from waitQ and Q in txQ now that the |
206 | * chip is awake |
207 | */ |
208 | while ((waiting_skb = skb_dequeue(list: &st_gdata->tx_waitq))) |
209 | skb_queue_tail(list: &st_gdata->txq, newsk: waiting_skb); |
210 | |
211 | /* state forwarded to ST LL */ |
212 | st_ll_sleep_state(st_gdata, (unsigned long)cmd); |
213 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
214 | |
215 | /* wake up to send the recently copied skbs from waitQ */ |
216 | st_tx_wakeup(st_data: st_gdata); |
217 | } |
218 | |
219 | /* |
220 | * st_int_recv - ST's internal receive function. |
221 | * Decodes received RAW data and forwards to corresponding |
222 | * client drivers (Bluetooth,FM,GPS..etc). |
223 | * This can receive various types of packets, |
224 | * HCI-Events, ACL, SCO, 4 types of HCI-LL PM packets |
225 | * CH-8 packets from FM, CH-9 packets from GPS cores. |
226 | */ |
227 | static void st_int_recv(void *disc_data, const u8 *ptr, size_t count) |
228 | { |
229 | struct st_proto_s *proto; |
230 | unsigned short payload_len = 0; |
231 | int len = 0; |
232 | unsigned char type = 0; |
233 | unsigned char *plen; |
234 | struct st_data_s *st_gdata = (struct st_data_s *)disc_data; |
235 | unsigned long flags; |
236 | |
237 | if (st_gdata == NULL) { |
238 | pr_err(" received null from TTY " ); |
239 | return; |
240 | } |
241 | |
242 | pr_debug("count %zu rx_state %ld" |
243 | "rx_count %ld" , count, st_gdata->rx_state, |
244 | st_gdata->rx_count); |
245 | |
246 | spin_lock_irqsave(&st_gdata->lock, flags); |
247 | /* Decode received bytes here */ |
248 | while (count) { |
249 | if (st_gdata->rx_count) { |
250 | len = min_t(unsigned int, st_gdata->rx_count, count); |
251 | skb_put_data(skb: st_gdata->rx_skb, data: ptr, len); |
252 | st_gdata->rx_count -= len; |
253 | count -= len; |
254 | ptr += len; |
255 | |
256 | if (st_gdata->rx_count) |
257 | continue; |
258 | |
259 | /* Check ST RX state machine , where are we? */ |
260 | switch (st_gdata->rx_state) { |
261 | /* Waiting for complete packet ? */ |
262 | case ST_W4_DATA: |
263 | pr_debug("Complete pkt received" ); |
264 | /* |
265 | * Ask ST CORE to forward |
266 | * the packet to protocol driver |
267 | */ |
268 | st_send_frame(chnl_id: st_gdata->rx_chnl, st_gdata); |
269 | |
270 | st_gdata->rx_state = ST_W4_PACKET_TYPE; |
271 | st_gdata->rx_skb = NULL; |
272 | continue; |
273 | /* parse the header to know details */ |
274 | case ST_W4_HEADER: |
275 | proto = st_gdata->list[st_gdata->rx_chnl]; |
276 | plen = |
277 | &st_gdata->rx_skb->data |
278 | [proto->offset_len_in_hdr]; |
279 | pr_debug("plen pointing to %x\n" , *plen); |
280 | if (proto->len_size == 1) /* 1 byte len field */ |
281 | payload_len = *(unsigned char *)plen; |
282 | else if (proto->len_size == 2) |
283 | payload_len = |
284 | __le16_to_cpu(*(unsigned short *)plen); |
285 | else |
286 | pr_info("%s: invalid length " |
287 | "for id %d\n" , |
288 | __func__, proto->chnl_id); |
289 | st_check_data_len(st_gdata, chnl_id: proto->chnl_id, |
290 | len: payload_len); |
291 | pr_debug("off %d, pay len %d\n" , |
292 | proto->offset_len_in_hdr, payload_len); |
293 | continue; |
294 | } /* end of switch rx_state */ |
295 | } |
296 | |
297 | /* end of if rx_count */ |
298 | |
299 | /* |
300 | * Check first byte of packet and identify module |
301 | * owner (BT/FM/GPS) |
302 | */ |
303 | switch (*ptr) { |
304 | case LL_SLEEP_IND: |
305 | case LL_SLEEP_ACK: |
306 | case LL_WAKE_UP_IND: |
307 | pr_debug("PM packet" ); |
308 | /* |
309 | * this takes appropriate action based on |
310 | * sleep state received -- |
311 | */ |
312 | st_ll_sleep_state(st_gdata, *ptr); |
313 | /* |
314 | * if WAKEUP_IND collides copy from waitq to txq |
315 | * and assume chip awake |
316 | */ |
317 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
318 | if (st_ll_getstate(st_gdata) == ST_LL_AWAKE) |
319 | st_wakeup_ack(st_gdata, LL_WAKE_UP_ACK); |
320 | spin_lock_irqsave(&st_gdata->lock, flags); |
321 | |
322 | ptr++; |
323 | count--; |
324 | continue; |
325 | case LL_WAKE_UP_ACK: |
326 | pr_debug("PM packet" ); |
327 | |
328 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
329 | /* wake up ack received */ |
330 | st_wakeup_ack(st_gdata, cmd: *ptr); |
331 | spin_lock_irqsave(&st_gdata->lock, flags); |
332 | |
333 | ptr++; |
334 | count--; |
335 | continue; |
336 | /* Unknown packet? */ |
337 | default: |
338 | type = *ptr; |
339 | |
340 | /* |
341 | * Default case means non-HCILL packets, |
342 | * possibilities are packets for: |
343 | * (a) valid protocol - Supported Protocols within |
344 | * the ST_MAX_CHANNELS. |
345 | * (b) registered protocol - Checked by |
346 | * "st_gdata->list[type] == NULL)" are supported |
347 | * protocols only. |
348 | * Rules out any invalid protocol and |
349 | * unregistered protocols with channel ID < 16. |
350 | */ |
351 | |
352 | if ((type >= ST_MAX_CHANNELS) || |
353 | (st_gdata->list[type] == NULL)) { |
354 | pr_err("chip/interface misbehavior: " |
355 | "dropping frame starting " |
356 | "with 0x%02x\n" , type); |
357 | goto done; |
358 | } |
359 | |
360 | st_gdata->rx_skb = alloc_skb( |
361 | size: st_gdata->list[type]->max_frame_size, |
362 | GFP_ATOMIC); |
363 | if (st_gdata->rx_skb == NULL) { |
364 | pr_err("out of memory: dropping\n" ); |
365 | goto done; |
366 | } |
367 | |
368 | skb_reserve(skb: st_gdata->rx_skb, |
369 | len: st_gdata->list[type]->reserve); |
370 | /* next 2 required for BT only */ |
371 | st_gdata->rx_skb->cb[0] = type; /*pkt_type*/ |
372 | st_gdata->rx_skb->cb[1] = 0; /*incoming*/ |
373 | st_gdata->rx_chnl = *ptr; |
374 | st_gdata->rx_state = ST_W4_HEADER; |
375 | st_gdata->rx_count = st_gdata->list[type]->hdr_len; |
376 | pr_debug("rx_count %ld\n" , st_gdata->rx_count); |
377 | } |
378 | ptr++; |
379 | count--; |
380 | } |
381 | done: |
382 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
383 | pr_debug("done %s" , __func__); |
384 | return; |
385 | } |
386 | |
387 | /* |
388 | * st_int_dequeue - internal de-Q function. |
389 | * If the previous data set was not written |
390 | * completely, return that skb which has the pending data. |
391 | * In normal cases, return top of txq. |
392 | */ |
393 | static struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata) |
394 | { |
395 | struct sk_buff *returning_skb; |
396 | |
397 | pr_debug("%s" , __func__); |
398 | if (st_gdata->tx_skb != NULL) { |
399 | returning_skb = st_gdata->tx_skb; |
400 | st_gdata->tx_skb = NULL; |
401 | return returning_skb; |
402 | } |
403 | return skb_dequeue(list: &st_gdata->txq); |
404 | } |
405 | |
406 | /* |
407 | * st_int_enqueue - internal Q-ing function. |
408 | * Will either Q the skb to txq or the tx_waitq |
409 | * depending on the ST LL state. |
410 | * If the chip is asleep, then Q it onto waitq and |
411 | * wakeup the chip. |
412 | * txq and waitq needs protection since the other contexts |
413 | * may be sending data, waking up chip. |
414 | */ |
415 | static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb) |
416 | { |
417 | unsigned long flags = 0; |
418 | |
419 | pr_debug("%s" , __func__); |
420 | spin_lock_irqsave(&st_gdata->lock, flags); |
421 | |
422 | switch (st_ll_getstate(st_gdata)) { |
423 | case ST_LL_AWAKE: |
424 | pr_debug("ST LL is AWAKE, sending normally" ); |
425 | skb_queue_tail(list: &st_gdata->txq, newsk: skb); |
426 | break; |
427 | case ST_LL_ASLEEP_TO_AWAKE: |
428 | skb_queue_tail(list: &st_gdata->tx_waitq, newsk: skb); |
429 | break; |
430 | case ST_LL_AWAKE_TO_ASLEEP: |
431 | pr_err("ST LL is illegal state(%ld)," |
432 | "purging received skb." , st_ll_getstate(st_gdata)); |
433 | dev_kfree_skb_irq(skb); |
434 | break; |
435 | case ST_LL_ASLEEP: |
436 | skb_queue_tail(list: &st_gdata->tx_waitq, newsk: skb); |
437 | st_ll_wakeup(st_gdata); |
438 | break; |
439 | default: |
440 | pr_err("ST LL is illegal state(%ld)," |
441 | "purging received skb." , st_ll_getstate(st_gdata)); |
442 | dev_kfree_skb_irq(skb); |
443 | break; |
444 | } |
445 | |
446 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
447 | pr_debug("done %s" , __func__); |
448 | return; |
449 | } |
450 | |
451 | /* |
452 | * internal wakeup function |
453 | * called from either |
454 | * - TTY layer when write's finished |
455 | * - st_write (in context of the protocol stack) |
456 | */ |
457 | static void work_fn_write_wakeup(struct work_struct *work) |
458 | { |
459 | struct st_data_s *st_gdata = container_of(work, struct st_data_s, |
460 | work_write_wakeup); |
461 | |
462 | st_tx_wakeup(st_data: (void *)st_gdata); |
463 | } |
464 | void st_tx_wakeup(struct st_data_s *st_data) |
465 | { |
466 | struct sk_buff *skb; |
467 | unsigned long flags; /* for irq save flags */ |
468 | pr_debug("%s" , __func__); |
469 | /* check for sending & set flag sending here */ |
470 | if (test_and_set_bit(ST_TX_SENDING, addr: &st_data->tx_state)) { |
471 | pr_debug("ST already sending" ); |
472 | /* keep sending */ |
473 | set_bit(ST_TX_WAKEUP, addr: &st_data->tx_state); |
474 | return; |
475 | /* TX_WAKEUP will be checked in another |
476 | * context |
477 | */ |
478 | } |
479 | do { /* come back if st_tx_wakeup is set */ |
480 | /* woke-up to write */ |
481 | clear_bit(ST_TX_WAKEUP, addr: &st_data->tx_state); |
482 | while ((skb = st_int_dequeue(st_gdata: st_data))) { |
483 | int len; |
484 | spin_lock_irqsave(&st_data->lock, flags); |
485 | /* enable wake-up from TTY */ |
486 | set_bit(TTY_DO_WRITE_WAKEUP, addr: &st_data->tty->flags); |
487 | len = st_int_write(st_gdata: st_data, data: skb->data, count: skb->len); |
488 | skb_pull(skb, len); |
489 | /* if skb->len = len as expected, skb->len=0 */ |
490 | if (skb->len) { |
491 | /* would be the next skb to be sent */ |
492 | st_data->tx_skb = skb; |
493 | spin_unlock_irqrestore(lock: &st_data->lock, flags); |
494 | break; |
495 | } |
496 | dev_kfree_skb_irq(skb); |
497 | spin_unlock_irqrestore(lock: &st_data->lock, flags); |
498 | } |
499 | /* if wake-up is set in another context- restart sending */ |
500 | } while (test_bit(ST_TX_WAKEUP, &st_data->tx_state)); |
501 | |
502 | /* clear flag sending */ |
503 | clear_bit(ST_TX_SENDING, addr: &st_data->tx_state); |
504 | } |
505 | |
506 | /********************************************************************/ |
507 | /* functions called from ST KIM |
508 | */ |
509 | void kim_st_list_protocols(struct st_data_s *st_gdata, void *buf) |
510 | { |
511 | seq_printf(m: buf, fmt: "[%d]\nBT=%c\nFM=%c\nGPS=%c\n" , |
512 | st_gdata->protos_registered, |
513 | st_gdata->is_registered[0x04] == true ? 'R' : 'U', |
514 | st_gdata->is_registered[0x08] == true ? 'R' : 'U', |
515 | st_gdata->is_registered[0x09] == true ? 'R' : 'U'); |
516 | } |
517 | |
518 | /********************************************************************/ |
519 | /* |
520 | * functions called from protocol stack drivers |
521 | * to be EXPORT-ed |
522 | */ |
523 | long st_register(struct st_proto_s *new_proto) |
524 | { |
525 | struct st_data_s *st_gdata; |
526 | long err = 0; |
527 | unsigned long flags = 0; |
528 | |
529 | st_kim_ref(&st_gdata, 0); |
530 | if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL |
531 | || new_proto->reg_complete_cb == NULL) { |
532 | pr_err("gdata/new_proto/recv or reg_complete_cb not ready" ); |
533 | return -EINVAL; |
534 | } |
535 | |
536 | if (new_proto->chnl_id >= ST_MAX_CHANNELS) { |
537 | pr_err("chnl_id %d not supported" , new_proto->chnl_id); |
538 | return -EPROTONOSUPPORT; |
539 | } |
540 | |
541 | if (st_gdata->is_registered[new_proto->chnl_id] == true) { |
542 | pr_err("chnl_id %d already registered" , new_proto->chnl_id); |
543 | return -EALREADY; |
544 | } |
545 | |
546 | /* can be from process context only */ |
547 | spin_lock_irqsave(&st_gdata->lock, flags); |
548 | |
549 | if (test_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state)) { |
550 | pr_info(" ST_REG_IN_PROGRESS:%d " , new_proto->chnl_id); |
551 | /* fw download in progress */ |
552 | |
553 | add_channel_to_table(st_gdata, new_proto); |
554 | st_gdata->protos_registered++; |
555 | new_proto->write = st_write; |
556 | |
557 | set_bit(ST_REG_PENDING, addr: &st_gdata->st_state); |
558 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
559 | return -EINPROGRESS; |
560 | } else if (st_gdata->protos_registered == ST_EMPTY) { |
561 | pr_info(" chnl_id list empty :%d " , new_proto->chnl_id); |
562 | set_bit(ST_REG_IN_PROGRESS, addr: &st_gdata->st_state); |
563 | st_recv = st_kim_recv; |
564 | |
565 | /* enable the ST LL - to set default chip state */ |
566 | st_ll_enable(st_gdata); |
567 | |
568 | /* release lock previously held - re-locked below */ |
569 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
570 | |
571 | /* |
572 | * this may take a while to complete |
573 | * since it involves BT fw download |
574 | */ |
575 | err = st_kim_start(st_gdata->kim_data); |
576 | if (err != 0) { |
577 | clear_bit(ST_REG_IN_PROGRESS, addr: &st_gdata->st_state); |
578 | if ((st_gdata->protos_registered != ST_EMPTY) && |
579 | (test_bit(ST_REG_PENDING, &st_gdata->st_state))) { |
580 | pr_err(" KIM failure complete callback " ); |
581 | spin_lock_irqsave(&st_gdata->lock, flags); |
582 | st_reg_complete(st_gdata, err); |
583 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
584 | clear_bit(ST_REG_PENDING, addr: &st_gdata->st_state); |
585 | } |
586 | return -EINVAL; |
587 | } |
588 | |
589 | spin_lock_irqsave(&st_gdata->lock, flags); |
590 | |
591 | clear_bit(ST_REG_IN_PROGRESS, addr: &st_gdata->st_state); |
592 | st_recv = st_int_recv; |
593 | |
594 | /* |
595 | * this is where all pending registration |
596 | * are signalled to be complete by calling callback functions |
597 | */ |
598 | if ((st_gdata->protos_registered != ST_EMPTY) && |
599 | (test_bit(ST_REG_PENDING, &st_gdata->st_state))) { |
600 | pr_debug(" call reg complete callback " ); |
601 | st_reg_complete(st_gdata, err: 0); |
602 | } |
603 | clear_bit(ST_REG_PENDING, addr: &st_gdata->st_state); |
604 | |
605 | /* |
606 | * check for already registered once more, |
607 | * since the above check is old |
608 | */ |
609 | if (st_gdata->is_registered[new_proto->chnl_id] == true) { |
610 | pr_err(" proto %d already registered " , |
611 | new_proto->chnl_id); |
612 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
613 | return -EALREADY; |
614 | } |
615 | |
616 | add_channel_to_table(st_gdata, new_proto); |
617 | st_gdata->protos_registered++; |
618 | new_proto->write = st_write; |
619 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
620 | return err; |
621 | } |
622 | /* if fw is already downloaded & new stack registers protocol */ |
623 | else { |
624 | add_channel_to_table(st_gdata, new_proto); |
625 | st_gdata->protos_registered++; |
626 | new_proto->write = st_write; |
627 | |
628 | /* lock already held before entering else */ |
629 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
630 | return err; |
631 | } |
632 | } |
633 | EXPORT_SYMBOL_GPL(st_register); |
634 | |
635 | /* |
636 | * to unregister a protocol - |
637 | * to be called from protocol stack driver |
638 | */ |
639 | long st_unregister(struct st_proto_s *proto) |
640 | { |
641 | long err = 0; |
642 | unsigned long flags = 0; |
643 | struct st_data_s *st_gdata; |
644 | |
645 | pr_debug("%s: %d " , __func__, proto->chnl_id); |
646 | |
647 | st_kim_ref(&st_gdata, 0); |
648 | if (!st_gdata || proto->chnl_id >= ST_MAX_CHANNELS) { |
649 | pr_err(" chnl_id %d not supported" , proto->chnl_id); |
650 | return -EPROTONOSUPPORT; |
651 | } |
652 | |
653 | spin_lock_irqsave(&st_gdata->lock, flags); |
654 | |
655 | if (st_gdata->is_registered[proto->chnl_id] == false) { |
656 | pr_err(" chnl_id %d not registered" , proto->chnl_id); |
657 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
658 | return -EPROTONOSUPPORT; |
659 | } |
660 | |
661 | if (st_gdata->protos_registered) |
662 | st_gdata->protos_registered--; |
663 | |
664 | remove_channel_from_table(st_gdata, proto); |
665 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
666 | |
667 | if ((st_gdata->protos_registered == ST_EMPTY) && |
668 | (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) { |
669 | pr_info(" all chnl_ids unregistered " ); |
670 | |
671 | /* stop traffic on tty */ |
672 | if (st_gdata->tty) { |
673 | tty_ldisc_flush(tty: st_gdata->tty); |
674 | stop_tty(tty: st_gdata->tty); |
675 | } |
676 | |
677 | /* all chnl_ids now unregistered */ |
678 | st_kim_stop(st_gdata->kim_data); |
679 | /* disable ST LL */ |
680 | st_ll_disable(st_gdata); |
681 | } |
682 | return err; |
683 | } |
684 | |
685 | /* |
686 | * called in protocol stack drivers |
687 | * via the write function pointer |
688 | */ |
689 | long st_write(struct sk_buff *skb) |
690 | { |
691 | struct st_data_s *st_gdata; |
692 | long len; |
693 | |
694 | st_kim_ref(&st_gdata, 0); |
695 | if (unlikely(skb == NULL || st_gdata == NULL |
696 | || st_gdata->tty == NULL)) { |
697 | pr_err("data/tty unavailable to perform write" ); |
698 | return -EINVAL; |
699 | } |
700 | |
701 | pr_debug("%d to be written" , skb->len); |
702 | len = skb->len; |
703 | |
704 | /* st_ll to decide where to enqueue the skb */ |
705 | st_int_enqueue(st_gdata, skb); |
706 | /* wake up */ |
707 | st_tx_wakeup(st_data: st_gdata); |
708 | |
709 | /* return number of bytes written */ |
710 | return len; |
711 | } |
712 | |
713 | /* for protocols making use of shared transport */ |
714 | EXPORT_SYMBOL_GPL(st_unregister); |
715 | |
716 | /********************************************************************/ |
717 | /* |
718 | * functions called from TTY layer |
719 | */ |
720 | static int st_tty_open(struct tty_struct *tty) |
721 | { |
722 | struct st_data_s *st_gdata; |
723 | pr_info("%s " , __func__); |
724 | |
725 | st_kim_ref(&st_gdata, 0); |
726 | st_gdata->tty = tty; |
727 | tty->disc_data = st_gdata; |
728 | |
729 | /* don't do an wakeup for now */ |
730 | clear_bit(TTY_DO_WRITE_WAKEUP, addr: &tty->flags); |
731 | |
732 | /* mem already allocated |
733 | */ |
734 | tty->receive_room = 65536; |
735 | /* Flush any pending characters in the driver and discipline. */ |
736 | tty_ldisc_flush(tty); |
737 | tty_driver_flush_buffer(tty); |
738 | /* |
739 | * signal to UIM via KIM that - |
740 | * installation of N_TI_WL ldisc is complete |
741 | */ |
742 | st_kim_complete(st_gdata->kim_data); |
743 | pr_debug("done %s" , __func__); |
744 | |
745 | return 0; |
746 | } |
747 | |
748 | static void st_tty_close(struct tty_struct *tty) |
749 | { |
750 | unsigned char i; |
751 | unsigned long flags; |
752 | struct st_data_s *st_gdata = tty->disc_data; |
753 | |
754 | pr_info("%s " , __func__); |
755 | |
756 | /* |
757 | * TODO: |
758 | * if a protocol has been registered & line discipline |
759 | * un-installed for some reason - what should be done ? |
760 | */ |
761 | spin_lock_irqsave(&st_gdata->lock, flags); |
762 | for (i = ST_BT; i < ST_MAX_CHANNELS; i++) { |
763 | if (st_gdata->is_registered[i] == true) |
764 | pr_err("%d not un-registered" , i); |
765 | st_gdata->list[i] = NULL; |
766 | st_gdata->is_registered[i] = false; |
767 | } |
768 | st_gdata->protos_registered = 0; |
769 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
770 | /* |
771 | * signal to UIM via KIM that - |
772 | * N_TI_WL ldisc is un-installed |
773 | */ |
774 | st_kim_complete(st_gdata->kim_data); |
775 | st_gdata->tty = NULL; |
776 | /* Flush any pending characters in the driver and discipline. */ |
777 | tty_ldisc_flush(tty); |
778 | tty_driver_flush_buffer(tty); |
779 | |
780 | spin_lock_irqsave(&st_gdata->lock, flags); |
781 | /* empty out txq and tx_waitq */ |
782 | skb_queue_purge(list: &st_gdata->txq); |
783 | skb_queue_purge(list: &st_gdata->tx_waitq); |
784 | /* reset the TTY Rx states of ST */ |
785 | st_gdata->rx_count = 0; |
786 | st_gdata->rx_state = ST_W4_PACKET_TYPE; |
787 | kfree_skb(skb: st_gdata->rx_skb); |
788 | st_gdata->rx_skb = NULL; |
789 | spin_unlock_irqrestore(lock: &st_gdata->lock, flags); |
790 | |
791 | pr_debug("%s: done " , __func__); |
792 | } |
793 | |
794 | static void st_tty_receive(struct tty_struct *tty, const u8 *data, |
795 | const u8 *tty_flags, size_t count) |
796 | { |
797 | #ifdef VERBOSE |
798 | print_hex_dump(KERN_DEBUG, ">in>" , DUMP_PREFIX_NONE, |
799 | 16, 1, data, count, 0); |
800 | #endif |
801 | |
802 | /* |
803 | * if fw download is in progress then route incoming data |
804 | * to KIM for validation |
805 | */ |
806 | st_recv(tty->disc_data, data, count); |
807 | pr_debug("done %s" , __func__); |
808 | } |
809 | |
810 | /* |
811 | * wake-up function called in from the TTY layer |
812 | * inside the internal wakeup function will be called |
813 | */ |
814 | static void st_tty_wakeup(struct tty_struct *tty) |
815 | { |
816 | struct st_data_s *st_gdata = tty->disc_data; |
817 | pr_debug("%s " , __func__); |
818 | /* don't do an wakeup for now */ |
819 | clear_bit(TTY_DO_WRITE_WAKEUP, addr: &tty->flags); |
820 | |
821 | /* |
822 | * schedule the internal wakeup instead of calling directly to |
823 | * avoid lockup (port->lock needed in tty->ops->write is |
824 | * already taken here |
825 | */ |
826 | schedule_work(work: &st_gdata->work_write_wakeup); |
827 | } |
828 | |
829 | static void st_tty_flush_buffer(struct tty_struct *tty) |
830 | { |
831 | struct st_data_s *st_gdata = tty->disc_data; |
832 | pr_debug("%s " , __func__); |
833 | |
834 | kfree_skb(skb: st_gdata->tx_skb); |
835 | st_gdata->tx_skb = NULL; |
836 | |
837 | tty_driver_flush_buffer(tty); |
838 | return; |
839 | } |
840 | |
841 | static struct tty_ldisc_ops st_ldisc_ops = { |
842 | .num = N_TI_WL, |
843 | .name = "n_st" , |
844 | .open = st_tty_open, |
845 | .close = st_tty_close, |
846 | .receive_buf = st_tty_receive, |
847 | .write_wakeup = st_tty_wakeup, |
848 | .flush_buffer = st_tty_flush_buffer, |
849 | .owner = THIS_MODULE |
850 | }; |
851 | |
852 | /********************************************************************/ |
853 | int st_core_init(struct st_data_s **core_data) |
854 | { |
855 | struct st_data_s *st_gdata; |
856 | long err; |
857 | |
858 | err = tty_register_ldisc(new_ldisc: &st_ldisc_ops); |
859 | if (err) { |
860 | pr_err("error registering %d line discipline %ld" , |
861 | N_TI_WL, err); |
862 | return err; |
863 | } |
864 | pr_debug("registered n_shared line discipline" ); |
865 | |
866 | st_gdata = kzalloc(size: sizeof(struct st_data_s), GFP_KERNEL); |
867 | if (!st_gdata) { |
868 | pr_err("memory allocation failed" ); |
869 | err = -ENOMEM; |
870 | goto err_unreg_ldisc; |
871 | } |
872 | |
873 | /* Initialize ST TxQ and Tx waitQ queue head. All BT/FM/GPS module skb's |
874 | * will be pushed in this queue for actual transmission. |
875 | */ |
876 | skb_queue_head_init(list: &st_gdata->txq); |
877 | skb_queue_head_init(list: &st_gdata->tx_waitq); |
878 | |
879 | /* Locking used in st_int_enqueue() to avoid multiple execution */ |
880 | spin_lock_init(&st_gdata->lock); |
881 | |
882 | err = st_ll_init(st_gdata); |
883 | if (err) { |
884 | pr_err("error during st_ll initialization(%ld)" , err); |
885 | goto err_free_gdata; |
886 | } |
887 | |
888 | INIT_WORK(&st_gdata->work_write_wakeup, work_fn_write_wakeup); |
889 | |
890 | *core_data = st_gdata; |
891 | return 0; |
892 | err_free_gdata: |
893 | kfree(objp: st_gdata); |
894 | err_unreg_ldisc: |
895 | tty_unregister_ldisc(ldisc: &st_ldisc_ops); |
896 | return err; |
897 | } |
898 | |
899 | void st_core_exit(struct st_data_s *st_gdata) |
900 | { |
901 | long err; |
902 | /* internal module cleanup */ |
903 | err = st_ll_deinit(st_gdata); |
904 | if (err) |
905 | pr_err("error during deinit of ST LL %ld" , err); |
906 | |
907 | if (st_gdata != NULL) { |
908 | /* Free ST Tx Qs and skbs */ |
909 | skb_queue_purge(list: &st_gdata->txq); |
910 | skb_queue_purge(list: &st_gdata->tx_waitq); |
911 | kfree_skb(skb: st_gdata->rx_skb); |
912 | kfree_skb(skb: st_gdata->tx_skb); |
913 | /* TTY ldisc cleanup */ |
914 | tty_unregister_ldisc(ldisc: &st_ldisc_ops); |
915 | /* free the global data pointer */ |
916 | kfree(objp: st_gdata); |
917 | } |
918 | } |
919 | |