diff options
Diffstat (limited to 'drivers/isdn/gigaset/bas-gigaset.c')
-rw-r--r-- | drivers/isdn/gigaset/bas-gigaset.c | 89 |
1 files changed, 36 insertions, 53 deletions
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 707d9c94cf9e..131976d880d0 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -438,23 +438,27 @@ static void cmd_in_timeout(unsigned long data) | |||
438 | return; | 438 | return; |
439 | } | 439 | } |
440 | 440 | ||
441 | if (ucs->retry_cmd_in++ < BAS_RETRY) { | 441 | if (ucs->retry_cmd_in++ >= BAS_RETRY) { |
442 | dev_notice(cs->dev, "control read: timeout, retry %d\n", | ||
443 | ucs->retry_cmd_in); | ||
444 | rc = atread_submit(cs, BAS_TIMEOUT); | ||
445 | if (rc >= 0 || rc == -ENODEV) | ||
446 | /* resubmitted or disconnected */ | ||
447 | /* - bypass regular exit block */ | ||
448 | return; | ||
449 | } else { | ||
450 | dev_err(cs->dev, | 442 | dev_err(cs->dev, |
451 | "control read: timeout, giving up after %d tries\n", | 443 | "control read: timeout, giving up after %d tries\n", |
452 | ucs->retry_cmd_in); | 444 | ucs->retry_cmd_in); |
445 | kfree(ucs->rcvbuf); | ||
446 | ucs->rcvbuf = NULL; | ||
447 | ucs->rcvbuf_size = 0; | ||
448 | error_reset(cs); | ||
449 | return; | ||
450 | } | ||
451 | |||
452 | gig_dbg(DEBUG_USBREQ, "%s: timeout, retry %d", | ||
453 | __func__, ucs->retry_cmd_in); | ||
454 | rc = atread_submit(cs, BAS_TIMEOUT); | ||
455 | if (rc < 0) { | ||
456 | kfree(ucs->rcvbuf); | ||
457 | ucs->rcvbuf = NULL; | ||
458 | ucs->rcvbuf_size = 0; | ||
459 | if (rc != -ENODEV) | ||
460 | error_reset(cs); | ||
453 | } | 461 | } |
454 | kfree(ucs->rcvbuf); | ||
455 | ucs->rcvbuf = NULL; | ||
456 | ucs->rcvbuf_size = 0; | ||
457 | error_reset(cs); | ||
458 | } | 462 | } |
459 | 463 | ||
460 | /* read_ctrl_callback | 464 | /* read_ctrl_callback |
@@ -470,18 +474,11 @@ static void read_ctrl_callback(struct urb *urb) | |||
470 | struct cardstate *cs = inbuf->cs; | 474 | struct cardstate *cs = inbuf->cs; |
471 | struct bas_cardstate *ucs = cs->hw.bas; | 475 | struct bas_cardstate *ucs = cs->hw.bas; |
472 | int status = urb->status; | 476 | int status = urb->status; |
473 | int have_data = 0; | ||
474 | unsigned numbytes; | 477 | unsigned numbytes; |
475 | int rc; | 478 | int rc; |
476 | 479 | ||
477 | update_basstate(ucs, 0, BS_ATRDPEND); | 480 | update_basstate(ucs, 0, BS_ATRDPEND); |
478 | wake_up(&ucs->waitqueue); | 481 | wake_up(&ucs->waitqueue); |
479 | |||
480 | if (!ucs->rcvbuf_size) { | ||
481 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); | ||
482 | return; | ||
483 | } | ||
484 | |||
485 | del_timer(&ucs->timer_cmd_in); | 482 | del_timer(&ucs->timer_cmd_in); |
486 | 483 | ||
487 | switch (status) { | 484 | switch (status) { |
@@ -495,19 +492,10 @@ static void read_ctrl_callback(struct urb *urb) | |||
495 | numbytes = ucs->rcvbuf_size; | 492 | numbytes = ucs->rcvbuf_size; |
496 | } | 493 | } |
497 | 494 | ||
498 | /* copy received bytes to inbuf */ | 495 | /* copy received bytes to inbuf, notify event layer */ |
499 | have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes); | 496 | if (gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes)) { |
500 | 497 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); | |
501 | if (unlikely(numbytes < ucs->rcvbuf_size)) { | 498 | gigaset_schedule_event(cs); |
502 | /* incomplete - resubmit for remaining bytes */ | ||
503 | ucs->rcvbuf_size -= numbytes; | ||
504 | ucs->retry_cmd_in = 0; | ||
505 | rc = atread_submit(cs, BAS_TIMEOUT); | ||
506 | if (rc >= 0 || rc == -ENODEV) | ||
507 | /* resubmitted or disconnected */ | ||
508 | /* - bypass regular exit block */ | ||
509 | return; | ||
510 | error_reset(cs); | ||
511 | } | 499 | } |
512 | break; | 500 | break; |
513 | 501 | ||
@@ -516,37 +504,32 @@ static void read_ctrl_callback(struct urb *urb) | |||
516 | case -EINPROGRESS: /* pending */ | 504 | case -EINPROGRESS: /* pending */ |
517 | case -ENODEV: /* device removed */ | 505 | case -ENODEV: /* device removed */ |
518 | case -ESHUTDOWN: /* device shut down */ | 506 | case -ESHUTDOWN: /* device shut down */ |
519 | /* no action necessary */ | 507 | /* no further action necessary */ |
520 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 508 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
521 | __func__, get_usb_statmsg(status)); | 509 | __func__, get_usb_statmsg(status)); |
522 | break; | 510 | break; |
523 | 511 | ||
524 | default: /* severe trouble */ | 512 | default: /* other errors: retry */ |
525 | dev_warn(cs->dev, "control read: %s\n", | ||
526 | get_usb_statmsg(status)); | ||
527 | if (ucs->retry_cmd_in++ < BAS_RETRY) { | 513 | if (ucs->retry_cmd_in++ < BAS_RETRY) { |
528 | dev_notice(cs->dev, "control read: retry %d\n", | 514 | gig_dbg(DEBUG_USBREQ, "%s: %s, retry %d", __func__, |
529 | ucs->retry_cmd_in); | 515 | get_usb_statmsg(status), ucs->retry_cmd_in); |
530 | rc = atread_submit(cs, BAS_TIMEOUT); | 516 | rc = atread_submit(cs, BAS_TIMEOUT); |
531 | if (rc >= 0 || rc == -ENODEV) | 517 | if (rc >= 0) |
532 | /* resubmitted or disconnected */ | 518 | /* successfully resubmitted, skip freeing */ |
533 | /* - bypass regular exit block */ | ||
534 | return; | 519 | return; |
535 | } else { | 520 | if (rc == -ENODEV) |
536 | dev_err(cs->dev, | 521 | /* disconnect, no further action necessary */ |
537 | "control read: giving up after %d tries\n", | 522 | break; |
538 | ucs->retry_cmd_in); | ||
539 | } | 523 | } |
524 | dev_err(cs->dev, "control read: %s, giving up after %d tries\n", | ||
525 | get_usb_statmsg(status), ucs->retry_cmd_in); | ||
540 | error_reset(cs); | 526 | error_reset(cs); |
541 | } | 527 | } |
542 | 528 | ||
529 | /* read finished, free buffer */ | ||
543 | kfree(ucs->rcvbuf); | 530 | kfree(ucs->rcvbuf); |
544 | ucs->rcvbuf = NULL; | 531 | ucs->rcvbuf = NULL; |
545 | ucs->rcvbuf_size = 0; | 532 | ucs->rcvbuf_size = 0; |
546 | if (have_data) { | ||
547 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); | ||
548 | gigaset_schedule_event(cs); | ||
549 | } | ||
550 | } | 533 | } |
551 | 534 | ||
552 | /* atread_submit | 535 | /* atread_submit |
@@ -1598,13 +1581,13 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1598 | 1581 | ||
1599 | ret = starturbs(bcs); | 1582 | ret = starturbs(bcs); |
1600 | if (ret < 0) { | 1583 | if (ret < 0) { |
1584 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1601 | dev_err(cs->dev, | 1585 | dev_err(cs->dev, |
1602 | "could not start isochronous I/O for channel B%d: %s\n", | 1586 | "could not start isochronous I/O for channel B%d: %s\n", |
1603 | bcs->channel + 1, | 1587 | bcs->channel + 1, |
1604 | ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); | 1588 | ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); |
1605 | if (ret != -ENODEV) | 1589 | if (ret != -ENODEV) |
1606 | error_hangup(bcs); | 1590 | error_hangup(bcs); |
1607 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1608 | return ret; | 1591 | return ret; |
1609 | } | 1592 | } |
1610 | 1593 | ||
@@ -1614,11 +1597,11 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1614 | dev_err(cs->dev, "could not open channel B%d\n", | 1597 | dev_err(cs->dev, "could not open channel B%d\n", |
1615 | bcs->channel + 1); | 1598 | bcs->channel + 1); |
1616 | stopurbs(bcs->hw.bas); | 1599 | stopurbs(bcs->hw.bas); |
1617 | if (ret != -ENODEV) | ||
1618 | error_hangup(bcs); | ||
1619 | } | 1600 | } |
1620 | 1601 | ||
1621 | spin_unlock_irqrestore(&cs->lock, flags); | 1602 | spin_unlock_irqrestore(&cs->lock, flags); |
1603 | if (ret < 0 && ret != -ENODEV) | ||
1604 | error_hangup(bcs); | ||
1622 | return ret; | 1605 | return ret; |
1623 | } | 1606 | } |
1624 | 1607 | ||