net: DCB: Validate DCB_ATTR_DCB_BUFFER argument
[linux/fpc-iii.git] / drivers / usb / host / xhci-dbgtty.c
blobbe726c791323af16c066ea642aeee359474bce4c
1 // SPDX-License-Identifier: GPL-2.0
2 /**
3 * xhci-dbgtty.c - tty glue for xHCI debug capability
5 * Copyright (C) 2017 Intel Corporation
7 * Author: Lu Baolu <baolu.lu@linux.intel.com>
8 */
10 #include <linux/slab.h>
11 #include <linux/tty.h>
12 #include <linux/tty_flip.h>
14 #include "xhci.h"
15 #include "xhci-dbgcap.h"
17 static unsigned int
18 dbc_send_packet(struct dbc_port *port, char *packet, unsigned int size)
20 unsigned int len;
22 len = kfifo_len(&port->write_fifo);
23 if (len < size)
24 size = len;
25 if (size != 0)
26 size = kfifo_out(&port->write_fifo, packet, size);
27 return size;
30 static int dbc_start_tx(struct dbc_port *port)
31 __releases(&port->port_lock)
32 __acquires(&port->port_lock)
34 int len;
35 struct dbc_request *req;
36 int status = 0;
37 bool do_tty_wake = false;
38 struct list_head *pool = &port->write_pool;
40 while (!list_empty(pool)) {
41 req = list_entry(pool->next, struct dbc_request, list_pool);
42 len = dbc_send_packet(port, req->buf, DBC_MAX_PACKET);
43 if (len == 0)
44 break;
45 do_tty_wake = true;
47 req->length = len;
48 list_del(&req->list_pool);
50 spin_unlock(&port->port_lock);
51 status = dbc_ep_queue(port->out, req, GFP_ATOMIC);
52 spin_lock(&port->port_lock);
54 if (status) {
55 list_add(&req->list_pool, pool);
56 break;
60 if (do_tty_wake && port->port.tty)
61 tty_wakeup(port->port.tty);
63 return status;
66 static void dbc_start_rx(struct dbc_port *port)
67 __releases(&port->port_lock)
68 __acquires(&port->port_lock)
70 struct dbc_request *req;
71 int status;
72 struct list_head *pool = &port->read_pool;
74 while (!list_empty(pool)) {
75 if (!port->port.tty)
76 break;
78 req = list_entry(pool->next, struct dbc_request, list_pool);
79 list_del(&req->list_pool);
80 req->length = DBC_MAX_PACKET;
82 spin_unlock(&port->port_lock);
83 status = dbc_ep_queue(port->in, req, GFP_ATOMIC);
84 spin_lock(&port->port_lock);
86 if (status) {
87 list_add(&req->list_pool, pool);
88 break;
93 static void
94 dbc_read_complete(struct xhci_hcd *xhci, struct dbc_request *req)
96 unsigned long flags;
97 struct xhci_dbc *dbc = xhci->dbc;
98 struct dbc_port *port = &dbc->port;
100 spin_lock_irqsave(&port->port_lock, flags);
101 list_add_tail(&req->list_pool, &port->read_queue);
102 tasklet_schedule(&port->push);
103 spin_unlock_irqrestore(&port->port_lock, flags);
106 static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req)
108 unsigned long flags;
109 struct xhci_dbc *dbc = xhci->dbc;
110 struct dbc_port *port = &dbc->port;
112 spin_lock_irqsave(&port->port_lock, flags);
113 list_add(&req->list_pool, &port->write_pool);
114 switch (req->status) {
115 case 0:
116 dbc_start_tx(port);
117 break;
118 case -ESHUTDOWN:
119 break;
120 default:
121 xhci_warn(xhci, "unexpected write complete status %d\n",
122 req->status);
123 break;
125 spin_unlock_irqrestore(&port->port_lock, flags);
128 static void xhci_dbc_free_req(struct dbc_ep *dep, struct dbc_request *req)
130 kfree(req->buf);
131 dbc_free_request(dep, req);
134 static int
135 xhci_dbc_alloc_requests(struct dbc_ep *dep, struct list_head *head,
136 void (*fn)(struct xhci_hcd *, struct dbc_request *))
138 int i;
139 struct dbc_request *req;
141 for (i = 0; i < DBC_QUEUE_SIZE; i++) {
142 req = dbc_alloc_request(dep, GFP_KERNEL);
143 if (!req)
144 break;
146 req->length = DBC_MAX_PACKET;
147 req->buf = kmalloc(req->length, GFP_KERNEL);
148 if (!req->buf) {
149 dbc_free_request(dep, req);
150 break;
153 req->complete = fn;
154 list_add_tail(&req->list_pool, head);
157 return list_empty(head) ? -ENOMEM : 0;
160 static void
161 xhci_dbc_free_requests(struct dbc_ep *dep, struct list_head *head)
163 struct dbc_request *req;
165 while (!list_empty(head)) {
166 req = list_entry(head->next, struct dbc_request, list_pool);
167 list_del(&req->list_pool);
168 xhci_dbc_free_req(dep, req);
172 static int dbc_tty_install(struct tty_driver *driver, struct tty_struct *tty)
174 struct dbc_port *port = driver->driver_state;
176 tty->driver_data = port;
178 return tty_port_install(&port->port, driver, tty);
181 static int dbc_tty_open(struct tty_struct *tty, struct file *file)
183 struct dbc_port *port = tty->driver_data;
185 return tty_port_open(&port->port, tty, file);
188 static void dbc_tty_close(struct tty_struct *tty, struct file *file)
190 struct dbc_port *port = tty->driver_data;
192 tty_port_close(&port->port, tty, file);
195 static int dbc_tty_write(struct tty_struct *tty,
196 const unsigned char *buf,
197 int count)
199 struct dbc_port *port = tty->driver_data;
200 unsigned long flags;
202 spin_lock_irqsave(&port->port_lock, flags);
203 if (count)
204 count = kfifo_in(&port->write_fifo, buf, count);
205 dbc_start_tx(port);
206 spin_unlock_irqrestore(&port->port_lock, flags);
208 return count;
211 static int dbc_tty_put_char(struct tty_struct *tty, unsigned char ch)
213 struct dbc_port *port = tty->driver_data;
214 unsigned long flags;
215 int status;
217 spin_lock_irqsave(&port->port_lock, flags);
218 status = kfifo_put(&port->write_fifo, ch);
219 spin_unlock_irqrestore(&port->port_lock, flags);
221 return status;
224 static void dbc_tty_flush_chars(struct tty_struct *tty)
226 struct dbc_port *port = tty->driver_data;
227 unsigned long flags;
229 spin_lock_irqsave(&port->port_lock, flags);
230 dbc_start_tx(port);
231 spin_unlock_irqrestore(&port->port_lock, flags);
234 static int dbc_tty_write_room(struct tty_struct *tty)
236 struct dbc_port *port = tty->driver_data;
237 unsigned long flags;
238 int room = 0;
240 spin_lock_irqsave(&port->port_lock, flags);
241 room = kfifo_avail(&port->write_fifo);
242 spin_unlock_irqrestore(&port->port_lock, flags);
244 return room;
247 static int dbc_tty_chars_in_buffer(struct tty_struct *tty)
249 struct dbc_port *port = tty->driver_data;
250 unsigned long flags;
251 int chars = 0;
253 spin_lock_irqsave(&port->port_lock, flags);
254 chars = kfifo_len(&port->write_fifo);
255 spin_unlock_irqrestore(&port->port_lock, flags);
257 return chars;
260 static void dbc_tty_unthrottle(struct tty_struct *tty)
262 struct dbc_port *port = tty->driver_data;
263 unsigned long flags;
265 spin_lock_irqsave(&port->port_lock, flags);
266 tasklet_schedule(&port->push);
267 spin_unlock_irqrestore(&port->port_lock, flags);
270 static const struct tty_operations dbc_tty_ops = {
271 .install = dbc_tty_install,
272 .open = dbc_tty_open,
273 .close = dbc_tty_close,
274 .write = dbc_tty_write,
275 .put_char = dbc_tty_put_char,
276 .flush_chars = dbc_tty_flush_chars,
277 .write_room = dbc_tty_write_room,
278 .chars_in_buffer = dbc_tty_chars_in_buffer,
279 .unthrottle = dbc_tty_unthrottle,
282 static struct tty_driver *dbc_tty_driver;
284 int xhci_dbc_tty_register_driver(struct xhci_hcd *xhci)
286 int status;
287 struct xhci_dbc *dbc = xhci->dbc;
289 dbc_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
290 TTY_DRIVER_DYNAMIC_DEV);
291 if (IS_ERR(dbc_tty_driver)) {
292 status = PTR_ERR(dbc_tty_driver);
293 dbc_tty_driver = NULL;
294 return status;
297 dbc_tty_driver->driver_name = "dbc_serial";
298 dbc_tty_driver->name = "ttyDBC";
300 dbc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
301 dbc_tty_driver->subtype = SERIAL_TYPE_NORMAL;
302 dbc_tty_driver->init_termios = tty_std_termios;
303 dbc_tty_driver->init_termios.c_cflag =
304 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
305 dbc_tty_driver->init_termios.c_ispeed = 9600;
306 dbc_tty_driver->init_termios.c_ospeed = 9600;
307 dbc_tty_driver->driver_state = &dbc->port;
309 tty_set_operations(dbc_tty_driver, &dbc_tty_ops);
311 status = tty_register_driver(dbc_tty_driver);
312 if (status) {
313 xhci_err(xhci,
314 "can't register dbc tty driver, err %d\n", status);
315 put_tty_driver(dbc_tty_driver);
316 dbc_tty_driver = NULL;
319 return status;
322 void xhci_dbc_tty_unregister_driver(void)
324 if (dbc_tty_driver) {
325 tty_unregister_driver(dbc_tty_driver);
326 put_tty_driver(dbc_tty_driver);
327 dbc_tty_driver = NULL;
331 static void dbc_rx_push(unsigned long _port)
333 struct dbc_request *req;
334 struct tty_struct *tty;
335 unsigned long flags;
336 bool do_push = false;
337 bool disconnect = false;
338 struct dbc_port *port = (void *)_port;
339 struct list_head *queue = &port->read_queue;
341 spin_lock_irqsave(&port->port_lock, flags);
342 tty = port->port.tty;
343 while (!list_empty(queue)) {
344 req = list_first_entry(queue, struct dbc_request, list_pool);
346 if (tty && tty_throttled(tty))
347 break;
349 switch (req->status) {
350 case 0:
351 break;
352 case -ESHUTDOWN:
353 disconnect = true;
354 break;
355 default:
356 pr_warn("ttyDBC0: unexpected RX status %d\n",
357 req->status);
358 break;
361 if (req->actual) {
362 char *packet = req->buf;
363 unsigned int n, size = req->actual;
364 int count;
366 n = port->n_read;
367 if (n) {
368 packet += n;
369 size -= n;
372 count = tty_insert_flip_string(&port->port, packet,
373 size);
374 if (count)
375 do_push = true;
376 if (count != size) {
377 port->n_read += count;
378 break;
380 port->n_read = 0;
383 list_move(&req->list_pool, &port->read_pool);
386 if (do_push)
387 tty_flip_buffer_push(&port->port);
389 if (!list_empty(queue) && tty) {
390 if (!tty_throttled(tty)) {
391 if (do_push)
392 tasklet_schedule(&port->push);
393 else
394 pr_warn("ttyDBC0: RX not scheduled?\n");
398 if (!disconnect)
399 dbc_start_rx(port);
401 spin_unlock_irqrestore(&port->port_lock, flags);
404 static int dbc_port_activate(struct tty_port *_port, struct tty_struct *tty)
406 unsigned long flags;
407 struct dbc_port *port = container_of(_port, struct dbc_port, port);
409 spin_lock_irqsave(&port->port_lock, flags);
410 dbc_start_rx(port);
411 spin_unlock_irqrestore(&port->port_lock, flags);
413 return 0;
416 static const struct tty_port_operations dbc_port_ops = {
417 .activate = dbc_port_activate,
420 static void
421 xhci_dbc_tty_init_port(struct xhci_hcd *xhci, struct dbc_port *port)
423 tty_port_init(&port->port);
424 spin_lock_init(&port->port_lock);
425 tasklet_init(&port->push, dbc_rx_push, (unsigned long)port);
426 INIT_LIST_HEAD(&port->read_pool);
427 INIT_LIST_HEAD(&port->read_queue);
428 INIT_LIST_HEAD(&port->write_pool);
430 port->in = get_in_ep(xhci);
431 port->out = get_out_ep(xhci);
432 port->port.ops = &dbc_port_ops;
433 port->n_read = 0;
436 static void
437 xhci_dbc_tty_exit_port(struct dbc_port *port)
439 tasklet_kill(&port->push);
440 tty_port_destroy(&port->port);
443 int xhci_dbc_tty_register_device(struct xhci_hcd *xhci)
445 int ret;
446 struct device *tty_dev;
447 struct xhci_dbc *dbc = xhci->dbc;
448 struct dbc_port *port = &dbc->port;
450 xhci_dbc_tty_init_port(xhci, port);
451 tty_dev = tty_port_register_device(&port->port,
452 dbc_tty_driver, 0, NULL);
453 if (IS_ERR(tty_dev)) {
454 ret = PTR_ERR(tty_dev);
455 goto register_fail;
458 ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL);
459 if (ret)
460 goto buf_alloc_fail;
462 ret = xhci_dbc_alloc_requests(port->in, &port->read_pool,
463 dbc_read_complete);
464 if (ret)
465 goto request_fail;
467 ret = xhci_dbc_alloc_requests(port->out, &port->write_pool,
468 dbc_write_complete);
469 if (ret)
470 goto request_fail;
472 port->registered = true;
474 return 0;
476 request_fail:
477 xhci_dbc_free_requests(port->in, &port->read_pool);
478 xhci_dbc_free_requests(port->out, &port->write_pool);
479 kfifo_free(&port->write_fifo);
481 buf_alloc_fail:
482 tty_unregister_device(dbc_tty_driver, 0);
484 register_fail:
485 xhci_dbc_tty_exit_port(port);
487 xhci_err(xhci, "can't register tty port, err %d\n", ret);
489 return ret;
492 void xhci_dbc_tty_unregister_device(struct xhci_hcd *xhci)
494 struct xhci_dbc *dbc = xhci->dbc;
495 struct dbc_port *port = &dbc->port;
497 tty_unregister_device(dbc_tty_driver, 0);
498 xhci_dbc_tty_exit_port(port);
499 port->registered = false;
501 kfifo_free(&port->write_fifo);
502 xhci_dbc_free_requests(get_out_ep(xhci), &port->read_pool);
503 xhci_dbc_free_requests(get_out_ep(xhci), &port->read_queue);
504 xhci_dbc_free_requests(get_in_ep(xhci), &port->write_pool);