Lines Matching +full:port +full:-

1 // SPDX-License-Identifier: GPL-2.0
3 * xhci-dbgtty.c - tty glue for xHCI debug capability
16 #include "xhci-dbgcap.h"
24 return dbc->priv; in dbc_to_port()
28 dbc_kfifo_to_req(struct dbc_port *port, char *packet) in dbc_kfifo_to_req() argument
32 len = kfifo_len(&port->port.xmit_fifo); in dbc_kfifo_to_req()
39 if (port->tx_boundary) in dbc_kfifo_to_req()
40 len = min(port->tx_boundary, len); in dbc_kfifo_to_req()
42 len = kfifo_out(&port->port.xmit_fifo, packet, len); in dbc_kfifo_to_req()
44 if (port->tx_boundary) in dbc_kfifo_to_req()
45 port->tx_boundary -= len; in dbc_kfifo_to_req()
50 static int dbc_start_tx(struct dbc_port *port) in dbc_start_tx() argument
51 __releases(&port->port_lock) in dbc_start_tx()
52 __acquires(&port->port_lock) in dbc_start_tx()
58 struct list_head *pool = &port->write_pool; in dbc_start_tx()
61 req = list_entry(pool->next, struct dbc_request, list_pool); in dbc_start_tx()
62 len = dbc_kfifo_to_req(port, req->buf); in dbc_start_tx()
67 req->length = len; in dbc_start_tx()
68 list_del(&req->list_pool); in dbc_start_tx()
70 spin_unlock(&port->port_lock); in dbc_start_tx()
72 spin_lock(&port->port_lock); in dbc_start_tx()
75 list_add(&req->list_pool, pool); in dbc_start_tx()
80 if (do_tty_wake && port->port.tty) in dbc_start_tx()
81 tty_wakeup(port->port.tty); in dbc_start_tx()
86 static void dbc_start_rx(struct dbc_port *port) in dbc_start_rx() argument
87 __releases(&port->port_lock) in dbc_start_rx()
88 __acquires(&port->port_lock) in dbc_start_rx()
92 struct list_head *pool = &port->read_pool; in dbc_start_rx()
95 if (!port->port.tty) in dbc_start_rx()
98 req = list_entry(pool->next, struct dbc_request, list_pool); in dbc_start_rx()
99 list_del(&req->list_pool); in dbc_start_rx()
100 req->length = DBC_MAX_PACKET; in dbc_start_rx()
102 spin_unlock(&port->port_lock); in dbc_start_rx()
104 spin_lock(&port->port_lock); in dbc_start_rx()
107 list_add(&req->list_pool, pool); in dbc_start_rx()
120 static int dbc_rx_push_buffer(struct dbc_port *port, struct dbc_request *req) in dbc_rx_push_buffer() argument
122 char *packet = req->buf; in dbc_rx_push_buffer()
123 unsigned int n, size = req->actual; in dbc_rx_push_buffer()
126 if (!req->actual) in dbc_rx_push_buffer()
130 n = port->n_read; in dbc_rx_push_buffer()
133 size -= n; in dbc_rx_push_buffer()
136 count = tty_insert_flip_string(&port->port, packet, size); in dbc_rx_push_buffer()
138 tty_flip_buffer_push(&port->port); in dbc_rx_push_buffer()
140 port->n_read += count; in dbc_rx_push_buffer()
141 return size - count; in dbc_rx_push_buffer()
144 port->n_read = 0; in dbc_rx_push_buffer()
152 struct dbc_port *port = dbc_to_port(dbc); in dbc_read_complete() local
156 tty = port->port.tty; in dbc_read_complete()
158 spin_lock_irqsave(&port->port_lock, flags); in dbc_read_complete()
162 * - !list_empty(&port->read_queue), there are older pending data in dbc_read_complete()
163 * - tty is throttled in dbc_read_complete()
164 * - failed to copy all data to buffer, defer remaining part in dbc_read_complete()
167 if (list_empty(&port->read_queue) && tty && !tty_throttled(tty)) { in dbc_read_complete()
168 untransferred = dbc_rx_push_buffer(port, req); in dbc_read_complete()
170 list_add_tail(&req->list_pool, &port->read_pool); in dbc_read_complete()
171 if (req->status != -ESHUTDOWN) in dbc_read_complete()
172 dbc_start_rx(port); in dbc_read_complete()
178 list_add_tail(&req->list_pool, &port->read_queue); in dbc_read_complete()
179 tasklet_schedule(&port->push); in dbc_read_complete()
181 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_read_complete()
187 struct dbc_port *port = dbc_to_port(dbc); in dbc_write_complete() local
189 spin_lock_irqsave(&port->port_lock, flags); in dbc_write_complete()
190 list_add(&req->list_pool, &port->write_pool); in dbc_write_complete()
191 switch (req->status) { in dbc_write_complete()
193 dbc_start_tx(port); in dbc_write_complete()
195 case -ESHUTDOWN: in dbc_write_complete()
198 dev_warn(dbc->dev, "unexpected write complete status %d\n", in dbc_write_complete()
199 req->status); in dbc_write_complete()
202 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_write_complete()
207 kfree(req->buf); in xhci_dbc_free_req()
224 req->length = DBC_MAX_PACKET; in xhci_dbc_alloc_requests()
225 req->buf = kmalloc(req->length, GFP_KERNEL); in xhci_dbc_alloc_requests()
226 if (!req->buf) { in xhci_dbc_alloc_requests()
231 req->complete = fn; in xhci_dbc_alloc_requests()
232 list_add_tail(&req->list_pool, head); in xhci_dbc_alloc_requests()
235 return list_empty(head) ? -ENOMEM : 0; in xhci_dbc_alloc_requests()
244 req = list_entry(head->next, struct dbc_request, list_pool); in xhci_dbc_free_requests()
245 list_del(&req->list_pool); in xhci_dbc_free_requests()
252 struct dbc_port *port; in dbc_tty_install() local
255 port = idr_find(&dbc_tty_minors, tty->index); in dbc_tty_install()
258 if (!port) in dbc_tty_install()
259 return -ENXIO; in dbc_tty_install()
261 tty->driver_data = port; in dbc_tty_install()
263 return tty_port_install(&port->port, driver, tty); in dbc_tty_install()
268 struct dbc_port *port = tty->driver_data; in dbc_tty_open() local
270 return tty_port_open(&port->port, tty, file); in dbc_tty_open()
275 struct dbc_port *port = tty->driver_data; in dbc_tty_close() local
277 tty_port_close(&port->port, tty, file); in dbc_tty_close()
283 struct dbc_port *port = tty->driver_data; in dbc_tty_write() local
287 spin_lock_irqsave(&port->port_lock, flags); in dbc_tty_write()
294 if (port->tx_boundary) { in dbc_tty_write()
295 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_tty_write()
300 written = kfifo_in(&port->port.xmit_fifo, buf, count); in dbc_tty_write()
303 port->tx_boundary = kfifo_len(&port->port.xmit_fifo); in dbc_tty_write()
305 dbc_start_tx(port); in dbc_tty_write()
308 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_tty_write()
315 struct dbc_port *port = tty->driver_data; in dbc_tty_put_char() local
319 spin_lock_irqsave(&port->port_lock, flags); in dbc_tty_put_char()
320 status = kfifo_put(&port->port.xmit_fifo, ch); in dbc_tty_put_char()
321 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_tty_put_char()
328 struct dbc_port *port = tty->driver_data; in dbc_tty_flush_chars() local
331 spin_lock_irqsave(&port->port_lock, flags); in dbc_tty_flush_chars()
332 dbc_start_tx(port); in dbc_tty_flush_chars()
333 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_tty_flush_chars()
338 struct dbc_port *port = tty->driver_data; in dbc_tty_write_room() local
342 spin_lock_irqsave(&port->port_lock, flags); in dbc_tty_write_room()
343 room = kfifo_avail(&port->port.xmit_fifo); in dbc_tty_write_room()
345 if (port->tx_boundary) in dbc_tty_write_room()
348 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_tty_write_room()
355 struct dbc_port *port = tty->driver_data; in dbc_tty_chars_in_buffer() local
359 spin_lock_irqsave(&port->port_lock, flags); in dbc_tty_chars_in_buffer()
360 chars = kfifo_len(&port->port.xmit_fifo); in dbc_tty_chars_in_buffer()
361 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_tty_chars_in_buffer()
368 struct dbc_port *port = tty->driver_data; in dbc_tty_unthrottle() local
371 spin_lock_irqsave(&port->port_lock, flags); in dbc_tty_unthrottle()
372 tasklet_schedule(&port->push); in dbc_tty_unthrottle()
373 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_tty_unthrottle()
394 struct dbc_port *port = from_tasklet(port, t, push); in dbc_rx_push() local
395 struct list_head *queue = &port->read_queue; in dbc_rx_push()
398 spin_lock_irqsave(&port->port_lock, flags); in dbc_rx_push()
399 tty = port->port.tty; in dbc_rx_push()
406 switch (req->status) { in dbc_rx_push()
409 case -ESHUTDOWN: in dbc_rx_push()
414 req->status); in dbc_rx_push()
418 untransferred = dbc_rx_push_buffer(port, req); in dbc_rx_push()
422 list_move_tail(&req->list_pool, &port->read_pool); in dbc_rx_push()
426 tasklet_schedule(&port->push); in dbc_rx_push()
429 dbc_start_rx(port); in dbc_rx_push()
431 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_rx_push()
437 struct dbc_port *port = container_of(_port, struct dbc_port, port); in dbc_port_activate() local
439 spin_lock_irqsave(&port->port_lock, flags); in dbc_port_activate()
440 dbc_start_rx(port); in dbc_port_activate()
441 spin_unlock_irqrestore(&port->port_lock, flags); in dbc_port_activate()
451 xhci_dbc_tty_init_port(struct xhci_dbc *dbc, struct dbc_port *port) in xhci_dbc_tty_init_port() argument
453 tty_port_init(&port->port); in xhci_dbc_tty_init_port()
454 spin_lock_init(&port->port_lock); in xhci_dbc_tty_init_port()
455 tasklet_setup(&port->push, dbc_rx_push); in xhci_dbc_tty_init_port()
456 INIT_LIST_HEAD(&port->read_pool); in xhci_dbc_tty_init_port()
457 INIT_LIST_HEAD(&port->read_queue); in xhci_dbc_tty_init_port()
458 INIT_LIST_HEAD(&port->write_pool); in xhci_dbc_tty_init_port()
460 port->port.ops = &dbc_port_ops; in xhci_dbc_tty_init_port()
461 port->n_read = 0; in xhci_dbc_tty_init_port()
465 xhci_dbc_tty_exit_port(struct dbc_port *port) in xhci_dbc_tty_exit_port() argument
467 tasklet_kill(&port->push); in xhci_dbc_tty_exit_port()
468 tty_port_destroy(&port->port); in xhci_dbc_tty_exit_port()
475 struct dbc_port *port = dbc_to_port(dbc); in xhci_dbc_tty_register_device() local
477 if (port->registered) in xhci_dbc_tty_register_device()
478 return -EBUSY; in xhci_dbc_tty_register_device()
480 xhci_dbc_tty_init_port(dbc, port); in xhci_dbc_tty_register_device()
483 port->minor = idr_alloc(&dbc_tty_minors, port, 0, 64, GFP_KERNEL); in xhci_dbc_tty_register_device()
486 if (port->minor < 0) { in xhci_dbc_tty_register_device()
487 ret = port->minor; in xhci_dbc_tty_register_device()
491 ret = kfifo_alloc(&port->port.xmit_fifo, DBC_WRITE_BUF_SIZE, in xhci_dbc_tty_register_device()
496 ret = xhci_dbc_alloc_requests(dbc, BULK_IN, &port->read_pool, in xhci_dbc_tty_register_device()
501 ret = xhci_dbc_alloc_requests(dbc, BULK_OUT, &port->write_pool, in xhci_dbc_tty_register_device()
506 tty_dev = tty_port_register_device(&port->port, in xhci_dbc_tty_register_device()
507 dbc_tty_driver, port->minor, NULL); in xhci_dbc_tty_register_device()
513 port->registered = true; in xhci_dbc_tty_register_device()
518 xhci_dbc_free_requests(&port->read_pool); in xhci_dbc_tty_register_device()
519 xhci_dbc_free_requests(&port->write_pool); in xhci_dbc_tty_register_device()
521 kfifo_free(&port->port.xmit_fifo); in xhci_dbc_tty_register_device()
523 idr_remove(&dbc_tty_minors, port->minor); in xhci_dbc_tty_register_device()
525 xhci_dbc_tty_exit_port(port); in xhci_dbc_tty_register_device()
527 dev_err(dbc->dev, "can't register tty port, err %d\n", ret); in xhci_dbc_tty_register_device()
534 struct dbc_port *port = dbc_to_port(dbc); in xhci_dbc_tty_unregister_device() local
536 if (!port->registered) in xhci_dbc_tty_unregister_device()
538 tty_unregister_device(dbc_tty_driver, port->minor); in xhci_dbc_tty_unregister_device()
539 xhci_dbc_tty_exit_port(port); in xhci_dbc_tty_unregister_device()
540 port->registered = false; in xhci_dbc_tty_unregister_device()
543 idr_remove(&dbc_tty_minors, port->minor); in xhci_dbc_tty_unregister_device()
546 kfifo_free(&port->port.xmit_fifo); in xhci_dbc_tty_unregister_device()
547 xhci_dbc_free_requests(&port->read_pool); in xhci_dbc_tty_unregister_device()
548 xhci_dbc_free_requests(&port->read_queue); in xhci_dbc_tty_unregister_device()
549 xhci_dbc_free_requests(&port->write_pool); in xhci_dbc_tty_unregister_device()
560 struct dbc_port *port; in xhci_dbc_tty_probe() local
564 return -ENODEV; in xhci_dbc_tty_probe()
566 port = kzalloc(sizeof(*port), GFP_KERNEL); in xhci_dbc_tty_probe()
567 if (!port) in xhci_dbc_tty_probe()
568 return -ENOMEM; in xhci_dbc_tty_probe()
573 status = -ENOMEM; in xhci_dbc_tty_probe()
577 dbc->priv = port; in xhci_dbc_tty_probe()
580 xhci->dbc = dbc; in xhci_dbc_tty_probe()
584 kfree(port); in xhci_dbc_tty_probe()
595 struct dbc_port *port = dbc_to_port(dbc); in xhci_dbc_tty_remove() local
598 kfree(port); in xhci_dbc_tty_remove()
614 dbc_tty_driver->driver_name = "dbc_serial"; in dbc_tty_init()
615 dbc_tty_driver->name = "ttyDBC"; in dbc_tty_init()
617 dbc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; in dbc_tty_init()
618 dbc_tty_driver->subtype = SERIAL_TYPE_NORMAL; in dbc_tty_init()
619 dbc_tty_driver->init_termios = tty_std_termios; in dbc_tty_init()
620 dbc_tty_driver->init_termios.c_cflag = in dbc_tty_init()
622 dbc_tty_driver->init_termios.c_ispeed = 9600; in dbc_tty_init()
623 dbc_tty_driver->init_termios.c_ospeed = 9600; in dbc_tty_init()