diff options
author | Tilman Schmidt <tilman@imap.cc> | 2008-02-06 04:38:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-06 13:41:12 -0500 |
commit | e468c04894f36045cf93d1384183a461014b6840 (patch) | |
tree | b734bbc4ee65f8282de5299dc200f47ea466067a /drivers/isdn/gigaset/usb-gigaset.c | |
parent | 9d4bee2b9de9e30057a860d2d6794f874caffc5e (diff) |
Gigaset: permit module unload
Fix the initialization and reference counting of the Gigaset driver modules
so that they can be unloaded when they are not actually in use.
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
Cc: Hansjoerg Lipp <hjlipp@web.de>
Cc: Greg KH <gregkh@suse.de>
Cc: Karsten Keil <kkeil@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/isdn/gigaset/usb-gigaset.c')
-rw-r--r-- | drivers/isdn/gigaset/usb-gigaset.c | 30 |
1 files changed, 12 insertions, 18 deletions
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index c58ddee68dea..77d20ab0cd4d 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c | |||
@@ -115,7 +115,6 @@ static int gigaset_resume(struct usb_interface *intf); | |||
115 | static int gigaset_pre_reset(struct usb_interface *intf); | 115 | static int gigaset_pre_reset(struct usb_interface *intf); |
116 | 116 | ||
117 | static struct gigaset_driver *driver = NULL; | 117 | static struct gigaset_driver *driver = NULL; |
118 | static struct cardstate *cardstate = NULL; | ||
119 | 118 | ||
120 | /* 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 */ |
121 | static struct usb_driver gigaset_usb_driver = { | 120 | static struct usb_driver gigaset_usb_driver = { |
@@ -727,11 +726,10 @@ static int gigaset_probe(struct usb_interface *interface, | |||
727 | 726 | ||
728 | dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); | 727 | dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); |
729 | 728 | ||
730 | cs = gigaset_getunassignedcs(driver); | 729 | /* allocate memory for our device state and intialize it */ |
731 | if (!cs) { | 730 | cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); |
732 | dev_warn(&udev->dev, "no free cardstate\n"); | 731 | if (!cs) |
733 | return -ENODEV; | 732 | return -ENODEV; |
734 | } | ||
735 | ucs = cs->hw.usb; | 733 | ucs = cs->hw.usb; |
736 | 734 | ||
737 | /* save off device structure ptrs for later use */ | 735 | /* save off device structure ptrs for later use */ |
@@ -818,7 +816,7 @@ error: | |||
818 | usb_put_dev(ucs->udev); | 816 | usb_put_dev(ucs->udev); |
819 | ucs->udev = NULL; | 817 | ucs->udev = NULL; |
820 | ucs->interface = NULL; | 818 | ucs->interface = NULL; |
821 | gigaset_unassign(cs); | 819 | gigaset_freecs(cs); |
822 | return retval; | 820 | return retval; |
823 | } | 821 | } |
824 | 822 | ||
@@ -852,7 +850,7 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
852 | ucs->interface = NULL; | 850 | ucs->interface = NULL; |
853 | ucs->udev = NULL; | 851 | ucs->udev = NULL; |
854 | cs->dev = NULL; | 852 | cs->dev = NULL; |
855 | gigaset_unassign(cs); | 853 | gigaset_freecs(cs); |
856 | } | 854 | } |
857 | 855 | ||
858 | /* gigaset_suspend | 856 | /* gigaset_suspend |
@@ -934,11 +932,6 @@ static int __init usb_gigaset_init(void) | |||
934 | &ops, THIS_MODULE)) == NULL) | 932 | &ops, THIS_MODULE)) == NULL) |
935 | goto error; | 933 | goto error; |
936 | 934 | ||
937 | /* allocate memory for our device state and intialize it */ | ||
938 | cardstate = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); | ||
939 | if (!cardstate) | ||
940 | goto error; | ||
941 | |||
942 | /* register this driver with the USB subsystem */ | 935 | /* register this driver with the USB subsystem */ |
943 | result = usb_register(&gigaset_usb_driver); | 936 | result = usb_register(&gigaset_usb_driver); |
944 | if (result < 0) { | 937 | if (result < 0) { |
@@ -951,9 +944,7 @@ static int __init usb_gigaset_init(void) | |||
951 | info(DRIVER_DESC); | 944 | info(DRIVER_DESC); |
952 | return 0; | 945 | return 0; |
953 | 946 | ||
954 | error: if (cardstate) | 947 | error: |
955 | gigaset_freecs(cardstate); | ||
956 | cardstate = NULL; | ||
957 | if (driver) | 948 | if (driver) |
958 | gigaset_freedriver(driver); | 949 | gigaset_freedriver(driver); |
959 | driver = NULL; | 950 | driver = NULL; |
@@ -967,11 +958,16 @@ error: if (cardstate) | |||
967 | */ | 958 | */ |
968 | static void __exit usb_gigaset_exit(void) | 959 | static void __exit usb_gigaset_exit(void) |
969 | { | 960 | { |
961 | int i; | ||
962 | |||
970 | gigaset_blockdriver(driver); /* => probe will fail | 963 | gigaset_blockdriver(driver); /* => probe will fail |
971 | * => no gigaset_start any more | 964 | * => no gigaset_start any more |
972 | */ | 965 | */ |
973 | 966 | ||
974 | gigaset_shutdown(cardstate); | 967 | /* stop all connected devices */ |
968 | for (i = 0; i < driver->minors; i++) | ||
969 | gigaset_shutdown(driver->cs + i); | ||
970 | |||
975 | /* from now on, no isdn callback should be possible */ | 971 | /* from now on, no isdn callback should be possible */ |
976 | 972 | ||
977 | /* deregister this driver with the USB subsystem */ | 973 | /* deregister this driver with the USB subsystem */ |
@@ -979,8 +975,6 @@ static void __exit usb_gigaset_exit(void) | |||
979 | /* this will call the disconnect-callback */ | 975 | /* this will call the disconnect-callback */ |
980 | /* from now on, no disconnect/probe callback should be running */ | 976 | /* from now on, no disconnect/probe callback should be running */ |
981 | 977 | ||
982 | gigaset_freecs(cardstate); | ||
983 | cardstate = NULL; | ||
984 | gigaset_freedriver(driver); | 978 | gigaset_freedriver(driver); |
985 | driver = NULL; | 979 | driver = NULL; |
986 | } | 980 | } |