diff options
author | Tilman Schmidt <tilman@imap.cc> | 2008-02-06 01:38:29 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-06 10:41:12 -0800 |
commit | e468c04894f36045cf93d1384183a461014b6840 (patch) | |
tree | b734bbc4ee65f8282de5299dc200f47ea466067a /drivers/isdn/gigaset/usb-gigaset.c | |
parent | 9d4bee2b9de9e30057a860d2d6794f874caffc5e (diff) | |
download | lwn-e468c04894f36045cf93d1384183a461014b6840.tar.gz lwn-e468c04894f36045cf93d1384183a461014b6840.zip |
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); static int gigaset_pre_reset(struct usb_interface *intf); static struct gigaset_driver *driver = NULL; -static struct cardstate *cardstate = NULL; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gigaset_usb_driver = { @@ -727,11 +726,10 @@ static int gigaset_probe(struct usb_interface *interface, dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); - cs = gigaset_getunassignedcs(driver); - if (!cs) { - dev_warn(&udev->dev, "no free cardstate\n"); + /* allocate memory for our device state and intialize it */ + cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); + if (!cs) return -ENODEV; - } ucs = cs->hw.usb; /* save off device structure ptrs for later use */ @@ -818,7 +816,7 @@ error: usb_put_dev(ucs->udev); ucs->udev = NULL; ucs->interface = NULL; - gigaset_unassign(cs); + gigaset_freecs(cs); return retval; } @@ -852,7 +850,7 @@ static void gigaset_disconnect(struct usb_interface *interface) ucs->interface = NULL; ucs->udev = NULL; cs->dev = NULL; - gigaset_unassign(cs); + gigaset_freecs(cs); } /* gigaset_suspend @@ -934,11 +932,6 @@ static int __init usb_gigaset_init(void) &ops, THIS_MODULE)) == NULL) goto error; - /* allocate memory for our device state and intialize it */ - cardstate = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); - if (!cardstate) - goto error; - /* register this driver with the USB subsystem */ result = usb_register(&gigaset_usb_driver); if (result < 0) { @@ -951,9 +944,7 @@ static int __init usb_gigaset_init(void) info(DRIVER_DESC); return 0; -error: if (cardstate) - gigaset_freecs(cardstate); - cardstate = NULL; +error: if (driver) gigaset_freedriver(driver); driver = NULL; @@ -967,11 +958,16 @@ error: if (cardstate) */ static void __exit usb_gigaset_exit(void) { + int i; + gigaset_blockdriver(driver); /* => probe will fail * => no gigaset_start any more */ - gigaset_shutdown(cardstate); + /* stop all connected devices */ + for (i = 0; i < driver->minors; i++) + gigaset_shutdown(driver->cs + i); + /* from now on, no isdn callback should be possible */ /* deregister this driver with the USB subsystem */ @@ -979,8 +975,6 @@ static void __exit usb_gigaset_exit(void) /* this will call the disconnect-callback */ /* from now on, no disconnect/probe callback should be running */ - gigaset_freecs(cardstate); - cardstate = NULL; gigaset_freedriver(driver); driver = NULL; } |