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