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