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 unsigned int 18 dbc_send_packet(struct dbc_port *port, char *packet, unsigned int size) 19 { 20 unsigned int len; 21 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; 28 } 29 30 static int dbc_start_tx(struct dbc_port *port) 31 __releases(&port->port_lock) 32 __acquires(&port->port_lock) 33 { 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; 39 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; 46 47 req->length = len; 48 list_del(&req->list_pool); 49 50 spin_unlock(&port->port_lock); 51 status = dbc_ep_queue(port->out, req, GFP_ATOMIC); 52 spin_lock(&port->port_lock); 53 54 if (status) { 55 list_add(&req->list_pool, pool); 56 break; 57 } 58 } 59 60 if (do_tty_wake && port->port.tty) 61 tty_wakeup(port->port.tty); 62 63 return status; 64 } 65 66 static void dbc_start_rx(struct dbc_port *port) 67 __releases(&port->port_lock) 68 __acquires(&port->port_lock) 69 { 70 struct dbc_request *req; 71 int status; 72 struct list_head *pool = &port->read_pool; 73 74 while (!list_empty(pool)) { 75 if (!port->port.tty) 76 break; 77 78 req = list_entry(pool->next, struct dbc_request, list_pool); 79 list_del(&req->list_pool); 80 req->length = DBC_MAX_PACKET; 81 82 spin_unlock(&port->port_lock); 83 status = dbc_ep_queue(port->in, req, GFP_ATOMIC); 84 spin_lock(&port->port_lock); 85 86 if (status) { 87 list_add(&req->list_pool, pool); 88 break; 89 } 90 } 91 } 92 93 static void 94 dbc_read_complete(struct xhci_hcd *xhci, struct dbc_request *req) 95 { 96 unsigned long flags; 97 struct xhci_dbc *dbc = xhci->dbc; 98 struct dbc_port *port = &dbc->port; 99 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); 104 } 105 106 static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req) 107 { 108 unsigned long flags; 109 struct xhci_dbc *dbc = xhci->dbc; 110 struct dbc_port *port = &dbc->port; 111 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; 124 } 125 spin_unlock_irqrestore(&port->port_lock, flags); 126 } 127 128 static void xhci_dbc_free_req(struct dbc_ep *dep, struct dbc_request *req) 129 { 130 kfree(req->buf); 131 dbc_free_request(dep, req); 132 } 133 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 *)) 137 { 138 int i; 139 struct dbc_request *req; 140 141 for (i = 0; i < DBC_QUEUE_SIZE; i++) { 142 req = dbc_alloc_request(dep, GFP_KERNEL); 143 if (!req) 144 break; 145 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; 151 } 152 153 req->complete = fn; 154 list_add_tail(&req->list_pool, head); 155 } 156 157 return list_empty(head) ? -ENOMEM : 0; 158 } 159 160 static void 161 xhci_dbc_free_requests(struct dbc_ep *dep, struct list_head *head) 162 { 163 struct dbc_request *req; 164 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); 169 } 170 } 171 172 static int dbc_tty_install(struct tty_driver *driver, struct tty_struct *tty) 173 { 174 struct dbc_port *port = driver->driver_state; 175 176 tty->driver_data = port; 177 178 return tty_port_install(&port->port, driver, tty); 179 } 180 181 static int dbc_tty_open(struct tty_struct *tty, struct file *file) 182 { 183 struct dbc_port *port = tty->driver_data; 184 185 return tty_port_open(&port->port, tty, file); 186 } 187 188 static void dbc_tty_close(struct tty_struct *tty, struct file *file) 189 { 190 struct dbc_port *port = tty->driver_data; 191 192 tty_port_close(&port->port, tty, file); 193 } 194 195 static int dbc_tty_write(struct tty_struct *tty, 196 const unsigned char *buf, 197 int count) 198 { 199 struct dbc_port *port = tty->driver_data; 200 unsigned long flags; 201 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); 207 208 return count; 209 } 210 211 static int dbc_tty_put_char(struct tty_struct *tty, unsigned char ch) 212 { 213 struct dbc_port *port = tty->driver_data; 214 unsigned long flags; 215 int status; 216 217 spin_lock_irqsave(&port->port_lock, flags); 218 status = kfifo_put(&port->write_fifo, ch); 219 spin_unlock_irqrestore(&port->port_lock, flags); 220 221 return status; 222 } 223 224 static void dbc_tty_flush_chars(struct tty_struct *tty) 225 { 226 struct dbc_port *port = tty->driver_data; 227 unsigned long flags; 228 229 spin_lock_irqsave(&port->port_lock, flags); 230 dbc_start_tx(port); 231 spin_unlock_irqrestore(&port->port_lock, flags); 232 } 233 234 static int dbc_tty_write_room(struct tty_struct *tty) 235 { 236 struct dbc_port *port = tty->driver_data; 237 unsigned long flags; 238 int room = 0; 239 240 spin_lock_irqsave(&port->port_lock, flags); 241 room = kfifo_avail(&port->write_fifo); 242 spin_unlock_irqrestore(&port->port_lock, flags); 243 244 return room; 245 } 246 247 static int dbc_tty_chars_in_buffer(struct tty_struct *tty) 248 { 249 struct dbc_port *port = tty->driver_data; 250 unsigned long flags; 251 int chars = 0; 252 253 spin_lock_irqsave(&port->port_lock, flags); 254 chars = kfifo_len(&port->write_fifo); 255 spin_unlock_irqrestore(&port->port_lock, flags); 256 257 return chars; 258 } 259 260 static void dbc_tty_unthrottle(struct tty_struct *tty) 261 { 262 struct dbc_port *port = tty->driver_data; 263 unsigned long flags; 264 265 spin_lock_irqsave(&port->port_lock, flags); 266 tasklet_schedule(&port->push); 267 spin_unlock_irqrestore(&port->port_lock, flags); 268 } 269 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, 280 }; 281 282 static struct tty_driver *dbc_tty_driver; 283 284 int xhci_dbc_tty_register_driver(struct xhci_hcd *xhci) 285 { 286 int status; 287 struct xhci_dbc *dbc = xhci->dbc; 288 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; 295 } 296 297 dbc_tty_driver->driver_name = "dbc_serial"; 298 dbc_tty_driver->name = "ttyDBC"; 299 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; 308 309 tty_set_operations(dbc_tty_driver, &dbc_tty_ops); 310 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; 317 } 318 319 return status; 320 } 321 322 void xhci_dbc_tty_unregister_driver(void) 323 { 324 if (dbc_tty_driver) { 325 tty_unregister_driver(dbc_tty_driver); 326 put_tty_driver(dbc_tty_driver); 327 dbc_tty_driver = NULL; 328 } 329 } 330 331 static void dbc_rx_push(unsigned long _port) 332 { 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; 340 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); 345 346 if (tty && tty_throttled(tty)) 347 break; 348 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; 359 } 360 361 if (req->actual) { 362 char *packet = req->buf; 363 unsigned int n, size = req->actual; 364 int count; 365 366 n = port->n_read; 367 if (n) { 368 packet += n; 369 size -= n; 370 } 371 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; 379 } 380 port->n_read = 0; 381 } 382 383 list_move(&req->list_pool, &port->read_pool); 384 } 385 386 if (do_push) 387 tty_flip_buffer_push(&port->port); 388 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"); 395 } 396 } 397 398 if (!disconnect) 399 dbc_start_rx(port); 400 401 spin_unlock_irqrestore(&port->port_lock, flags); 402 } 403 404 static int dbc_port_activate(struct tty_port *_port, struct tty_struct *tty) 405 { 406 unsigned long flags; 407 struct dbc_port *port = container_of(_port, struct dbc_port, port); 408 409 spin_lock_irqsave(&port->port_lock, flags); 410 dbc_start_rx(port); 411 spin_unlock_irqrestore(&port->port_lock, flags); 412 413 return 0; 414 } 415 416 static const struct tty_port_operations dbc_port_ops = { 417 .activate = dbc_port_activate, 418 }; 419 420 static void 421 xhci_dbc_tty_init_port(struct xhci_hcd *xhci, struct dbc_port *port) 422 { 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); 429 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; 434 } 435 436 static void 437 xhci_dbc_tty_exit_port(struct dbc_port *port) 438 { 439 tasklet_kill(&port->push); 440 tty_port_destroy(&port->port); 441 } 442 443 int xhci_dbc_tty_register_device(struct xhci_hcd *xhci) 444 { 445 int ret; 446 struct device *tty_dev; 447 struct xhci_dbc *dbc = xhci->dbc; 448 struct dbc_port *port = &dbc->port; 449 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; 456 } 457 458 ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL); 459 if (ret) 460 goto buf_alloc_fail; 461 462 ret = xhci_dbc_alloc_requests(port->in, &port->read_pool, 463 dbc_read_complete); 464 if (ret) 465 goto request_fail; 466 467 ret = xhci_dbc_alloc_requests(port->out, &port->write_pool, 468 dbc_write_complete); 469 if (ret) 470 goto request_fail; 471 472 port->registered = true; 473 474 return 0; 475 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); 480 481 buf_alloc_fail: 482 tty_unregister_device(dbc_tty_driver, 0); 483 484 register_fail: 485 xhci_dbc_tty_exit_port(port); 486 487 xhci_err(xhci, "can't register tty port, err %d\n", ret); 488 489 return ret; 490 } 491 492 void xhci_dbc_tty_unregister_device(struct xhci_hcd *xhci) 493 { 494 struct xhci_dbc *dbc = xhci->dbc; 495 struct dbc_port *port = &dbc->port; 496 497 tty_unregister_device(dbc_tty_driver, 0); 498 xhci_dbc_tty_exit_port(port); 499 port->registered = false; 500 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); 505 } 506