aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
authorTilman Schmidt <tilman@imap.cc>2010-03-14 08:58:05 -0400
committerDavid S. Miller <davem@davemloft.net>2010-03-15 19:00:49 -0400
commitbc35b4e347c047fb1c665bb761ddb22482539f7f (patch)
tree4f5b4b1c882b2f36015e0aada78e9307e812a0f9 /drivers/isdn
parent4d823be98c5b24d94c7f41a384a4bb60d7848ad5 (diff)
gigaset: avoid registering CAPI driver more than once
Registering/unregistering the Gigaset CAPI driver when a device is connected/disconnected causes an Oops when disconnecting two Gigaset devices in a row, because the same capi_driver structure gets unregistered twice. Fix by making driver registration/unregistration a separate operation (empty in the ISDN4Linux case) called when the main module is loaded/unloaded. Impact: bugfix Signed-off-by: Tilman Schmidt <tilman@imap.cc> Acked-by: Karsten Keil <keil@b1-systems.de> CC: stable@kernel.org Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/gigaset/capi.c44
-rw-r--r--drivers/isdn/gigaset/common.c6
-rw-r--r--drivers/isdn/gigaset/gigaset.h6
-rw-r--r--drivers/isdn/gigaset/i4l.c28
4 files changed, 53 insertions, 31 deletions
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 6643d6533ccb..4a31962ddf71 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -2191,36 +2191,24 @@ static const struct file_operations gigaset_proc_fops = {
2191 .release = single_release, 2191 .release = single_release,
2192}; 2192};
2193 2193
2194static struct capi_driver capi_driver_gigaset = {
2195 .name = "gigaset",
2196 .revision = "1.0",
2197};
2198
2199/** 2194/**
2200 * gigaset_isdn_register() - register to LL 2195 * gigaset_isdn_regdev() - register device to LL
2201 * @cs: device descriptor structure. 2196 * @cs: device descriptor structure.
2202 * @isdnid: device name. 2197 * @isdnid: device name.
2203 * 2198 *
2204 * Called by main module to register the device with the LL.
2205 *
2206 * Return value: 1 for success, 0 for failure 2199 * Return value: 1 for success, 0 for failure
2207 */ 2200 */
2208int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) 2201int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
2209{ 2202{
2210 struct gigaset_capi_ctr *iif; 2203 struct gigaset_capi_ctr *iif;
2211 int rc; 2204 int rc;
2212 2205
2213 pr_info("Kernel CAPI interface\n");
2214
2215 iif = kmalloc(sizeof(*iif), GFP_KERNEL); 2206 iif = kmalloc(sizeof(*iif), GFP_KERNEL);
2216 if (!iif) { 2207 if (!iif) {
2217 pr_err("%s: out of memory\n", __func__); 2208 pr_err("%s: out of memory\n", __func__);
2218 return 0; 2209 return 0;
2219 } 2210 }
2220 2211
2221 /* register driver with CAPI (ToDo: what for?) */
2222 register_capi_driver(&capi_driver_gigaset);
2223
2224 /* prepare controller structure */ 2212 /* prepare controller structure */
2225 iif->ctr.owner = THIS_MODULE; 2213 iif->ctr.owner = THIS_MODULE;
2226 iif->ctr.driverdata = cs; 2214 iif->ctr.driverdata = cs;
@@ -2241,7 +2229,6 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
2241 rc = attach_capi_ctr(&iif->ctr); 2229 rc = attach_capi_ctr(&iif->ctr);
2242 if (rc) { 2230 if (rc) {
2243 pr_err("attach_capi_ctr failed (%d)\n", rc); 2231 pr_err("attach_capi_ctr failed (%d)\n", rc);
2244 unregister_capi_driver(&capi_driver_gigaset);
2245 kfree(iif); 2232 kfree(iif);
2246 return 0; 2233 return 0;
2247 } 2234 }
@@ -2252,17 +2239,36 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
2252} 2239}
2253 2240
2254/** 2241/**
2255 * gigaset_isdn_unregister() - unregister from LL 2242 * gigaset_isdn_unregdev() - unregister device from LL
2256 * @cs: device descriptor structure. 2243 * @cs: device descriptor structure.
2257 *
2258 * Called by main module to unregister the device from the LL.
2259 */ 2244 */
2260void gigaset_isdn_unregister(struct cardstate *cs) 2245void gigaset_isdn_unregdev(struct cardstate *cs)
2261{ 2246{
2262 struct gigaset_capi_ctr *iif = cs->iif; 2247 struct gigaset_capi_ctr *iif = cs->iif;
2263 2248
2264 detach_capi_ctr(&iif->ctr); 2249 detach_capi_ctr(&iif->ctr);
2265 kfree(iif); 2250 kfree(iif);
2266 cs->iif = NULL; 2251 cs->iif = NULL;
2252}
2253
2254static struct capi_driver capi_driver_gigaset = {
2255 .name = "gigaset",
2256 .revision = "1.0",
2257};
2258
2259/**
2260 * gigaset_isdn_regdrv() - register driver to LL
2261 */
2262void gigaset_isdn_regdrv(void)
2263{
2264 pr_info("Kernel CAPI interface\n");
2265 register_capi_driver(&capi_driver_gigaset);
2266}
2267
2268/**
2269 * gigaset_isdn_unregdrv() - unregister driver from LL
2270 */
2271void gigaset_isdn_unregdrv(void)
2272{
2267 unregister_capi_driver(&capi_driver_gigaset); 2273 unregister_capi_driver(&capi_driver_gigaset);
2268} 2274}
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 85de3399a2f2..bdc01cb9f0ab 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -507,7 +507,7 @@ void gigaset_freecs(struct cardstate *cs)
507 case 2: /* error in initcshw */ 507 case 2: /* error in initcshw */
508 /* Deregister from LL */ 508 /* Deregister from LL */
509 make_invalid(cs, VALID_ID); 509 make_invalid(cs, VALID_ID);
510 gigaset_isdn_unregister(cs); 510 gigaset_isdn_unregdev(cs);
511 511
512 /* fall through */ 512 /* fall through */
513 case 1: /* error when registering to LL */ 513 case 1: /* error when registering to LL */
@@ -769,7 +769,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
769 cs->cmdbytes = 0; 769 cs->cmdbytes = 0;
770 770
771 gig_dbg(DEBUG_INIT, "setting up iif"); 771 gig_dbg(DEBUG_INIT, "setting up iif");
772 if (!gigaset_isdn_register(cs, modulename)) { 772 if (!gigaset_isdn_regdev(cs, modulename)) {
773 pr_err("error registering ISDN device\n"); 773 pr_err("error registering ISDN device\n");
774 goto error; 774 goto error;
775 } 775 }
@@ -1205,11 +1205,13 @@ static int __init gigaset_init_module(void)
1205 gigaset_debuglevel = DEBUG_DEFAULT; 1205 gigaset_debuglevel = DEBUG_DEFAULT;
1206 1206
1207 pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n"); 1207 pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n");
1208 gigaset_isdn_regdrv();
1208 return 0; 1209 return 0;
1209} 1210}
1210 1211
1211static void __exit gigaset_exit_module(void) 1212static void __exit gigaset_exit_module(void)
1212{ 1213{
1214 gigaset_isdn_unregdrv();
1213} 1215}
1214 1216
1215module_init(gigaset_init_module); 1217module_init(gigaset_init_module);
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 1875ab80b335..cdd144ecdc5f 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -675,8 +675,10 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size);
675 */ 675 */
676 676
677/* Called from common.c for setting up/shutting down with the ISDN subsystem */ 677/* Called from common.c for setting up/shutting down with the ISDN subsystem */
678int gigaset_isdn_register(struct cardstate *cs, const char *isdnid); 678void gigaset_isdn_regdrv(void);
679void gigaset_isdn_unregister(struct cardstate *cs); 679void gigaset_isdn_unregdrv(void);
680int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid);
681void gigaset_isdn_unregdev(struct cardstate *cs);
680 682
681/* Called from hardware module to indicate completion of an skb */ 683/* Called from hardware module to indicate completion of an skb */
682void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); 684void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb);
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index f0acb9dc9e33..c22e5ace8276 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -592,15 +592,13 @@ void gigaset_isdn_stop(struct cardstate *cs)
592} 592}
593 593
594/** 594/**
595 * gigaset_isdn_register() - register to LL 595 * gigaset_isdn_regdev() - register to LL
596 * @cs: device descriptor structure. 596 * @cs: device descriptor structure.
597 * @isdnid: device name. 597 * @isdnid: device name.
598 * 598 *
599 * Called by main module to register the device with the LL.
600 *
601 * Return value: 1 for success, 0 for failure 599 * Return value: 1 for success, 0 for failure
602 */ 600 */
603int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) 601int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
604{ 602{
605 isdn_if *iif; 603 isdn_if *iif;
606 604
@@ -650,15 +648,29 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
650} 648}
651 649
652/** 650/**
653 * gigaset_isdn_unregister() - unregister from LL 651 * gigaset_isdn_unregdev() - unregister device from LL
654 * @cs: device descriptor structure. 652 * @cs: device descriptor structure.
655 *
656 * Called by main module to unregister the device from the LL.
657 */ 653 */
658void gigaset_isdn_unregister(struct cardstate *cs) 654void gigaset_isdn_unregdev(struct cardstate *cs)
659{ 655{
660 gig_dbg(DEBUG_CMD, "sending UNLOAD"); 656 gig_dbg(DEBUG_CMD, "sending UNLOAD");
661 gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); 657 gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
662 kfree(cs->iif); 658 kfree(cs->iif);
663 cs->iif = NULL; 659 cs->iif = NULL;
664} 660}
661
662/**
663 * gigaset_isdn_regdrv() - register driver to LL
664 */
665void gigaset_isdn_regdrv(void)
666{
667 /* nothing to do */
668}
669
670/**
671 * gigaset_isdn_unregdrv() - unregister driver from LL
672 */
673void gigaset_isdn_unregdrv(void)
674{
675 /* nothing to do */
676}