aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/gigaset/bas-gigaset.c
diff options
context:
space:
mode:
authorTilman Schmidt <tilman@imap.cc>2008-02-06 04:38:29 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-06 13:41:12 -0500
commite468c04894f36045cf93d1384183a461014b6840 (patch)
treeb734bbc4ee65f8282de5299dc200f47ea466067a /drivers/isdn/gigaset/bas-gigaset.c
parent9d4bee2b9de9e30057a860d2d6794f874caffc5e (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/bas-gigaset.c')
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c80
1 files changed, 39 insertions, 41 deletions
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 7c905305406b..5255b5e20e13 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -134,7 +134,6 @@ struct bas_cardstate {
134 134
135 135
136static struct gigaset_driver *driver = NULL; 136static struct gigaset_driver *driver = NULL;
137static struct cardstate *cardstate = NULL;
138 137
139/* 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 */
140static struct usb_driver gigaset_usb_driver = { 139static struct usb_driver gigaset_usb_driver = {
@@ -2247,11 +2246,11 @@ static int gigaset_probe(struct usb_interface *interface,
2247 __func__, le16_to_cpu(udev->descriptor.idVendor), 2246 __func__, le16_to_cpu(udev->descriptor.idVendor),
2248 le16_to_cpu(udev->descriptor.idProduct)); 2247 le16_to_cpu(udev->descriptor.idProduct));
2249 2248
2250 cs = gigaset_getunassignedcs(driver); 2249 /* allocate memory for our device state and intialize it */
2251 if (!cs) { 2250 cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode,
2252 dev_err(&udev->dev, "no free cardstate\n"); 2251 GIGASET_MODULENAME);
2252 if (!cs)
2253 return -ENODEV; 2253 return -ENODEV;
2254 }
2255 ucs = cs->hw.bas; 2254 ucs = cs->hw.bas;
2256 2255
2257 /* save off device structure ptrs for later use */ 2256 /* save off device structure ptrs for later use */
@@ -2320,7 +2319,7 @@ allocerr:
2320error: 2319error:
2321 freeurbs(cs); 2320 freeurbs(cs);
2322 usb_set_intfdata(interface, NULL); 2321 usb_set_intfdata(interface, NULL);
2323 gigaset_unassign(cs); 2322 gigaset_freecs(cs);
2324 return -ENODEV; 2323 return -ENODEV;
2325} 2324}
2326 2325
@@ -2362,7 +2361,7 @@ static void gigaset_disconnect(struct usb_interface *interface)
2362 ucs->interface = NULL; 2361 ucs->interface = NULL;
2363 ucs->udev = NULL; 2362 ucs->udev = NULL;
2364 cs->dev = NULL; 2363 cs->dev = NULL;
2365 gigaset_unassign(cs); 2364 gigaset_freecs(cs);
2366} 2365}
2367 2366
2368/* gigaset_suspend 2367/* gigaset_suspend
@@ -2501,12 +2500,6 @@ static int __init bas_gigaset_init(void)
2501 &gigops, THIS_MODULE)) == NULL) 2500 &gigops, THIS_MODULE)) == NULL)
2502 goto error; 2501 goto error;
2503 2502
2504 /* allocate memory for our device state and intialize it */
2505 cardstate = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode,
2506 GIGASET_MODULENAME);
2507 if (!cardstate)
2508 goto error;
2509
2510 /* register this driver with the USB subsystem */ 2503 /* register this driver with the USB subsystem */
2511 result = usb_register(&gigaset_usb_driver); 2504 result = usb_register(&gigaset_usb_driver);
2512 if (result < 0) { 2505 if (result < 0) {
@@ -2518,9 +2511,7 @@ static int __init bas_gigaset_init(void)
2518 info(DRIVER_DESC); 2511 info(DRIVER_DESC);
2519 return 0; 2512 return 0;
2520 2513
2521error: if (cardstate) 2514error:
2522 gigaset_freecs(cardstate);
2523 cardstate = NULL;
2524 if (driver) 2515 if (driver)
2525 gigaset_freedriver(driver); 2516 gigaset_freedriver(driver);
2526 driver = NULL; 2517 driver = NULL;
@@ -2532,43 +2523,50 @@ error: if (cardstate)
2532 */ 2523 */
2533static void __exit bas_gigaset_exit(void) 2524static void __exit bas_gigaset_exit(void)
2534{ 2525{
2535 struct bas_cardstate *ucs = cardstate->hw.bas; 2526 struct bas_cardstate *ucs;
2527 int i;
2536 2528
2537 gigaset_blockdriver(driver); /* => probe will fail 2529 gigaset_blockdriver(driver); /* => probe will fail
2538 * => no gigaset_start any more 2530 * => no gigaset_start any more
2539 */ 2531 */
2540 2532
2541 gigaset_shutdown(cardstate); 2533 /* stop all connected devices */
2542 /* from now on, no isdn callback should be possible */ 2534 for (i = 0; i < driver->minors; i++) {
2543 2535 if (gigaset_shutdown(driver->cs + i) < 0)
2544 /* close all still open channels */ 2536 continue; /* no device */
2545 if (ucs->basstate & BS_B1OPEN) { 2537 /* from now on, no isdn callback should be possible */
2546 gig_dbg(DEBUG_INIT, "closing B1 channel"); 2538
2547 usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), 2539 /* close all still open channels */
2548 HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0, 2540 ucs = driver->cs[i].hw.bas;
2549 NULL, 0, BAS_TIMEOUT); 2541 if (ucs->basstate & BS_B1OPEN) {
2550 } 2542 gig_dbg(DEBUG_INIT, "closing B1 channel");
2551 if (ucs->basstate & BS_B2OPEN) { 2543 usb_control_msg(ucs->udev,
2552 gig_dbg(DEBUG_INIT, "closing B2 channel"); 2544 usb_sndctrlpipe(ucs->udev, 0),
2553 usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), 2545 HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ,
2554 HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0, 2546 0, 0, NULL, 0, BAS_TIMEOUT);
2555 NULL, 0, BAS_TIMEOUT); 2547 }
2556 } 2548 if (ucs->basstate & BS_B2OPEN) {
2557 if (ucs->basstate & BS_ATOPEN) { 2549 gig_dbg(DEBUG_INIT, "closing B2 channel");
2558 gig_dbg(DEBUG_INIT, "closing AT channel"); 2550 usb_control_msg(ucs->udev,
2559 usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), 2551 usb_sndctrlpipe(ucs->udev, 0),
2560 HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0, 2552 HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ,
2561 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;
2562 } 2563 }
2563 ucs->basstate = 0;
2564 2564
2565 /* deregister this driver with the USB subsystem */ 2565 /* deregister this driver with the USB subsystem */
2566 usb_deregister(&gigaset_usb_driver); 2566 usb_deregister(&gigaset_usb_driver);
2567 /* this will call the disconnect-callback */ 2567 /* this will call the disconnect-callback */
2568 /* from now on, no disconnect/probe callback should be running */ 2568 /* from now on, no disconnect/probe callback should be running */
2569 2569
2570 gigaset_freecs(cardstate);
2571 cardstate = NULL;
2572 gigaset_freedriver(driver); 2570 gigaset_freedriver(driver);
2573 driver = NULL; 2571 driver = NULL;
2574} 2572}