aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/cypress_m8.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2010-05-16 14:33:50 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:49 -0400
commit117fb8d086cfc6e51c729fe5533bb83cb55c150a (patch)
tree638ecc35e7181a482a425250729622cbe2f2016e /drivers/usb/serial/cypress_m8.c
parentc4f4736fc4518b92d7071016c4e28fe4f4e13e82 (diff)
USB: cypress_m8: use kfifo to implement write buffering
Kill custom fifo implementation. Note that cypress_m8 has no port write fifo as it has no bulk-out endpoint. Compile-only tested. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/cypress_m8.c')
-rw-r--r--drivers/usb/serial/cypress_m8.c239
1 files changed, 17 insertions, 222 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index d96374865289..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,7 +80,7 @@ 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
@@ -134,7 +135,7 @@ struct cypress_private {
134 int bytes_out; /* used for statistics */ 135 int bytes_out; /* used for statistics */
135 int cmd_count; /* used for statistics */ 136 int cmd_count; /* used for statistics */
136 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 */
137 struct cypress_buf *buf; /* write buffer */ 138 struct kfifo write_fifo; /* write fifo */
138 int write_urb_in_use; /* write urb in use indicator */ 139 int write_urb_in_use; /* write urb in use indicator */
139 int write_urb_interval; /* interval to use for write urb */ 140 int write_urb_interval; /* interval to use for write urb */
140 int read_urb_interval; /* interval to use for read urb */ 141 int read_urb_interval; /* interval to use for read urb */
@@ -156,14 +157,6 @@ struct cypress_private {
156 struct ktermios tmp_termios; /* stores the old termios settings */ 157 struct ktermios tmp_termios; /* stores the old termios settings */
157}; 158};
158 159
159/* write buffer structure */
160struct cypress_buf {
161 unsigned int buf_size;
162 char *buf_buf;
163 char *buf_get;
164 char *buf_put;
165};
166
167/* function prototypes for the Cypress USB to serial device */ 160/* function prototypes for the Cypress USB to serial device */
168static int cypress_earthmate_startup(struct usb_serial *serial); 161static int cypress_earthmate_startup(struct usb_serial *serial);
169static int cypress_hidcom_startup(struct usb_serial *serial); 162static int cypress_hidcom_startup(struct usb_serial *serial);
@@ -189,17 +182,6 @@ static void cypress_unthrottle(struct tty_struct *tty);
189static void cypress_set_dead(struct usb_serial_port *port); 182static void cypress_set_dead(struct usb_serial_port *port);
190static void cypress_read_int_callback(struct urb *urb); 183static void cypress_read_int_callback(struct urb *urb);
191static void cypress_write_int_callback(struct urb *urb); 184static void cypress_write_int_callback(struct urb *urb);
192/* write buffer functions */
193static struct cypress_buf *cypress_buf_alloc(unsigned int size);
194static void cypress_buf_free(struct cypress_buf *cb);
195static void cypress_buf_clear(struct cypress_buf *cb);
196static unsigned int cypress_buf_data_avail(struct cypress_buf *cb);
197static unsigned int cypress_buf_space_avail(struct cypress_buf *cb);
198static unsigned int cypress_buf_put(struct cypress_buf *cb,
199 const char *buf, unsigned int count);
200static unsigned int cypress_buf_get(struct cypress_buf *cb,
201 char *buf, unsigned int count);
202
203 185
204static struct usb_serial_driver cypress_earthmate_device = { 186static struct usb_serial_driver cypress_earthmate_device = {
205 .driver = { 187 .driver = {
@@ -502,8 +484,7 @@ static int generic_startup(struct usb_serial *serial)
502 484
503 priv->comm_is_ok = !0; 485 priv->comm_is_ok = !0;
504 spin_lock_init(&priv->lock); 486 spin_lock_init(&priv->lock);
505 priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE); 487 if (kfifo_alloc(&priv->write_fifo, CYPRESS_BUF_SIZE, GFP_KERNEL)) {
506 if (priv->buf == NULL) {
507 kfree(priv); 488 kfree(priv);
508 return -ENOMEM; 489 return -ENOMEM;
509 } 490 }
@@ -626,7 +607,7 @@ static void cypress_release(struct usb_serial *serial)
626 priv = usb_get_serial_port_data(serial->port[0]); 607 priv = usb_get_serial_port_data(serial->port[0]);
627 608
628 if (priv) { 609 if (priv) {
629 cypress_buf_free(priv->buf); 610 kfifo_free(&priv->write_fifo);
630 kfree(priv); 611 kfree(priv);
631 } 612 }
632} 613}
@@ -703,6 +684,7 @@ static void cypress_dtr_rts(struct usb_serial_port *port, int on)
703static void cypress_close(struct usb_serial_port *port) 684static void cypress_close(struct usb_serial_port *port)
704{ 685{
705 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;
706 688
707 dbg("%s - port %d", __func__, port->number); 689 dbg("%s - port %d", __func__, port->number);
708 690
@@ -712,12 +694,14 @@ static void cypress_close(struct usb_serial_port *port)
712 mutex_unlock(&port->serial->disc_mutex); 694 mutex_unlock(&port->serial->disc_mutex);
713 return; 695 return;
714 } 696 }
715 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
716 dbg("%s - stopping urbs", __func__); 701 dbg("%s - stopping urbs", __func__);
717 usb_kill_urb(port->interrupt_in_urb); 702 usb_kill_urb(port->interrupt_in_urb);
718 usb_kill_urb(port->interrupt_out_urb); 703 usb_kill_urb(port->interrupt_out_urb);
719 704
720
721 if (stats) 705 if (stats)
722 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",
723 priv->bytes_in, priv->bytes_out, priv->cmd_count); 707 priv->bytes_in, priv->bytes_out, priv->cmd_count);
@@ -729,7 +713,6 @@ static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
729 const unsigned char *buf, int count) 713 const unsigned char *buf, int count)
730{ 714{
731 struct cypress_private *priv = usb_get_serial_port_data(port); 715 struct cypress_private *priv = usb_get_serial_port_data(port);
732 unsigned long flags;
733 716
734 dbg("%s - port %d, %d bytes", __func__, port->number, count); 717 dbg("%s - port %d, %d bytes", __func__, port->number, count);
735 718
@@ -744,9 +727,7 @@ static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
744 if (!count) 727 if (!count)
745 return count; 728 return count;
746 729
747 spin_lock_irqsave(&priv->lock, flags); 730 count = kfifo_in_locked(&priv->write_fifo, buf, count, &priv->lock);
748 count = cypress_buf_put(priv->buf, buf, count);
749 spin_unlock_irqrestore(&priv->lock, flags);
750 731
751finish: 732finish:
752 cypress_send(port); 733 cypress_send(port);
@@ -806,9 +787,10 @@ static void cypress_send(struct usb_serial_port *port)
806 } else 787 } else
807 spin_unlock_irqrestore(&priv->lock, flags); 788 spin_unlock_irqrestore(&priv->lock, flags);
808 789
809 count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset], 790 count = kfifo_out_locked(&priv->write_fifo,
810 port->interrupt_out_size-offset); 791 &port->interrupt_out_buffer[offset],
811 792 port->interrupt_out_size - offset,
793 &priv->lock);
812 if (count == 0) 794 if (count == 0)
813 return; 795 return;
814 796
@@ -874,7 +856,7 @@ static int cypress_write_room(struct tty_struct *tty)
874 dbg("%s - port %d", __func__, port->number); 856 dbg("%s - port %d", __func__, port->number);
875 857
876 spin_lock_irqsave(&priv->lock, flags); 858 spin_lock_irqsave(&priv->lock, flags);
877 room = cypress_buf_space_avail(priv->buf); 859 room = kfifo_avail(&priv->write_fifo);
878 spin_unlock_irqrestore(&priv->lock, flags); 860 spin_unlock_irqrestore(&priv->lock, flags);
879 861
880 dbg("%s - returns %d", __func__, room); 862 dbg("%s - returns %d", __func__, room);
@@ -1142,7 +1124,7 @@ static int cypress_chars_in_buffer(struct tty_struct *tty)
1142 dbg("%s - port %d", __func__, port->number); 1124 dbg("%s - port %d", __func__, port->number);
1143 1125
1144 spin_lock_irqsave(&priv->lock, flags); 1126 spin_lock_irqsave(&priv->lock, flags);
1145 chars = cypress_buf_data_avail(priv->buf); 1127 chars = kfifo_len(&priv->write_fifo);
1146 spin_unlock_irqrestore(&priv->lock, flags); 1128 spin_unlock_irqrestore(&priv->lock, flags);
1147 1129
1148 dbg("%s - returns %d", __func__, chars); 1130 dbg("%s - returns %d", __func__, chars);
@@ -1396,193 +1378,6 @@ static void cypress_write_int_callback(struct urb *urb)
1396 1378
1397 1379
1398/***************************************************************************** 1380/*****************************************************************************
1399 * Write buffer functions - buffering code from pl2303 used
1400 *****************************************************************************/
1401
1402/*
1403 * cypress_buf_alloc
1404 *
1405 * Allocate a circular buffer and all associated memory.
1406 */
1407
1408static struct cypress_buf *cypress_buf_alloc(unsigned int size)
1409{
1410
1411 struct cypress_buf *cb;
1412
1413
1414 if (size == 0)
1415 return NULL;
1416
1417 cb = kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);
1418 if (cb == NULL)
1419 return NULL;
1420
1421 cb->buf_buf = kmalloc(size, GFP_KERNEL);
1422 if (cb->buf_buf == NULL) {
1423 kfree(cb);
1424 return NULL;
1425 }
1426
1427 cb->buf_size = size;
1428 cb->buf_get = cb->buf_put = cb->buf_buf;
1429
1430 return cb;
1431
1432}
1433
1434
1435/*
1436 * cypress_buf_free
1437 *
1438 * Free the buffer and all associated memory.
1439 */
1440
1441static void cypress_buf_free(struct cypress_buf *cb)
1442{
1443 if (cb) {
1444 kfree(cb->buf_buf);
1445 kfree(cb);
1446 }
1447}
1448
1449
1450/*
1451 * cypress_buf_clear
1452 *
1453 * Clear out all data in the circular buffer.
1454 */
1455
1456static void cypress_buf_clear(struct cypress_buf *cb)
1457{
1458 if (cb != NULL)
1459 cb->buf_get = cb->buf_put;
1460 /* equivalent to a get of all data available */
1461}
1462
1463
1464/*
1465 * cypress_buf_data_avail
1466 *
1467 * Return the number of bytes of data available in the circular
1468 * buffer.
1469 */
1470
1471static unsigned int cypress_buf_data_avail(struct cypress_buf *cb)
1472{
1473 if (cb != NULL)
1474 return (cb->buf_size + cb->buf_put - cb->buf_get)
1475 % cb->buf_size;
1476 else
1477 return 0;
1478}
1479
1480
1481/*
1482 * cypress_buf_space_avail
1483 *
1484 * Return the number of bytes of space available in the circular
1485 * buffer.
1486 */
1487
1488static unsigned int cypress_buf_space_avail(struct cypress_buf *cb)
1489{
1490 if (cb != NULL)
1491 return (cb->buf_size + cb->buf_get - cb->buf_put - 1)
1492 % cb->buf_size;
1493 else
1494 return 0;
1495}
1496
1497
1498/*
1499 * cypress_buf_put
1500 *
1501 * Copy data data from a user buffer and put it into the circular buffer.
1502 * Restrict to the amount of space available.
1503 *
1504 * Return the number of bytes copied.
1505 */
1506
1507static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf,
1508 unsigned int count)
1509{
1510
1511 unsigned int len;
1512
1513
1514 if (cb == NULL)
1515 return 0;
1516
1517 len = cypress_buf_space_avail(cb);
1518 if (count > len)
1519 count = len;
1520
1521 if (count == 0)
1522 return 0;
1523
1524 len = cb->buf_buf + cb->buf_size - cb->buf_put;
1525 if (count > len) {
1526 memcpy(cb->buf_put, buf, len);
1527 memcpy(cb->buf_buf, buf+len, count - len);
1528 cb->buf_put = cb->buf_buf + count - len;
1529 } else {
1530 memcpy(cb->buf_put, buf, count);
1531 if (count < len)
1532 cb->buf_put += count;
1533 else /* count == len */
1534 cb->buf_put = cb->buf_buf;
1535 }
1536
1537 return count;
1538
1539}
1540
1541
1542/*
1543 * cypress_buf_get
1544 *
1545 * Get data from the circular buffer and copy to the given buffer.
1546 * Restrict to the amount of data available.
1547 *
1548 * Return the number of bytes copied.
1549 */
1550
1551static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf,
1552 unsigned int count)
1553{
1554
1555 unsigned int len;
1556
1557
1558 if (cb == NULL)
1559 return 0;
1560
1561 len = cypress_buf_data_avail(cb);
1562 if (count > len)
1563 count = len;
1564
1565 if (count == 0)
1566 return 0;
1567
1568 len = cb->buf_buf + cb->buf_size - cb->buf_get;
1569 if (count > len) {
1570 memcpy(buf, cb->buf_get, len);
1571 memcpy(buf+len, cb->buf_buf, count - len);
1572 cb->buf_get = cb->buf_buf + count - len;
1573 } else {
1574 memcpy(buf, cb->buf_get, count);
1575 if (count < len)
1576 cb->buf_get += count;
1577 else /* count == len */
1578 cb->buf_get = cb->buf_buf;
1579 }
1580
1581 return count;
1582
1583}
1584
1585/*****************************************************************************
1586 * Module functions 1381 * Module functions
1587 *****************************************************************************/ 1382 *****************************************************************************/
1588 1383