0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/slab.h>
0011 #include <linux/tty.h>
0012 #include <linux/tty_flip.h>
0013 #include <linux/idr.h>
0014
0015 #include "xhci.h"
0016 #include "xhci-dbgcap.h"
0017
0018 static struct tty_driver *dbc_tty_driver;
0019 static struct idr dbc_tty_minors;
0020 static DEFINE_MUTEX(dbc_tty_minors_lock);
0021
0022 static inline struct dbc_port *dbc_to_port(struct xhci_dbc *dbc)
0023 {
0024 return dbc->priv;
0025 }
0026
0027 static unsigned int
0028 dbc_send_packet(struct dbc_port *port, char *packet, unsigned int size)
0029 {
0030 unsigned int len;
0031
0032 len = kfifo_len(&port->write_fifo);
0033 if (len < size)
0034 size = len;
0035 if (size != 0)
0036 size = kfifo_out(&port->write_fifo, packet, size);
0037 return size;
0038 }
0039
0040 static int dbc_start_tx(struct dbc_port *port)
0041 __releases(&port->port_lock)
0042 __acquires(&port->port_lock)
0043 {
0044 int len;
0045 struct dbc_request *req;
0046 int status = 0;
0047 bool do_tty_wake = false;
0048 struct list_head *pool = &port->write_pool;
0049
0050 while (!list_empty(pool)) {
0051 req = list_entry(pool->next, struct dbc_request, list_pool);
0052 len = dbc_send_packet(port, req->buf, DBC_MAX_PACKET);
0053 if (len == 0)
0054 break;
0055 do_tty_wake = true;
0056
0057 req->length = len;
0058 list_del(&req->list_pool);
0059
0060 spin_unlock(&port->port_lock);
0061 status = dbc_ep_queue(req);
0062 spin_lock(&port->port_lock);
0063
0064 if (status) {
0065 list_add(&req->list_pool, pool);
0066 break;
0067 }
0068 }
0069
0070 if (do_tty_wake && port->port.tty)
0071 tty_wakeup(port->port.tty);
0072
0073 return status;
0074 }
0075
0076 static void dbc_start_rx(struct dbc_port *port)
0077 __releases(&port->port_lock)
0078 __acquires(&port->port_lock)
0079 {
0080 struct dbc_request *req;
0081 int status;
0082 struct list_head *pool = &port->read_pool;
0083
0084 while (!list_empty(pool)) {
0085 if (!port->port.tty)
0086 break;
0087
0088 req = list_entry(pool->next, struct dbc_request, list_pool);
0089 list_del(&req->list_pool);
0090 req->length = DBC_MAX_PACKET;
0091
0092 spin_unlock(&port->port_lock);
0093 status = dbc_ep_queue(req);
0094 spin_lock(&port->port_lock);
0095
0096 if (status) {
0097 list_add(&req->list_pool, pool);
0098 break;
0099 }
0100 }
0101 }
0102
0103 static void
0104 dbc_read_complete(struct xhci_dbc *dbc, struct dbc_request *req)
0105 {
0106 unsigned long flags;
0107 struct dbc_port *port = dbc_to_port(dbc);
0108
0109 spin_lock_irqsave(&port->port_lock, flags);
0110 list_add_tail(&req->list_pool, &port->read_queue);
0111 tasklet_schedule(&port->push);
0112 spin_unlock_irqrestore(&port->port_lock, flags);
0113 }
0114
0115 static void dbc_write_complete(struct xhci_dbc *dbc, struct dbc_request *req)
0116 {
0117 unsigned long flags;
0118 struct dbc_port *port = dbc_to_port(dbc);
0119
0120 spin_lock_irqsave(&port->port_lock, flags);
0121 list_add(&req->list_pool, &port->write_pool);
0122 switch (req->status) {
0123 case 0:
0124 dbc_start_tx(port);
0125 break;
0126 case -ESHUTDOWN:
0127 break;
0128 default:
0129 dev_warn(dbc->dev, "unexpected write complete status %d\n",
0130 req->status);
0131 break;
0132 }
0133 spin_unlock_irqrestore(&port->port_lock, flags);
0134 }
0135
0136 static void xhci_dbc_free_req(struct dbc_request *req)
0137 {
0138 kfree(req->buf);
0139 dbc_free_request(req);
0140 }
0141
0142 static int
0143 xhci_dbc_alloc_requests(struct xhci_dbc *dbc, unsigned int direction,
0144 struct list_head *head,
0145 void (*fn)(struct xhci_dbc *, struct dbc_request *))
0146 {
0147 int i;
0148 struct dbc_request *req;
0149
0150 for (i = 0; i < DBC_QUEUE_SIZE; i++) {
0151 req = dbc_alloc_request(dbc, direction, GFP_KERNEL);
0152 if (!req)
0153 break;
0154
0155 req->length = DBC_MAX_PACKET;
0156 req->buf = kmalloc(req->length, GFP_KERNEL);
0157 if (!req->buf) {
0158 dbc_free_request(req);
0159 break;
0160 }
0161
0162 req->complete = fn;
0163 list_add_tail(&req->list_pool, head);
0164 }
0165
0166 return list_empty(head) ? -ENOMEM : 0;
0167 }
0168
0169 static void
0170 xhci_dbc_free_requests(struct list_head *head)
0171 {
0172 struct dbc_request *req;
0173
0174 while (!list_empty(head)) {
0175 req = list_entry(head->next, struct dbc_request, list_pool);
0176 list_del(&req->list_pool);
0177 xhci_dbc_free_req(req);
0178 }
0179 }
0180
0181 static int dbc_tty_install(struct tty_driver *driver, struct tty_struct *tty)
0182 {
0183 struct dbc_port *port;
0184
0185 mutex_lock(&dbc_tty_minors_lock);
0186 port = idr_find(&dbc_tty_minors, tty->index);
0187 mutex_unlock(&dbc_tty_minors_lock);
0188
0189 if (!port)
0190 return -ENXIO;
0191
0192 tty->driver_data = port;
0193
0194 return tty_port_install(&port->port, driver, tty);
0195 }
0196
0197 static int dbc_tty_open(struct tty_struct *tty, struct file *file)
0198 {
0199 struct dbc_port *port = tty->driver_data;
0200
0201 return tty_port_open(&port->port, tty, file);
0202 }
0203
0204 static void dbc_tty_close(struct tty_struct *tty, struct file *file)
0205 {
0206 struct dbc_port *port = tty->driver_data;
0207
0208 tty_port_close(&port->port, tty, file);
0209 }
0210
0211 static int dbc_tty_write(struct tty_struct *tty,
0212 const unsigned char *buf,
0213 int count)
0214 {
0215 struct dbc_port *port = tty->driver_data;
0216 unsigned long flags;
0217
0218 spin_lock_irqsave(&port->port_lock, flags);
0219 if (count)
0220 count = kfifo_in(&port->write_fifo, buf, count);
0221 dbc_start_tx(port);
0222 spin_unlock_irqrestore(&port->port_lock, flags);
0223
0224 return count;
0225 }
0226
0227 static int dbc_tty_put_char(struct tty_struct *tty, unsigned char ch)
0228 {
0229 struct dbc_port *port = tty->driver_data;
0230 unsigned long flags;
0231 int status;
0232
0233 spin_lock_irqsave(&port->port_lock, flags);
0234 status = kfifo_put(&port->write_fifo, ch);
0235 spin_unlock_irqrestore(&port->port_lock, flags);
0236
0237 return status;
0238 }
0239
0240 static void dbc_tty_flush_chars(struct tty_struct *tty)
0241 {
0242 struct dbc_port *port = tty->driver_data;
0243 unsigned long flags;
0244
0245 spin_lock_irqsave(&port->port_lock, flags);
0246 dbc_start_tx(port);
0247 spin_unlock_irqrestore(&port->port_lock, flags);
0248 }
0249
0250 static unsigned int dbc_tty_write_room(struct tty_struct *tty)
0251 {
0252 struct dbc_port *port = tty->driver_data;
0253 unsigned long flags;
0254 unsigned int room;
0255
0256 spin_lock_irqsave(&port->port_lock, flags);
0257 room = kfifo_avail(&port->write_fifo);
0258 spin_unlock_irqrestore(&port->port_lock, flags);
0259
0260 return room;
0261 }
0262
0263 static unsigned int dbc_tty_chars_in_buffer(struct tty_struct *tty)
0264 {
0265 struct dbc_port *port = tty->driver_data;
0266 unsigned long flags;
0267 unsigned int chars;
0268
0269 spin_lock_irqsave(&port->port_lock, flags);
0270 chars = kfifo_len(&port->write_fifo);
0271 spin_unlock_irqrestore(&port->port_lock, flags);
0272
0273 return chars;
0274 }
0275
0276 static void dbc_tty_unthrottle(struct tty_struct *tty)
0277 {
0278 struct dbc_port *port = tty->driver_data;
0279 unsigned long flags;
0280
0281 spin_lock_irqsave(&port->port_lock, flags);
0282 tasklet_schedule(&port->push);
0283 spin_unlock_irqrestore(&port->port_lock, flags);
0284 }
0285
0286 static const struct tty_operations dbc_tty_ops = {
0287 .install = dbc_tty_install,
0288 .open = dbc_tty_open,
0289 .close = dbc_tty_close,
0290 .write = dbc_tty_write,
0291 .put_char = dbc_tty_put_char,
0292 .flush_chars = dbc_tty_flush_chars,
0293 .write_room = dbc_tty_write_room,
0294 .chars_in_buffer = dbc_tty_chars_in_buffer,
0295 .unthrottle = dbc_tty_unthrottle,
0296 };
0297
0298 static void dbc_rx_push(struct tasklet_struct *t)
0299 {
0300 struct dbc_request *req;
0301 struct tty_struct *tty;
0302 unsigned long flags;
0303 bool do_push = false;
0304 bool disconnect = false;
0305 struct dbc_port *port = from_tasklet(port, t, push);
0306 struct list_head *queue = &port->read_queue;
0307
0308 spin_lock_irqsave(&port->port_lock, flags);
0309 tty = port->port.tty;
0310 while (!list_empty(queue)) {
0311 req = list_first_entry(queue, struct dbc_request, list_pool);
0312
0313 if (tty && tty_throttled(tty))
0314 break;
0315
0316 switch (req->status) {
0317 case 0:
0318 break;
0319 case -ESHUTDOWN:
0320 disconnect = true;
0321 break;
0322 default:
0323 pr_warn("ttyDBC0: unexpected RX status %d\n",
0324 req->status);
0325 break;
0326 }
0327
0328 if (req->actual) {
0329 char *packet = req->buf;
0330 unsigned int n, size = req->actual;
0331 int count;
0332
0333 n = port->n_read;
0334 if (n) {
0335 packet += n;
0336 size -= n;
0337 }
0338
0339 count = tty_insert_flip_string(&port->port, packet,
0340 size);
0341 if (count)
0342 do_push = true;
0343 if (count != size) {
0344 port->n_read += count;
0345 break;
0346 }
0347 port->n_read = 0;
0348 }
0349
0350 list_move(&req->list_pool, &port->read_pool);
0351 }
0352
0353 if (do_push)
0354 tty_flip_buffer_push(&port->port);
0355
0356 if (!list_empty(queue) && tty) {
0357 if (!tty_throttled(tty)) {
0358 if (do_push)
0359 tasklet_schedule(&port->push);
0360 else
0361 pr_warn("ttyDBC0: RX not scheduled?\n");
0362 }
0363 }
0364
0365 if (!disconnect)
0366 dbc_start_rx(port);
0367
0368 spin_unlock_irqrestore(&port->port_lock, flags);
0369 }
0370
0371 static int dbc_port_activate(struct tty_port *_port, struct tty_struct *tty)
0372 {
0373 unsigned long flags;
0374 struct dbc_port *port = container_of(_port, struct dbc_port, port);
0375
0376 spin_lock_irqsave(&port->port_lock, flags);
0377 dbc_start_rx(port);
0378 spin_unlock_irqrestore(&port->port_lock, flags);
0379
0380 return 0;
0381 }
0382
0383 static const struct tty_port_operations dbc_port_ops = {
0384 .activate = dbc_port_activate,
0385 };
0386
0387 static void
0388 xhci_dbc_tty_init_port(struct xhci_dbc *dbc, struct dbc_port *port)
0389 {
0390 tty_port_init(&port->port);
0391 spin_lock_init(&port->port_lock);
0392 tasklet_setup(&port->push, dbc_rx_push);
0393 INIT_LIST_HEAD(&port->read_pool);
0394 INIT_LIST_HEAD(&port->read_queue);
0395 INIT_LIST_HEAD(&port->write_pool);
0396
0397 port->port.ops = &dbc_port_ops;
0398 port->n_read = 0;
0399 }
0400
0401 static void
0402 xhci_dbc_tty_exit_port(struct dbc_port *port)
0403 {
0404 tasklet_kill(&port->push);
0405 tty_port_destroy(&port->port);
0406 }
0407
0408 static int xhci_dbc_tty_register_device(struct xhci_dbc *dbc)
0409 {
0410 int ret;
0411 struct device *tty_dev;
0412 struct dbc_port *port = dbc_to_port(dbc);
0413
0414 if (port->registered)
0415 return -EBUSY;
0416
0417 xhci_dbc_tty_init_port(dbc, port);
0418
0419 mutex_lock(&dbc_tty_minors_lock);
0420 port->minor = idr_alloc(&dbc_tty_minors, port, 0, 64, GFP_KERNEL);
0421 mutex_unlock(&dbc_tty_minors_lock);
0422
0423 if (port->minor < 0) {
0424 ret = port->minor;
0425 goto err_idr;
0426 }
0427
0428 ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL);
0429 if (ret)
0430 goto err_exit_port;
0431
0432 ret = xhci_dbc_alloc_requests(dbc, BULK_IN, &port->read_pool,
0433 dbc_read_complete);
0434 if (ret)
0435 goto err_free_fifo;
0436
0437 ret = xhci_dbc_alloc_requests(dbc, BULK_OUT, &port->write_pool,
0438 dbc_write_complete);
0439 if (ret)
0440 goto err_free_requests;
0441
0442 tty_dev = tty_port_register_device(&port->port,
0443 dbc_tty_driver, port->minor, NULL);
0444 if (IS_ERR(tty_dev)) {
0445 ret = PTR_ERR(tty_dev);
0446 goto err_free_requests;
0447 }
0448
0449 port->registered = true;
0450
0451 return 0;
0452
0453 err_free_requests:
0454 xhci_dbc_free_requests(&port->read_pool);
0455 xhci_dbc_free_requests(&port->write_pool);
0456 err_free_fifo:
0457 kfifo_free(&port->write_fifo);
0458 err_exit_port:
0459 idr_remove(&dbc_tty_minors, port->minor);
0460 err_idr:
0461 xhci_dbc_tty_exit_port(port);
0462
0463 dev_err(dbc->dev, "can't register tty port, err %d\n", ret);
0464
0465 return ret;
0466 }
0467
0468 static void xhci_dbc_tty_unregister_device(struct xhci_dbc *dbc)
0469 {
0470 struct dbc_port *port = dbc_to_port(dbc);
0471
0472 if (!port->registered)
0473 return;
0474 tty_unregister_device(dbc_tty_driver, port->minor);
0475 xhci_dbc_tty_exit_port(port);
0476 port->registered = false;
0477
0478 mutex_lock(&dbc_tty_minors_lock);
0479 idr_remove(&dbc_tty_minors, port->minor);
0480 mutex_unlock(&dbc_tty_minors_lock);
0481
0482 kfifo_free(&port->write_fifo);
0483 xhci_dbc_free_requests(&port->read_pool);
0484 xhci_dbc_free_requests(&port->read_queue);
0485 xhci_dbc_free_requests(&port->write_pool);
0486 }
0487
0488 static const struct dbc_driver dbc_driver = {
0489 .configure = xhci_dbc_tty_register_device,
0490 .disconnect = xhci_dbc_tty_unregister_device,
0491 };
0492
0493 int xhci_dbc_tty_probe(struct device *dev, void __iomem *base, struct xhci_hcd *xhci)
0494 {
0495 struct xhci_dbc *dbc;
0496 struct dbc_port *port;
0497 int status;
0498
0499 if (!dbc_tty_driver)
0500 return -ENODEV;
0501
0502 port = kzalloc(sizeof(*port), GFP_KERNEL);
0503 if (!port)
0504 return -ENOMEM;
0505
0506 dbc = xhci_alloc_dbc(dev, base, &dbc_driver);
0507
0508 if (!dbc) {
0509 status = -ENOMEM;
0510 goto out2;
0511 }
0512
0513 dbc->priv = port;
0514
0515
0516 xhci->dbc = dbc;
0517
0518 return 0;
0519 out2:
0520 kfree(port);
0521
0522 return status;
0523 }
0524
0525
0526
0527
0528
0529 void xhci_dbc_tty_remove(struct xhci_dbc *dbc)
0530 {
0531 struct dbc_port *port = dbc_to_port(dbc);
0532
0533 xhci_dbc_remove(dbc);
0534 kfree(port);
0535 }
0536
0537 int dbc_tty_init(void)
0538 {
0539 int ret;
0540
0541 idr_init(&dbc_tty_minors);
0542
0543 dbc_tty_driver = tty_alloc_driver(64, TTY_DRIVER_REAL_RAW |
0544 TTY_DRIVER_DYNAMIC_DEV);
0545 if (IS_ERR(dbc_tty_driver)) {
0546 idr_destroy(&dbc_tty_minors);
0547 return PTR_ERR(dbc_tty_driver);
0548 }
0549
0550 dbc_tty_driver->driver_name = "dbc_serial";
0551 dbc_tty_driver->name = "ttyDBC";
0552
0553 dbc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
0554 dbc_tty_driver->subtype = SERIAL_TYPE_NORMAL;
0555 dbc_tty_driver->init_termios = tty_std_termios;
0556 dbc_tty_driver->init_termios.c_cflag =
0557 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
0558 dbc_tty_driver->init_termios.c_ispeed = 9600;
0559 dbc_tty_driver->init_termios.c_ospeed = 9600;
0560
0561 tty_set_operations(dbc_tty_driver, &dbc_tty_ops);
0562
0563 ret = tty_register_driver(dbc_tty_driver);
0564 if (ret) {
0565 pr_err("Can't register dbc tty driver\n");
0566 tty_driver_kref_put(dbc_tty_driver);
0567 idr_destroy(&dbc_tty_minors);
0568 }
0569
0570 return ret;
0571 }
0572
0573 void dbc_tty_exit(void)
0574 {
0575 if (dbc_tty_driver) {
0576 tty_unregister_driver(dbc_tty_driver);
0577 tty_driver_kref_put(dbc_tty_driver);
0578 dbc_tty_driver = NULL;
0579 }
0580
0581 idr_destroy(&dbc_tty_minors);
0582 }