diff options
author | Tilman Schmidt <tilman@imap.cc> | 2010-03-14 08:58:05 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-03-15 19:00:49 -0400 |
commit | bc35b4e347c047fb1c665bb761ddb22482539f7f (patch) | |
tree | 4f5b4b1c882b2f36015e0aada78e9307e812a0f9 /drivers/isdn/gigaset/capi.c | |
parent | 4d823be98c5b24d94c7f41a384a4bb60d7848ad5 (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/gigaset/capi.c')
-rw-r--r-- | drivers/isdn/gigaset/capi.c | 44 |
1 files changed, 25 insertions, 19 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 | ||
2194 | static 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 | */ |
2208 | int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) | 2201 | int 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 | */ |
2260 | void gigaset_isdn_unregister(struct cardstate *cs) | 2245 | void 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 | |||
2254 | static 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 | */ | ||
2262 | void 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 | */ | ||
2271 | void gigaset_isdn_unregdrv(void) | ||
2272 | { | ||
2267 | unregister_capi_driver(&capi_driver_gigaset); | 2273 | unregister_capi_driver(&capi_driver_gigaset); |
2268 | } | 2274 | } |