aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/sierra.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/sierra.c')
-rw-r--r--drivers/usb/serial/sierra.c371
1 files changed, 159 insertions, 212 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index ac1829c6e8f0..e7db20343d1a 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -86,15 +86,14 @@ static int debug;
86#define N_IN_URB 4 86#define N_IN_URB 4
87#define N_OUT_URB 4 87#define N_OUT_URB 4
88#define IN_BUFLEN 4096 88#define IN_BUFLEN 4096
89#define OUT_BUFLEN 128
90 89
91struct sierra_port_private { 90struct sierra_port_private {
91 spinlock_t lock; /* lock the structure */
92 int outstanding_urbs; /* number of out urbs in flight */
93
92 /* Input endpoints and buffer for this port */ 94 /* Input endpoints and buffer for this port */
93 struct urb *in_urbs[N_IN_URB]; 95 struct urb *in_urbs[N_IN_URB];
94 char in_buffer[N_IN_URB][IN_BUFLEN]; 96 char in_buffer[N_IN_URB][IN_BUFLEN];
95 /* Output endpoints and buffer for this port */
96 struct urb *out_urbs[N_OUT_URB];
97 char out_buffer[N_OUT_URB][OUT_BUFLEN];
98 97
99 /* Settings for the port */ 98 /* Settings for the port */
100 int rts_state; /* Handshaking pins (outputs) */ 99 int rts_state; /* Handshaking pins (outputs) */
@@ -103,8 +102,6 @@ struct sierra_port_private {
103 int dsr_state; 102 int dsr_state;
104 int dcd_state; 103 int dcd_state;
105 int ri_state; 104 int ri_state;
106
107 unsigned long tx_start_time[N_OUT_URB];
108}; 105};
109 106
110static int sierra_send_setup(struct usb_serial_port *port) 107static int sierra_send_setup(struct usb_serial_port *port)
@@ -197,61 +194,98 @@ static int sierra_ioctl(struct usb_serial_port *port, struct file *file,
197 return -ENOIOCTLCMD; 194 return -ENOIOCTLCMD;
198} 195}
199 196
197static void sierra_outdat_callback(struct urb *urb)
198{
199 struct usb_serial_port *port = urb->context;
200 struct sierra_port_private *portdata = usb_get_serial_port_data(port);
201 int status = urb->status;
202 unsigned long flags;
203
204 dbg("%s - port %d", __FUNCTION__, port->number);
205
206 /* free up the transfer buffer, as usb_free_urb() does not do this */
207 kfree(urb->transfer_buffer);
208
209 if (status)
210 dbg("%s - nonzero write bulk status received: %d",
211 __FUNCTION__, status);
212
213 spin_lock_irqsave(&portdata->lock, flags);
214 --portdata->outstanding_urbs;
215 spin_unlock_irqrestore(&portdata->lock, flags);
216
217 usb_serial_port_softint(port);
218}
219
200/* Write */ 220/* Write */
201static int sierra_write(struct usb_serial_port *port, 221static int sierra_write(struct usb_serial_port *port,
202 const unsigned char *buf, int count) 222 const unsigned char *buf, int count)
203{ 223{
204 struct sierra_port_private *portdata; 224 struct sierra_port_private *portdata = usb_get_serial_port_data(port);
205 int i; 225 struct usb_serial *serial = port->serial;
206 int left, todo; 226 unsigned long flags;
207 struct urb *this_urb = NULL; /* spurious */ 227 unsigned char *buffer;
208 int err; 228 struct urb *urb;
229 int status;
209 230
210 portdata = usb_get_serial_port_data(port); 231 portdata = usb_get_serial_port_data(port);
211 232
212 dbg("%s: write (%d chars)", __FUNCTION__, count); 233 dbg("%s: write (%d chars)", __FUNCTION__, count);
213 234
214 i = 0; 235 spin_lock_irqsave(&portdata->lock, flags);
215 left = count; 236 if (portdata->outstanding_urbs > N_OUT_URB) {
216 for (i=0; left > 0 && i < N_OUT_URB; i++) { 237 spin_unlock_irqrestore(&portdata->lock, flags);
217 todo = left; 238 dbg("%s - write limit hit\n", __FUNCTION__);
218 if (todo > OUT_BUFLEN) 239 return 0;
219 todo = OUT_BUFLEN; 240 }
220 241 portdata->outstanding_urbs++;
221 this_urb = portdata->out_urbs[i]; 242 spin_unlock_irqrestore(&portdata->lock, flags);
222 if (this_urb->status == -EINPROGRESS) { 243
223 if (time_before(jiffies, 244 buffer = kmalloc(count, GFP_ATOMIC);
224 portdata->tx_start_time[i] + 10 * HZ)) 245 if (!buffer) {
225 continue; 246 dev_err(&port->dev, "out of memory\n");
226 usb_unlink_urb(this_urb); 247 count = -ENOMEM;
227 continue; 248 goto error_no_buffer;
228 } 249 }
229 if (this_urb->status != 0) 250
230 dbg("usb_write %p failed (err=%d)", 251 urb = usb_alloc_urb(0, GFP_ATOMIC);
231 this_urb, this_urb->status); 252 if (!urb) {
232 253 dev_err(&port->dev, "no more free urbs\n");
233 dbg("%s: endpoint %d buf %d", __FUNCTION__, 254 count = -ENOMEM;
234 usb_pipeendpoint(this_urb->pipe), i); 255 goto error_no_urb;
235 256 }
236 /* send the data */ 257
237 memcpy (this_urb->transfer_buffer, buf, todo); 258 memcpy(buffer, buf, count);
238 this_urb->transfer_buffer_length = todo; 259
239 260 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
240 this_urb->dev = port->serial->dev; 261
241 err = usb_submit_urb(this_urb, GFP_ATOMIC); 262 usb_fill_bulk_urb(urb, serial->dev,
242 if (err) { 263 usb_sndbulkpipe(serial->dev,
243 dbg("usb_submit_urb %p (write bulk) failed " 264 port->bulk_out_endpointAddress),
244 "(%d, has %d)", this_urb, 265 buffer, count, sierra_outdat_callback, port);
245 err, this_urb->status); 266
246 continue; 267 /* send it down the pipe */
247 } 268 status = usb_submit_urb(urb, GFP_ATOMIC);
248 portdata->tx_start_time[i] = jiffies; 269 if (status) {
249 buf += todo; 270 dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
250 left -= todo; 271 "with status = %d\n", __FUNCTION__, status);
272 count = status;
273 goto error;
251 } 274 }
252 275
253 count -= left; 276 /* we are done with this urb, so let the host driver
254 dbg("%s: wrote (did %d)", __FUNCTION__, count); 277 * really free it when it is finished with it */
278 usb_free_urb(urb);
279
280 return count;
281error:
282 usb_free_urb(urb);
283error_no_urb:
284 kfree(buffer);
285error_no_buffer:
286 spin_lock_irqsave(&portdata->lock, flags);
287 --portdata->outstanding_urbs;
288 spin_unlock_irqrestore(&portdata->lock, flags);
255 return count; 289 return count;
256} 290}
257 291
@@ -262,15 +296,16 @@ static void sierra_indat_callback(struct urb *urb)
262 struct usb_serial_port *port; 296 struct usb_serial_port *port;
263 struct tty_struct *tty; 297 struct tty_struct *tty;
264 unsigned char *data = urb->transfer_buffer; 298 unsigned char *data = urb->transfer_buffer;
299 int status = urb->status;
265 300
266 dbg("%s: %p", __FUNCTION__, urb); 301 dbg("%s: %p", __FUNCTION__, urb);
267 302
268 endpoint = usb_pipeendpoint(urb->pipe); 303 endpoint = usb_pipeendpoint(urb->pipe);
269 port = (struct usb_serial_port *) urb->context; 304 port = (struct usb_serial_port *) urb->context;
270 305
271 if (urb->status) { 306 if (status) {
272 dbg("%s: nonzero status: %d on endpoint %02x.", 307 dbg("%s: nonzero status: %d on endpoint %02x.",
273 __FUNCTION__, urb->status, endpoint); 308 __FUNCTION__, status, endpoint);
274 } else { 309 } else {
275 tty = port->tty; 310 tty = port->tty;
276 if (urb->actual_length) { 311 if (urb->actual_length) {
@@ -282,30 +317,20 @@ static void sierra_indat_callback(struct urb *urb)
282 } 317 }
283 318
284 /* Resubmit urb so we continue receiving */ 319 /* Resubmit urb so we continue receiving */
285 if (port->open_count && urb->status != -ESHUTDOWN) { 320 if (port->open_count && status != -ESHUTDOWN) {
286 err = usb_submit_urb(urb, GFP_ATOMIC); 321 err = usb_submit_urb(urb, GFP_ATOMIC);
287 if (err) 322 if (err)
288 printk(KERN_ERR "%s: resubmit read urb failed. " 323 dev_err(&port->dev, "resubmit read urb failed."
289 "(%d)", __FUNCTION__, err); 324 "(%d)", err);
290 } 325 }
291 } 326 }
292 return; 327 return;
293} 328}
294 329
295static void sierra_outdat_callback(struct urb *urb)
296{
297 struct usb_serial_port *port;
298
299 dbg("%s", __FUNCTION__);
300
301 port = (struct usb_serial_port *) urb->context;
302
303 usb_serial_port_softint(port);
304}
305
306static void sierra_instat_callback(struct urb *urb) 330static void sierra_instat_callback(struct urb *urb)
307{ 331{
308 int err; 332 int err;
333 int status = urb->status;
309 struct usb_serial_port *port = (struct usb_serial_port *) urb->context; 334 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
310 struct sierra_port_private *portdata = usb_get_serial_port_data(port); 335 struct sierra_port_private *portdata = usb_get_serial_port_data(port);
311 struct usb_serial *serial = port->serial; 336 struct usb_serial *serial = port->serial;
@@ -313,7 +338,7 @@ static void sierra_instat_callback(struct urb *urb)
313 dbg("%s", __FUNCTION__); 338 dbg("%s", __FUNCTION__);
314 dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); 339 dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
315 340
316 if (urb->status == 0) { 341 if (status == 0) {
317 struct usb_ctrlrequest *req_pkt = 342 struct usb_ctrlrequest *req_pkt =
318 (struct usb_ctrlrequest *)urb->transfer_buffer; 343 (struct usb_ctrlrequest *)urb->transfer_buffer;
319 344
@@ -344,10 +369,10 @@ static void sierra_instat_callback(struct urb *urb)
344 req_pkt->bRequestType,req_pkt->bRequest); 369 req_pkt->bRequestType,req_pkt->bRequest);
345 } 370 }
346 } else 371 } else
347 dbg("%s: error %d", __FUNCTION__, urb->status); 372 dbg("%s: error %d", __FUNCTION__, status);
348 373
349 /* Resubmit urb so we continue receiving IRQ data */ 374 /* Resubmit urb so we continue receiving IRQ data */
350 if (urb->status != -ESHUTDOWN) { 375 if (status != -ESHUTDOWN) {
351 urb->dev = serial->dev; 376 urb->dev = serial->dev;
352 err = usb_submit_urb(urb, GFP_ATOMIC); 377 err = usb_submit_urb(urb, GFP_ATOMIC);
353 if (err) 378 if (err)
@@ -358,46 +383,42 @@ static void sierra_instat_callback(struct urb *urb)
358 383
359static int sierra_write_room(struct usb_serial_port *port) 384static int sierra_write_room(struct usb_serial_port *port)
360{ 385{
361 struct sierra_port_private *portdata; 386 struct sierra_port_private *portdata = usb_get_serial_port_data(port);
362 int i; 387 unsigned long flags;
363 int data_len = 0;
364 struct urb *this_urb;
365 388
366 portdata = usb_get_serial_port_data(port); 389 dbg("%s - port %d", __FUNCTION__, port->number);
367 390
368 for (i=0; i < N_OUT_URB; i++) { 391 /* try to give a good number back based on if we have any free urbs at
369 this_urb = portdata->out_urbs[i]; 392 * this point in time */
370 if (this_urb && this_urb->status != -EINPROGRESS) 393 spin_lock_irqsave(&portdata->lock, flags);
371 data_len += OUT_BUFLEN; 394 if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) {
395 spin_unlock_irqrestore(&portdata->lock, flags);
396 dbg("%s - write limit hit\n", __FUNCTION__);
397 return 0;
372 } 398 }
399 spin_unlock_irqrestore(&portdata->lock, flags);
373 400
374 dbg("%s: %d", __FUNCTION__, data_len); 401 return 2048;
375 return data_len;
376} 402}
377 403
378static int sierra_chars_in_buffer(struct usb_serial_port *port) 404static int sierra_chars_in_buffer(struct usb_serial_port *port)
379{ 405{
380 struct sierra_port_private *portdata; 406 dbg("%s - port %d", __FUNCTION__, port->number);
381 int i; 407
382 int data_len = 0; 408 /*
383 struct urb *this_urb; 409 * We can't really account for how much data we
384 410 * have sent out, but hasn't made it through to the
385 portdata = usb_get_serial_port_data(port); 411 * device as we can't see the backend here, so just
386 412 * tell the tty layer that everything is flushed.
387 for (i=0; i < N_OUT_URB; i++) { 413 */
388 this_urb = portdata->out_urbs[i]; 414 return 0;
389 if (this_urb && this_urb->status == -EINPROGRESS)
390 data_len += this_urb->transfer_buffer_length;
391 }
392 dbg("%s: %d", __FUNCTION__, data_len);
393 return data_len;
394} 415}
395 416
396static int sierra_open(struct usb_serial_port *port, struct file *filp) 417static int sierra_open(struct usb_serial_port *port, struct file *filp)
397{ 418{
398 struct sierra_port_private *portdata; 419 struct sierra_port_private *portdata;
399 struct usb_serial *serial = port->serial; 420 struct usb_serial *serial = port->serial;
400 int i, err; 421 int i;
401 struct urb *urb; 422 struct urb *urb;
402 int result; 423 int result;
403 __u16 set_mode_dzero = 0x0000; 424 __u16 set_mode_dzero = 0x0000;
@@ -413,7 +434,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
413 /* Reset low level data toggle and start reading from endpoints */ 434 /* Reset low level data toggle and start reading from endpoints */
414 for (i = 0; i < N_IN_URB; i++) { 435 for (i = 0; i < N_IN_URB; i++) {
415 urb = portdata->in_urbs[i]; 436 urb = portdata->in_urbs[i];
416 if (! urb) 437 if (!urb)
417 continue; 438 continue;
418 if (urb->dev != serial->dev) { 439 if (urb->dev != serial->dev) {
419 dbg("%s: dev %p != %p", __FUNCTION__, 440 dbg("%s: dev %p != %p", __FUNCTION__,
@@ -427,24 +448,13 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
427 */ 448 */
428 usb_clear_halt(urb->dev, urb->pipe); 449 usb_clear_halt(urb->dev, urb->pipe);
429 450
430 err = usb_submit_urb(urb, GFP_KERNEL); 451 result = usb_submit_urb(urb, GFP_KERNEL);
431 if (err) { 452 if (result) {
432 dbg("%s: submit urb %d failed (%d) %d", 453 dev_err(&port->dev, "submit urb %d failed (%d) %d",
433 __FUNCTION__, i, err, 454 i, result, urb->transfer_buffer_length);
434 urb->transfer_buffer_length);
435 } 455 }
436 } 456 }
437 457
438 /* Reset low level data toggle on out endpoints */
439 for (i = 0; i < N_OUT_URB; i++) {
440 urb = portdata->out_urbs[i];
441 if (! urb)
442 continue;
443 urb->dev = serial->dev;
444 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
445 usb_pipeout(urb->pipe), 0); */
446 }
447
448 port->tty->low_latency = 1; 458 port->tty->low_latency = 1;
449 459
450 /* set mode to D0 */ 460 /* set mode to D0 */
@@ -455,7 +465,14 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
455 465
456 sierra_send_setup(port); 466 sierra_send_setup(port);
457 467
458 return (0); 468 /* start up the interrupt endpoint if we have one */
469 if (port->interrupt_in_urb) {
470 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
471 if (result)
472 dev_err(&port->dev, "submit irq_in urb failed %d",
473 result);
474 }
475 return 0;
459} 476}
460 477
461static void sierra_close(struct usb_serial_port *port, struct file *filp) 478static void sierra_close(struct usb_serial_port *port, struct file *filp)
@@ -475,71 +492,21 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
475 492
476 /* Stop reading/writing urbs */ 493 /* Stop reading/writing urbs */
477 for (i = 0; i < N_IN_URB; i++) 494 for (i = 0; i < N_IN_URB; i++)
478 usb_unlink_urb(portdata->in_urbs[i]); 495 usb_kill_urb(portdata->in_urbs[i]);
479 for (i = 0; i < N_OUT_URB; i++)
480 usb_unlink_urb(portdata->out_urbs[i]);
481 } 496 }
482 port->tty = NULL;
483}
484
485/* Helper functions used by sierra_setup_urbs */
486static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint,
487 int dir, void *ctx, char *buf, int len,
488 usb_complete_t callback)
489{
490 struct urb *urb;
491
492 if (endpoint == -1)
493 return NULL; /* endpoint not needed */
494
495 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
496 if (urb == NULL) {
497 dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
498 return NULL;
499 }
500
501 /* Fill URB using supplied data. */
502 usb_fill_bulk_urb(urb, serial->dev,
503 usb_sndbulkpipe(serial->dev, endpoint) | dir,
504 buf, len, callback, ctx);
505
506 return urb;
507}
508 497
509/* Setup urbs */ 498 usb_kill_urb(port->interrupt_in_urb);
510static void sierra_setup_urbs(struct usb_serial *serial)
511{
512 int i,j;
513 struct usb_serial_port *port;
514 struct sierra_port_private *portdata;
515
516 dbg("%s", __FUNCTION__);
517 499
518 for (i = 0; i < serial->num_ports; i++) { 500 port->tty = NULL;
519 port = serial->port[i];
520 portdata = usb_get_serial_port_data(port);
521
522 /* Do indat endpoints first */
523 for (j = 0; j < N_IN_URB; ++j) {
524 portdata->in_urbs[j] = sierra_setup_urb (serial,
525 port->bulk_in_endpointAddress, USB_DIR_IN, port,
526 portdata->in_buffer[j], IN_BUFLEN, sierra_indat_callback);
527 }
528
529 /* outdat endpoints */
530 for (j = 0; j < N_OUT_URB; ++j) {
531 portdata->out_urbs[j] = sierra_setup_urb (serial,
532 port->bulk_out_endpointAddress, USB_DIR_OUT, port,
533 portdata->out_buffer[j], OUT_BUFLEN, sierra_outdat_callback);
534 }
535 }
536} 501}
537 502
538static int sierra_startup(struct usb_serial *serial) 503static int sierra_startup(struct usb_serial *serial)
539{ 504{
540 int i, err;
541 struct usb_serial_port *port; 505 struct usb_serial_port *port;
542 struct sierra_port_private *portdata; 506 struct sierra_port_private *portdata;
507 struct urb *urb;
508 int i;
509 int j;
543 510
544 dbg("%s", __FUNCTION__); 511 dbg("%s", __FUNCTION__);
545 512
@@ -550,22 +517,31 @@ static int sierra_startup(struct usb_serial *serial)
550 if (!portdata) { 517 if (!portdata) {
551 dbg("%s: kmalloc for sierra_port_private (%d) failed!.", 518 dbg("%s: kmalloc for sierra_port_private (%d) failed!.",
552 __FUNCTION__, i); 519 __FUNCTION__, i);
553 return (1); 520 return -ENOMEM;
554 } 521 }
522 spin_lock_init(&portdata->lock);
555 523
556 usb_set_serial_port_data(port, portdata); 524 usb_set_serial_port_data(port, portdata);
557 525
558 if (! port->interrupt_in_urb) 526 /* initialize the in urbs */
559 continue; 527 for (j = 0; j < N_IN_URB; ++j) {
560 err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 528 urb = usb_alloc_urb(0, GFP_KERNEL);
561 if (err) 529 if (urb == NULL) {
562 dbg("%s: submit irq_in urb failed %d", 530 dbg("%s: alloc for in port failed.",
563 __FUNCTION__, err); 531 __FUNCTION__);
532 continue;
533 }
534 /* Fill URB using supplied data. */
535 usb_fill_bulk_urb(urb, serial->dev,
536 usb_rcvbulkpipe(serial->dev,
537 port->bulk_in_endpointAddress),
538 portdata->in_buffer[j], IN_BUFLEN,
539 sierra_indat_callback, port);
540 portdata->in_urbs[j] = urb;
541 }
564 } 542 }
565 543
566 sierra_setup_urbs(serial); 544 return 0;
567
568 return (0);
569} 545}
570 546
571static void sierra_shutdown(struct usb_serial *serial) 547static void sierra_shutdown(struct usb_serial *serial)
@@ -576,22 +552,6 @@ static void sierra_shutdown(struct usb_serial *serial)
576 552
577 dbg("%s", __FUNCTION__); 553 dbg("%s", __FUNCTION__);
578 554
579 /* Stop reading/writing urbs */
580 for (i = 0; i < serial->num_ports; ++i) {
581 port = serial->port[i];
582 if (!port)
583 continue;
584 portdata = usb_get_serial_port_data(port);
585 if (!portdata)
586 continue;
587
588 for (j = 0; j < N_IN_URB; j++)
589 usb_unlink_urb(portdata->in_urbs[j]);
590 for (j = 0; j < N_OUT_URB; j++)
591 usb_unlink_urb(portdata->out_urbs[j]);
592 }
593
594 /* Now free them */
595 for (i = 0; i < serial->num_ports; ++i) { 555 for (i = 0; i < serial->num_ports; ++i) {
596 port = serial->port[i]; 556 port = serial->port[i];
597 if (!port) 557 if (!port)
@@ -601,25 +561,12 @@ static void sierra_shutdown(struct usb_serial *serial)
601 continue; 561 continue;
602 562
603 for (j = 0; j < N_IN_URB; j++) { 563 for (j = 0; j < N_IN_URB; j++) {
604 if (portdata->in_urbs[j]) { 564 usb_kill_urb(portdata->in_urbs[j]);
605 usb_free_urb(portdata->in_urbs[j]); 565 usb_free_urb(portdata->in_urbs[j]);
606 portdata->in_urbs[j] = NULL; 566 portdata->in_urbs[j] = NULL;
607 }
608 } 567 }
609 for (j = 0; j < N_OUT_URB; j++) { 568 kfree(portdata);
610 if (portdata->out_urbs[j]) { 569 usb_set_serial_port_data(port, NULL);
611 usb_free_urb(portdata->out_urbs[j]);
612 portdata->out_urbs[j] = NULL;
613 }
614 }
615 }
616
617 /* Now free per port private data */
618 for (i = 0; i < serial->num_ports; i++) {
619 port = serial->port[i];
620 if (!port)
621 continue;
622 kfree(usb_get_serial_port_data(port));
623 } 570 }
624} 571}
625 572