diff options
author | Johan Hovold <jhovold@gmail.com> | 2010-03-17 18:06:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:34 -0400 |
commit | 684c6e30d389f67ef727c8f5a7b23a09b4cb02e4 (patch) | |
tree | 58be2cbd2253af3980fea1007d1178a484d107f7 | |
parent | 50a5f70cee11636908711abd339f5c5933375a7d (diff) |
USB: pl2303: switch to generic write implementation
Replace custom fifo-based write implementation with the generic
kfifo-based one.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/serial/pl2303.c | 330 |
1 files changed, 4 insertions, 326 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 77e968045f75..28037c1af93e 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -40,16 +40,6 @@ static int debug; | |||
40 | 40 | ||
41 | #define PL2303_CLOSING_WAIT (30*HZ) | 41 | #define PL2303_CLOSING_WAIT (30*HZ) |
42 | 42 | ||
43 | #define PL2303_BUF_SIZE 1024 | ||
44 | #define PL2303_TMP_BUF_SIZE 1024 | ||
45 | |||
46 | struct pl2303_buf { | ||
47 | unsigned int buf_size; | ||
48 | char *buf_buf; | ||
49 | char *buf_get; | ||
50 | char *buf_put; | ||
51 | }; | ||
52 | |||
53 | static const struct usb_device_id id_table[] = { | 43 | static const struct usb_device_id id_table[] = { |
54 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, | 44 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, |
55 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, | 45 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, |
@@ -157,173 +147,12 @@ enum pl2303_type { | |||
157 | 147 | ||
158 | struct pl2303_private { | 148 | struct pl2303_private { |
159 | spinlock_t lock; | 149 | spinlock_t lock; |
160 | struct pl2303_buf *buf; | ||
161 | int write_urb_in_use; | ||
162 | wait_queue_head_t delta_msr_wait; | 150 | wait_queue_head_t delta_msr_wait; |
163 | u8 line_control; | 151 | u8 line_control; |
164 | u8 line_status; | 152 | u8 line_status; |
165 | enum pl2303_type type; | 153 | enum pl2303_type type; |
166 | }; | 154 | }; |
167 | 155 | ||
168 | /* | ||
169 | * pl2303_buf_alloc | ||
170 | * | ||
171 | * Allocate a circular buffer and all associated memory. | ||
172 | */ | ||
173 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) | ||
174 | { | ||
175 | struct pl2303_buf *pb; | ||
176 | |||
177 | if (size == 0) | ||
178 | return NULL; | ||
179 | |||
180 | pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); | ||
181 | if (pb == NULL) | ||
182 | return NULL; | ||
183 | |||
184 | pb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
185 | if (pb->buf_buf == NULL) { | ||
186 | kfree(pb); | ||
187 | return NULL; | ||
188 | } | ||
189 | |||
190 | pb->buf_size = size; | ||
191 | pb->buf_get = pb->buf_put = pb->buf_buf; | ||
192 | |||
193 | return pb; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * pl2303_buf_free | ||
198 | * | ||
199 | * Free the buffer and all associated memory. | ||
200 | */ | ||
201 | static void pl2303_buf_free(struct pl2303_buf *pb) | ||
202 | { | ||
203 | if (pb) { | ||
204 | kfree(pb->buf_buf); | ||
205 | kfree(pb); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * pl2303_buf_clear | ||
211 | * | ||
212 | * Clear out all data in the circular buffer. | ||
213 | */ | ||
214 | static void pl2303_buf_clear(struct pl2303_buf *pb) | ||
215 | { | ||
216 | if (pb != NULL) | ||
217 | pb->buf_get = pb->buf_put; | ||
218 | /* equivalent to a get of all data available */ | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * pl2303_buf_data_avail | ||
223 | * | ||
224 | * Return the number of bytes of data available in the circular | ||
225 | * buffer. | ||
226 | */ | ||
227 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) | ||
228 | { | ||
229 | if (pb == NULL) | ||
230 | return 0; | ||
231 | |||
232 | return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size; | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | * pl2303_buf_space_avail | ||
237 | * | ||
238 | * Return the number of bytes of space available in the circular | ||
239 | * buffer. | ||
240 | */ | ||
241 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) | ||
242 | { | ||
243 | if (pb == NULL) | ||
244 | return 0; | ||
245 | |||
246 | return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size; | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * pl2303_buf_put | ||
251 | * | ||
252 | * Copy data data from a user buffer and put it into the circular buffer. | ||
253 | * Restrict to the amount of space available. | ||
254 | * | ||
255 | * Return the number of bytes copied. | ||
256 | */ | ||
257 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
258 | unsigned int count) | ||
259 | { | ||
260 | unsigned int len; | ||
261 | |||
262 | if (pb == NULL) | ||
263 | return 0; | ||
264 | |||
265 | len = pl2303_buf_space_avail(pb); | ||
266 | if (count > len) | ||
267 | count = len; | ||
268 | |||
269 | if (count == 0) | ||
270 | return 0; | ||
271 | |||
272 | len = pb->buf_buf + pb->buf_size - pb->buf_put; | ||
273 | if (count > len) { | ||
274 | memcpy(pb->buf_put, buf, len); | ||
275 | memcpy(pb->buf_buf, buf+len, count - len); | ||
276 | pb->buf_put = pb->buf_buf + count - len; | ||
277 | } else { | ||
278 | memcpy(pb->buf_put, buf, count); | ||
279 | if (count < len) | ||
280 | pb->buf_put += count; | ||
281 | else /* count == len */ | ||
282 | pb->buf_put = pb->buf_buf; | ||
283 | } | ||
284 | |||
285 | return count; | ||
286 | } | ||
287 | |||
288 | /* | ||
289 | * pl2303_buf_get | ||
290 | * | ||
291 | * Get data from the circular buffer and copy to the given buffer. | ||
292 | * Restrict to the amount of data available. | ||
293 | * | ||
294 | * Return the number of bytes copied. | ||
295 | */ | ||
296 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
297 | unsigned int count) | ||
298 | { | ||
299 | unsigned int len; | ||
300 | |||
301 | if (pb == NULL) | ||
302 | return 0; | ||
303 | |||
304 | len = pl2303_buf_data_avail(pb); | ||
305 | if (count > len) | ||
306 | count = len; | ||
307 | |||
308 | if (count == 0) | ||
309 | return 0; | ||
310 | |||
311 | len = pb->buf_buf + pb->buf_size - pb->buf_get; | ||
312 | if (count > len) { | ||
313 | memcpy(buf, pb->buf_get, len); | ||
314 | memcpy(buf+len, pb->buf_buf, count - len); | ||
315 | pb->buf_get = pb->buf_buf + count - len; | ||
316 | } else { | ||
317 | memcpy(buf, pb->buf_get, count); | ||
318 | if (count < len) | ||
319 | pb->buf_get += count; | ||
320 | else /* count == len */ | ||
321 | pb->buf_get = pb->buf_buf; | ||
322 | } | ||
323 | |||
324 | return count; | ||
325 | } | ||
326 | |||
327 | static int pl2303_vendor_read(__u16 value, __u16 index, | 156 | static int pl2303_vendor_read(__u16 value, __u16 index, |
328 | struct usb_serial *serial, unsigned char *buf) | 157 | struct usb_serial *serial, unsigned char *buf) |
329 | { | 158 | { |
@@ -372,11 +201,6 @@ static int pl2303_startup(struct usb_serial *serial) | |||
372 | if (!priv) | 201 | if (!priv) |
373 | goto cleanup; | 202 | goto cleanup; |
374 | spin_lock_init(&priv->lock); | 203 | spin_lock_init(&priv->lock); |
375 | priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE); | ||
376 | if (priv->buf == NULL) { | ||
377 | kfree(priv); | ||
378 | goto cleanup; | ||
379 | } | ||
380 | init_waitqueue_head(&priv->delta_msr_wait); | 204 | init_waitqueue_head(&priv->delta_msr_wait); |
381 | priv->type = type; | 205 | priv->type = type; |
382 | usb_set_serial_port_data(serial->port[i], priv); | 206 | usb_set_serial_port_data(serial->port[i], priv); |
@@ -404,7 +228,6 @@ cleanup: | |||
404 | kfree(buf); | 228 | kfree(buf); |
405 | for (--i; i >= 0; --i) { | 229 | for (--i; i >= 0; --i) { |
406 | priv = usb_get_serial_port_data(serial->port[i]); | 230 | priv = usb_get_serial_port_data(serial->port[i]); |
407 | pl2303_buf_free(priv->buf); | ||
408 | kfree(priv); | 231 | kfree(priv); |
409 | usb_set_serial_port_data(serial->port[i], NULL); | 232 | usb_set_serial_port_data(serial->port[i], NULL); |
410 | } | 233 | } |
@@ -422,102 +245,6 @@ static int set_control_lines(struct usb_device *dev, u8 value) | |||
422 | return retval; | 245 | return retval; |
423 | } | 246 | } |
424 | 247 | ||
425 | static void pl2303_send(struct usb_serial_port *port) | ||
426 | { | ||
427 | int count, result; | ||
428 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
429 | unsigned long flags; | ||
430 | |||
431 | dbg("%s - port %d", __func__, port->number); | ||
432 | |||
433 | spin_lock_irqsave(&priv->lock, flags); | ||
434 | |||
435 | if (priv->write_urb_in_use) { | ||
436 | spin_unlock_irqrestore(&priv->lock, flags); | ||
437 | return; | ||
438 | } | ||
439 | |||
440 | count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, | ||
441 | port->bulk_out_size); | ||
442 | |||
443 | if (count == 0) { | ||
444 | spin_unlock_irqrestore(&priv->lock, flags); | ||
445 | return; | ||
446 | } | ||
447 | |||
448 | priv->write_urb_in_use = 1; | ||
449 | |||
450 | spin_unlock_irqrestore(&priv->lock, flags); | ||
451 | |||
452 | usb_serial_debug_data(debug, &port->dev, __func__, count, | ||
453 | port->write_urb->transfer_buffer); | ||
454 | |||
455 | port->write_urb->transfer_buffer_length = count; | ||
456 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
457 | if (result) { | ||
458 | dev_err(&port->dev, "%s - failed submitting write urb," | ||
459 | " error %d\n", __func__, result); | ||
460 | priv->write_urb_in_use = 0; | ||
461 | /* TODO: reschedule pl2303_send */ | ||
462 | } | ||
463 | |||
464 | usb_serial_port_softint(port); | ||
465 | } | ||
466 | |||
467 | static int pl2303_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
468 | const unsigned char *buf, int count) | ||
469 | { | ||
470 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
471 | unsigned long flags; | ||
472 | |||
473 | dbg("%s - port %d, %d bytes", __func__, port->number, count); | ||
474 | |||
475 | if (!count) | ||
476 | return count; | ||
477 | |||
478 | spin_lock_irqsave(&priv->lock, flags); | ||
479 | count = pl2303_buf_put(priv->buf, buf, count); | ||
480 | spin_unlock_irqrestore(&priv->lock, flags); | ||
481 | |||
482 | pl2303_send(port); | ||
483 | |||
484 | return count; | ||
485 | } | ||
486 | |||
487 | static int pl2303_write_room(struct tty_struct *tty) | ||
488 | { | ||
489 | struct usb_serial_port *port = tty->driver_data; | ||
490 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
491 | int room = 0; | ||
492 | unsigned long flags; | ||
493 | |||
494 | dbg("%s - port %d", __func__, port->number); | ||
495 | |||
496 | spin_lock_irqsave(&priv->lock, flags); | ||
497 | room = pl2303_buf_space_avail(priv->buf); | ||
498 | spin_unlock_irqrestore(&priv->lock, flags); | ||
499 | |||
500 | dbg("%s - returns %d", __func__, room); | ||
501 | return room; | ||
502 | } | ||
503 | |||
504 | static int pl2303_chars_in_buffer(struct tty_struct *tty) | ||
505 | { | ||
506 | struct usb_serial_port *port = tty->driver_data; | ||
507 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
508 | int chars = 0; | ||
509 | unsigned long flags; | ||
510 | |||
511 | dbg("%s - port %d", __func__, port->number); | ||
512 | |||
513 | spin_lock_irqsave(&priv->lock, flags); | ||
514 | chars = pl2303_buf_data_avail(priv->buf); | ||
515 | spin_unlock_irqrestore(&priv->lock, flags); | ||
516 | |||
517 | dbg("%s - returns %d", __func__, chars); | ||
518 | return chars; | ||
519 | } | ||
520 | |||
521 | static void pl2303_set_termios(struct tty_struct *tty, | 248 | static void pl2303_set_termios(struct tty_struct *tty, |
522 | struct usb_serial_port *port, struct ktermios *old_termios) | 249 | struct usb_serial_port *port, struct ktermios *old_termios) |
523 | { | 250 | { |
@@ -729,15 +456,14 @@ static void pl2303_dtr_rts(struct usb_serial_port *port, int on) | |||
729 | 456 | ||
730 | static void pl2303_close(struct usb_serial_port *port) | 457 | static void pl2303_close(struct usb_serial_port *port) |
731 | { | 458 | { |
732 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
733 | unsigned long flags; | 459 | unsigned long flags; |
734 | 460 | ||
735 | dbg("%s - port %d", __func__, port->number); | 461 | dbg("%s - port %d", __func__, port->number); |
736 | 462 | ||
737 | spin_lock_irqsave(&priv->lock, flags); | 463 | spin_lock_irqsave(&port->lock, flags); |
738 | /* clear out any remaining data in the buffer */ | 464 | /* clear out any remaining data in the buffer */ |
739 | pl2303_buf_clear(priv->buf); | 465 | kfifo_reset_out(&port->write_fifo); |
740 | spin_unlock_irqrestore(&priv->lock, flags); | 466 | spin_unlock_irqrestore(&port->lock, flags); |
741 | 467 | ||
742 | /* shutdown our urbs */ | 468 | /* shutdown our urbs */ |
743 | dbg("%s - shutting down urbs", __func__); | 469 | dbg("%s - shutting down urbs", __func__); |
@@ -951,10 +677,7 @@ static void pl2303_release(struct usb_serial *serial) | |||
951 | 677 | ||
952 | for (i = 0; i < serial->num_ports; ++i) { | 678 | for (i = 0; i < serial->num_ports; ++i) { |
953 | priv = usb_get_serial_port_data(serial->port[i]); | 679 | priv = usb_get_serial_port_data(serial->port[i]); |
954 | if (priv) { | 680 | kfree(priv); |
955 | pl2303_buf_free(priv->buf); | ||
956 | kfree(priv); | ||
957 | } | ||
958 | } | 681 | } |
959 | } | 682 | } |
960 | 683 | ||
@@ -1086,47 +809,6 @@ static void pl2303_process_read_urb(struct urb *urb) | |||
1086 | tty_kref_put(tty); | 809 | tty_kref_put(tty); |
1087 | } | 810 | } |
1088 | 811 | ||
1089 | static void pl2303_write_bulk_callback(struct urb *urb) | ||
1090 | { | ||
1091 | struct usb_serial_port *port = urb->context; | ||
1092 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
1093 | int result; | ||
1094 | int status = urb->status; | ||
1095 | |||
1096 | dbg("%s - port %d", __func__, port->number); | ||
1097 | |||
1098 | switch (status) { | ||
1099 | case 0: | ||
1100 | /* success */ | ||
1101 | break; | ||
1102 | case -ECONNRESET: | ||
1103 | case -ENOENT: | ||
1104 | case -ESHUTDOWN: | ||
1105 | /* this urb is terminated, clean up */ | ||
1106 | dbg("%s - urb shutting down with status: %d", __func__, | ||
1107 | status); | ||
1108 | priv->write_urb_in_use = 0; | ||
1109 | return; | ||
1110 | default: | ||
1111 | /* error in the urb, so we have to resubmit it */ | ||
1112 | dbg("%s - Overflow in write", __func__); | ||
1113 | dbg("%s - nonzero write bulk status received: %d", __func__, | ||
1114 | status); | ||
1115 | port->write_urb->transfer_buffer_length = 1; | ||
1116 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
1117 | if (result) | ||
1118 | dev_err(&urb->dev->dev, "%s - failed resubmitting write" | ||
1119 | " urb, error %d\n", __func__, result); | ||
1120 | else | ||
1121 | return; | ||
1122 | } | ||
1123 | |||
1124 | priv->write_urb_in_use = 0; | ||
1125 | |||
1126 | /* send any buffered data */ | ||
1127 | pl2303_send(port); | ||
1128 | } | ||
1129 | |||
1130 | /* All of the device info needed for the PL2303 SIO serial converter */ | 812 | /* All of the device info needed for the PL2303 SIO serial converter */ |
1131 | static struct usb_serial_driver pl2303_device = { | 813 | static struct usb_serial_driver pl2303_device = { |
1132 | .driver = { | 814 | .driver = { |
@@ -1142,7 +824,6 @@ static struct usb_serial_driver pl2303_device = { | |||
1142 | .close = pl2303_close, | 824 | .close = pl2303_close, |
1143 | .dtr_rts = pl2303_dtr_rts, | 825 | .dtr_rts = pl2303_dtr_rts, |
1144 | .carrier_raised = pl2303_carrier_raised, | 826 | .carrier_raised = pl2303_carrier_raised, |
1145 | .write = pl2303_write, | ||
1146 | .ioctl = pl2303_ioctl, | 827 | .ioctl = pl2303_ioctl, |
1147 | .break_ctl = pl2303_break_ctl, | 828 | .break_ctl = pl2303_break_ctl, |
1148 | .set_termios = pl2303_set_termios, | 829 | .set_termios = pl2303_set_termios, |
@@ -1150,9 +831,6 @@ static struct usb_serial_driver pl2303_device = { | |||
1150 | .tiocmset = pl2303_tiocmset, | 831 | .tiocmset = pl2303_tiocmset, |
1151 | .process_read_urb = pl2303_process_read_urb, | 832 | .process_read_urb = pl2303_process_read_urb, |
1152 | .read_int_callback = pl2303_read_int_callback, | 833 | .read_int_callback = pl2303_read_int_callback, |
1153 | .write_bulk_callback = pl2303_write_bulk_callback, | ||
1154 | .write_room = pl2303_write_room, | ||
1155 | .chars_in_buffer = pl2303_chars_in_buffer, | ||
1156 | .attach = pl2303_startup, | 834 | .attach = pl2303_startup, |
1157 | .release = pl2303_release, | 835 | .release = pl2303_release, |
1158 | }; | 836 | }; |