aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/gigaset/bas-gigaset.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/gigaset/bas-gigaset.c')
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c89
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