diff options
Diffstat (limited to 'drivers/isdn/gigaset/bas-gigaset.c')
-rw-r--r-- | drivers/isdn/gigaset/bas-gigaset.c | 423 |
1 files changed, 296 insertions, 127 deletions
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index af7648274b38..5255b5e20e13 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -73,6 +73,14 @@ static int gigaset_probe(struct usb_interface *interface, | |||
73 | /* Function will be called if the device is unplugged */ | 73 | /* Function will be called if the device is unplugged */ |
74 | static void gigaset_disconnect(struct usb_interface *interface); | 74 | static void gigaset_disconnect(struct usb_interface *interface); |
75 | 75 | ||
76 | /* functions called before/after suspend */ | ||
77 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); | ||
78 | static int gigaset_resume(struct usb_interface *intf); | ||
79 | |||
80 | /* functions called before/after device reset */ | ||
81 | static int gigaset_pre_reset(struct usb_interface *intf); | ||
82 | static int gigaset_post_reset(struct usb_interface *intf); | ||
83 | |||
76 | static int atread_submit(struct cardstate *, int); | 84 | static int atread_submit(struct cardstate *, int); |
77 | static void stopurbs(struct bas_bc_state *); | 85 | static void stopurbs(struct bas_bc_state *); |
78 | static int req_submit(struct bc_state *, int, int, int); | 86 | static int req_submit(struct bc_state *, int, int, int); |
@@ -105,8 +113,9 @@ struct bas_cardstate { | |||
105 | unsigned char int_in_buf[3]; | 113 | unsigned char int_in_buf[3]; |
106 | 114 | ||
107 | spinlock_t lock; /* locks all following */ | 115 | spinlock_t lock; /* locks all following */ |
108 | atomic_t basstate; /* bitmap (BS_*) */ | 116 | int basstate; /* bitmap (BS_*) */ |
109 | int pending; /* uncompleted base request */ | 117 | int pending; /* uncompleted base request */ |
118 | wait_queue_head_t waitqueue; | ||
110 | int rcvbuf_size; /* size of AT receive buffer */ | 119 | int rcvbuf_size; /* size of AT receive buffer */ |
111 | /* 0: no receive in progress */ | 120 | /* 0: no receive in progress */ |
112 | int retry_cmd_in; /* receive req retry count */ | 121 | int retry_cmd_in; /* receive req retry count */ |
@@ -121,10 +130,10 @@ struct bas_cardstate { | |||
121 | #define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ | 130 | #define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ |
122 | #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ | 131 | #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ |
123 | #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ | 132 | #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ |
133 | #define BS_SUSPEND 0x100 /* USB port suspended */ | ||
124 | 134 | ||
125 | 135 | ||
126 | static struct gigaset_driver *driver = NULL; | 136 | static struct gigaset_driver *driver = NULL; |
127 | static struct cardstate *cardstate = NULL; | ||
128 | 137 | ||
129 | /* usb specific object needed to register this driver with the usb subsystem */ | 138 | /* usb specific object needed to register this driver with the usb subsystem */ |
130 | static struct usb_driver gigaset_usb_driver = { | 139 | static struct usb_driver gigaset_usb_driver = { |
@@ -132,6 +141,11 @@ static struct usb_driver gigaset_usb_driver = { | |||
132 | .probe = gigaset_probe, | 141 | .probe = gigaset_probe, |
133 | .disconnect = gigaset_disconnect, | 142 | .disconnect = gigaset_disconnect, |
134 | .id_table = gigaset_table, | 143 | .id_table = gigaset_table, |
144 | .suspend = gigaset_suspend, | ||
145 | .resume = gigaset_resume, | ||
146 | .reset_resume = gigaset_post_reset, | ||
147 | .pre_reset = gigaset_pre_reset, | ||
148 | .post_reset = gigaset_post_reset, | ||
135 | }; | 149 | }; |
136 | 150 | ||
137 | /* get message text for usb_submit_urb return code | 151 | /* get message text for usb_submit_urb return code |
@@ -248,12 +262,12 @@ static inline void dump_urb(enum debuglevel level, const char *tag, | |||
248 | if (urb) { | 262 | if (urb) { |
249 | gig_dbg(level, | 263 | gig_dbg(level, |
250 | " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " | 264 | " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " |
251 | "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,", | 265 | "hcpriv=0x%08lx, transfer_flags=0x%x,", |
252 | (unsigned long) urb->dev, | 266 | (unsigned long) urb->dev, |
253 | usb_pipetype_str(urb->pipe), | 267 | usb_pipetype_str(urb->pipe), |
254 | usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), | 268 | usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), |
255 | usb_pipein(urb->pipe) ? "in" : "out", | 269 | usb_pipein(urb->pipe) ? "in" : "out", |
256 | urb->status, (unsigned long) urb->hcpriv, | 270 | (unsigned long) urb->hcpriv, |
257 | urb->transfer_flags); | 271 | urb->transfer_flags); |
258 | gig_dbg(level, | 272 | gig_dbg(level, |
259 | " transfer_buffer=0x%08lx[%d], actual_length=%d, " | 273 | " transfer_buffer=0x%08lx[%d], actual_length=%d, " |
@@ -355,27 +369,27 @@ static void check_pending(struct bas_cardstate *ucs) | |||
355 | case 0: | 369 | case 0: |
356 | break; | 370 | break; |
357 | case HD_OPEN_ATCHANNEL: | 371 | case HD_OPEN_ATCHANNEL: |
358 | if (atomic_read(&ucs->basstate) & BS_ATOPEN) | 372 | if (ucs->basstate & BS_ATOPEN) |
359 | ucs->pending = 0; | 373 | ucs->pending = 0; |
360 | break; | 374 | break; |
361 | case HD_OPEN_B1CHANNEL: | 375 | case HD_OPEN_B1CHANNEL: |
362 | if (atomic_read(&ucs->basstate) & BS_B1OPEN) | 376 | if (ucs->basstate & BS_B1OPEN) |
363 | ucs->pending = 0; | 377 | ucs->pending = 0; |
364 | break; | 378 | break; |
365 | case HD_OPEN_B2CHANNEL: | 379 | case HD_OPEN_B2CHANNEL: |
366 | if (atomic_read(&ucs->basstate) & BS_B2OPEN) | 380 | if (ucs->basstate & BS_B2OPEN) |
367 | ucs->pending = 0; | 381 | ucs->pending = 0; |
368 | break; | 382 | break; |
369 | case HD_CLOSE_ATCHANNEL: | 383 | case HD_CLOSE_ATCHANNEL: |
370 | if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) | 384 | if (!(ucs->basstate & BS_ATOPEN)) |
371 | ucs->pending = 0; | 385 | ucs->pending = 0; |
372 | break; | 386 | break; |
373 | case HD_CLOSE_B1CHANNEL: | 387 | case HD_CLOSE_B1CHANNEL: |
374 | if (!(atomic_read(&ucs->basstate) & BS_B1OPEN)) | 388 | if (!(ucs->basstate & BS_B1OPEN)) |
375 | ucs->pending = 0; | 389 | ucs->pending = 0; |
376 | break; | 390 | break; |
377 | case HD_CLOSE_B2CHANNEL: | 391 | case HD_CLOSE_B2CHANNEL: |
378 | if (!(atomic_read(&ucs->basstate) & BS_B2OPEN)) | 392 | if (!(ucs->basstate & BS_B2OPEN)) |
379 | ucs->pending = 0; | 393 | ucs->pending = 0; |
380 | break; | 394 | break; |
381 | case HD_DEVICE_INIT_ACK: /* no reply expected */ | 395 | case HD_DEVICE_INIT_ACK: /* no reply expected */ |
@@ -441,8 +455,8 @@ inline static int update_basstate(struct bas_cardstate *ucs, | |||
441 | int state; | 455 | int state; |
442 | 456 | ||
443 | spin_lock_irqsave(&ucs->lock, flags); | 457 | spin_lock_irqsave(&ucs->lock, flags); |
444 | state = atomic_read(&ucs->basstate); | 458 | state = ucs->basstate; |
445 | atomic_set(&ucs->basstate, (state & ~clear) | set); | 459 | ucs->basstate = (state & ~clear) | set; |
446 | spin_unlock_irqrestore(&ucs->lock, flags); | 460 | spin_unlock_irqrestore(&ucs->lock, flags); |
447 | return state; | 461 | return state; |
448 | } | 462 | } |
@@ -459,11 +473,13 @@ static void read_ctrl_callback(struct urb *urb) | |||
459 | struct inbuf_t *inbuf = urb->context; | 473 | struct inbuf_t *inbuf = urb->context; |
460 | struct cardstate *cs = inbuf->cs; | 474 | struct cardstate *cs = inbuf->cs; |
461 | struct bas_cardstate *ucs = cs->hw.bas; | 475 | struct bas_cardstate *ucs = cs->hw.bas; |
476 | int status = urb->status; | ||
462 | int have_data = 0; | 477 | int have_data = 0; |
463 | unsigned numbytes; | 478 | unsigned numbytes; |
464 | int rc; | 479 | int rc; |
465 | 480 | ||
466 | update_basstate(ucs, 0, BS_ATRDPEND); | 481 | update_basstate(ucs, 0, BS_ATRDPEND); |
482 | wake_up(&ucs->waitqueue); | ||
467 | 483 | ||
468 | if (!ucs->rcvbuf_size) { | 484 | if (!ucs->rcvbuf_size) { |
469 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); | 485 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); |
@@ -472,7 +488,7 @@ static void read_ctrl_callback(struct urb *urb) | |||
472 | 488 | ||
473 | del_timer(&ucs->timer_cmd_in); | 489 | del_timer(&ucs->timer_cmd_in); |
474 | 490 | ||
475 | switch (urb->status) { | 491 | switch (status) { |
476 | case 0: /* normal completion */ | 492 | case 0: /* normal completion */ |
477 | numbytes = urb->actual_length; | 493 | numbytes = urb->actual_length; |
478 | if (unlikely(numbytes != ucs->rcvbuf_size)) { | 494 | if (unlikely(numbytes != ucs->rcvbuf_size)) { |
@@ -506,12 +522,12 @@ static void read_ctrl_callback(struct urb *urb) | |||
506 | case -ESHUTDOWN: /* device shut down */ | 522 | case -ESHUTDOWN: /* device shut down */ |
507 | /* no action necessary */ | 523 | /* no action necessary */ |
508 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 524 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
509 | __func__, get_usb_statmsg(urb->status)); | 525 | __func__, get_usb_statmsg(status)); |
510 | break; | 526 | break; |
511 | 527 | ||
512 | default: /* severe trouble */ | 528 | default: /* severe trouble */ |
513 | dev_warn(cs->dev, "control read: %s\n", | 529 | dev_warn(cs->dev, "control read: %s\n", |
514 | get_usb_statmsg(urb->status)); | 530 | get_usb_statmsg(status)); |
515 | if (ucs->retry_cmd_in++ < BAS_RETRY) { | 531 | if (ucs->retry_cmd_in++ < BAS_RETRY) { |
516 | dev_notice(cs->dev, "control read: retry %d\n", | 532 | dev_notice(cs->dev, "control read: retry %d\n", |
517 | ucs->retry_cmd_in); | 533 | ucs->retry_cmd_in); |
@@ -550,17 +566,28 @@ static void read_ctrl_callback(struct urb *urb) | |||
550 | static int atread_submit(struct cardstate *cs, int timeout) | 566 | static int atread_submit(struct cardstate *cs, int timeout) |
551 | { | 567 | { |
552 | struct bas_cardstate *ucs = cs->hw.bas; | 568 | struct bas_cardstate *ucs = cs->hw.bas; |
569 | int basstate; | ||
553 | int ret; | 570 | int ret; |
554 | 571 | ||
555 | gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", | 572 | gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", |
556 | ucs->rcvbuf_size); | 573 | ucs->rcvbuf_size); |
557 | 574 | ||
558 | if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) { | 575 | basstate = update_basstate(ucs, BS_ATRDPEND, 0); |
576 | if (basstate & BS_ATRDPEND) { | ||
559 | dev_err(cs->dev, | 577 | dev_err(cs->dev, |
560 | "could not submit HD_READ_ATMESSAGE: URB busy\n"); | 578 | "could not submit HD_READ_ATMESSAGE: URB busy\n"); |
561 | return -EBUSY; | 579 | return -EBUSY; |
562 | } | 580 | } |
563 | 581 | ||
582 | if (basstate & BS_SUSPEND) { | ||
583 | dev_notice(cs->dev, | ||
584 | "HD_READ_ATMESSAGE not submitted, " | ||
585 | "suspend in progress\n"); | ||
586 | update_basstate(ucs, 0, BS_ATRDPEND); | ||
587 | /* treat like disconnect */ | ||
588 | return -ENODEV; | ||
589 | } | ||
590 | |||
564 | ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ; | 591 | ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ; |
565 | ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE; | 592 | ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE; |
566 | ucs->dr_cmd_in.wValue = 0; | 593 | ucs->dr_cmd_in.wValue = 0; |
@@ -601,12 +628,13 @@ static void read_int_callback(struct urb *urb) | |||
601 | struct cardstate *cs = urb->context; | 628 | struct cardstate *cs = urb->context; |
602 | struct bas_cardstate *ucs = cs->hw.bas; | 629 | struct bas_cardstate *ucs = cs->hw.bas; |
603 | struct bc_state *bcs; | 630 | struct bc_state *bcs; |
631 | int status = urb->status; | ||
604 | unsigned long flags; | 632 | unsigned long flags; |
605 | int rc; | 633 | int rc; |
606 | unsigned l; | 634 | unsigned l; |
607 | int channel; | 635 | int channel; |
608 | 636 | ||
609 | switch (urb->status) { | 637 | switch (status) { |
610 | case 0: /* success */ | 638 | case 0: /* success */ |
611 | break; | 639 | break; |
612 | case -ENOENT: /* cancelled */ | 640 | case -ENOENT: /* cancelled */ |
@@ -614,7 +642,7 @@ static void read_int_callback(struct urb *urb) | |||
614 | case -EINPROGRESS: /* pending */ | 642 | case -EINPROGRESS: /* pending */ |
615 | /* ignore silently */ | 643 | /* ignore silently */ |
616 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 644 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
617 | __func__, get_usb_statmsg(urb->status)); | 645 | __func__, get_usb_statmsg(status)); |
618 | return; | 646 | return; |
619 | case -ENODEV: /* device removed */ | 647 | case -ENODEV: /* device removed */ |
620 | case -ESHUTDOWN: /* device shut down */ | 648 | case -ESHUTDOWN: /* device shut down */ |
@@ -623,7 +651,7 @@ static void read_int_callback(struct urb *urb) | |||
623 | return; | 651 | return; |
624 | default: /* severe trouble */ | 652 | default: /* severe trouble */ |
625 | dev_warn(cs->dev, "interrupt read: %s\n", | 653 | dev_warn(cs->dev, "interrupt read: %s\n", |
626 | get_usb_statmsg(urb->status)); | 654 | get_usb_statmsg(status)); |
627 | //FIXME corrective action? resubmission always ok? | 655 | //FIXME corrective action? resubmission always ok? |
628 | goto resubmit; | 656 | goto resubmit; |
629 | } | 657 | } |
@@ -745,6 +773,7 @@ static void read_int_callback(struct urb *urb) | |||
745 | } | 773 | } |
746 | 774 | ||
747 | check_pending(ucs); | 775 | check_pending(ucs); |
776 | wake_up(&ucs->waitqueue); | ||
748 | 777 | ||
749 | resubmit: | 778 | resubmit: |
750 | rc = usb_submit_urb(urb, GFP_ATOMIC); | 779 | rc = usb_submit_urb(urb, GFP_ATOMIC); |
@@ -766,17 +795,18 @@ static void read_iso_callback(struct urb *urb) | |||
766 | { | 795 | { |
767 | struct bc_state *bcs; | 796 | struct bc_state *bcs; |
768 | struct bas_bc_state *ubc; | 797 | struct bas_bc_state *ubc; |
798 | int status = urb->status; | ||
769 | unsigned long flags; | 799 | unsigned long flags; |
770 | int i, rc; | 800 | int i, rc; |
771 | 801 | ||
772 | /* status codes not worth bothering the tasklet with */ | 802 | /* status codes not worth bothering the tasklet with */ |
773 | if (unlikely(urb->status == -ENOENT || | 803 | if (unlikely(status == -ENOENT || |
774 | urb->status == -ECONNRESET || | 804 | status == -ECONNRESET || |
775 | urb->status == -EINPROGRESS || | 805 | status == -EINPROGRESS || |
776 | urb->status == -ENODEV || | 806 | status == -ENODEV || |
777 | urb->status == -ESHUTDOWN)) { | 807 | status == -ESHUTDOWN)) { |
778 | gig_dbg(DEBUG_ISO, "%s: %s", | 808 | gig_dbg(DEBUG_ISO, "%s: %s", |
779 | __func__, get_usb_statmsg(urb->status)); | 809 | __func__, get_usb_statmsg(status)); |
780 | return; | 810 | return; |
781 | } | 811 | } |
782 | 812 | ||
@@ -787,10 +817,11 @@ static void read_iso_callback(struct urb *urb) | |||
787 | if (likely(ubc->isoindone == NULL)) { | 817 | if (likely(ubc->isoindone == NULL)) { |
788 | /* pass URB to tasklet */ | 818 | /* pass URB to tasklet */ |
789 | ubc->isoindone = urb; | 819 | ubc->isoindone = urb; |
820 | ubc->isoinstatus = status; | ||
790 | tasklet_schedule(&ubc->rcvd_tasklet); | 821 | tasklet_schedule(&ubc->rcvd_tasklet); |
791 | } else { | 822 | } else { |
792 | /* tasklet still busy, drop data and resubmit URB */ | 823 | /* tasklet still busy, drop data and resubmit URB */ |
793 | ubc->loststatus = urb->status; | 824 | ubc->loststatus = status; |
794 | for (i = 0; i < BAS_NUMFRAMES; i++) { | 825 | for (i = 0; i < BAS_NUMFRAMES; i++) { |
795 | ubc->isoinlost += urb->iso_frame_desc[i].actual_length; | 826 | ubc->isoinlost += urb->iso_frame_desc[i].actual_length; |
796 | if (unlikely(urb->iso_frame_desc[i].status != 0 && | 827 | if (unlikely(urb->iso_frame_desc[i].status != 0 && |
@@ -800,7 +831,7 @@ static void read_iso_callback(struct urb *urb) | |||
800 | urb->iso_frame_desc[i].status = 0; | 831 | urb->iso_frame_desc[i].status = 0; |
801 | urb->iso_frame_desc[i].actual_length = 0; | 832 | urb->iso_frame_desc[i].actual_length = 0; |
802 | } | 833 | } |
803 | if (likely(atomic_read(&ubc->running))) { | 834 | if (likely(ubc->running)) { |
804 | /* urb->dev is clobbered by USB subsystem */ | 835 | /* urb->dev is clobbered by USB subsystem */ |
805 | urb->dev = bcs->cs->hw.bas->udev; | 836 | urb->dev = bcs->cs->hw.bas->udev; |
806 | urb->transfer_flags = URB_ISO_ASAP; | 837 | urb->transfer_flags = URB_ISO_ASAP; |
@@ -831,22 +862,24 @@ static void write_iso_callback(struct urb *urb) | |||
831 | { | 862 | { |
832 | struct isow_urbctx_t *ucx; | 863 | struct isow_urbctx_t *ucx; |
833 | struct bas_bc_state *ubc; | 864 | struct bas_bc_state *ubc; |
865 | int status = urb->status; | ||
834 | unsigned long flags; | 866 | unsigned long flags; |
835 | 867 | ||
836 | /* status codes not worth bothering the tasklet with */ | 868 | /* status codes not worth bothering the tasklet with */ |
837 | if (unlikely(urb->status == -ENOENT || | 869 | if (unlikely(status == -ENOENT || |
838 | urb->status == -ECONNRESET || | 870 | status == -ECONNRESET || |
839 | urb->status == -EINPROGRESS || | 871 | status == -EINPROGRESS || |
840 | urb->status == -ENODEV || | 872 | status == -ENODEV || |
841 | urb->status == -ESHUTDOWN)) { | 873 | status == -ESHUTDOWN)) { |
842 | gig_dbg(DEBUG_ISO, "%s: %s", | 874 | gig_dbg(DEBUG_ISO, "%s: %s", |
843 | __func__, get_usb_statmsg(urb->status)); | 875 | __func__, get_usb_statmsg(status)); |
844 | return; | 876 | return; |
845 | } | 877 | } |
846 | 878 | ||
847 | /* pass URB context to tasklet */ | 879 | /* pass URB context to tasklet */ |
848 | ucx = urb->context; | 880 | ucx = urb->context; |
849 | ubc = ucx->bcs->hw.bas; | 881 | ubc = ucx->bcs->hw.bas; |
882 | ucx->status = status; | ||
850 | 883 | ||
851 | spin_lock_irqsave(&ubc->isooutlock, flags); | 884 | spin_lock_irqsave(&ubc->isooutlock, flags); |
852 | ubc->isooutovfl = ubc->isooutdone; | 885 | ubc->isooutovfl = ubc->isooutdone; |
@@ -875,7 +908,7 @@ static int starturbs(struct bc_state *bcs) | |||
875 | bcs->inputstate |= INS_flag_hunt; | 908 | bcs->inputstate |= INS_flag_hunt; |
876 | 909 | ||
877 | /* submit all isochronous input URBs */ | 910 | /* submit all isochronous input URBs */ |
878 | atomic_set(&ubc->running, 1); | 911 | ubc->running = 1; |
879 | for (k = 0; k < BAS_INURBS; k++) { | 912 | for (k = 0; k < BAS_INURBS; k++) { |
880 | urb = ubc->isoinurbs[k]; | 913 | urb = ubc->isoinurbs[k]; |
881 | if (!urb) { | 914 | if (!urb) { |
@@ -932,15 +965,15 @@ static int starturbs(struct bc_state *bcs) | |||
932 | ubc->isoouturbs[k].limit = -1; | 965 | ubc->isoouturbs[k].limit = -1; |
933 | } | 966 | } |
934 | 967 | ||
935 | /* submit two URBs, keep third one */ | 968 | /* keep one URB free, submit the others */ |
936 | for (k = 0; k < 2; ++k) { | 969 | for (k = 0; k < BAS_OUTURBS-1; ++k) { |
937 | dump_urb(DEBUG_ISO, "Initial isoc write", urb); | 970 | dump_urb(DEBUG_ISO, "Initial isoc write", urb); |
938 | rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC); | 971 | rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC); |
939 | if (rc != 0) | 972 | if (rc != 0) |
940 | goto error; | 973 | goto error; |
941 | } | 974 | } |
942 | dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); | 975 | dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); |
943 | ubc->isooutfree = &ubc->isoouturbs[2]; | 976 | ubc->isooutfree = &ubc->isoouturbs[BAS_OUTURBS-1]; |
944 | ubc->isooutdone = ubc->isooutovfl = NULL; | 977 | ubc->isooutdone = ubc->isooutovfl = NULL; |
945 | return 0; | 978 | return 0; |
946 | error: | 979 | error: |
@@ -958,7 +991,7 @@ static void stopurbs(struct bas_bc_state *ubc) | |||
958 | { | 991 | { |
959 | int k, rc; | 992 | int k, rc; |
960 | 993 | ||
961 | atomic_set(&ubc->running, 0); | 994 | ubc->running = 0; |
962 | 995 | ||
963 | for (k = 0; k < BAS_INURBS; ++k) { | 996 | for (k = 0; k < BAS_INURBS; ++k) { |
964 | rc = usb_unlink_urb(ubc->isoinurbs[k]); | 997 | rc = usb_unlink_urb(ubc->isoinurbs[k]); |
@@ -1034,7 +1067,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
1034 | } | 1067 | } |
1035 | break; | 1068 | break; |
1036 | } | 1069 | } |
1037 | ucx->limit = atomic_read(&ubc->isooutbuf->nextread); | 1070 | ucx->limit = ubc->isooutbuf->nextread; |
1038 | ifd->status = 0; | 1071 | ifd->status = 0; |
1039 | ifd->actual_length = 0; | 1072 | ifd->actual_length = 0; |
1040 | } | 1073 | } |
@@ -1070,6 +1103,7 @@ static void write_iso_tasklet(unsigned long data) | |||
1070 | struct cardstate *cs = bcs->cs; | 1103 | struct cardstate *cs = bcs->cs; |
1071 | struct isow_urbctx_t *done, *next, *ovfl; | 1104 | struct isow_urbctx_t *done, *next, *ovfl; |
1072 | struct urb *urb; | 1105 | struct urb *urb; |
1106 | int status; | ||
1073 | struct usb_iso_packet_descriptor *ifd; | 1107 | struct usb_iso_packet_descriptor *ifd; |
1074 | int offset; | 1108 | int offset; |
1075 | unsigned long flags; | 1109 | unsigned long flags; |
@@ -1080,7 +1114,7 @@ static void write_iso_tasklet(unsigned long data) | |||
1080 | 1114 | ||
1081 | /* loop while completed URBs arrive in time */ | 1115 | /* loop while completed URBs arrive in time */ |
1082 | for (;;) { | 1116 | for (;;) { |
1083 | if (unlikely(!(atomic_read(&ubc->running)))) { | 1117 | if (unlikely(!(ubc->running))) { |
1084 | gig_dbg(DEBUG_ISO, "%s: not running", __func__); | 1118 | gig_dbg(DEBUG_ISO, "%s: not running", __func__); |
1085 | return; | 1119 | return; |
1086 | } | 1120 | } |
@@ -1126,7 +1160,8 @@ static void write_iso_tasklet(unsigned long data) | |||
1126 | 1160 | ||
1127 | /* process completed URB */ | 1161 | /* process completed URB */ |
1128 | urb = done->urb; | 1162 | urb = done->urb; |
1129 | switch (urb->status) { | 1163 | status = done->status; |
1164 | switch (status) { | ||
1130 | case -EXDEV: /* partial completion */ | 1165 | case -EXDEV: /* partial completion */ |
1131 | gig_dbg(DEBUG_ISO, "%s: URB partially completed", | 1166 | gig_dbg(DEBUG_ISO, "%s: URB partially completed", |
1132 | __func__); | 1167 | __func__); |
@@ -1179,12 +1214,12 @@ static void write_iso_tasklet(unsigned long data) | |||
1179 | break; | 1214 | break; |
1180 | default: /* severe trouble */ | 1215 | default: /* severe trouble */ |
1181 | dev_warn(cs->dev, "isochronous write: %s\n", | 1216 | dev_warn(cs->dev, "isochronous write: %s\n", |
1182 | get_usb_statmsg(urb->status)); | 1217 | get_usb_statmsg(status)); |
1183 | } | 1218 | } |
1184 | 1219 | ||
1185 | /* mark the write buffer area covered by this URB as free */ | 1220 | /* mark the write buffer area covered by this URB as free */ |
1186 | if (done->limit >= 0) | 1221 | if (done->limit >= 0) |
1187 | atomic_set(&ubc->isooutbuf->read, done->limit); | 1222 | ubc->isooutbuf->read = done->limit; |
1188 | 1223 | ||
1189 | /* mark URB as free */ | 1224 | /* mark URB as free */ |
1190 | spin_lock_irqsave(&ubc->isooutlock, flags); | 1225 | spin_lock_irqsave(&ubc->isooutlock, flags); |
@@ -1233,6 +1268,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1233 | struct bas_bc_state *ubc = bcs->hw.bas; | 1268 | struct bas_bc_state *ubc = bcs->hw.bas; |
1234 | struct cardstate *cs = bcs->cs; | 1269 | struct cardstate *cs = bcs->cs; |
1235 | struct urb *urb; | 1270 | struct urb *urb; |
1271 | int status; | ||
1236 | char *rcvbuf; | 1272 | char *rcvbuf; |
1237 | unsigned long flags; | 1273 | unsigned long flags; |
1238 | int totleft, numbytes, offset, frame, rc; | 1274 | int totleft, numbytes, offset, frame, rc; |
@@ -1245,6 +1281,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1245 | spin_unlock_irqrestore(&ubc->isoinlock, flags); | 1281 | spin_unlock_irqrestore(&ubc->isoinlock, flags); |
1246 | return; | 1282 | return; |
1247 | } | 1283 | } |
1284 | status = ubc->isoinstatus; | ||
1248 | ubc->isoindone = NULL; | 1285 | ubc->isoindone = NULL; |
1249 | if (unlikely(ubc->loststatus != -EINPROGRESS)) { | 1286 | if (unlikely(ubc->loststatus != -EINPROGRESS)) { |
1250 | dev_warn(cs->dev, | 1287 | dev_warn(cs->dev, |
@@ -1256,15 +1293,15 @@ static void read_iso_tasklet(unsigned long data) | |||
1256 | } | 1293 | } |
1257 | spin_unlock_irqrestore(&ubc->isoinlock, flags); | 1294 | spin_unlock_irqrestore(&ubc->isoinlock, flags); |
1258 | 1295 | ||
1259 | if (unlikely(!(atomic_read(&ubc->running)))) { | 1296 | if (unlikely(!(ubc->running))) { |
1260 | gig_dbg(DEBUG_ISO, | 1297 | gig_dbg(DEBUG_ISO, |
1261 | "%s: channel not running, " | 1298 | "%s: channel not running, " |
1262 | "dropped URB with status: %s", | 1299 | "dropped URB with status: %s", |
1263 | __func__, get_usb_statmsg(urb->status)); | 1300 | __func__, get_usb_statmsg(status)); |
1264 | return; | 1301 | return; |
1265 | } | 1302 | } |
1266 | 1303 | ||
1267 | switch (urb->status) { | 1304 | switch (status) { |
1268 | case 0: /* normal completion */ | 1305 | case 0: /* normal completion */ |
1269 | break; | 1306 | break; |
1270 | case -EXDEV: /* inspect individual frames | 1307 | case -EXDEV: /* inspect individual frames |
@@ -1276,7 +1313,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1276 | case -ECONNRESET: | 1313 | case -ECONNRESET: |
1277 | case -EINPROGRESS: | 1314 | case -EINPROGRESS: |
1278 | gig_dbg(DEBUG_ISO, "%s: %s", | 1315 | gig_dbg(DEBUG_ISO, "%s: %s", |
1279 | __func__, get_usb_statmsg(urb->status)); | 1316 | __func__, get_usb_statmsg(status)); |
1280 | continue; /* -> skip */ | 1317 | continue; /* -> skip */ |
1281 | case -EPIPE: | 1318 | case -EPIPE: |
1282 | dev_err(cs->dev, "isochronous read stalled\n"); | 1319 | dev_err(cs->dev, "isochronous read stalled\n"); |
@@ -1284,7 +1321,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1284 | continue; /* -> skip */ | 1321 | continue; /* -> skip */ |
1285 | default: /* severe trouble */ | 1322 | default: /* severe trouble */ |
1286 | dev_warn(cs->dev, "isochronous read: %s\n", | 1323 | dev_warn(cs->dev, "isochronous read: %s\n", |
1287 | get_usb_statmsg(urb->status)); | 1324 | get_usb_statmsg(status)); |
1288 | goto error; | 1325 | goto error; |
1289 | } | 1326 | } |
1290 | 1327 | ||
@@ -1406,6 +1443,8 @@ static void req_timeout(unsigned long data) | |||
1406 | dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", | 1443 | dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", |
1407 | pending); | 1444 | pending); |
1408 | } | 1445 | } |
1446 | |||
1447 | wake_up(&ucs->waitqueue); | ||
1409 | } | 1448 | } |
1410 | 1449 | ||
1411 | /* write_ctrl_callback | 1450 | /* write_ctrl_callback |
@@ -1418,11 +1457,12 @@ static void req_timeout(unsigned long data) | |||
1418 | static void write_ctrl_callback(struct urb *urb) | 1457 | static void write_ctrl_callback(struct urb *urb) |
1419 | { | 1458 | { |
1420 | struct bas_cardstate *ucs = urb->context; | 1459 | struct bas_cardstate *ucs = urb->context; |
1460 | int status = urb->status; | ||
1421 | int rc; | 1461 | int rc; |
1422 | unsigned long flags; | 1462 | unsigned long flags; |
1423 | 1463 | ||
1424 | /* check status */ | 1464 | /* check status */ |
1425 | switch (urb->status) { | 1465 | switch (status) { |
1426 | case 0: /* normal completion */ | 1466 | case 0: /* normal completion */ |
1427 | spin_lock_irqsave(&ucs->lock, flags); | 1467 | spin_lock_irqsave(&ucs->lock, flags); |
1428 | switch (ucs->pending) { | 1468 | switch (ucs->pending) { |
@@ -1441,20 +1481,22 @@ static void write_ctrl_callback(struct urb *urb) | |||
1441 | case -ESHUTDOWN: /* device shut down */ | 1481 | case -ESHUTDOWN: /* device shut down */ |
1442 | /* ignore silently */ | 1482 | /* ignore silently */ |
1443 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 1483 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
1444 | __func__, get_usb_statmsg(urb->status)); | 1484 | __func__, get_usb_statmsg(status)); |
1445 | break; | 1485 | break; |
1446 | 1486 | ||
1447 | default: /* any failure */ | 1487 | default: /* any failure */ |
1448 | if (++ucs->retry_ctrl > BAS_RETRY) { | 1488 | /* don't retry if suspend requested */ |
1489 | if (++ucs->retry_ctrl > BAS_RETRY || | ||
1490 | (ucs->basstate & BS_SUSPEND)) { | ||
1449 | dev_err(&ucs->interface->dev, | 1491 | dev_err(&ucs->interface->dev, |
1450 | "control request 0x%02x failed: %s\n", | 1492 | "control request 0x%02x failed: %s\n", |
1451 | ucs->dr_ctrl.bRequest, | 1493 | ucs->dr_ctrl.bRequest, |
1452 | get_usb_statmsg(urb->status)); | 1494 | get_usb_statmsg(status)); |
1453 | break; /* give up */ | 1495 | break; /* give up */ |
1454 | } | 1496 | } |
1455 | dev_notice(&ucs->interface->dev, | 1497 | dev_notice(&ucs->interface->dev, |
1456 | "control request 0x%02x: %s, retry %d\n", | 1498 | "control request 0x%02x: %s, retry %d\n", |
1457 | ucs->dr_ctrl.bRequest, get_usb_statmsg(urb->status), | 1499 | ucs->dr_ctrl.bRequest, get_usb_statmsg(status), |
1458 | ucs->retry_ctrl); | 1500 | ucs->retry_ctrl); |
1459 | /* urb->dev is clobbered by USB subsystem */ | 1501 | /* urb->dev is clobbered by USB subsystem */ |
1460 | urb->dev = ucs->udev; | 1502 | urb->dev = ucs->udev; |
@@ -1474,6 +1516,7 @@ static void write_ctrl_callback(struct urb *urb) | |||
1474 | del_timer(&ucs->timer_ctrl); | 1516 | del_timer(&ucs->timer_ctrl); |
1475 | ucs->pending = 0; | 1517 | ucs->pending = 0; |
1476 | spin_unlock_irqrestore(&ucs->lock, flags); | 1518 | spin_unlock_irqrestore(&ucs->lock, flags); |
1519 | wake_up(&ucs->waitqueue); | ||
1477 | } | 1520 | } |
1478 | 1521 | ||
1479 | /* req_submit | 1522 | /* req_submit |
@@ -1548,37 +1591,46 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) | |||
1548 | */ | 1591 | */ |
1549 | static int gigaset_init_bchannel(struct bc_state *bcs) | 1592 | static int gigaset_init_bchannel(struct bc_state *bcs) |
1550 | { | 1593 | { |
1594 | struct cardstate *cs = bcs->cs; | ||
1551 | int req, ret; | 1595 | int req, ret; |
1552 | unsigned long flags; | 1596 | unsigned long flags; |
1553 | 1597 | ||
1554 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1598 | spin_lock_irqsave(&cs->lock, flags); |
1555 | if (unlikely(!bcs->cs->connected)) { | 1599 | if (unlikely(!cs->connected)) { |
1556 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | 1600 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); |
1557 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1601 | spin_unlock_irqrestore(&cs->lock, flags); |
1558 | return -ENODEV; | 1602 | return -ENODEV; |
1559 | } | 1603 | } |
1560 | 1604 | ||
1605 | if (cs->hw.bas->basstate & BS_SUSPEND) { | ||
1606 | dev_notice(cs->dev, | ||
1607 | "not starting isochronous I/O, " | ||
1608 | "suspend in progress\n"); | ||
1609 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1610 | return -EHOSTUNREACH; | ||
1611 | } | ||
1612 | |||
1561 | if ((ret = starturbs(bcs)) < 0) { | 1613 | if ((ret = starturbs(bcs)) < 0) { |
1562 | dev_err(bcs->cs->dev, | 1614 | dev_err(cs->dev, |
1563 | "could not start isochronous I/O for channel B%d: %s\n", | 1615 | "could not start isochronous I/O for channel B%d: %s\n", |
1564 | bcs->channel + 1, | 1616 | bcs->channel + 1, |
1565 | ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); | 1617 | ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); |
1566 | if (ret != -ENODEV) | 1618 | if (ret != -ENODEV) |
1567 | error_hangup(bcs); | 1619 | error_hangup(bcs); |
1568 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1620 | spin_unlock_irqrestore(&cs->lock, flags); |
1569 | return ret; | 1621 | return ret; |
1570 | } | 1622 | } |
1571 | 1623 | ||
1572 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; | 1624 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; |
1573 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { | 1625 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { |
1574 | dev_err(bcs->cs->dev, "could not open channel B%d\n", | 1626 | dev_err(cs->dev, "could not open channel B%d\n", |
1575 | bcs->channel + 1); | 1627 | bcs->channel + 1); |
1576 | stopurbs(bcs->hw.bas); | 1628 | stopurbs(bcs->hw.bas); |
1577 | if (ret != -ENODEV) | 1629 | if (ret != -ENODEV) |
1578 | error_hangup(bcs); | 1630 | error_hangup(bcs); |
1579 | } | 1631 | } |
1580 | 1632 | ||
1581 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1633 | spin_unlock_irqrestore(&cs->lock, flags); |
1582 | return ret; | 1634 | return ret; |
1583 | } | 1635 | } |
1584 | 1636 | ||
@@ -1594,20 +1646,20 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1594 | */ | 1646 | */ |
1595 | static int gigaset_close_bchannel(struct bc_state *bcs) | 1647 | static int gigaset_close_bchannel(struct bc_state *bcs) |
1596 | { | 1648 | { |
1649 | struct cardstate *cs = bcs->cs; | ||
1597 | int req, ret; | 1650 | int req, ret; |
1598 | unsigned long flags; | 1651 | unsigned long flags; |
1599 | 1652 | ||
1600 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1653 | spin_lock_irqsave(&cs->lock, flags); |
1601 | if (unlikely(!bcs->cs->connected)) { | 1654 | if (unlikely(!cs->connected)) { |
1602 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1655 | spin_unlock_irqrestore(&cs->lock, flags); |
1603 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | 1656 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); |
1604 | return -ENODEV; | 1657 | return -ENODEV; |
1605 | } | 1658 | } |
1606 | 1659 | ||
1607 | if (!(atomic_read(&bcs->cs->hw.bas->basstate) & | 1660 | if (!(cs->hw.bas->basstate & (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { |
1608 | (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { | ||
1609 | /* channel not running: just signal common.c */ | 1661 | /* channel not running: just signal common.c */ |
1610 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1662 | spin_unlock_irqrestore(&cs->lock, flags); |
1611 | gigaset_bchannel_down(bcs); | 1663 | gigaset_bchannel_down(bcs); |
1612 | return 0; | 1664 | return 0; |
1613 | } | 1665 | } |
@@ -1615,10 +1667,10 @@ static int gigaset_close_bchannel(struct bc_state *bcs) | |||
1615 | /* channel running: tell device to close it */ | 1667 | /* channel running: tell device to close it */ |
1616 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; | 1668 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; |
1617 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) | 1669 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) |
1618 | dev_err(bcs->cs->dev, "closing channel B%d failed\n", | 1670 | dev_err(cs->dev, "closing channel B%d failed\n", |
1619 | bcs->channel + 1); | 1671 | bcs->channel + 1); |
1620 | 1672 | ||
1621 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1673 | spin_unlock_irqrestore(&cs->lock, flags); |
1622 | return ret; | 1674 | return ret; |
1623 | } | 1675 | } |
1624 | 1676 | ||
@@ -1665,12 +1717,14 @@ static void write_command_callback(struct urb *urb) | |||
1665 | { | 1717 | { |
1666 | struct cardstate *cs = urb->context; | 1718 | struct cardstate *cs = urb->context; |
1667 | struct bas_cardstate *ucs = cs->hw.bas; | 1719 | struct bas_cardstate *ucs = cs->hw.bas; |
1720 | int status = urb->status; | ||
1668 | unsigned long flags; | 1721 | unsigned long flags; |
1669 | 1722 | ||
1670 | update_basstate(ucs, 0, BS_ATWRPEND); | 1723 | update_basstate(ucs, 0, BS_ATWRPEND); |
1724 | wake_up(&ucs->waitqueue); | ||
1671 | 1725 | ||
1672 | /* check status */ | 1726 | /* check status */ |
1673 | switch (urb->status) { | 1727 | switch (status) { |
1674 | case 0: /* normal completion */ | 1728 | case 0: /* normal completion */ |
1675 | break; | 1729 | break; |
1676 | case -ENOENT: /* cancelled */ | 1730 | case -ENOENT: /* cancelled */ |
@@ -1680,26 +1734,33 @@ static void write_command_callback(struct urb *urb) | |||
1680 | case -ESHUTDOWN: /* device shut down */ | 1734 | case -ESHUTDOWN: /* device shut down */ |
1681 | /* ignore silently */ | 1735 | /* ignore silently */ |
1682 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 1736 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
1683 | __func__, get_usb_statmsg(urb->status)); | 1737 | __func__, get_usb_statmsg(status)); |
1684 | return; | 1738 | return; |
1685 | default: /* any failure */ | 1739 | default: /* any failure */ |
1686 | if (++ucs->retry_cmd_out > BAS_RETRY) { | 1740 | if (++ucs->retry_cmd_out > BAS_RETRY) { |
1687 | dev_warn(cs->dev, | 1741 | dev_warn(cs->dev, |
1688 | "command write: %s, " | 1742 | "command write: %s, " |
1689 | "giving up after %d retries\n", | 1743 | "giving up after %d retries\n", |
1690 | get_usb_statmsg(urb->status), | 1744 | get_usb_statmsg(status), |
1691 | ucs->retry_cmd_out); | 1745 | ucs->retry_cmd_out); |
1692 | break; | 1746 | break; |
1693 | } | 1747 | } |
1748 | if (ucs->basstate & BS_SUSPEND) { | ||
1749 | dev_warn(cs->dev, | ||
1750 | "command write: %s, " | ||
1751 | "won't retry - suspend requested\n", | ||
1752 | get_usb_statmsg(status)); | ||
1753 | break; | ||
1754 | } | ||
1694 | if (cs->cmdbuf == NULL) { | 1755 | if (cs->cmdbuf == NULL) { |
1695 | dev_warn(cs->dev, | 1756 | dev_warn(cs->dev, |
1696 | "command write: %s, " | 1757 | "command write: %s, " |
1697 | "cannot retry - cmdbuf gone\n", | 1758 | "cannot retry - cmdbuf gone\n", |
1698 | get_usb_statmsg(urb->status)); | 1759 | get_usb_statmsg(status)); |
1699 | break; | 1760 | break; |
1700 | } | 1761 | } |
1701 | dev_notice(cs->dev, "command write: %s, retry %d\n", | 1762 | dev_notice(cs->dev, "command write: %s, retry %d\n", |
1702 | get_usb_statmsg(urb->status), ucs->retry_cmd_out); | 1763 | get_usb_statmsg(status), ucs->retry_cmd_out); |
1703 | if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) | 1764 | if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) |
1704 | /* resubmitted - bypass regular exit block */ | 1765 | /* resubmitted - bypass regular exit block */ |
1705 | return; | 1766 | return; |
@@ -1799,8 +1860,14 @@ static int start_cbsend(struct cardstate *cs) | |||
1799 | int rc; | 1860 | int rc; |
1800 | int retval = 0; | 1861 | int retval = 0; |
1801 | 1862 | ||
1863 | /* check if suspend requested */ | ||
1864 | if (ucs->basstate & BS_SUSPEND) { | ||
1865 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "suspending"); | ||
1866 | return -EHOSTUNREACH; | ||
1867 | } | ||
1868 | |||
1802 | /* check if AT channel is open */ | 1869 | /* check if AT channel is open */ |
1803 | if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) { | 1870 | if (!(ucs->basstate & BS_ATOPEN)) { |
1804 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); | 1871 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); |
1805 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); | 1872 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); |
1806 | if (rc < 0) { | 1873 | if (rc < 0) { |
@@ -1816,8 +1883,7 @@ static int start_cbsend(struct cardstate *cs) | |||
1816 | /* try to send first command in queue */ | 1883 | /* try to send first command in queue */ |
1817 | spin_lock_irqsave(&cs->cmdlock, flags); | 1884 | spin_lock_irqsave(&cs->cmdlock, flags); |
1818 | 1885 | ||
1819 | while ((cb = cs->cmdbuf) != NULL && | 1886 | while ((cb = cs->cmdbuf) != NULL && (ucs->basstate & BS_ATREADY)) { |
1820 | atomic_read(&ucs->basstate) & BS_ATREADY) { | ||
1821 | ucs->retry_cmd_out = 0; | 1887 | ucs->retry_cmd_out = 0; |
1822 | rc = atwrite_submit(cs, cb->buf, cb->len); | 1888 | rc = atwrite_submit(cs, cb->buf, cb->len); |
1823 | if (unlikely(rc)) { | 1889 | if (unlikely(rc)) { |
@@ -1855,7 +1921,7 @@ static int gigaset_write_cmd(struct cardstate *cs, | |||
1855 | unsigned long flags; | 1921 | unsigned long flags; |
1856 | int rc; | 1922 | int rc; |
1857 | 1923 | ||
1858 | gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? | 1924 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? |
1859 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 1925 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
1860 | "CMD Transmit", len, buf); | 1926 | "CMD Transmit", len, buf); |
1861 | 1927 | ||
@@ -1970,7 +2036,7 @@ static int gigaset_freebcshw(struct bc_state *bcs) | |||
1970 | return 0; | 2036 | return 0; |
1971 | 2037 | ||
1972 | /* kill URBs and tasklets before freeing - better safe than sorry */ | 2038 | /* kill URBs and tasklets before freeing - better safe than sorry */ |
1973 | atomic_set(&ubc->running, 0); | 2039 | ubc->running = 0; |
1974 | gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__); | 2040 | gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__); |
1975 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2041 | for (i = 0; i < BAS_OUTURBS; ++i) { |
1976 | usb_kill_urb(ubc->isoouturbs[i].urb); | 2042 | usb_kill_urb(ubc->isoouturbs[i].urb); |
@@ -2005,7 +2071,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) | |||
2005 | return 0; | 2071 | return 0; |
2006 | } | 2072 | } |
2007 | 2073 | ||
2008 | atomic_set(&ubc->running, 0); | 2074 | ubc->running = 0; |
2009 | atomic_set(&ubc->corrbytes, 0); | 2075 | atomic_set(&ubc->corrbytes, 0); |
2010 | spin_lock_init(&ubc->isooutlock); | 2076 | spin_lock_init(&ubc->isooutlock); |
2011 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2077 | for (i = 0; i < BAS_OUTURBS; ++i) { |
@@ -2050,7 +2116,7 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) | |||
2050 | { | 2116 | { |
2051 | struct bas_bc_state *ubc = bcs->hw.bas; | 2117 | struct bas_bc_state *ubc = bcs->hw.bas; |
2052 | 2118 | ||
2053 | atomic_set(&bcs->hw.bas->running, 0); | 2119 | bcs->hw.bas->running = 0; |
2054 | atomic_set(&bcs->hw.bas->corrbytes, 0); | 2120 | atomic_set(&bcs->hw.bas->corrbytes, 0); |
2055 | bcs->hw.bas->numsub = 0; | 2121 | bcs->hw.bas->numsub = 0; |
2056 | spin_lock_init(&ubc->isooutlock); | 2122 | spin_lock_init(&ubc->isooutlock); |
@@ -2081,10 +2147,11 @@ static int gigaset_initcshw(struct cardstate *cs) | |||
2081 | spin_lock_init(&ucs->lock); | 2147 | spin_lock_init(&ucs->lock); |
2082 | ucs->pending = 0; | 2148 | ucs->pending = 0; |
2083 | 2149 | ||
2084 | atomic_set(&ucs->basstate, 0); | 2150 | ucs->basstate = 0; |
2085 | init_timer(&ucs->timer_ctrl); | 2151 | init_timer(&ucs->timer_ctrl); |
2086 | init_timer(&ucs->timer_atrdy); | 2152 | init_timer(&ucs->timer_atrdy); |
2087 | init_timer(&ucs->timer_cmd_in); | 2153 | init_timer(&ucs->timer_cmd_in); |
2154 | init_waitqueue_head(&ucs->waitqueue); | ||
2088 | 2155 | ||
2089 | return 1; | 2156 | return 1; |
2090 | } | 2157 | } |
@@ -2102,7 +2169,7 @@ static void freeurbs(struct cardstate *cs) | |||
2102 | int i, j; | 2169 | int i, j; |
2103 | 2170 | ||
2104 | gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); | 2171 | gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); |
2105 | for (j = 0; j < 2; ++j) { | 2172 | for (j = 0; j < BAS_CHANNELS; ++j) { |
2106 | ubc = cs->bcs[j].hw.bas; | 2173 | ubc = cs->bcs[j].hw.bas; |
2107 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2174 | for (i = 0; i < BAS_OUTURBS; ++i) { |
2108 | usb_kill_urb(ubc->isoouturbs[i].urb); | 2175 | usb_kill_urb(ubc->isoouturbs[i].urb); |
@@ -2179,11 +2246,11 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2179 | __func__, le16_to_cpu(udev->descriptor.idVendor), | 2246 | __func__, le16_to_cpu(udev->descriptor.idVendor), |
2180 | le16_to_cpu(udev->descriptor.idProduct)); | 2247 | le16_to_cpu(udev->descriptor.idProduct)); |
2181 | 2248 | ||
2182 | cs = gigaset_getunassignedcs(driver); | 2249 | /* allocate memory for our device state and intialize it */ |
2183 | if (!cs) { | 2250 | cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode, |
2184 | dev_err(&udev->dev, "no free cardstate\n"); | 2251 | GIGASET_MODULENAME); |
2252 | if (!cs) | ||
2185 | return -ENODEV; | 2253 | return -ENODEV; |
2186 | } | ||
2187 | ucs = cs->hw.bas; | 2254 | ucs = cs->hw.bas; |
2188 | 2255 | ||
2189 | /* save off device structure ptrs for later use */ | 2256 | /* save off device structure ptrs for later use */ |
@@ -2203,7 +2270,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2203 | !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL))) | 2270 | !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL))) |
2204 | goto allocerr; | 2271 | goto allocerr; |
2205 | 2272 | ||
2206 | for (j = 0; j < 2; ++j) { | 2273 | for (j = 0; j < BAS_CHANNELS; ++j) { |
2207 | ubc = cs->bcs[j].hw.bas; | 2274 | ubc = cs->bcs[j].hw.bas; |
2208 | for (i = 0; i < BAS_OUTURBS; ++i) | 2275 | for (i = 0; i < BAS_OUTURBS; ++i) |
2209 | if (!(ubc->isoouturbs[i].urb = | 2276 | if (!(ubc->isoouturbs[i].urb = |
@@ -2237,7 +2304,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2237 | 2304 | ||
2238 | /* tell common part that the device is ready */ | 2305 | /* tell common part that the device is ready */ |
2239 | if (startmode == SM_LOCKED) | 2306 | if (startmode == SM_LOCKED) |
2240 | atomic_set(&cs->mstate, MS_LOCKED); | 2307 | cs->mstate = MS_LOCKED; |
2241 | 2308 | ||
2242 | /* save address of controller structure */ | 2309 | /* save address of controller structure */ |
2243 | usb_set_intfdata(interface, cs); | 2310 | usb_set_intfdata(interface, cs); |
@@ -2252,7 +2319,7 @@ allocerr: | |||
2252 | error: | 2319 | error: |
2253 | freeurbs(cs); | 2320 | freeurbs(cs); |
2254 | usb_set_intfdata(interface, NULL); | 2321 | usb_set_intfdata(interface, NULL); |
2255 | gigaset_unassign(cs); | 2322 | gigaset_freecs(cs); |
2256 | return -ENODEV; | 2323 | return -ENODEV; |
2257 | } | 2324 | } |
2258 | 2325 | ||
@@ -2272,11 +2339,10 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
2272 | dev_info(cs->dev, "disconnecting Gigaset base\n"); | 2339 | dev_info(cs->dev, "disconnecting Gigaset base\n"); |
2273 | 2340 | ||
2274 | /* mark base as not ready, all channels disconnected */ | 2341 | /* mark base as not ready, all channels disconnected */ |
2275 | atomic_set(&ucs->basstate, 0); | 2342 | ucs->basstate = 0; |
2276 | 2343 | ||
2277 | /* tell LL all channels are down */ | 2344 | /* tell LL all channels are down */ |
2278 | //FIXME shouldn't gigaset_stop() do this? | 2345 | for (j = 0; j < BAS_CHANNELS; ++j) |
2279 | for (j = 0; j < 2; ++j) | ||
2280 | gigaset_bchannel_down(cs->bcs + j); | 2346 | gigaset_bchannel_down(cs->bcs + j); |
2281 | 2347 | ||
2282 | /* stop driver (common part) */ | 2348 | /* stop driver (common part) */ |
@@ -2295,9 +2361,113 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
2295 | ucs->interface = NULL; | 2361 | ucs->interface = NULL; |
2296 | ucs->udev = NULL; | 2362 | ucs->udev = NULL; |
2297 | cs->dev = NULL; | 2363 | cs->dev = NULL; |
2298 | gigaset_unassign(cs); | 2364 | gigaset_freecs(cs); |
2299 | } | 2365 | } |
2300 | 2366 | ||
2367 | /* gigaset_suspend | ||
2368 | * This function is called before the USB connection is suspended. | ||
2369 | */ | ||
2370 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) | ||
2371 | { | ||
2372 | struct cardstate *cs = usb_get_intfdata(intf); | ||
2373 | struct bas_cardstate *ucs = cs->hw.bas; | ||
2374 | int rc; | ||
2375 | |||
2376 | /* set suspend flag; this stops AT command/response traffic */ | ||
2377 | if (update_basstate(ucs, BS_SUSPEND, 0) & BS_SUSPEND) { | ||
2378 | gig_dbg(DEBUG_SUSPEND, "already suspended"); | ||
2379 | return 0; | ||
2380 | } | ||
2381 | |||
2382 | /* wait a bit for blocking conditions to go away */ | ||
2383 | rc = wait_event_timeout(ucs->waitqueue, | ||
2384 | !(ucs->basstate & | ||
2385 | (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)), | ||
2386 | BAS_TIMEOUT*HZ/10); | ||
2387 | gig_dbg(DEBUG_SUSPEND, "wait_event_timeout() -> %d", rc); | ||
2388 | |||
2389 | /* check for conditions preventing suspend */ | ||
2390 | if (ucs->basstate & (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)) { | ||
2391 | dev_warn(cs->dev, "cannot suspend:\n"); | ||
2392 | if (ucs->basstate & BS_B1OPEN) | ||
2393 | dev_warn(cs->dev, " B channel 1 open\n"); | ||
2394 | if (ucs->basstate & BS_B2OPEN) | ||
2395 | dev_warn(cs->dev, " B channel 2 open\n"); | ||
2396 | if (ucs->basstate & BS_ATRDPEND) | ||
2397 | dev_warn(cs->dev, " receiving AT reply\n"); | ||
2398 | if (ucs->basstate & BS_ATWRPEND) | ||
2399 | dev_warn(cs->dev, " sending AT command\n"); | ||
2400 | update_basstate(ucs, 0, BS_SUSPEND); | ||
2401 | return -EBUSY; | ||
2402 | } | ||
2403 | |||
2404 | /* close AT channel if open */ | ||
2405 | if (ucs->basstate & BS_ATOPEN) { | ||
2406 | gig_dbg(DEBUG_SUSPEND, "closing AT channel"); | ||
2407 | rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, 0); | ||
2408 | if (rc) { | ||
2409 | update_basstate(ucs, 0, BS_SUSPEND); | ||
2410 | return rc; | ||
2411 | } | ||
2412 | wait_event_timeout(ucs->waitqueue, !ucs->pending, | ||
2413 | BAS_TIMEOUT*HZ/10); | ||
2414 | /* in case of timeout, proceed anyway */ | ||
2415 | } | ||
2416 | |||
2417 | /* kill all URBs and timers that might still be pending */ | ||
2418 | usb_kill_urb(ucs->urb_ctrl); | ||
2419 | usb_kill_urb(ucs->urb_int_in); | ||
2420 | del_timer_sync(&ucs->timer_ctrl); | ||
2421 | |||
2422 | gig_dbg(DEBUG_SUSPEND, "suspend complete"); | ||
2423 | return 0; | ||
2424 | } | ||
2425 | |||
2426 | /* gigaset_resume | ||
2427 | * This function is called after the USB connection has been resumed. | ||
2428 | */ | ||
2429 | static int gigaset_resume(struct usb_interface *intf) | ||
2430 | { | ||
2431 | struct cardstate *cs = usb_get_intfdata(intf); | ||
2432 | struct bas_cardstate *ucs = cs->hw.bas; | ||
2433 | int rc; | ||
2434 | |||
2435 | /* resubmit interrupt URB for spontaneous messages from base */ | ||
2436 | rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); | ||
2437 | if (rc) { | ||
2438 | dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", | ||
2439 | get_usb_rcmsg(rc)); | ||
2440 | return rc; | ||
2441 | } | ||
2442 | |||
2443 | /* clear suspend flag to reallow activity */ | ||
2444 | update_basstate(ucs, 0, BS_SUSPEND); | ||
2445 | |||
2446 | gig_dbg(DEBUG_SUSPEND, "resume complete"); | ||
2447 | return 0; | ||
2448 | } | ||
2449 | |||
2450 | /* gigaset_pre_reset | ||
2451 | * This function is called before the USB connection is reset. | ||
2452 | */ | ||
2453 | static int gigaset_pre_reset(struct usb_interface *intf) | ||
2454 | { | ||
2455 | /* handle just like suspend */ | ||
2456 | return gigaset_suspend(intf, PMSG_ON); | ||
2457 | } | ||
2458 | |||
2459 | /* gigaset_post_reset | ||
2460 | * This function is called after the USB connection has been reset. | ||
2461 | */ | ||
2462 | static int gigaset_post_reset(struct usb_interface *intf) | ||
2463 | { | ||
2464 | /* FIXME: send HD_DEVICE_INIT_ACK? */ | ||
2465 | |||
2466 | /* resume operations */ | ||
2467 | return gigaset_resume(intf); | ||
2468 | } | ||
2469 | |||
2470 | |||
2301 | static const struct gigaset_ops gigops = { | 2471 | static const struct gigaset_ops gigops = { |
2302 | gigaset_write_cmd, | 2472 | gigaset_write_cmd, |
2303 | gigaset_write_room, | 2473 | gigaset_write_room, |
@@ -2330,12 +2500,6 @@ static int __init bas_gigaset_init(void) | |||
2330 | &gigops, THIS_MODULE)) == NULL) | 2500 | &gigops, THIS_MODULE)) == NULL) |
2331 | goto error; | 2501 | goto error; |
2332 | 2502 | ||
2333 | /* allocate memory for our device state and intialize it */ | ||
2334 | cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, | ||
2335 | GIGASET_MODULENAME); | ||
2336 | if (!cardstate) | ||
2337 | goto error; | ||
2338 | |||
2339 | /* register this driver with the USB subsystem */ | 2503 | /* register this driver with the USB subsystem */ |
2340 | result = usb_register(&gigaset_usb_driver); | 2504 | result = usb_register(&gigaset_usb_driver); |
2341 | if (result < 0) { | 2505 | if (result < 0) { |
@@ -2347,9 +2511,7 @@ static int __init bas_gigaset_init(void) | |||
2347 | info(DRIVER_DESC); | 2511 | info(DRIVER_DESC); |
2348 | return 0; | 2512 | return 0; |
2349 | 2513 | ||
2350 | error: if (cardstate) | 2514 | error: |
2351 | gigaset_freecs(cardstate); | ||
2352 | cardstate = NULL; | ||
2353 | if (driver) | 2515 | if (driver) |
2354 | gigaset_freedriver(driver); | 2516 | gigaset_freedriver(driver); |
2355 | driver = NULL; | 2517 | driver = NULL; |
@@ -2361,43 +2523,50 @@ error: if (cardstate) | |||
2361 | */ | 2523 | */ |
2362 | static void __exit bas_gigaset_exit(void) | 2524 | static void __exit bas_gigaset_exit(void) |
2363 | { | 2525 | { |
2364 | struct bas_cardstate *ucs = cardstate->hw.bas; | 2526 | struct bas_cardstate *ucs; |
2527 | int i; | ||
2365 | 2528 | ||
2366 | gigaset_blockdriver(driver); /* => probe will fail | 2529 | gigaset_blockdriver(driver); /* => probe will fail |
2367 | * => no gigaset_start any more | 2530 | * => no gigaset_start any more |
2368 | */ | 2531 | */ |
2369 | 2532 | ||
2370 | gigaset_shutdown(cardstate); | 2533 | /* stop all connected devices */ |
2371 | /* from now on, no isdn callback should be possible */ | 2534 | for (i = 0; i < driver->minors; i++) { |
2372 | 2535 | if (gigaset_shutdown(driver->cs + i) < 0) | |
2373 | /* close all still open channels */ | 2536 | continue; /* no device */ |
2374 | if (atomic_read(&ucs->basstate) & BS_B1OPEN) { | 2537 | /* from now on, no isdn callback should be possible */ |
2375 | gig_dbg(DEBUG_INIT, "closing B1 channel"); | 2538 | |
2376 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | 2539 | /* close all still open channels */ |
2377 | HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0, | 2540 | ucs = driver->cs[i].hw.bas; |
2378 | NULL, 0, BAS_TIMEOUT); | 2541 | if (ucs->basstate & BS_B1OPEN) { |
2379 | } | 2542 | gig_dbg(DEBUG_INIT, "closing B1 channel"); |
2380 | if (atomic_read(&ucs->basstate) & BS_B2OPEN) { | 2543 | usb_control_msg(ucs->udev, |
2381 | gig_dbg(DEBUG_INIT, "closing B2 channel"); | 2544 | usb_sndctrlpipe(ucs->udev, 0), |
2382 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | 2545 | HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, |
2383 | HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0, | 2546 | 0, 0, NULL, 0, BAS_TIMEOUT); |
2384 | NULL, 0, BAS_TIMEOUT); | 2547 | } |
2385 | } | 2548 | if (ucs->basstate & BS_B2OPEN) { |
2386 | if (atomic_read(&ucs->basstate) & BS_ATOPEN) { | 2549 | gig_dbg(DEBUG_INIT, "closing B2 channel"); |
2387 | gig_dbg(DEBUG_INIT, "closing AT channel"); | 2550 | usb_control_msg(ucs->udev, |
2388 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | 2551 | usb_sndctrlpipe(ucs->udev, 0), |
2389 | HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0, | 2552 | HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, |
2390 | NULL, 0, BAS_TIMEOUT); | 2553 | 0, 0, NULL, 0, BAS_TIMEOUT); |
2554 | } | ||
2555 | if (ucs->basstate & BS_ATOPEN) { | ||
2556 | gig_dbg(DEBUG_INIT, "closing AT channel"); | ||
2557 | usb_control_msg(ucs->udev, | ||
2558 | usb_sndctrlpipe(ucs->udev, 0), | ||
2559 | HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, | ||
2560 | 0, 0, NULL, 0, BAS_TIMEOUT); | ||
2561 | } | ||
2562 | ucs->basstate = 0; | ||
2391 | } | 2563 | } |
2392 | atomic_set(&ucs->basstate, 0); | ||
2393 | 2564 | ||
2394 | /* deregister this driver with the USB subsystem */ | 2565 | /* deregister this driver with the USB subsystem */ |
2395 | usb_deregister(&gigaset_usb_driver); | 2566 | usb_deregister(&gigaset_usb_driver); |
2396 | /* this will call the disconnect-callback */ | 2567 | /* this will call the disconnect-callback */ |
2397 | /* from now on, no disconnect/probe callback should be running */ | 2568 | /* from now on, no disconnect/probe callback should be running */ |
2398 | 2569 | ||
2399 | gigaset_freecs(cardstate); | ||
2400 | cardstate = NULL; | ||
2401 | gigaset_freedriver(driver); | 2570 | gigaset_freedriver(driver); |
2402 | driver = NULL; | 2571 | driver = NULL; |
2403 | } | 2572 | } |