Merge tag 'nios2-v4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/lftan...
[sfrench/cifs-2.6.git] / drivers / usb / host / xhci-dbgtty.c
1 /**
2  * xhci-dbgtty.c - tty glue for xHCI debug capability
3  *
4  * Copyright (C) 2017 Intel Corporation
5  *
6  * Author: Lu Baolu <baolu.lu@linux.intel.com>
7  */
8
9 #include <linux/slab.h>
10 #include <linux/tty.h>
11 #include <linux/tty_flip.h>
12
13 #include "xhci.h"
14 #include "xhci-dbgcap.h"
15
16 static unsigned int
17 dbc_send_packet(struct dbc_port *port, char *packet, unsigned int size)
18 {
19         unsigned int            len;
20
21         len = kfifo_len(&port->write_fifo);
22         if (len < size)
23                 size = len;
24         if (size != 0)
25                 size = kfifo_out(&port->write_fifo, packet, size);
26         return size;
27 }
28
29 static int dbc_start_tx(struct dbc_port *port)
30         __releases(&port->port_lock)
31         __acquires(&port->port_lock)
32 {
33         int                     len;
34         struct dbc_request      *req;
35         int                     status = 0;
36         bool                    do_tty_wake = false;
37         struct list_head        *pool = &port->write_pool;
38
39         while (!list_empty(pool)) {
40                 req = list_entry(pool->next, struct dbc_request, list_pool);
41                 len = dbc_send_packet(port, req->buf, DBC_MAX_PACKET);
42                 if (len == 0)
43                         break;
44                 do_tty_wake = true;
45
46                 req->length = len;
47                 list_del(&req->list_pool);
48
49                 spin_unlock(&port->port_lock);
50                 status = dbc_ep_queue(port->out, req, GFP_ATOMIC);
51                 spin_lock(&port->port_lock);
52
53                 if (status) {
54                         list_add(&req->list_pool, pool);
55                         break;
56                 }
57         }
58
59         if (do_tty_wake && port->port.tty)
60                 tty_wakeup(port->port.tty);
61
62         return status;
63 }
64
65 static void dbc_start_rx(struct dbc_port *port)
66         __releases(&port->port_lock)
67         __acquires(&port->port_lock)
68 {
69         struct dbc_request      *req;
70         int                     status;
71         struct list_head        *pool = &port->read_pool;
72
73         while (!list_empty(pool)) {
74                 if (!port->port.tty)
75                         break;
76
77                 req = list_entry(pool->next, struct dbc_request, list_pool);
78                 list_del(&req->list_pool);
79                 req->length = DBC_MAX_PACKET;
80
81                 spin_unlock(&port->port_lock);
82                 status = dbc_ep_queue(port->in, req, GFP_ATOMIC);
83                 spin_lock(&port->port_lock);
84
85                 if (status) {
86                         list_add(&req->list_pool, pool);
87                         break;
88                 }
89         }
90 }
91
92 static void
93 dbc_read_complete(struct xhci_hcd *xhci, struct dbc_request *req)
94 {
95         unsigned long           flags;
96         struct xhci_dbc         *dbc = xhci->dbc;
97         struct dbc_port         *port = &dbc->port;
98
99         spin_lock_irqsave(&port->port_lock, flags);
100         list_add_tail(&req->list_pool, &port->read_queue);
101         tasklet_schedule(&port->push);
102         spin_unlock_irqrestore(&port->port_lock, flags);
103 }
104
105 static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req)
106 {
107         unsigned long           flags;
108         struct xhci_dbc         *dbc = xhci->dbc;
109         struct dbc_port         *port = &dbc->port;
110
111         spin_lock_irqsave(&port->port_lock, flags);
112         list_add(&req->list_pool, &port->write_pool);
113         switch (req->status) {
114         case 0:
115                 dbc_start_tx(port);
116                 break;
117         case -ESHUTDOWN:
118                 break;
119         default:
120                 xhci_warn(xhci, "unexpected write complete status %d\n",
121                           req->status);
122                 break;
123         }
124         spin_unlock_irqrestore(&port->port_lock, flags);
125 }
126
127 static void xhci_dbc_free_req(struct dbc_ep *dep, struct dbc_request *req)
128 {
129         kfree(req->buf);
130         dbc_free_request(dep, req);
131 }
132
133 static int
134 xhci_dbc_alloc_requests(struct dbc_ep *dep, struct list_head *head,
135                         void (*fn)(struct xhci_hcd *, struct dbc_request *))
136 {
137         int                     i;
138         struct dbc_request      *req;
139
140         for (i = 0; i < DBC_QUEUE_SIZE; i++) {
141                 req = dbc_alloc_request(dep, GFP_ATOMIC);
142                 if (!req)
143                         break;
144
145                 req->length = DBC_MAX_PACKET;
146                 req->buf = kmalloc(req->length, GFP_KERNEL);
147                 if (!req->buf) {
148                         xhci_dbc_free_req(dep, req);
149                         break;
150                 }
151
152                 req->complete = fn;
153                 list_add_tail(&req->list_pool, head);
154         }
155
156         return list_empty(head) ? -ENOMEM : 0;
157 }
158
159 static void
160 xhci_dbc_free_requests(struct dbc_ep *dep, struct list_head *head)
161 {
162         struct dbc_request      *req;
163
164         while (!list_empty(head)) {
165                 req = list_entry(head->next, struct dbc_request, list_pool);
166                 list_del(&req->list_pool);
167                 xhci_dbc_free_req(dep, req);
168         }
169 }
170
171 static int dbc_tty_install(struct tty_driver *driver, struct tty_struct *tty)
172 {
173         struct dbc_port         *port = driver->driver_state;
174
175         tty->driver_data = port;
176
177         return tty_port_install(&port->port, driver, tty);
178 }
179
180 static int dbc_tty_open(struct tty_struct *tty, struct file *file)
181 {
182         struct dbc_port         *port = tty->driver_data;
183
184         return tty_port_open(&port->port, tty, file);
185 }
186
187 static void dbc_tty_close(struct tty_struct *tty, struct file *file)
188 {
189         struct dbc_port         *port = tty->driver_data;
190
191         tty_port_close(&port->port, tty, file);
192 }
193
194 static int dbc_tty_write(struct tty_struct *tty,
195                          const unsigned char *buf,
196                          int count)
197 {
198         struct dbc_port         *port = tty->driver_data;
199         unsigned long           flags;
200
201         spin_lock_irqsave(&port->port_lock, flags);
202         if (count)
203                 count = kfifo_in(&port->write_fifo, buf, count);
204         dbc_start_tx(port);
205         spin_unlock_irqrestore(&port->port_lock, flags);
206
207         return count;
208 }
209
210 static int dbc_tty_put_char(struct tty_struct *tty, unsigned char ch)
211 {
212         struct dbc_port         *port = tty->driver_data;
213         unsigned long           flags;
214         int                     status;
215
216         spin_lock_irqsave(&port->port_lock, flags);
217         status = kfifo_put(&port->write_fifo, ch);
218         spin_unlock_irqrestore(&port->port_lock, flags);
219
220         return status;
221 }
222
223 static void dbc_tty_flush_chars(struct tty_struct *tty)
224 {
225         struct dbc_port         *port = tty->driver_data;
226         unsigned long           flags;
227
228         spin_lock_irqsave(&port->port_lock, flags);
229         dbc_start_tx(port);
230         spin_unlock_irqrestore(&port->port_lock, flags);
231 }
232
233 static int dbc_tty_write_room(struct tty_struct *tty)
234 {
235         struct dbc_port         *port = tty->driver_data;
236         unsigned long           flags;
237         int                     room = 0;
238
239         spin_lock_irqsave(&port->port_lock, flags);
240         room = kfifo_avail(&port->write_fifo);
241         spin_unlock_irqrestore(&port->port_lock, flags);
242
243         return room;
244 }
245
246 static int dbc_tty_chars_in_buffer(struct tty_struct *tty)
247 {
248         struct dbc_port         *port = tty->driver_data;
249         unsigned long           flags;
250         int                     chars = 0;
251
252         spin_lock_irqsave(&port->port_lock, flags);
253         chars = kfifo_len(&port->write_fifo);
254         spin_unlock_irqrestore(&port->port_lock, flags);
255
256         return chars;
257 }
258
259 static void dbc_tty_unthrottle(struct tty_struct *tty)
260 {
261         struct dbc_port         *port = tty->driver_data;
262         unsigned long           flags;
263
264         spin_lock_irqsave(&port->port_lock, flags);
265         tasklet_schedule(&port->push);
266         spin_unlock_irqrestore(&port->port_lock, flags);
267 }
268
269 static const struct tty_operations dbc_tty_ops = {
270         .install                = dbc_tty_install,
271         .open                   = dbc_tty_open,
272         .close                  = dbc_tty_close,
273         .write                  = dbc_tty_write,
274         .put_char               = dbc_tty_put_char,
275         .flush_chars            = dbc_tty_flush_chars,
276         .write_room             = dbc_tty_write_room,
277         .chars_in_buffer        = dbc_tty_chars_in_buffer,
278         .unthrottle             = dbc_tty_unthrottle,
279 };
280
281 static struct tty_driver *dbc_tty_driver;
282
283 int xhci_dbc_tty_register_driver(struct xhci_hcd *xhci)
284 {
285         int                     status;
286         struct xhci_dbc         *dbc = xhci->dbc;
287
288         dbc_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
289                                           TTY_DRIVER_DYNAMIC_DEV);
290         if (IS_ERR(dbc_tty_driver)) {
291                 status = PTR_ERR(dbc_tty_driver);
292                 dbc_tty_driver = NULL;
293                 return status;
294         }
295
296         dbc_tty_driver->driver_name = "dbc_serial";
297         dbc_tty_driver->name = "ttyDBC";
298
299         dbc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
300         dbc_tty_driver->subtype = SERIAL_TYPE_NORMAL;
301         dbc_tty_driver->init_termios = tty_std_termios;
302         dbc_tty_driver->init_termios.c_cflag =
303                         B9600 | CS8 | CREAD | HUPCL | CLOCAL;
304         dbc_tty_driver->init_termios.c_ispeed = 9600;
305         dbc_tty_driver->init_termios.c_ospeed = 9600;
306         dbc_tty_driver->driver_state = &dbc->port;
307
308         tty_set_operations(dbc_tty_driver, &dbc_tty_ops);
309
310         status = tty_register_driver(dbc_tty_driver);
311         if (status) {
312                 xhci_err(xhci,
313                          "can't register dbc tty driver, err %d\n", status);
314                 put_tty_driver(dbc_tty_driver);
315                 dbc_tty_driver = NULL;
316         }
317
318         return status;
319 }
320
321 void xhci_dbc_tty_unregister_driver(void)
322 {
323         tty_unregister_driver(dbc_tty_driver);
324         put_tty_driver(dbc_tty_driver);
325         dbc_tty_driver = NULL;
326 }
327
328 static void dbc_rx_push(unsigned long _port)
329 {
330         struct dbc_request      *req;
331         struct tty_struct       *tty;
332         unsigned long           flags;
333         bool                    do_push = false;
334         bool                    disconnect = false;
335         struct dbc_port         *port = (void *)_port;
336         struct list_head        *queue = &port->read_queue;
337
338         spin_lock_irqsave(&port->port_lock, flags);
339         tty = port->port.tty;
340         while (!list_empty(queue)) {
341                 req = list_first_entry(queue, struct dbc_request, list_pool);
342
343                 if (tty && tty_throttled(tty))
344                         break;
345
346                 switch (req->status) {
347                 case 0:
348                         break;
349                 case -ESHUTDOWN:
350                         disconnect = true;
351                         break;
352                 default:
353                         pr_warn("ttyDBC0: unexpected RX status %d\n",
354                                 req->status);
355                         break;
356                 }
357
358                 if (req->actual) {
359                         char            *packet = req->buf;
360                         unsigned int    n, size = req->actual;
361                         int             count;
362
363                         n = port->n_read;
364                         if (n) {
365                                 packet += n;
366                                 size -= n;
367                         }
368
369                         count = tty_insert_flip_string(&port->port, packet,
370                                                        size);
371                         if (count)
372                                 do_push = true;
373                         if (count != size) {
374                                 port->n_read += count;
375                                 break;
376                         }
377                         port->n_read = 0;
378                 }
379
380                 list_move(&req->list_pool, &port->read_pool);
381         }
382
383         if (do_push)
384                 tty_flip_buffer_push(&port->port);
385
386         if (!list_empty(queue) && tty) {
387                 if (!tty_throttled(tty)) {
388                         if (do_push)
389                                 tasklet_schedule(&port->push);
390                         else
391                                 pr_warn("ttyDBC0: RX not scheduled?\n");
392                 }
393         }
394
395         if (!disconnect)
396                 dbc_start_rx(port);
397
398         spin_unlock_irqrestore(&port->port_lock, flags);
399 }
400
401 static int dbc_port_activate(struct tty_port *_port, struct tty_struct *tty)
402 {
403         unsigned long   flags;
404         struct dbc_port *port = container_of(_port, struct dbc_port, port);
405
406         spin_lock_irqsave(&port->port_lock, flags);
407         dbc_start_rx(port);
408         spin_unlock_irqrestore(&port->port_lock, flags);
409
410         return 0;
411 }
412
413 static const struct tty_port_operations dbc_port_ops = {
414         .activate =     dbc_port_activate,
415 };
416
417 static void
418 xhci_dbc_tty_init_port(struct xhci_hcd *xhci, struct dbc_port *port)
419 {
420         tty_port_init(&port->port);
421         spin_lock_init(&port->port_lock);
422         tasklet_init(&port->push, dbc_rx_push, (unsigned long)port);
423         INIT_LIST_HEAD(&port->read_pool);
424         INIT_LIST_HEAD(&port->read_queue);
425         INIT_LIST_HEAD(&port->write_pool);
426
427         port->in =              get_in_ep(xhci);
428         port->out =             get_out_ep(xhci);
429         port->port.ops =        &dbc_port_ops;
430         port->n_read =          0;
431 }
432
433 static void
434 xhci_dbc_tty_exit_port(struct dbc_port *port)
435 {
436         tasklet_kill(&port->push);
437         tty_port_destroy(&port->port);
438 }
439
440 int xhci_dbc_tty_register_device(struct xhci_hcd *xhci)
441 {
442         int                     ret;
443         struct device           *tty_dev;
444         struct xhci_dbc         *dbc = xhci->dbc;
445         struct dbc_port         *port = &dbc->port;
446
447         xhci_dbc_tty_init_port(xhci, port);
448         tty_dev = tty_port_register_device(&port->port,
449                                            dbc_tty_driver, 0, NULL);
450         if (IS_ERR(tty_dev)) {
451                 ret = PTR_ERR(tty_dev);
452                 goto register_fail;
453         }
454
455         ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL);
456         if (ret)
457                 goto buf_alloc_fail;
458
459         ret = xhci_dbc_alloc_requests(port->in, &port->read_pool,
460                                       dbc_read_complete);
461         if (ret)
462                 goto request_fail;
463
464         ret = xhci_dbc_alloc_requests(port->out, &port->write_pool,
465                                       dbc_write_complete);
466         if (ret)
467                 goto request_fail;
468
469         port->registered = true;
470
471         return 0;
472
473 request_fail:
474         xhci_dbc_free_requests(port->in, &port->read_pool);
475         xhci_dbc_free_requests(port->out, &port->write_pool);
476         kfifo_free(&port->write_fifo);
477
478 buf_alloc_fail:
479         tty_unregister_device(dbc_tty_driver, 0);
480
481 register_fail:
482         xhci_dbc_tty_exit_port(port);
483
484         xhci_err(xhci, "can't register tty port, err %d\n", ret);
485
486         return ret;
487 }
488
489 void xhci_dbc_tty_unregister_device(struct xhci_hcd *xhci)
490 {
491         struct xhci_dbc         *dbc = xhci->dbc;
492         struct dbc_port         *port = &dbc->port;
493
494         tty_unregister_device(dbc_tty_driver, 0);
495         xhci_dbc_tty_exit_port(port);
496         port->registered = false;
497
498         kfifo_free(&port->write_fifo);
499         xhci_dbc_free_requests(get_out_ep(xhci), &port->read_pool);
500         xhci_dbc_free_requests(get_out_ep(xhci), &port->read_queue);
501         xhci_dbc_free_requests(get_in_ep(xhci), &port->write_pool);
502 }