MT6620: add the new driver JB2 V1.0
[firefly-linux-kernel-4.4.55.git] / drivers / mtk_wcn_combo / common / linux / stp_uart.c
1 #include <linux/version.h>
2 #include <linux/module.h>
3
4 #include <linux/kernel.h>
5 #include <linux/init.h>
6 #include <linux/types.h>
7 #include <linux/fcntl.h>
8 #include <linux/interrupt.h>
9 #include <linux/ptrace.h>
10 #include <linux/poll.h>
11
12 #include <linux/slab.h>
13 #include <linux/tty.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/signal.h>
17 #include <linux/ioctl.h>
18 #include <linux/skbuff.h>
19
20 #include <linux/spinlock.h>
21
22 #include <linux/time.h>
23 #include <linux/delay.h>
24 #include <linux/err.h>
25 #include <linux/kfifo.h>
26
27
28 #include "stp_exp.h"
29
30 #define N_MTKSTP              (15 + 1) /* refer to linux tty.h use N_HCI. */
31
32 #define HCIUARTSETPROTO        _IOW('U', 200, int)
33
34 #define MAX(a,b)        ((a) > (b) ? (a) : (b))
35 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
36
37 #define PFX                         "[UART] "
38 #define UART_LOG_LOUD                 4
39 #define UART_LOG_DBG                  3
40 #define UART_LOG_INFO                 2
41 #define UART_LOG_WARN                 1
42 #define UART_LOG_ERR                  0
43
44 #define MAX_PACKET_ALLOWED                2000
45
46
47 unsigned int gDbgLevel = UART_LOG_INFO;
48
49 #define UART_DBG_FUNC(fmt, arg...)    if(gDbgLevel >= UART_LOG_DBG){  printk(KERN_DEBUG PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
50 #define UART_INFO_FUNC(fmt, arg...)   if(gDbgLevel >= UART_LOG_INFO){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
51 #define UART_WARN_FUNC(fmt, arg...)   if(gDbgLevel >= UART_LOG_WARN){ printk(PFX "%s: "  fmt, __FUNCTION__ ,##arg);}
52 #define UART_ERR_FUNC(fmt, arg...)    if(gDbgLevel >= UART_LOG_ERR){  printk(PFX "%s: "   fmt, __FUNCTION__ ,##arg);}
53 #define UART_TRC_FUNC(f)              if(gDbgLevel >= UART_LOG_DBG){  printk(KERN_DEBUG PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);}
54
55
56 #include <linux/kfifo.h>
57 #define LDISC_RX_TASKLET  0
58 #define LDISC_RX_WORK  1
59
60 #if WMT_UART_RX_MODE_WORK
61 #define LDISC_RX LDISC_RX_WORK
62 #else
63 #define LDISC_RX LDISC_RX_TASKLET
64 #endif
65
66 #if (LDISC_RX == LDISC_RX_TASKLET)
67 #define LDISC_RX_FIFO_SIZE (0x20000) /*8192 bytes*/
68 struct kfifo *g_stp_uart_rx_fifo = NULL;
69 spinlock_t    g_stp_uart_rx_fifo_spinlock;
70 struct tasklet_struct g_stp_uart_rx_fifo_tasklet;
71 #define RX_BUFFER_LEN 1024
72 unsigned char g_rx_data[RX_BUFFER_LEN];
73
74 //static DEFINE_RWLOCK(g_stp_uart_rx_handling_lock);
75 #elif (LDISC_RX == LDISC_RX_WORK)
76
77 #define LDISC_RX_FIFO_SIZE (0x4000) /* 16K bytes shall be enough...... */
78 #define LDISC_RX_BUF_SIZE (2048) /* 2K bytes in one shot is enough */
79
80 UINT8 *g_stp_uart_rx_buf; /* for stp rx data parsing */
81 struct kfifo *g_stp_uart_rx_fifo = NULL; /* for uart tty data receiving */
82 spinlock_t g_stp_uart_rx_fifo_spinlock; /* fifo spinlock */
83 struct workqueue_struct *g_stp_uart_rx_wq; /* rx work queue (do not use system_wq) */
84 struct work_struct *g_stp_uart_rx_work; /* rx work */
85
86 #endif
87
88 struct tty_struct *stp_tty = 0x0;
89
90 unsigned char tx_buf[MTKSTP_BUFFER_SIZE] = {0x0};
91 int rd_idx = 0;
92 int wr_idx = 0;
93 //struct semaphore buf_mtx;
94 spinlock_t         buf_lock;
95 static INT32  mtk_wcn_uart_tx(const UINT8 *data, const UINT32 size, UINT32 *written_size);
96
97
98 static inline int stp_uart_tx_wakeup(struct tty_struct *tty)
99 {
100     int len = 0;
101     int written = 0;
102     int written_count = 0;
103     static int i = 0;
104     //unsigned long flags;
105     // get data from ring buffer
106 //    down(&buf_mtx);
107     UART_DBG_FUNC("++\n");
108 ////    spin_lock_irqsave(&buf_lock, flags);
109
110 #if 0
111     if((i > 1000) && (i % 5)== 0)
112     {
113         UART_INFO_FUNC("i=(%d), ****** drop data from uart******\n", i);
114         i++;
115         return 0;
116     } else {
117
118         UART_INFO_FUNC("i=(%d)at stp uart **\n", i);
119     }
120 #endif
121
122     len = (wr_idx >= rd_idx) ? (wr_idx - rd_idx) : (MTKSTP_BUFFER_SIZE - rd_idx);
123     if(len > 0 && len < MAX_PACKET_ALLOWED)
124     {
125         i++;
126         /*
127          *     ops->write is called by the kernel to write a series of
128          *     characters to the tty device.  The characters may come from
129          *     user space or kernel space.  This routine will return the
130          *    number of characters actually accepted for writing.
131         */
132         set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
133         written = tty->ops->write(tty, &tx_buf[rd_idx], len);
134         if(written != len) {
135            UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]tty-ops->write FAIL!len(%d)wr(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, written, wr_idx, rd_idx);
136            return -1;
137         }
138         written_count = written;
139         //printk("len = %d, written = %d\n", len, written);
140         rd_idx = ((rd_idx + written) % MTKSTP_BUFFER_SIZE);
141         // all data is accepted by UART driver, check again in case roll over
142             len = (wr_idx >= rd_idx) ? (wr_idx - rd_idx) : (MTKSTP_BUFFER_SIZE - rd_idx);
143             if(len > 0 && len < MAX_PACKET_ALLOWED)
144             {
145                 set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
146                 written = tty->ops->write(tty, &tx_buf[rd_idx], len);
147                 if (written != len)
148                 {
149                     UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]len(%d)wr(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, written, wr_idx, rd_idx);
150                     return -1;
151                 }
152                 rd_idx = ((rd_idx + written) % MTKSTP_BUFFER_SIZE);
153                 written_count += written;
154             }
155             else if(len < 0 || len >= MAX_PACKET_ALLOWED)
156             {
157                 UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]length verfication(external) warnning,len(%d), wr_idx(%d), rd_idx(%d)!\n\r", i, current->pid, current->comm, len, wr_idx, rd_idx);
158                 return -1;
159             }
160     }
161     else
162     {
163         UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]length verfication(external) warnning,len(%d), wr_idx(%d), rd_idx(%d)!\n\r", i, current->pid, current->comm, len, wr_idx, rd_idx);
164         return -1;
165     }
166     //up(&buf_mtx);
167 ////    spin_unlock_irqrestore(&buf_lock, flags);
168     UART_DBG_FUNC("--\n");
169     return written_count;
170 }
171
172 /* ------ LDISC part ------ */
173 /* stp_uart_tty_open
174  *
175  *     Called when line discipline changed to HCI_UART.
176  *
177  * Arguments:
178  *     tty    pointer to tty info structure
179  * Return Value:
180  *     0 if success, otherwise error code
181  */
182 static int stp_uart_tty_open(struct tty_struct *tty)
183 {
184     UART_DBG_FUNC("stp_uart_tty_opentty: %p\n", tty);
185
186     tty->receive_room = 65536;
187     tty->low_latency = 1;
188
189     /* Flush any pending characters in the driver and line discipline. */
190
191     /* FIXME: why is this needed. Note don't use ldisc_ref here as the
192        open path is before the ldisc is referencable */
193
194 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
195     /* definition changed!! */
196     if (tty->ldisc->ops->flush_buffer) {
197         tty->ldisc->ops->flush_buffer(tty);
198     }
199 #else
200     if (tty->ldisc.ops->flush_buffer) {
201         tty->ldisc.ops->flush_buffer(tty);
202     }
203 #endif
204
205     tty_driver_flush_buffer(tty);
206
207 //    init_MUTEX(&buf_mtx);
208 ////    spin_lock_init(&buf_lock);
209
210     rd_idx = wr_idx = 0;
211     stp_tty = tty;
212     mtk_wcn_stp_register_if_tx(STP_UART_IF_TX,  mtk_wcn_uart_tx);
213
214     return 0;
215 }
216
217 /* stp_uart_tty_close()
218  *
219  *    Called when the line discipline is changed to something
220  *    else, the tty is closed, or the tty detects a hangup.
221  */
222 static void stp_uart_tty_close(struct tty_struct *tty)
223 {
224     UART_DBG_FUNC("stp_uart_tty_close(): tty %p\n", tty);
225     mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, NULL);
226
227     return;
228 }
229
230 /* stp_uart_tty_wakeup()
231  *
232  *    Callback for transmit wakeup. Called when low level
233  *    device driver can accept more send data.
234  *
235  * Arguments:        tty    pointer to associated tty instance data
236  * Return Value:    None
237  */
238 static void stp_uart_tty_wakeup(struct tty_struct *tty)
239 {
240     //printk("%s: start !!\n", __FUNCTION__);
241
242     //clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
243
244     //stp_uart_tx_wakeup(tty);
245
246     return;
247 }
248
249 /* stp_uart_tty_receive()
250  *
251  *     Called by tty low level driver when receive data is
252  *     available.
253  *
254  * Arguments:  tty          pointer to tty isntance data
255  *             data         pointer to received data
256  *             flags        pointer to flags for data
257  *             count        count of received data in bytes
258  *
259  * Return Value:    None
260  */
261 #if  (LDISC_RX  == LDISC_RX_TASKLET)
262
263 static int stp_uart_fifo_init(void)
264 {
265     int err = 0;
266     /*add rx fifo*/
267         #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
268         {
269         spin_lock_init(&g_stp_uart_rx_fifo_spinlock);
270         g_stp_uart_rx_fifo = kfifo_alloc(LDISC_RX_FIFO_SIZE, GFP_ATOMIC, &g_stp_uart_rx_fifo_spinlock);
271         if (NULL == g_stp_uart_rx_fifo)
272         {
273             UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.35)\n");
274             err = -1;
275         }
276         }
277         #else
278         {
279             g_stp_uart_rx_fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC);
280             if (NULL == g_stp_uart_rx_fifo)
281             {
282                 err = -2;
283                 UART_ERR_FUNC("kzalloc for g_stp_uart_rx_fifo failed (kernel version > 2.6.35)\n");
284             }
285             err = kfifo_alloc(g_stp_uart_rx_fifo, LDISC_RX_FIFO_SIZE, GFP_ATOMIC);
286             if (0 != err)
287             {
288                 UART_ERR_FUNC("kfifo_alloc failed, errno(%d)(kernel version > 2.6.35)\n", err);
289                 kfree(g_stp_uart_rx_fifo);
290                 g_stp_uart_rx_fifo = NULL;
291                 err = -3;    
292             }
293         }
294         #endif
295     if (0 == err)
296     {
297         if (NULL != g_stp_uart_rx_fifo)
298         {
299             kfifo_reset(g_stp_uart_rx_fifo);
300             UART_ERR_FUNC("stp_uart_fifo_init() success.\n");
301         }
302         else
303         {
304             err = -4;
305             UART_ERR_FUNC("abnormal case, err = 0 but g_stp_uart_rx_fifo = NULL, set err to %d\n", err);
306         }
307     }
308     else
309     {
310         UART_ERR_FUNC("stp_uart_fifo_init() failed.\n");
311     }
312     return err;
313 }
314
315 static int stp_uart_fifo_deinit(void)
316 {
317     if (NULL != g_stp_uart_rx_fifo)
318     {
319         kfifo_free(g_stp_uart_rx_fifo);
320         #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
321                 //do nothing
322         #else
323             kfree(g_stp_uart_rx_fifo);
324         #endif
325         g_stp_uart_rx_fifo = NULL;
326     }    
327     return 0;
328 }
329
330 static void stp_uart_rx_handling(unsigned long func_data){
331     unsigned int how_much_get = 0;
332     unsigned int how_much_to_get = 0;
333     unsigned int flag = 0;
334     
335 //    read_lock(&g_stp_uart_rx_handling_lock);
336     how_much_to_get = kfifo_len(g_stp_uart_rx_fifo);
337     
338     if (how_much_to_get >= RX_BUFFER_LEN)
339     {
340         flag = 1;
341         UART_INFO_FUNC ("fifolen(%d)\n", how_much_to_get);
342     }
343     
344     do{
345         #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
346         how_much_get= kfifo_get(g_stp_uart_rx_fifo, g_rx_data, RX_BUFFER_LEN);
347         #else
348         how_much_get= kfifo_out(g_stp_uart_rx_fifo, g_rx_data, RX_BUFFER_LEN);
349         #endif
350         //UART_INFO_FUNC ("fifoget(%d)\n", how_much_get);
351         mtk_wcn_stp_parser_data((UINT8 *)g_rx_data, how_much_get);
352         how_much_to_get = kfifo_len(g_stp_uart_rx_fifo);
353     }while(how_much_to_get > 0);
354     
355 //    read_unlock(&g_stp_uart_rx_handling_lock);
356     if (1 == flag)
357     {
358         UART_INFO_FUNC ("finish, fifolen(%d)\n", kfifo_len(g_stp_uart_rx_fifo));
359     }
360 }
361
362 static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
363 {
364     unsigned int fifo_avail_len = LDISC_RX_FIFO_SIZE - kfifo_len(g_stp_uart_rx_fifo);
365     unsigned int how_much_put = 0;
366 #if 0
367     {
368         struct timeval now;
369         do_gettimeofday(&now);
370         printk("[+STP][  ][R] %4d --> sec = %lu, --> usec --> %lu\n",
371             count, now.tv_sec, now.tv_usec);
372     }
373 #endif
374 //    write_lock(&g_stp_uart_rx_handling_lock);
375     if(count > 2000){
376         /*this is abnormal*/
377         UART_ERR_FUNC("abnormal: buffer count = %d\n", count);
378     }
379     /*How much empty seat?*/
380     if(fifo_avail_len > 0){
381     //UART_INFO_FUNC ("fifo left(%d), count(%d)\n", fifo_avail_len, count);
382         #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
383         how_much_put = kfifo_put(g_stp_uart_rx_fifo,(unsigned char *) data, count);
384             #else
385             how_much_put = kfifo_in(g_stp_uart_rx_fifo,(unsigned char *) data, count);
386             #endif
387
388         /*schedule it!*/
389         tasklet_schedule(&g_stp_uart_rx_fifo_tasklet);
390     }else{
391         UART_ERR_FUNC("stp_uart_tty_receive rxfifo is full!!\n");
392     }
393
394 #if 0
395     {
396         struct timeval now;
397         do_gettimeofday(&now);
398         printk("[-STP][  ][R] %4d --> sec = %lu, --> usec --> %lu\n",
399             count, now.tv_sec, now.tv_usec);
400     }
401 #endif
402
403 //    write_unlock(&g_stp_uart_rx_handling_lock);
404
405 }
406 #elif  (LDISC_RX  ==LDISC_RX_WORK)
407 static int stp_uart_fifo_init(void)
408 {
409     int err = 0;
410
411     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
412     g_stp_uart_rx_buf = vzalloc(LDISC_RX_BUF_SIZE);
413     if (!g_stp_uart_rx_buf) {
414         UART_ERR_FUNC("kfifo_alloc failed (kernel version >= 2.6.37)\n");
415         err = -4;
416         goto fifo_init_end;
417     }
418     #else
419     g_stp_uart_rx_buf = vmalloc(LDISC_RX_BUF_SIZE);
420     if (!g_stp_uart_rx_buf) {
421         UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.37)\n");
422         err = -4;
423         goto fifo_init_end;
424     }
425     memset(g_stp_uart_rx_buf, 0, LDISC_RX_BUF_SIZE);
426     #endif
427
428     UART_INFO_FUNC("g_stp_uart_rx_buf alloc ok(0x%p, %d)\n",
429         g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE);
430
431     /*add rx fifo*/
432     #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
433     spin_lock_init(&g_stp_uart_rx_fifo_spinlock);
434     g_stp_uart_rx_fifo = kfifo_alloc(LDISC_RX_FIFO_SIZE, GFP_KERNEL, &g_stp_uart_rx_fifo_spinlock);
435     if (NULL == g_stp_uart_rx_fifo) {
436         UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.33)\n");
437         err = -1;
438         goto fifo_init_end;
439     }
440     #else
441     /* allocate struct kfifo first */
442     g_stp_uart_rx_fifo = kzalloc(sizeof(struct kfifo), GFP_KERNEL);
443     if (NULL == g_stp_uart_rx_fifo) {
444         err = -2;
445         UART_ERR_FUNC("kzalloc struct kfifo failed (kernel version > 2.6.33)\n");
446         goto fifo_init_end;
447     }
448
449     /* allocate kfifo data buffer then */
450     err = kfifo_alloc(g_stp_uart_rx_fifo, LDISC_RX_FIFO_SIZE, GFP_KERNEL);
451     if (0 != err) {
452         UART_ERR_FUNC("kfifo_alloc failed, err(%d)(kernel version > 2.6.33)\n", err);
453         kfree(g_stp_uart_rx_fifo);
454         g_stp_uart_rx_fifo = NULL;
455         err = -3;
456         goto fifo_init_end;
457     }
458     #endif
459     UART_INFO_FUNC("g_stp_uart_rx_fifo alloc ok\n");
460
461 fifo_init_end:
462
463     if (0 == err) {
464         /* kfifo init ok */
465         kfifo_reset(g_stp_uart_rx_fifo);
466         UART_DBG_FUNC("g_stp_uart_rx_fifo init success\n");
467     }
468     else {
469         UART_ERR_FUNC("stp_uart_fifo_init() fail(%d)\n", err);
470         if (g_stp_uart_rx_buf) {
471             UART_ERR_FUNC("free g_stp_uart_rx_buf\n");
472             vfree(g_stp_uart_rx_buf);
473             g_stp_uart_rx_buf = NULL;
474         }
475     }
476
477     return err;
478 }
479
480 static int stp_uart_fifo_deinit(void)
481 {
482     if (g_stp_uart_rx_buf) {
483         vfree(g_stp_uart_rx_buf);
484         g_stp_uart_rx_buf = NULL;
485     }
486
487     if (NULL != g_stp_uart_rx_fifo) {
488         kfifo_free(g_stp_uart_rx_fifo);
489         #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
490         //do nothing
491         #else
492         kfree(g_stp_uart_rx_fifo);
493         #endif
494         g_stp_uart_rx_fifo = NULL;
495     }
496     return 0;
497 }
498
499 static void stp_uart_fifo_reset (void) {
500     if (NULL != g_stp_uart_rx_fifo) {
501         kfifo_reset(g_stp_uart_rx_fifo);
502     }
503 }
504
505 static void stp_uart_rx_worker (struct work_struct *work)
506 {
507     unsigned int read;
508
509     if (unlikely(!g_stp_uart_rx_fifo)) {
510         UART_ERR_FUNC("NULL rx fifo!\n");
511         return;
512     }
513     if (unlikely(!g_stp_uart_rx_buf)) {
514         UART_ERR_FUNC("NULL rx buf!\n");
515         return;
516     }
517         
518
519     /* run until fifo becomes empty */
520 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
521     while (kfifo_len(g_stp_uart_rx_fifo)) {
522         read = kfifo_get(g_stp_uart_rx_fifo, g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE);
523         //UART_LOUD_FUNC("kfifo_get(%d)\n", read);
524         if (likely(read)) {
525             mtk_wcn_stp_parser_data((UINT8 *)g_stp_uart_rx_buf, read);
526         }
527     }
528 #else
529     while (!kfifo_is_empty(g_stp_uart_rx_fifo)) {
530         read = kfifo_out(g_stp_uart_rx_fifo, g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE);
531         UART_DBG_FUNC("kfifo_out(%d)\n", read);
532                 //printk("rx_work:%d\n\r",read);
533         if (likely(read)) {
534             //UART_LOUD_FUNC("->%d\n", read);
535             mtk_wcn_stp_parser_data((UINT8 *)g_stp_uart_rx_buf, read);
536             //UART_LOUD_FUNC("<-\n", read);
537         }
538     }
539 #endif
540
541     return;
542 }
543
544 /* stp_uart_tty_receive()
545  *
546  *     Called by tty low level driver when receive data is
547  *     available.
548  *
549  * Arguments:  tty          pointer to tty isntance data
550  *             data         pointer to received data
551  *             flags        pointer to flags for data
552  *             count        count of received data in bytes
553  *
554  * Return Value:    None
555  */
556 static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
557 {
558     unsigned int written;
559
560     //UART_LOUD_FUNC("URX:%d\n", count);
561     if (unlikely(count > 2000)) {
562         UART_WARN_FUNC("abnormal: buffer count = %d\n", count);
563     }
564
565     if (unlikely(!g_stp_uart_rx_fifo || !g_stp_uart_rx_work || !g_stp_uart_rx_wq)) {
566         UART_ERR_FUNC("abnormal g_stp_uart_rx_fifo(0x%p),g_stp_uart_rx_work(0x%p),g_stp_uart_rx_wq(0x%p)\n",
567             g_stp_uart_rx_fifo, g_stp_uart_rx_work, g_stp_uart_rx_wq);
568         return;
569     }
570
571     /* need to check available buffer size? skip! */
572
573     /* need to lock fifo? skip for single writer single reader! */
574
575 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
576     written = kfifo_put(g_stp_uart_rx_fifo, (unsigned char *) data, count);
577 #else
578     written = kfifo_in(g_stp_uart_rx_fifo, (unsigned char *) data, count);
579 #endif
580         //printk("uart_rx:%d,wr:%d\n\r",count,written);
581
582     queue_work(g_stp_uart_rx_wq, g_stp_uart_rx_work);
583
584     if (unlikely(written != count)) {
585         UART_ERR_FUNC("c(%d),w(%d) bytes dropped\n", count, written);
586     }
587
588     return;
589 }
590
591 #else
592
593 static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
594 {
595
596 #if 0
597     mtk_wcn_stp_debug_gpio_assert(IDX_STP_RX_PROC, DBG_TIE_LOW);
598 #endif
599
600     if(count > 2000){
601         /*this is abnormal*/
602         UART_ERR_FUNC("stp_uart_tty_receive buffer count = %d\n", count);
603     }
604
605 #if 0
606     {
607         struct timeval now;
608
609         do_gettimeofday(&now);
610
611         printk("[+STP][  ][R] %4d --> sec = %d, --> usec --> %d\n",
612             count, now.tv_sec, now.tv_usec);
613     }
614 #endif
615
616
617     /*There are multi-context to access here? Need to spinlock?*/
618     /*Only one context: flush_to_ldisc in tty_buffer.c*/
619     mtk_wcn_stp_parser_data((UINT8 *)data, (UINT32)count);
620
621 #if 0
622     mtk_wcn_stp_debug_gpio_assert(IDX_STP_RX_PROC, DBG_TIE_HIGH);
623 #endif
624
625     tty_unthrottle(tty);
626
627 #if 0
628     {
629         struct timeval now;
630
631         do_gettimeofday(&now);
632
633         printk("[-STP][  ][R] %4d --> sec = %d, --> usec --> %d\n",
634             count, now.tv_sec, now.tv_usec);
635     }
636 #endif
637     return;
638 }
639 #endif
640
641 /* stp_uart_tty_ioctl()
642  *
643  *    Process IOCTL system call for the tty device.
644  *
645  * Arguments:
646  *
647  *    tty        pointer to tty instance data
648  *    file       pointer to open file object for device
649  *    cmd        IOCTL command code
650  *    arg        argument for IOCTL call (cmd dependent)
651  *
652  * Return Value:    Command dependent
653  */
654 static int stp_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
655                     unsigned int cmd, unsigned long arg)
656 {
657     int err = 0;
658
659     UART_DBG_FUNC("%s =>\n", __FUNCTION__);
660
661     switch (cmd) {
662     case HCIUARTSETPROTO:
663             UART_DBG_FUNC("<!!> Set low_latency to TRUE <!!>\n");
664             tty->low_latency = 1;
665         break;
666     default:
667         UART_DBG_FUNC("<!!> n_tty_ioctl_helper <!!>\n");
668         err = n_tty_ioctl_helper(tty, file, cmd, arg);
669         break;
670     };
671     UART_DBG_FUNC("%s <=\n", __FUNCTION__);
672
673     return err;
674 }
675
676 /*
677  * We don't provide read/write/poll interface for user space.
678  */
679 static ssize_t stp_uart_tty_read(struct tty_struct *tty, struct file *file,
680                     unsigned char __user *buf, size_t nr)
681 {
682     return 0;
683 }
684
685 static ssize_t stp_uart_tty_write(struct tty_struct *tty, struct file *file,
686                     const unsigned char *data, size_t count)
687 {
688     return 0;
689 }
690
691 static unsigned int stp_uart_tty_poll(struct tty_struct *tty,
692                     struct file *filp, poll_table *wait)
693 {
694     return 0;
695 }
696
697 INT32  mtk_wcn_uart_tx(const UINT8 *data, const UINT32 size, UINT32 *written_size)
698 {
699     int room;
700     //int idx = 0;
701     //unsigned long flags;
702     unsigned int  len;
703     //static int tmp=0;
704     static int i = 0;
705     if(stp_tty == NULL) return -1;
706     UART_DBG_FUNC("++\n");
707     (*written_size) = 0;
708
709     // put data into ring buffer
710     //down(&buf_mtx);
711
712
713     /*
714         [PatchNeed]
715         spin_lock_irqsave is redundant
716     */
717     //spin_lock_irqsave(&buf_lock, flags);
718
719     room = (wr_idx >= rd_idx) ? (MTKSTP_BUFFER_SIZE - (wr_idx - rd_idx) - 1) : (rd_idx - wr_idx - 1);
720     UART_DBG_FUNC("r(%d)s(%d)wr_i(%d)rd_i(%d)\n\r", room, size, wr_idx, rd_idx);
721     /*
722         [PatchNeed]
723         Block copy instead of byte copying
724     */
725     if(data == NULL){
726         UART_ERR_FUNC("pid(%d)(%s): data is NULL\n", current->pid, current->comm);
727         (*written_size) = 0;
728         UART_DBG_FUNC("--\n");
729         return -2;
730     }
731
732     #if 1
733     if(unlikely(size > room)){
734         UART_ERR_FUNC("pid(%d)(%s)room is not available, size needed(%d), wr_idx(%d), rd_idx(%d), room left(%d)\n", current->pid, current->comm, size, wr_idx, rd_idx, room);
735         UART_DBG_FUNC("--\n");
736         (*written_size) = 0;
737         return -3;
738     }
739     else {
740         /*
741             wr_idx : the position next to write
742             rd_idx : the position next to read
743         */
744         len = min(size, MTKSTP_BUFFER_SIZE - (unsigned int)wr_idx);
745         memcpy(&tx_buf[wr_idx], &data[0], len);
746         memcpy(&tx_buf[0], &data[len], size - len);
747         wr_idx = (wr_idx + size) % MTKSTP_BUFFER_SIZE;
748         UART_DBG_FUNC("r(%d)s(%d)wr_i(%d)rd_i(%d)\n\r", room, size, wr_idx, rd_idx);
749         i++;
750         if (size < 0)
751         {
752             UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]len(%d)size(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, size, wr_idx, rd_idx);
753             (*written_size) = 0;
754         }
755         else if (size == 0)
756         {
757             (*written_size) = 0;
758         }
759         else if (size < MAX_PACKET_ALLOWED)
760         {
761             //only size ~(0, 2000) is allowed
762             (*written_size) = stp_uart_tx_wakeup(stp_tty);
763             if(*written_size < 0)
764             {
765                 //reset read and write index of tx_buffer, is there any risk?
766                 wr_idx = rd_idx = 0;
767                 *written_size = 0;
768             }
769         }
770         else
771         {
772             //we filter all packet with size > 2000
773             UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]len(%d)size(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, size,  wr_idx, rd_idx);
774             (*written_size)= 0;
775         }
776     }
777     #endif
778
779
780     #if 0
781     while((room > 0) && (size > 0))
782     {
783         tx_buf[wr_idx] = data[idx];
784         wr_idx = ((wr_idx + 1) % MTKSTP_BUFFER_SIZE);
785         idx++;
786         room--;
787         size--;
788         (*written_size)++;
789     }
790     #endif
791     //up(&buf_mtx);
792     /*
793         [PatchNeed]
794         spin_lock_irqsave is redundant
795     */
796 ////    spin_lock_irqsave(&buf_lock, flags);
797
798     /*[PatchNeed]To add a tasklet to shedule Uart Tx*/
799     UART_DBG_FUNC("--\n");
800     return 0;
801 }
802
803 static int __init mtk_wcn_stp_uart_init(void)
804 {
805     static struct tty_ldisc_ops stp_uart_ldisc;
806     int err;
807         int fifo_init_done =0;
808
809     UART_INFO_FUNC("mtk_wcn_stp_uart_init(): MTK STP UART driver\n");
810
811 #if  (LDISC_RX == LDISC_RX_TASKLET)
812     err = stp_uart_fifo_init();
813     if (err != 0)
814     {
815         goto init_err;
816     }
817         fifo_init_done = 1;
818     /*init rx tasklet*/
819     tasklet_init(&g_stp_uart_rx_fifo_tasklet, stp_uart_rx_handling, (unsigned long) 0);
820         
821 #elif  (LDISC_RX == LDISC_RX_WORK)
822         err = stp_uart_fifo_init();
823         if (err != 0) {
824                 UART_ERR_FUNC("stp_uart_fifo_init(WORK) error(%d)\n", err);
825                 err = -EFAULT;
826                 goto init_err;
827         }
828         fifo_init_done = 1;
829
830         g_stp_uart_rx_work = vmalloc(sizeof(struct work_struct));
831         if (!g_stp_uart_rx_work) {
832                 UART_ERR_FUNC("vmalloc work_struct(%d) fail\n", sizeof(struct work_struct));
833                 err = -ENOMEM;
834                 goto init_err;
835         }
836
837         g_stp_uart_rx_wq = create_singlethread_workqueue("mtk_urxd");
838         if (!g_stp_uart_rx_wq) {
839                 UART_ERR_FUNC("create_singlethread_workqueue fail\n");
840                 err = -ENOMEM;
841                 goto init_err;
842         }
843
844         /* init rx work */
845         INIT_WORK(g_stp_uart_rx_work, stp_uart_rx_worker);
846
847 #endif
848
849      /* Register the tty discipline */
850     memset(&stp_uart_ldisc, 0, sizeof (stp_uart_ldisc));
851     stp_uart_ldisc.magic    = TTY_LDISC_MAGIC;
852     stp_uart_ldisc.name     = "n_mtkstp";
853     stp_uart_ldisc.open     = stp_uart_tty_open;
854     stp_uart_ldisc.close    = stp_uart_tty_close;
855     stp_uart_ldisc.read     = stp_uart_tty_read;
856     stp_uart_ldisc.write    = stp_uart_tty_write;
857     stp_uart_ldisc.ioctl    = stp_uart_tty_ioctl;
858     stp_uart_ldisc.poll     = stp_uart_tty_poll;
859     stp_uart_ldisc.receive_buf  = stp_uart_tty_receive;
860     stp_uart_ldisc.write_wakeup = stp_uart_tty_wakeup;
861     stp_uart_ldisc.owner    = THIS_MODULE;
862
863     if ((err = tty_register_ldisc(N_MTKSTP, &stp_uart_ldisc)))
864     {
865         UART_ERR_FUNC("MTK STP line discipline registration failed. (%d)\n", err);
866         goto init_err;
867     }
868
869     /*
870     mtk_wcn_stp_register_if_tx( mtk_wcn_uart_tx);
871     */
872
873     return 0;
874
875 init_err:
876         
877 #if (LDISC_RX == LDISC_RX_TASKLET)
878                 /* nothing */
879                 if (fifo_init_done) {
880                         stp_uart_fifo_deinit();
881                 }
882 #elif (LDISC_RX == LDISC_RX_WORK)
883                 if (g_stp_uart_rx_wq) {
884                         destroy_workqueue(g_stp_uart_rx_wq);
885                         g_stp_uart_rx_wq = NULL;
886                 }
887                 if (g_stp_uart_rx_work) {
888                         vfree(g_stp_uart_rx_work);
889                 }
890                 if (fifo_init_done) {
891                         stp_uart_fifo_deinit();
892                 }
893 #endif
894                 UART_ERR_FUNC("init fail, return(%d)\n", err);
895         
896                 return err;
897
898 }
899
900 static void __exit mtk_wcn_stp_uart_exit(void)
901 {
902     int err;
903
904     mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, NULL);    // unregister if_tx function
905
906     /* Release tty registration of line discipline */
907     if ((err = tty_unregister_ldisc(N_MTKSTP)))
908     {
909         UART_ERR_FUNC("Can't unregister MTK STP line discipline (%d)\n", err);
910     }
911
912 #if (LDISC_RX == LDISC_RX_TASKLET)
913     tasklet_kill(&g_stp_uart_rx_fifo_tasklet);
914     stp_uart_fifo_deinit();
915 #elif (LDISC_RX == LDISC_RX_WORK)
916         if (g_stp_uart_rx_work) {
917                 cancel_work_sync(g_stp_uart_rx_work);
918         }
919         if (g_stp_uart_rx_wq) {
920                 destroy_workqueue(g_stp_uart_rx_wq);
921                 g_stp_uart_rx_wq = NULL;
922         }
923         if (g_stp_uart_rx_work) {
924                 vfree(g_stp_uart_rx_work);
925                 g_stp_uart_rx_work = NULL;
926         }
927         stp_uart_fifo_deinit();
928
929 #endif
930     return;
931 }
932
933 module_init(mtk_wcn_stp_uart_init);
934 module_exit(mtk_wcn_stp_uart_exit);
935
936 MODULE_LICENSE("GPL");
937 MODULE_AUTHOR("MediaTek Inc WCN_SE_CS3");
938 MODULE_DESCRIPTION("STP-HIF UART Interface");