diff options
Diffstat (limited to 'drivers/usb/serial/oti6858.c')
-rw-r--r-- | drivers/usb/serial/oti6858.c | 254 |
1 files changed, 29 insertions, 225 deletions
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index deeacdea05db..e199b0f4f99c 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c | |||
@@ -51,12 +51,13 @@ | |||
51 | #include <linux/usb.h> | 51 | #include <linux/usb.h> |
52 | #include <linux/usb/serial.h> | 52 | #include <linux/usb/serial.h> |
53 | #include <linux/uaccess.h> | 53 | #include <linux/uaccess.h> |
54 | #include <linux/kfifo.h> | ||
54 | #include "oti6858.h" | 55 | #include "oti6858.h" |
55 | 56 | ||
56 | #define OTI6858_DESCRIPTION \ | 57 | #define OTI6858_DESCRIPTION \ |
57 | "Ours Technology Inc. OTi-6858 USB to serial adapter driver" | 58 | "Ours Technology Inc. OTi-6858 USB to serial adapter driver" |
58 | #define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>" | 59 | #define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>" |
59 | #define OTI6858_VERSION "0.1" | 60 | #define OTI6858_VERSION "0.2" |
60 | 61 | ||
61 | static const struct usb_device_id id_table[] = { | 62 | static const struct usb_device_id id_table[] = { |
62 | { USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) }, | 63 | { USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) }, |
@@ -75,18 +76,6 @@ static struct usb_driver oti6858_driver = { | |||
75 | 76 | ||
76 | static int debug; | 77 | static int debug; |
77 | 78 | ||
78 | |||
79 | /* buffering code, copied from pl2303 driver */ | ||
80 | #define PL2303_BUF_SIZE 1024 | ||
81 | #define PL2303_TMP_BUF_SIZE 1024 | ||
82 | |||
83 | struct oti6858_buf { | ||
84 | unsigned int buf_size; | ||
85 | char *buf_buf; | ||
86 | char *buf_get; | ||
87 | char *buf_put; | ||
88 | }; | ||
89 | |||
90 | /* requests */ | 79 | /* requests */ |
91 | #define OTI6858_REQ_GET_STATUS (USB_DIR_IN | USB_TYPE_VENDOR | 0x00) | 80 | #define OTI6858_REQ_GET_STATUS (USB_DIR_IN | USB_TYPE_VENDOR | 0x00) |
92 | #define OTI6858_REQ_T_GET_STATUS 0x01 | 81 | #define OTI6858_REQ_T_GET_STATUS 0x01 |
@@ -161,18 +150,6 @@ static int oti6858_tiocmset(struct tty_struct *tty, struct file *file, | |||
161 | static int oti6858_startup(struct usb_serial *serial); | 150 | static int oti6858_startup(struct usb_serial *serial); |
162 | static void oti6858_release(struct usb_serial *serial); | 151 | static void oti6858_release(struct usb_serial *serial); |
163 | 152 | ||
164 | /* functions operating on buffers */ | ||
165 | static struct oti6858_buf *oti6858_buf_alloc(unsigned int size); | ||
166 | static void oti6858_buf_free(struct oti6858_buf *pb); | ||
167 | static void oti6858_buf_clear(struct oti6858_buf *pb); | ||
168 | static unsigned int oti6858_buf_data_avail(struct oti6858_buf *pb); | ||
169 | static unsigned int oti6858_buf_space_avail(struct oti6858_buf *pb); | ||
170 | static unsigned int oti6858_buf_put(struct oti6858_buf *pb, const char *buf, | ||
171 | unsigned int count); | ||
172 | static unsigned int oti6858_buf_get(struct oti6858_buf *pb, char *buf, | ||
173 | unsigned int count); | ||
174 | |||
175 | |||
176 | /* device info */ | 153 | /* device info */ |
177 | static struct usb_serial_driver oti6858_device = { | 154 | static struct usb_serial_driver oti6858_device = { |
178 | .driver = { | 155 | .driver = { |
@@ -201,7 +178,6 @@ static struct usb_serial_driver oti6858_device = { | |||
201 | struct oti6858_private { | 178 | struct oti6858_private { |
202 | spinlock_t lock; | 179 | spinlock_t lock; |
203 | 180 | ||
204 | struct oti6858_buf *buf; | ||
205 | struct oti6858_control_pkt status; | 181 | struct oti6858_control_pkt status; |
206 | 182 | ||
207 | struct { | 183 | struct { |
@@ -295,7 +271,7 @@ static void setup_line(struct work_struct *work) | |||
295 | } | 271 | } |
296 | } | 272 | } |
297 | 273 | ||
298 | void send_data(struct work_struct *work) | 274 | static void send_data(struct work_struct *work) |
299 | { | 275 | { |
300 | struct oti6858_private *priv = container_of(work, | 276 | struct oti6858_private *priv = container_of(work, |
301 | struct oti6858_private, delayed_write_work.work); | 277 | struct oti6858_private, delayed_write_work.work); |
@@ -314,9 +290,12 @@ void send_data(struct work_struct *work) | |||
314 | return; | 290 | return; |
315 | } | 291 | } |
316 | priv->flags.write_urb_in_use = 1; | 292 | priv->flags.write_urb_in_use = 1; |
317 | |||
318 | count = oti6858_buf_data_avail(priv->buf); | ||
319 | spin_unlock_irqrestore(&priv->lock, flags); | 293 | spin_unlock_irqrestore(&priv->lock, flags); |
294 | |||
295 | spin_lock_irqsave(&port->lock, flags); | ||
296 | count = kfifo_len(&port->write_fifo); | ||
297 | spin_unlock_irqrestore(&port->lock, flags); | ||
298 | |||
320 | if (count > port->bulk_out_size) | 299 | if (count > port->bulk_out_size) |
321 | count = port->bulk_out_size; | 300 | count = port->bulk_out_size; |
322 | 301 | ||
@@ -350,10 +329,9 @@ void send_data(struct work_struct *work) | |||
350 | return; | 329 | return; |
351 | } | 330 | } |
352 | 331 | ||
353 | spin_lock_irqsave(&priv->lock, flags); | 332 | count = kfifo_out_locked(&port->write_fifo, |
354 | oti6858_buf_get(priv->buf, port->write_urb->transfer_buffer, count); | 333 | port->write_urb->transfer_buffer, |
355 | spin_unlock_irqrestore(&priv->lock, flags); | 334 | count, &port->lock); |
356 | |||
357 | port->write_urb->transfer_buffer_length = count; | 335 | port->write_urb->transfer_buffer_length = count; |
358 | port->write_urb->dev = port->serial->dev; | 336 | port->write_urb->dev = port->serial->dev; |
359 | result = usb_submit_urb(port->write_urb, GFP_NOIO); | 337 | result = usb_submit_urb(port->write_urb, GFP_NOIO); |
@@ -376,11 +354,6 @@ static int oti6858_startup(struct usb_serial *serial) | |||
376 | priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL); | 354 | priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL); |
377 | if (!priv) | 355 | if (!priv) |
378 | break; | 356 | break; |
379 | priv->buf = oti6858_buf_alloc(PL2303_BUF_SIZE); | ||
380 | if (priv->buf == NULL) { | ||
381 | kfree(priv); | ||
382 | break; | ||
383 | } | ||
384 | 357 | ||
385 | spin_lock_init(&priv->lock); | 358 | spin_lock_init(&priv->lock); |
386 | init_waitqueue_head(&priv->intr_wait); | 359 | init_waitqueue_head(&priv->intr_wait); |
@@ -397,7 +370,6 @@ static int oti6858_startup(struct usb_serial *serial) | |||
397 | 370 | ||
398 | for (--i; i >= 0; --i) { | 371 | for (--i; i >= 0; --i) { |
399 | priv = usb_get_serial_port_data(serial->port[i]); | 372 | priv = usb_get_serial_port_data(serial->port[i]); |
400 | oti6858_buf_free(priv->buf); | ||
401 | kfree(priv); | 373 | kfree(priv); |
402 | usb_set_serial_port_data(serial->port[i], NULL); | 374 | usb_set_serial_port_data(serial->port[i], NULL); |
403 | } | 375 | } |
@@ -407,17 +379,12 @@ static int oti6858_startup(struct usb_serial *serial) | |||
407 | static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, | 379 | static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, |
408 | const unsigned char *buf, int count) | 380 | const unsigned char *buf, int count) |
409 | { | 381 | { |
410 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
411 | unsigned long flags; | ||
412 | |||
413 | dbg("%s(port = %d, count = %d)", __func__, port->number, count); | 382 | dbg("%s(port = %d, count = %d)", __func__, port->number, count); |
414 | 383 | ||
415 | if (!count) | 384 | if (!count) |
416 | return count; | 385 | return count; |
417 | 386 | ||
418 | spin_lock_irqsave(&priv->lock, flags); | 387 | count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock); |
419 | count = oti6858_buf_put(priv->buf, buf, count); | ||
420 | spin_unlock_irqrestore(&priv->lock, flags); | ||
421 | 388 | ||
422 | return count; | 389 | return count; |
423 | } | 390 | } |
@@ -425,15 +392,14 @@ static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
425 | static int oti6858_write_room(struct tty_struct *tty) | 392 | static int oti6858_write_room(struct tty_struct *tty) |
426 | { | 393 | { |
427 | struct usb_serial_port *port = tty->driver_data; | 394 | struct usb_serial_port *port = tty->driver_data; |
428 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
429 | int room = 0; | 395 | int room = 0; |
430 | unsigned long flags; | 396 | unsigned long flags; |
431 | 397 | ||
432 | dbg("%s(port = %d)", __func__, port->number); | 398 | dbg("%s(port = %d)", __func__, port->number); |
433 | 399 | ||
434 | spin_lock_irqsave(&priv->lock, flags); | 400 | spin_lock_irqsave(&port->lock, flags); |
435 | room = oti6858_buf_space_avail(priv->buf); | 401 | room = kfifo_avail(&port->write_fifo); |
436 | spin_unlock_irqrestore(&priv->lock, flags); | 402 | spin_unlock_irqrestore(&port->lock, flags); |
437 | 403 | ||
438 | return room; | 404 | return room; |
439 | } | 405 | } |
@@ -441,15 +407,14 @@ static int oti6858_write_room(struct tty_struct *tty) | |||
441 | static int oti6858_chars_in_buffer(struct tty_struct *tty) | 407 | static int oti6858_chars_in_buffer(struct tty_struct *tty) |
442 | { | 408 | { |
443 | struct usb_serial_port *port = tty->driver_data; | 409 | struct usb_serial_port *port = tty->driver_data; |
444 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
445 | int chars = 0; | 410 | int chars = 0; |
446 | unsigned long flags; | 411 | unsigned long flags; |
447 | 412 | ||
448 | dbg("%s(port = %d)", __func__, port->number); | 413 | dbg("%s(port = %d)", __func__, port->number); |
449 | 414 | ||
450 | spin_lock_irqsave(&priv->lock, flags); | 415 | spin_lock_irqsave(&port->lock, flags); |
451 | chars = oti6858_buf_data_avail(priv->buf); | 416 | chars = kfifo_len(&port->write_fifo); |
452 | spin_unlock_irqrestore(&priv->lock, flags); | 417 | spin_unlock_irqrestore(&port->lock, flags); |
453 | 418 | ||
454 | return chars; | 419 | return chars; |
455 | } | 420 | } |
@@ -640,10 +605,10 @@ static void oti6858_close(struct usb_serial_port *port) | |||
640 | 605 | ||
641 | dbg("%s(port = %d)", __func__, port->number); | 606 | dbg("%s(port = %d)", __func__, port->number); |
642 | 607 | ||
643 | spin_lock_irqsave(&priv->lock, flags); | 608 | spin_lock_irqsave(&port->lock, flags); |
644 | /* clear out any remaining data in the buffer */ | 609 | /* clear out any remaining data in the buffer */ |
645 | oti6858_buf_clear(priv->buf); | 610 | kfifo_reset_out(&port->write_fifo); |
646 | spin_unlock_irqrestore(&priv->lock, flags); | 611 | spin_unlock_irqrestore(&port->lock, flags); |
647 | 612 | ||
648 | dbg("%s(): after buf_clear()", __func__); | 613 | dbg("%s(): after buf_clear()", __func__); |
649 | 614 | ||
@@ -785,18 +750,12 @@ static int oti6858_ioctl(struct tty_struct *tty, struct file *file, | |||
785 | 750 | ||
786 | static void oti6858_release(struct usb_serial *serial) | 751 | static void oti6858_release(struct usb_serial *serial) |
787 | { | 752 | { |
788 | struct oti6858_private *priv; | ||
789 | int i; | 753 | int i; |
790 | 754 | ||
791 | dbg("%s()", __func__); | 755 | dbg("%s()", __func__); |
792 | 756 | ||
793 | for (i = 0; i < serial->num_ports; ++i) { | 757 | for (i = 0; i < serial->num_ports; ++i) |
794 | priv = usb_get_serial_port_data(serial->port[i]); | 758 | kfree(usb_get_serial_port_data(serial->port[i])); |
795 | if (priv) { | ||
796 | oti6858_buf_free(priv->buf); | ||
797 | kfree(priv); | ||
798 | } | ||
799 | } | ||
800 | } | 759 | } |
801 | 760 | ||
802 | static void oti6858_read_int_callback(struct urb *urb) | 761 | static void oti6858_read_int_callback(struct urb *urb) |
@@ -889,10 +848,14 @@ static void oti6858_read_int_callback(struct urb *urb) | |||
889 | } | 848 | } |
890 | } else if (!transient) { | 849 | } else if (!transient) { |
891 | unsigned long flags; | 850 | unsigned long flags; |
851 | int count; | ||
852 | |||
853 | spin_lock_irqsave(&port->lock, flags); | ||
854 | count = kfifo_len(&port->write_fifo); | ||
855 | spin_unlock_irqrestore(&port->lock, flags); | ||
892 | 856 | ||
893 | spin_lock_irqsave(&priv->lock, flags); | 857 | spin_lock_irqsave(&priv->lock, flags); |
894 | if (priv->flags.write_urb_in_use == 0 | 858 | if (priv->flags.write_urb_in_use == 0 && count != 0) { |
895 | && oti6858_buf_data_avail(priv->buf) != 0) { | ||
896 | schedule_delayed_work(&priv->delayed_write_work, 0); | 859 | schedule_delayed_work(&priv->delayed_write_work, 0); |
897 | resubmit = 0; | 860 | resubmit = 0; |
898 | } | 861 | } |
@@ -1014,165 +977,6 @@ static void oti6858_write_bulk_callback(struct urb *urb) | |||
1014 | } | 977 | } |
1015 | } | 978 | } |
1016 | 979 | ||
1017 | |||
1018 | /* | ||
1019 | * oti6858_buf_alloc | ||
1020 | * | ||
1021 | * Allocate a circular buffer and all associated memory. | ||
1022 | */ | ||
1023 | static struct oti6858_buf *oti6858_buf_alloc(unsigned int size) | ||
1024 | { | ||
1025 | struct oti6858_buf *pb; | ||
1026 | |||
1027 | if (size == 0) | ||
1028 | return NULL; | ||
1029 | |||
1030 | pb = kmalloc(sizeof(struct oti6858_buf), GFP_KERNEL); | ||
1031 | if (pb == NULL) | ||
1032 | return NULL; | ||
1033 | |||
1034 | pb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
1035 | if (pb->buf_buf == NULL) { | ||
1036 | kfree(pb); | ||
1037 | return NULL; | ||
1038 | } | ||
1039 | |||
1040 | pb->buf_size = size; | ||
1041 | pb->buf_get = pb->buf_put = pb->buf_buf; | ||
1042 | |||
1043 | return pb; | ||
1044 | } | ||
1045 | |||
1046 | /* | ||
1047 | * oti6858_buf_free | ||
1048 | * | ||
1049 | * Free the buffer and all associated memory. | ||
1050 | */ | ||
1051 | static void oti6858_buf_free(struct oti6858_buf *pb) | ||
1052 | { | ||
1053 | if (pb) { | ||
1054 | kfree(pb->buf_buf); | ||
1055 | kfree(pb); | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | /* | ||
1060 | * oti6858_buf_clear | ||
1061 | * | ||
1062 | * Clear out all data in the circular buffer. | ||
1063 | */ | ||
1064 | static void oti6858_buf_clear(struct oti6858_buf *pb) | ||
1065 | { | ||
1066 | if (pb != NULL) { | ||
1067 | /* equivalent to a get of all data available */ | ||
1068 | pb->buf_get = pb->buf_put; | ||
1069 | } | ||
1070 | } | ||
1071 | |||
1072 | /* | ||
1073 | * oti6858_buf_data_avail | ||
1074 | * | ||
1075 | * Return the number of bytes of data available in the circular | ||
1076 | * buffer. | ||
1077 | */ | ||
1078 | static unsigned int oti6858_buf_data_avail(struct oti6858_buf *pb) | ||
1079 | { | ||
1080 | if (pb == NULL) | ||
1081 | return 0; | ||
1082 | return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size; | ||
1083 | } | ||
1084 | |||
1085 | /* | ||
1086 | * oti6858_buf_space_avail | ||
1087 | * | ||
1088 | * Return the number of bytes of space available in the circular | ||
1089 | * buffer. | ||
1090 | */ | ||
1091 | static unsigned int oti6858_buf_space_avail(struct oti6858_buf *pb) | ||
1092 | { | ||
1093 | if (pb == NULL) | ||
1094 | return 0; | ||
1095 | return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size; | ||
1096 | } | ||
1097 | |||
1098 | /* | ||
1099 | * oti6858_buf_put | ||
1100 | * | ||
1101 | * Copy data data from a user buffer and put it into the circular buffer. | ||
1102 | * Restrict to the amount of space available. | ||
1103 | * | ||
1104 | * Return the number of bytes copied. | ||
1105 | */ | ||
1106 | static unsigned int oti6858_buf_put(struct oti6858_buf *pb, const char *buf, | ||
1107 | unsigned int count) | ||
1108 | { | ||
1109 | unsigned int len; | ||
1110 | |||
1111 | if (pb == NULL) | ||
1112 | return 0; | ||
1113 | |||
1114 | len = oti6858_buf_space_avail(pb); | ||
1115 | if (count > len) | ||
1116 | count = len; | ||
1117 | |||
1118 | if (count == 0) | ||
1119 | return 0; | ||
1120 | |||
1121 | len = pb->buf_buf + pb->buf_size - pb->buf_put; | ||
1122 | if (count > len) { | ||
1123 | memcpy(pb->buf_put, buf, len); | ||
1124 | memcpy(pb->buf_buf, buf+len, count - len); | ||
1125 | pb->buf_put = pb->buf_buf + count - len; | ||
1126 | } else { | ||
1127 | memcpy(pb->buf_put, buf, count); | ||
1128 | if (count < len) | ||
1129 | pb->buf_put += count; | ||
1130 | else /* count == len */ | ||
1131 | pb->buf_put = pb->buf_buf; | ||
1132 | } | ||
1133 | |||
1134 | return count; | ||
1135 | } | ||
1136 | |||
1137 | /* | ||
1138 | * oti6858_buf_get | ||
1139 | * | ||
1140 | * Get data from the circular buffer and copy to the given buffer. | ||
1141 | * Restrict to the amount of data available. | ||
1142 | * | ||
1143 | * Return the number of bytes copied. | ||
1144 | */ | ||
1145 | static unsigned int oti6858_buf_get(struct oti6858_buf *pb, char *buf, | ||
1146 | unsigned int count) | ||
1147 | { | ||
1148 | unsigned int len; | ||
1149 | |||
1150 | if (pb == NULL) | ||
1151 | return 0; | ||
1152 | |||
1153 | len = oti6858_buf_data_avail(pb); | ||
1154 | if (count > len) | ||
1155 | count = len; | ||
1156 | |||
1157 | if (count == 0) | ||
1158 | return 0; | ||
1159 | |||
1160 | len = pb->buf_buf + pb->buf_size - pb->buf_get; | ||
1161 | if (count > len) { | ||
1162 | memcpy(buf, pb->buf_get, len); | ||
1163 | memcpy(buf+len, pb->buf_buf, count - len); | ||
1164 | pb->buf_get = pb->buf_buf + count - len; | ||
1165 | } else { | ||
1166 | memcpy(buf, pb->buf_get, count); | ||
1167 | if (count < len) | ||
1168 | pb->buf_get += count; | ||
1169 | else /* count == len */ | ||
1170 | pb->buf_get = pb->buf_buf; | ||
1171 | } | ||
1172 | |||
1173 | return count; | ||
1174 | } | ||
1175 | |||
1176 | /* module description and (de)initialization */ | 980 | /* module description and (de)initialization */ |
1177 | 981 | ||
1178 | static int __init oti6858_init(void) | 982 | static int __init oti6858_init(void) |