diff options
Diffstat (limited to 'drivers/usb/serial/cypress_m8.c')
-rw-r--r-- | drivers/usb/serial/cypress_m8.c | 242 |
1 files changed, 18 insertions, 224 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index e23c77925e7a..f5d06746cc3b 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/usb.h> | 64 | #include <linux/usb.h> |
65 | #include <linux/usb/serial.h> | 65 | #include <linux/usb/serial.h> |
66 | #include <linux/serial.h> | 66 | #include <linux/serial.h> |
67 | #include <linux/kfifo.h> | ||
67 | #include <linux/delay.h> | 68 | #include <linux/delay.h> |
68 | #include <linux/uaccess.h> | 69 | #include <linux/uaccess.h> |
69 | #include <asm/unaligned.h> | 70 | #include <asm/unaligned.h> |
@@ -79,13 +80,12 @@ static int unstable_bauds; | |||
79 | /* | 80 | /* |
80 | * Version Information | 81 | * Version Information |
81 | */ | 82 | */ |
82 | #define DRIVER_VERSION "v1.09" | 83 | #define DRIVER_VERSION "v1.10" |
83 | #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>" | 84 | #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>" |
84 | #define DRIVER_DESC "Cypress USB to Serial Driver" | 85 | #define DRIVER_DESC "Cypress USB to Serial Driver" |
85 | 86 | ||
86 | /* write buffer size defines */ | 87 | /* write buffer size defines */ |
87 | #define CYPRESS_BUF_SIZE 1024 | 88 | #define CYPRESS_BUF_SIZE 1024 |
88 | #define CYPRESS_CLOSING_WAIT (30*HZ) | ||
89 | 89 | ||
90 | static const struct usb_device_id id_table_earthmate[] = { | 90 | static const struct usb_device_id id_table_earthmate[] = { |
91 | { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, | 91 | { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, |
@@ -135,7 +135,7 @@ struct cypress_private { | |||
135 | int bytes_out; /* used for statistics */ | 135 | int bytes_out; /* used for statistics */ |
136 | int cmd_count; /* used for statistics */ | 136 | int cmd_count; /* used for statistics */ |
137 | int cmd_ctrl; /* always set this to 1 before issuing a command */ | 137 | int cmd_ctrl; /* always set this to 1 before issuing a command */ |
138 | struct cypress_buf *buf; /* write buffer */ | 138 | struct kfifo write_fifo; /* write fifo */ |
139 | int write_urb_in_use; /* write urb in use indicator */ | 139 | int write_urb_in_use; /* write urb in use indicator */ |
140 | int write_urb_interval; /* interval to use for write urb */ | 140 | int write_urb_interval; /* interval to use for write urb */ |
141 | int read_urb_interval; /* interval to use for read urb */ | 141 | int read_urb_interval; /* interval to use for read urb */ |
@@ -157,14 +157,6 @@ struct cypress_private { | |||
157 | struct ktermios tmp_termios; /* stores the old termios settings */ | 157 | struct ktermios tmp_termios; /* stores the old termios settings */ |
158 | }; | 158 | }; |
159 | 159 | ||
160 | /* write buffer structure */ | ||
161 | struct cypress_buf { | ||
162 | unsigned int buf_size; | ||
163 | char *buf_buf; | ||
164 | char *buf_get; | ||
165 | char *buf_put; | ||
166 | }; | ||
167 | |||
168 | /* function prototypes for the Cypress USB to serial device */ | 160 | /* function prototypes for the Cypress USB to serial device */ |
169 | static int cypress_earthmate_startup(struct usb_serial *serial); | 161 | static int cypress_earthmate_startup(struct usb_serial *serial); |
170 | static int cypress_hidcom_startup(struct usb_serial *serial); | 162 | static int cypress_hidcom_startup(struct usb_serial *serial); |
@@ -190,17 +182,6 @@ static void cypress_unthrottle(struct tty_struct *tty); | |||
190 | static void cypress_set_dead(struct usb_serial_port *port); | 182 | static void cypress_set_dead(struct usb_serial_port *port); |
191 | static void cypress_read_int_callback(struct urb *urb); | 183 | static void cypress_read_int_callback(struct urb *urb); |
192 | static void cypress_write_int_callback(struct urb *urb); | 184 | static void cypress_write_int_callback(struct urb *urb); |
193 | /* write buffer functions */ | ||
194 | static struct cypress_buf *cypress_buf_alloc(unsigned int size); | ||
195 | static void cypress_buf_free(struct cypress_buf *cb); | ||
196 | static void cypress_buf_clear(struct cypress_buf *cb); | ||
197 | static unsigned int cypress_buf_data_avail(struct cypress_buf *cb); | ||
198 | static unsigned int cypress_buf_space_avail(struct cypress_buf *cb); | ||
199 | static unsigned int cypress_buf_put(struct cypress_buf *cb, | ||
200 | const char *buf, unsigned int count); | ||
201 | static unsigned int cypress_buf_get(struct cypress_buf *cb, | ||
202 | char *buf, unsigned int count); | ||
203 | |||
204 | 185 | ||
205 | static struct usb_serial_driver cypress_earthmate_device = { | 186 | static struct usb_serial_driver cypress_earthmate_device = { |
206 | .driver = { | 187 | .driver = { |
@@ -503,8 +484,7 @@ static int generic_startup(struct usb_serial *serial) | |||
503 | 484 | ||
504 | priv->comm_is_ok = !0; | 485 | priv->comm_is_ok = !0; |
505 | spin_lock_init(&priv->lock); | 486 | spin_lock_init(&priv->lock); |
506 | priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE); | 487 | if (kfifo_alloc(&priv->write_fifo, CYPRESS_BUF_SIZE, GFP_KERNEL)) { |
507 | if (priv->buf == NULL) { | ||
508 | kfree(priv); | 488 | kfree(priv); |
509 | return -ENOMEM; | 489 | return -ENOMEM; |
510 | } | 490 | } |
@@ -627,7 +607,7 @@ static void cypress_release(struct usb_serial *serial) | |||
627 | priv = usb_get_serial_port_data(serial->port[0]); | 607 | priv = usb_get_serial_port_data(serial->port[0]); |
628 | 608 | ||
629 | if (priv) { | 609 | if (priv) { |
630 | cypress_buf_free(priv->buf); | 610 | kfifo_free(&priv->write_fifo); |
631 | kfree(priv); | 611 | kfree(priv); |
632 | } | 612 | } |
633 | } | 613 | } |
@@ -704,6 +684,7 @@ static void cypress_dtr_rts(struct usb_serial_port *port, int on) | |||
704 | static void cypress_close(struct usb_serial_port *port) | 684 | static void cypress_close(struct usb_serial_port *port) |
705 | { | 685 | { |
706 | struct cypress_private *priv = usb_get_serial_port_data(port); | 686 | struct cypress_private *priv = usb_get_serial_port_data(port); |
687 | unsigned long flags; | ||
707 | 688 | ||
708 | dbg("%s - port %d", __func__, port->number); | 689 | dbg("%s - port %d", __func__, port->number); |
709 | 690 | ||
@@ -713,12 +694,14 @@ static void cypress_close(struct usb_serial_port *port) | |||
713 | mutex_unlock(&port->serial->disc_mutex); | 694 | mutex_unlock(&port->serial->disc_mutex); |
714 | return; | 695 | return; |
715 | } | 696 | } |
716 | cypress_buf_clear(priv->buf); | 697 | spin_lock_irqsave(&priv->lock, flags); |
698 | kfifo_reset_out(&priv->write_fifo); | ||
699 | spin_unlock_irqrestore(&priv->lock, flags); | ||
700 | |||
717 | dbg("%s - stopping urbs", __func__); | 701 | dbg("%s - stopping urbs", __func__); |
718 | usb_kill_urb(port->interrupt_in_urb); | 702 | usb_kill_urb(port->interrupt_in_urb); |
719 | usb_kill_urb(port->interrupt_out_urb); | 703 | usb_kill_urb(port->interrupt_out_urb); |
720 | 704 | ||
721 | |||
722 | if (stats) | 705 | if (stats) |
723 | dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", | 706 | dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", |
724 | priv->bytes_in, priv->bytes_out, priv->cmd_count); | 707 | priv->bytes_in, priv->bytes_out, priv->cmd_count); |
@@ -730,7 +713,6 @@ static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
730 | const unsigned char *buf, int count) | 713 | const unsigned char *buf, int count) |
731 | { | 714 | { |
732 | struct cypress_private *priv = usb_get_serial_port_data(port); | 715 | struct cypress_private *priv = usb_get_serial_port_data(port); |
733 | unsigned long flags; | ||
734 | 716 | ||
735 | dbg("%s - port %d, %d bytes", __func__, port->number, count); | 717 | dbg("%s - port %d, %d bytes", __func__, port->number, count); |
736 | 718 | ||
@@ -745,9 +727,7 @@ static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
745 | if (!count) | 727 | if (!count) |
746 | return count; | 728 | return count; |
747 | 729 | ||
748 | spin_lock_irqsave(&priv->lock, flags); | 730 | count = kfifo_in_locked(&priv->write_fifo, buf, count, &priv->lock); |
749 | count = cypress_buf_put(priv->buf, buf, count); | ||
750 | spin_unlock_irqrestore(&priv->lock, flags); | ||
751 | 731 | ||
752 | finish: | 732 | finish: |
753 | cypress_send(port); | 733 | cypress_send(port); |
@@ -807,9 +787,10 @@ static void cypress_send(struct usb_serial_port *port) | |||
807 | } else | 787 | } else |
808 | spin_unlock_irqrestore(&priv->lock, flags); | 788 | spin_unlock_irqrestore(&priv->lock, flags); |
809 | 789 | ||
810 | count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset], | 790 | count = kfifo_out_locked(&priv->write_fifo, |
811 | port->interrupt_out_size-offset); | 791 | &port->interrupt_out_buffer[offset], |
812 | 792 | port->interrupt_out_size - offset, | |
793 | &priv->lock); | ||
813 | if (count == 0) | 794 | if (count == 0) |
814 | return; | 795 | return; |
815 | 796 | ||
@@ -875,7 +856,7 @@ static int cypress_write_room(struct tty_struct *tty) | |||
875 | dbg("%s - port %d", __func__, port->number); | 856 | dbg("%s - port %d", __func__, port->number); |
876 | 857 | ||
877 | spin_lock_irqsave(&priv->lock, flags); | 858 | spin_lock_irqsave(&priv->lock, flags); |
878 | room = cypress_buf_space_avail(priv->buf); | 859 | room = kfifo_avail(&priv->write_fifo); |
879 | spin_unlock_irqrestore(&priv->lock, flags); | 860 | spin_unlock_irqrestore(&priv->lock, flags); |
880 | 861 | ||
881 | dbg("%s - returns %d", __func__, room); | 862 | dbg("%s - returns %d", __func__, room); |
@@ -1143,7 +1124,7 @@ static int cypress_chars_in_buffer(struct tty_struct *tty) | |||
1143 | dbg("%s - port %d", __func__, port->number); | 1124 | dbg("%s - port %d", __func__, port->number); |
1144 | 1125 | ||
1145 | spin_lock_irqsave(&priv->lock, flags); | 1126 | spin_lock_irqsave(&priv->lock, flags); |
1146 | chars = cypress_buf_data_avail(priv->buf); | 1127 | chars = kfifo_len(&priv->write_fifo); |
1147 | spin_unlock_irqrestore(&priv->lock, flags); | 1128 | spin_unlock_irqrestore(&priv->lock, flags); |
1148 | 1129 | ||
1149 | dbg("%s - returns %d", __func__, chars); | 1130 | dbg("%s - returns %d", __func__, chars); |
@@ -1309,7 +1290,7 @@ static void cypress_read_int_callback(struct urb *urb) | |||
1309 | /* process read if there is data other than line status */ | 1290 | /* process read if there is data other than line status */ |
1310 | if (tty && bytes > i) { | 1291 | if (tty && bytes > i) { |
1311 | tty_insert_flip_string_fixed_flag(tty, data + i, | 1292 | tty_insert_flip_string_fixed_flag(tty, data + i, |
1312 | bytes - i, tty_flag); | 1293 | tty_flag, bytes - i); |
1313 | tty_flip_buffer_push(tty); | 1294 | tty_flip_buffer_push(tty); |
1314 | } | 1295 | } |
1315 | 1296 | ||
@@ -1397,193 +1378,6 @@ static void cypress_write_int_callback(struct urb *urb) | |||
1397 | 1378 | ||
1398 | 1379 | ||
1399 | /***************************************************************************** | 1380 | /***************************************************************************** |
1400 | * Write buffer functions - buffering code from pl2303 used | ||
1401 | *****************************************************************************/ | ||
1402 | |||
1403 | /* | ||
1404 | * cypress_buf_alloc | ||
1405 | * | ||
1406 | * Allocate a circular buffer and all associated memory. | ||
1407 | */ | ||
1408 | |||
1409 | static struct cypress_buf *cypress_buf_alloc(unsigned int size) | ||
1410 | { | ||
1411 | |||
1412 | struct cypress_buf *cb; | ||
1413 | |||
1414 | |||
1415 | if (size == 0) | ||
1416 | return NULL; | ||
1417 | |||
1418 | cb = kmalloc(sizeof(struct cypress_buf), GFP_KERNEL); | ||
1419 | if (cb == NULL) | ||
1420 | return NULL; | ||
1421 | |||
1422 | cb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
1423 | if (cb->buf_buf == NULL) { | ||
1424 | kfree(cb); | ||
1425 | return NULL; | ||
1426 | } | ||
1427 | |||
1428 | cb->buf_size = size; | ||
1429 | cb->buf_get = cb->buf_put = cb->buf_buf; | ||
1430 | |||
1431 | return cb; | ||
1432 | |||
1433 | } | ||
1434 | |||
1435 | |||
1436 | /* | ||
1437 | * cypress_buf_free | ||
1438 | * | ||
1439 | * Free the buffer and all associated memory. | ||
1440 | */ | ||
1441 | |||
1442 | static void cypress_buf_free(struct cypress_buf *cb) | ||
1443 | { | ||
1444 | if (cb) { | ||
1445 | kfree(cb->buf_buf); | ||
1446 | kfree(cb); | ||
1447 | } | ||
1448 | } | ||
1449 | |||
1450 | |||
1451 | /* | ||
1452 | * cypress_buf_clear | ||
1453 | * | ||
1454 | * Clear out all data in the circular buffer. | ||
1455 | */ | ||
1456 | |||
1457 | static void cypress_buf_clear(struct cypress_buf *cb) | ||
1458 | { | ||
1459 | if (cb != NULL) | ||
1460 | cb->buf_get = cb->buf_put; | ||
1461 | /* equivalent to a get of all data available */ | ||
1462 | } | ||
1463 | |||
1464 | |||
1465 | /* | ||
1466 | * cypress_buf_data_avail | ||
1467 | * | ||
1468 | * Return the number of bytes of data available in the circular | ||
1469 | * buffer. | ||
1470 | */ | ||
1471 | |||
1472 | static unsigned int cypress_buf_data_avail(struct cypress_buf *cb) | ||
1473 | { | ||
1474 | if (cb != NULL) | ||
1475 | return (cb->buf_size + cb->buf_put - cb->buf_get) | ||
1476 | % cb->buf_size; | ||
1477 | else | ||
1478 | return 0; | ||
1479 | } | ||
1480 | |||
1481 | |||
1482 | /* | ||
1483 | * cypress_buf_space_avail | ||
1484 | * | ||
1485 | * Return the number of bytes of space available in the circular | ||
1486 | * buffer. | ||
1487 | */ | ||
1488 | |||
1489 | static unsigned int cypress_buf_space_avail(struct cypress_buf *cb) | ||
1490 | { | ||
1491 | if (cb != NULL) | ||
1492 | return (cb->buf_size + cb->buf_get - cb->buf_put - 1) | ||
1493 | % cb->buf_size; | ||
1494 | else | ||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | |||
1499 | /* | ||
1500 | * cypress_buf_put | ||
1501 | * | ||
1502 | * Copy data data from a user buffer and put it into the circular buffer. | ||
1503 | * Restrict to the amount of space available. | ||
1504 | * | ||
1505 | * Return the number of bytes copied. | ||
1506 | */ | ||
1507 | |||
1508 | static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf, | ||
1509 | unsigned int count) | ||
1510 | { | ||
1511 | |||
1512 | unsigned int len; | ||
1513 | |||
1514 | |||
1515 | if (cb == NULL) | ||
1516 | return 0; | ||
1517 | |||
1518 | len = cypress_buf_space_avail(cb); | ||
1519 | if (count > len) | ||
1520 | count = len; | ||
1521 | |||
1522 | if (count == 0) | ||
1523 | return 0; | ||
1524 | |||
1525 | len = cb->buf_buf + cb->buf_size - cb->buf_put; | ||
1526 | if (count > len) { | ||
1527 | memcpy(cb->buf_put, buf, len); | ||
1528 | memcpy(cb->buf_buf, buf+len, count - len); | ||
1529 | cb->buf_put = cb->buf_buf + count - len; | ||
1530 | } else { | ||
1531 | memcpy(cb->buf_put, buf, count); | ||
1532 | if (count < len) | ||
1533 | cb->buf_put += count; | ||
1534 | else /* count == len */ | ||
1535 | cb->buf_put = cb->buf_buf; | ||
1536 | } | ||
1537 | |||
1538 | return count; | ||
1539 | |||
1540 | } | ||
1541 | |||
1542 | |||
1543 | /* | ||
1544 | * cypress_buf_get | ||
1545 | * | ||
1546 | * Get data from the circular buffer and copy to the given buffer. | ||
1547 | * Restrict to the amount of data available. | ||
1548 | * | ||
1549 | * Return the number of bytes copied. | ||
1550 | */ | ||
1551 | |||
1552 | static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, | ||
1553 | unsigned int count) | ||
1554 | { | ||
1555 | |||
1556 | unsigned int len; | ||
1557 | |||
1558 | |||
1559 | if (cb == NULL) | ||
1560 | return 0; | ||
1561 | |||
1562 | len = cypress_buf_data_avail(cb); | ||
1563 | if (count > len) | ||
1564 | count = len; | ||
1565 | |||
1566 | if (count == 0) | ||
1567 | return 0; | ||
1568 | |||
1569 | len = cb->buf_buf + cb->buf_size - cb->buf_get; | ||
1570 | if (count > len) { | ||
1571 | memcpy(buf, cb->buf_get, len); | ||
1572 | memcpy(buf+len, cb->buf_buf, count - len); | ||
1573 | cb->buf_get = cb->buf_buf + count - len; | ||
1574 | } else { | ||
1575 | memcpy(buf, cb->buf_get, count); | ||
1576 | if (count < len) | ||
1577 | cb->buf_get += count; | ||
1578 | else /* count == len */ | ||
1579 | cb->buf_get = cb->buf_buf; | ||
1580 | } | ||
1581 | |||
1582 | return count; | ||
1583 | |||
1584 | } | ||
1585 | |||
1586 | /***************************************************************************** | ||
1587 | * Module functions | 1381 | * Module functions |
1588 | *****************************************************************************/ | 1382 | *****************************************************************************/ |
1589 | 1383 | ||