diff options
Diffstat (limited to 'drivers/isdn/gigaset/usb-gigaset.c')
-rw-r--r-- | drivers/isdn/gigaset/usb-gigaset.c | 206 |
1 files changed, 127 insertions, 79 deletions
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index ca4bee173cfb..77d20ab0cd4d 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c | |||
@@ -104,12 +104,17 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); | |||
104 | * flags per packet. | 104 | * flags per packet. |
105 | */ | 105 | */ |
106 | 106 | ||
107 | /* functions called if a device of this driver is connected/disconnected */ | ||
107 | static int gigaset_probe(struct usb_interface *interface, | 108 | static int gigaset_probe(struct usb_interface *interface, |
108 | const struct usb_device_id *id); | 109 | const struct usb_device_id *id); |
109 | static void gigaset_disconnect(struct usb_interface *interface); | 110 | static void gigaset_disconnect(struct usb_interface *interface); |
110 | 111 | ||
112 | /* functions called before/after suspend */ | ||
113 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); | ||
114 | static int gigaset_resume(struct usb_interface *intf); | ||
115 | static int gigaset_pre_reset(struct usb_interface *intf); | ||
116 | |||
111 | static struct gigaset_driver *driver = NULL; | 117 | static struct gigaset_driver *driver = NULL; |
112 | static struct cardstate *cardstate = NULL; | ||
113 | 118 | ||
114 | /* usb specific object needed to register this driver with the usb subsystem */ | 119 | /* usb specific object needed to register this driver with the usb subsystem */ |
115 | static struct usb_driver gigaset_usb_driver = { | 120 | static struct usb_driver gigaset_usb_driver = { |
@@ -117,12 +122,17 @@ static struct usb_driver gigaset_usb_driver = { | |||
117 | .probe = gigaset_probe, | 122 | .probe = gigaset_probe, |
118 | .disconnect = gigaset_disconnect, | 123 | .disconnect = gigaset_disconnect, |
119 | .id_table = gigaset_table, | 124 | .id_table = gigaset_table, |
125 | .suspend = gigaset_suspend, | ||
126 | .resume = gigaset_resume, | ||
127 | .reset_resume = gigaset_resume, | ||
128 | .pre_reset = gigaset_pre_reset, | ||
129 | .post_reset = gigaset_resume, | ||
120 | }; | 130 | }; |
121 | 131 | ||
122 | struct usb_cardstate { | 132 | struct usb_cardstate { |
123 | struct usb_device *udev; /* usb device pointer */ | 133 | struct usb_device *udev; /* usb device pointer */ |
124 | struct usb_interface *interface; /* interface for this device */ | 134 | struct usb_interface *interface; /* interface for this device */ |
125 | atomic_t busy; /* bulk output in progress */ | 135 | int busy; /* bulk output in progress */ |
126 | 136 | ||
127 | /* Output buffer */ | 137 | /* Output buffer */ |
128 | unsigned char *bulk_out_buffer; | 138 | unsigned char *bulk_out_buffer; |
@@ -314,7 +324,7 @@ static void gigaset_modem_fill(unsigned long data) | |||
314 | 324 | ||
315 | gig_dbg(DEBUG_OUTPUT, "modem_fill"); | 325 | gig_dbg(DEBUG_OUTPUT, "modem_fill"); |
316 | 326 | ||
317 | if (atomic_read(&cs->hw.usb->busy)) { | 327 | if (cs->hw.usb->busy) { |
318 | gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); | 328 | gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); |
319 | return; | 329 | return; |
320 | } | 330 | } |
@@ -361,18 +371,13 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
361 | { | 371 | { |
362 | struct inbuf_t *inbuf = urb->context; | 372 | struct inbuf_t *inbuf = urb->context; |
363 | struct cardstate *cs = inbuf->cs; | 373 | struct cardstate *cs = inbuf->cs; |
364 | int resubmit = 0; | 374 | int status = urb->status; |
365 | int r; | 375 | int r; |
366 | unsigned numbytes; | 376 | unsigned numbytes; |
367 | unsigned char *src; | 377 | unsigned char *src; |
368 | unsigned long flags; | 378 | unsigned long flags; |
369 | 379 | ||
370 | if (!urb->status) { | 380 | if (!status) { |
371 | if (!cs->connected) { | ||
372 | err("%s: disconnected", __func__); /* should never happen */ | ||
373 | return; | ||
374 | } | ||
375 | |||
376 | numbytes = urb->actual_length; | 381 | numbytes = urb->actual_length; |
377 | 382 | ||
378 | if (numbytes) { | 383 | if (numbytes) { |
@@ -389,28 +394,26 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
389 | } | 394 | } |
390 | } else | 395 | } else |
391 | gig_dbg(DEBUG_INTR, "Received zero block length"); | 396 | gig_dbg(DEBUG_INTR, "Received zero block length"); |
392 | resubmit = 1; | ||
393 | } else { | 397 | } else { |
394 | /* The urb might have been killed. */ | 398 | /* The urb might have been killed. */ |
395 | gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", | 399 | gig_dbg(DEBUG_ANY, "%s - nonzero status received: %d", |
396 | __func__, urb->status); | 400 | __func__, status); |
397 | if (urb->status != -ENOENT) { /* not killed */ | 401 | if (status == -ENOENT || status == -ESHUTDOWN) |
398 | if (!cs->connected) { | 402 | /* killed or endpoint shutdown: don't resubmit */ |
399 | err("%s: disconnected", __func__); /* should never happen */ | 403 | return; |
400 | return; | ||
401 | } | ||
402 | resubmit = 1; | ||
403 | } | ||
404 | } | 404 | } |
405 | 405 | ||
406 | if (resubmit) { | 406 | /* resubmit URB */ |
407 | spin_lock_irqsave(&cs->lock, flags); | 407 | spin_lock_irqsave(&cs->lock, flags); |
408 | r = cs->connected ? usb_submit_urb(urb, GFP_ATOMIC) : -ENODEV; | 408 | if (!cs->connected) { |
409 | spin_unlock_irqrestore(&cs->lock, flags); | 409 | spin_unlock_irqrestore(&cs->lock, flags); |
410 | if (r) | 410 | err("%s: disconnected", __func__); |
411 | dev_err(cs->dev, "error %d when resubmitting urb.\n", | 411 | return; |
412 | -r); | ||
413 | } | 412 | } |
413 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
414 | spin_unlock_irqrestore(&cs->lock, flags); | ||
415 | if (r) | ||
416 | dev_err(cs->dev, "error %d resubmitting URB\n", -r); | ||
414 | } | 417 | } |
415 | 418 | ||
416 | 419 | ||
@@ -418,19 +421,28 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
418 | static void gigaset_write_bulk_callback(struct urb *urb) | 421 | static void gigaset_write_bulk_callback(struct urb *urb) |
419 | { | 422 | { |
420 | struct cardstate *cs = urb->context; | 423 | struct cardstate *cs = urb->context; |
424 | int status = urb->status; | ||
421 | unsigned long flags; | 425 | unsigned long flags; |
422 | 426 | ||
423 | if (urb->status) | 427 | switch (status) { |
428 | case 0: /* normal completion */ | ||
429 | break; | ||
430 | case -ENOENT: /* killed */ | ||
431 | gig_dbg(DEBUG_ANY, "%s: killed", __func__); | ||
432 | cs->hw.usb->busy = 0; | ||
433 | return; | ||
434 | default: | ||
424 | dev_err(cs->dev, "bulk transfer failed (status %d)\n", | 435 | dev_err(cs->dev, "bulk transfer failed (status %d)\n", |
425 | -urb->status); | 436 | -status); |
426 | /* That's all we can do. Communication problems | 437 | /* That's all we can do. Communication problems |
427 | are handled by timeouts or network protocols. */ | 438 | are handled by timeouts or network protocols. */ |
439 | } | ||
428 | 440 | ||
429 | spin_lock_irqsave(&cs->lock, flags); | 441 | spin_lock_irqsave(&cs->lock, flags); |
430 | if (!cs->connected) { | 442 | if (!cs->connected) { |
431 | err("%s: not connected", __func__); | 443 | err("%s: not connected", __func__); |
432 | } else { | 444 | } else { |
433 | atomic_set(&cs->hw.usb->busy, 0); | 445 | cs->hw.usb->busy = 0; |
434 | tasklet_schedule(&cs->write_tasklet); | 446 | tasklet_schedule(&cs->write_tasklet); |
435 | } | 447 | } |
436 | spin_unlock_irqrestore(&cs->lock, flags); | 448 | spin_unlock_irqrestore(&cs->lock, flags); |
@@ -478,14 +490,14 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) | |||
478 | 490 | ||
479 | cb->offset += count; | 491 | cb->offset += count; |
480 | cb->len -= count; | 492 | cb->len -= count; |
481 | atomic_set(&ucs->busy, 1); | 493 | ucs->busy = 1; |
482 | 494 | ||
483 | spin_lock_irqsave(&cs->lock, flags); | 495 | spin_lock_irqsave(&cs->lock, flags); |
484 | status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; | 496 | status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; |
485 | spin_unlock_irqrestore(&cs->lock, flags); | 497 | spin_unlock_irqrestore(&cs->lock, flags); |
486 | 498 | ||
487 | if (status) { | 499 | if (status) { |
488 | atomic_set(&ucs->busy, 0); | 500 | ucs->busy = 0; |
489 | err("could not submit urb (error %d)\n", | 501 | err("could not submit urb (error %d)\n", |
490 | -status); | 502 | -status); |
491 | cb->len = 0; /* skip urb => remove cb+wakeup | 503 | cb->len = 0; /* skip urb => remove cb+wakeup |
@@ -504,7 +516,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, | |||
504 | struct cmdbuf_t *cb; | 516 | struct cmdbuf_t *cb; |
505 | unsigned long flags; | 517 | unsigned long flags; |
506 | 518 | ||
507 | gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? | 519 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? |
508 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 520 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
509 | "CMD Transmit", len, buf); | 521 | "CMD Transmit", len, buf); |
510 | 522 | ||
@@ -641,7 +653,7 @@ static int write_modem(struct cardstate *cs) | |||
641 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); | 653 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); |
642 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); | 654 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); |
643 | skb_pull(bcs->tx_skb, count); | 655 | skb_pull(bcs->tx_skb, count); |
644 | atomic_set(&ucs->busy, 1); | 656 | ucs->busy = 1; |
645 | gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); | 657 | gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); |
646 | 658 | ||
647 | spin_lock_irqsave(&cs->lock, flags); | 659 | spin_lock_irqsave(&cs->lock, flags); |
@@ -659,7 +671,7 @@ static int write_modem(struct cardstate *cs) | |||
659 | 671 | ||
660 | if (ret) { | 672 | if (ret) { |
661 | err("could not submit urb (error %d)\n", -ret); | 673 | err("could not submit urb (error %d)\n", -ret); |
662 | atomic_set(&ucs->busy, 0); | 674 | ucs->busy = 0; |
663 | } | 675 | } |
664 | 676 | ||
665 | if (!bcs->tx_skb->len) { | 677 | if (!bcs->tx_skb->len) { |
@@ -680,53 +692,44 @@ static int gigaset_probe(struct usb_interface *interface, | |||
680 | { | 692 | { |
681 | int retval; | 693 | int retval; |
682 | struct usb_device *udev = interface_to_usbdev(interface); | 694 | struct usb_device *udev = interface_to_usbdev(interface); |
683 | unsigned int ifnum; | 695 | struct usb_host_interface *hostif = interface->cur_altsetting; |
684 | struct usb_host_interface *hostif; | ||
685 | struct cardstate *cs = NULL; | 696 | struct cardstate *cs = NULL; |
686 | struct usb_cardstate *ucs = NULL; | 697 | struct usb_cardstate *ucs = NULL; |
687 | struct usb_endpoint_descriptor *endpoint; | 698 | struct usb_endpoint_descriptor *endpoint; |
688 | int buffer_size; | 699 | int buffer_size; |
689 | int alt; | ||
690 | 700 | ||
691 | gig_dbg(DEBUG_ANY, | 701 | gig_dbg(DEBUG_ANY, "%s: Check if device matches ...", __func__); |
692 | "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", | ||
693 | __func__, le16_to_cpu(udev->descriptor.idVendor), | ||
694 | le16_to_cpu(udev->descriptor.idProduct)); | ||
695 | |||
696 | retval = -ENODEV; //FIXME | ||
697 | 702 | ||
698 | /* See if the device offered us matches what we can accept */ | 703 | /* See if the device offered us matches what we can accept */ |
699 | if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) || | 704 | if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) || |
700 | (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) | 705 | (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) { |
706 | gig_dbg(DEBUG_ANY, "device ID (0x%x, 0x%x) not for me - skip", | ||
707 | le16_to_cpu(udev->descriptor.idVendor), | ||
708 | le16_to_cpu(udev->descriptor.idProduct)); | ||
701 | return -ENODEV; | 709 | return -ENODEV; |
702 | 710 | } | |
703 | /* this starts to become ascii art... */ | 711 | if (hostif->desc.bInterfaceNumber != 0) { |
704 | hostif = interface->cur_altsetting; | 712 | gig_dbg(DEBUG_ANY, "interface %d not for me - skip", |
705 | alt = hostif->desc.bAlternateSetting; | 713 | hostif->desc.bInterfaceNumber); |
706 | ifnum = hostif->desc.bInterfaceNumber; // FIXME ? | 714 | return -ENODEV; |
707 | 715 | } | |
708 | if (alt != 0 || ifnum != 0) { | 716 | if (hostif->desc.bAlternateSetting != 0) { |
709 | dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt); | 717 | dev_notice(&udev->dev, "unsupported altsetting %d - skip", |
718 | hostif->desc.bAlternateSetting); | ||
710 | return -ENODEV; | 719 | return -ENODEV; |
711 | } | 720 | } |
712 | |||
713 | /* Reject application specific intefaces | ||
714 | * | ||
715 | */ | ||
716 | if (hostif->desc.bInterfaceClass != 255) { | 721 | if (hostif->desc.bInterfaceClass != 255) { |
717 | dev_info(&udev->dev, | 722 | dev_notice(&udev->dev, "unsupported interface class %d - skip", |
718 | "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n", | 723 | hostif->desc.bInterfaceClass); |
719 | __func__, ifnum, hostif->desc.bInterfaceClass); | ||
720 | return -ENODEV; | 724 | return -ENODEV; |
721 | } | 725 | } |
722 | 726 | ||
723 | dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); | 727 | dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); |
724 | 728 | ||
725 | cs = gigaset_getunassignedcs(driver); | 729 | /* allocate memory for our device state and intialize it */ |
726 | if (!cs) { | 730 | cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); |
727 | dev_warn(&udev->dev, "no free cardstate\n"); | 731 | if (!cs) |
728 | return -ENODEV; | 732 | return -ENODEV; |
729 | } | ||
730 | ucs = cs->hw.usb; | 733 | ucs = cs->hw.usb; |
731 | 734 | ||
732 | /* save off device structure ptrs for later use */ | 735 | /* save off device structure ptrs for later use */ |
@@ -759,7 +762,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
759 | 762 | ||
760 | endpoint = &hostif->endpoint[1].desc; | 763 | endpoint = &hostif->endpoint[1].desc; |
761 | 764 | ||
762 | atomic_set(&ucs->busy, 0); | 765 | ucs->busy = 0; |
763 | 766 | ||
764 | ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); | 767 | ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); |
765 | if (!ucs->read_urb) { | 768 | if (!ucs->read_urb) { |
@@ -792,7 +795,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
792 | 795 | ||
793 | /* tell common part that the device is ready */ | 796 | /* tell common part that the device is ready */ |
794 | if (startmode == SM_LOCKED) | 797 | if (startmode == SM_LOCKED) |
795 | atomic_set(&cs->mstate, MS_LOCKED); | 798 | cs->mstate = MS_LOCKED; |
796 | 799 | ||
797 | if (!gigaset_start(cs)) { | 800 | if (!gigaset_start(cs)) { |
798 | tasklet_kill(&cs->write_tasklet); | 801 | tasklet_kill(&cs->write_tasklet); |
@@ -813,7 +816,7 @@ error: | |||
813 | usb_put_dev(ucs->udev); | 816 | usb_put_dev(ucs->udev); |
814 | ucs->udev = NULL; | 817 | ucs->udev = NULL; |
815 | ucs->interface = NULL; | 818 | ucs->interface = NULL; |
816 | gigaset_unassign(cs); | 819 | gigaset_freecs(cs); |
817 | return retval; | 820 | return retval; |
818 | } | 821 | } |
819 | 822 | ||
@@ -824,6 +827,9 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
824 | 827 | ||
825 | cs = usb_get_intfdata(interface); | 828 | cs = usb_get_intfdata(interface); |
826 | ucs = cs->hw.usb; | 829 | ucs = cs->hw.usb; |
830 | |||
831 | dev_info(cs->dev, "disconnecting Gigaset USB adapter\n"); | ||
832 | |||
827 | usb_kill_urb(ucs->read_urb); | 833 | usb_kill_urb(ucs->read_urb); |
828 | 834 | ||
829 | gigaset_stop(cs); | 835 | gigaset_stop(cs); |
@@ -831,7 +837,7 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
831 | usb_set_intfdata(interface, NULL); | 837 | usb_set_intfdata(interface, NULL); |
832 | tasklet_kill(&cs->write_tasklet); | 838 | tasklet_kill(&cs->write_tasklet); |
833 | 839 | ||
834 | usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */ | 840 | usb_kill_urb(ucs->bulk_out_urb); |
835 | 841 | ||
836 | kfree(ucs->bulk_out_buffer); | 842 | kfree(ucs->bulk_out_buffer); |
837 | usb_free_urb(ucs->bulk_out_urb); | 843 | usb_free_urb(ucs->bulk_out_urb); |
@@ -844,7 +850,53 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
844 | ucs->interface = NULL; | 850 | ucs->interface = NULL; |
845 | ucs->udev = NULL; | 851 | ucs->udev = NULL; |
846 | cs->dev = NULL; | 852 | cs->dev = NULL; |
847 | gigaset_unassign(cs); | 853 | gigaset_freecs(cs); |
854 | } | ||
855 | |||
856 | /* gigaset_suspend | ||
857 | * This function is called before the USB connection is suspended or reset. | ||
858 | */ | ||
859 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) | ||
860 | { | ||
861 | struct cardstate *cs = usb_get_intfdata(intf); | ||
862 | |||
863 | /* stop activity */ | ||
864 | cs->connected = 0; /* prevent rescheduling */ | ||
865 | usb_kill_urb(cs->hw.usb->read_urb); | ||
866 | tasklet_kill(&cs->write_tasklet); | ||
867 | usb_kill_urb(cs->hw.usb->bulk_out_urb); | ||
868 | |||
869 | gig_dbg(DEBUG_SUSPEND, "suspend complete"); | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | /* gigaset_resume | ||
874 | * This function is called after the USB connection has been resumed or reset. | ||
875 | */ | ||
876 | static int gigaset_resume(struct usb_interface *intf) | ||
877 | { | ||
878 | struct cardstate *cs = usb_get_intfdata(intf); | ||
879 | int rc; | ||
880 | |||
881 | /* resubmit interrupt URB */ | ||
882 | cs->connected = 1; | ||
883 | rc = usb_submit_urb(cs->hw.usb->read_urb, GFP_KERNEL); | ||
884 | if (rc) { | ||
885 | dev_err(cs->dev, "Could not submit read URB (error %d)\n", -rc); | ||
886 | return rc; | ||
887 | } | ||
888 | |||
889 | gig_dbg(DEBUG_SUSPEND, "resume complete"); | ||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | /* gigaset_pre_reset | ||
894 | * This function is called before the USB connection is reset. | ||
895 | */ | ||
896 | static int gigaset_pre_reset(struct usb_interface *intf) | ||
897 | { | ||
898 | /* same as suspend */ | ||
899 | return gigaset_suspend(intf, PMSG_ON); | ||
848 | } | 900 | } |
849 | 901 | ||
850 | static const struct gigaset_ops ops = { | 902 | static const struct gigaset_ops ops = { |
@@ -880,11 +932,6 @@ static int __init usb_gigaset_init(void) | |||
880 | &ops, THIS_MODULE)) == NULL) | 932 | &ops, THIS_MODULE)) == NULL) |
881 | goto error; | 933 | goto error; |
882 | 934 | ||
883 | /* allocate memory for our device state and intialize it */ | ||
884 | cardstate = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); | ||
885 | if (!cardstate) | ||
886 | goto error; | ||
887 | |||
888 | /* register this driver with the USB subsystem */ | 935 | /* register this driver with the USB subsystem */ |
889 | result = usb_register(&gigaset_usb_driver); | 936 | result = usb_register(&gigaset_usb_driver); |
890 | if (result < 0) { | 937 | if (result < 0) { |
@@ -897,9 +944,7 @@ static int __init usb_gigaset_init(void) | |||
897 | info(DRIVER_DESC); | 944 | info(DRIVER_DESC); |
898 | return 0; | 945 | return 0; |
899 | 946 | ||
900 | error: if (cardstate) | 947 | error: |
901 | gigaset_freecs(cardstate); | ||
902 | cardstate = NULL; | ||
903 | if (driver) | 948 | if (driver) |
904 | gigaset_freedriver(driver); | 949 | gigaset_freedriver(driver); |
905 | driver = NULL; | 950 | driver = NULL; |
@@ -913,11 +958,16 @@ error: if (cardstate) | |||
913 | */ | 958 | */ |
914 | static void __exit usb_gigaset_exit(void) | 959 | static void __exit usb_gigaset_exit(void) |
915 | { | 960 | { |
961 | int i; | ||
962 | |||
916 | gigaset_blockdriver(driver); /* => probe will fail | 963 | gigaset_blockdriver(driver); /* => probe will fail |
917 | * => no gigaset_start any more | 964 | * => no gigaset_start any more |
918 | */ | 965 | */ |
919 | 966 | ||
920 | gigaset_shutdown(cardstate); | 967 | /* stop all connected devices */ |
968 | for (i = 0; i < driver->minors; i++) | ||
969 | gigaset_shutdown(driver->cs + i); | ||
970 | |||
921 | /* from now on, no isdn callback should be possible */ | 971 | /* from now on, no isdn callback should be possible */ |
922 | 972 | ||
923 | /* deregister this driver with the USB subsystem */ | 973 | /* deregister this driver with the USB subsystem */ |
@@ -925,8 +975,6 @@ static void __exit usb_gigaset_exit(void) | |||
925 | /* this will call the disconnect-callback */ | 975 | /* this will call the disconnect-callback */ |
926 | /* from now on, no disconnect/probe callback should be running */ | 976 | /* from now on, no disconnect/probe callback should be running */ |
927 | 977 | ||
928 | gigaset_freecs(cardstate); | ||
929 | cardstate = NULL; | ||
930 | gigaset_freedriver(driver); | 978 | gigaset_freedriver(driver); |
931 | driver = NULL; | 979 | driver = NULL; |
932 | } | 980 | } |