diff options
author | Jan Kiszka <jan.kiszka@web.de> | 2010-02-08 05:12:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-16 19:01:28 -0500 |
commit | 0159d5491fef4acadd116a989b671e1cd350382f (patch) | |
tree | 2cc7d1567c18a6629ea641922880ece36ad765de /drivers/isdn/capi | |
parent | e95ac143868752ad30d93068a6fc0b39cf3a1bf4 (diff) |
CAPI: Use kref on capiminor
Install a reference counter for capiminor objects. Acquire it when
obtaining a capiminor from the array during capinc_tty_open, drop it
when closing the tty again. Another reference is held for the hook-up
with capincci.
Signed-off-by: Jan Kiszka <jan.kiszka@web.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn/capi')
-rw-r--r-- | drivers/isdn/capi/capi.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index b1de0cbea69e..732cdb585b2d 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c | |||
@@ -83,6 +83,8 @@ struct datahandle_queue { | |||
83 | }; | 83 | }; |
84 | 84 | ||
85 | struct capiminor { | 85 | struct capiminor { |
86 | struct kref kref; | ||
87 | |||
86 | struct capincci *nccip; | 88 | struct capincci *nccip; |
87 | unsigned int minor; | 89 | unsigned int minor; |
88 | struct dentry *capifs_dentry; | 90 | struct dentry *capifs_dentry; |
@@ -223,6 +225,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) | |||
223 | return NULL; | 225 | return NULL; |
224 | } | 226 | } |
225 | 227 | ||
228 | kref_init(&mp->kref); | ||
229 | |||
226 | mp->ap = ap; | 230 | mp->ap = ap; |
227 | mp->ncci = ncci; | 231 | mp->ncci = ncci; |
228 | mp->msgid = 0; | 232 | mp->msgid = 0; |
@@ -265,18 +269,11 @@ err_out1: | |||
265 | return NULL; | 269 | return NULL; |
266 | } | 270 | } |
267 | 271 | ||
268 | static void capiminor_free(struct capiminor *mp) | 272 | static void capiminor_destroy(struct kref *kref) |
269 | { | 273 | { |
270 | unsigned long flags; | 274 | struct capiminor *mp = container_of(kref, struct capiminor, kref); |
271 | |||
272 | tty_unregister_device(capinc_tty_driver, mp->minor); | ||
273 | |||
274 | write_lock_irqsave(&capiminors_lock, flags); | ||
275 | capiminors[mp->minor] = NULL; | ||
276 | write_unlock_irqrestore(&capiminors_lock, flags); | ||
277 | 275 | ||
278 | kfree_skb(mp->ttyskb); | 276 | kfree_skb(mp->ttyskb); |
279 | mp->ttyskb = NULL; | ||
280 | skb_queue_purge(&mp->inqueue); | 277 | skb_queue_purge(&mp->inqueue); |
281 | skb_queue_purge(&mp->outqueue); | 278 | skb_queue_purge(&mp->outqueue); |
282 | capiminor_del_all_ack(mp); | 279 | capiminor_del_all_ack(mp); |
@@ -289,11 +286,31 @@ static struct capiminor *capiminor_get(unsigned int minor) | |||
289 | 286 | ||
290 | read_lock(&capiminors_lock); | 287 | read_lock(&capiminors_lock); |
291 | mp = capiminors[minor]; | 288 | mp = capiminors[minor]; |
289 | if (mp) | ||
290 | kref_get(&mp->kref); | ||
292 | read_unlock(&capiminors_lock); | 291 | read_unlock(&capiminors_lock); |
293 | 292 | ||
294 | return mp; | 293 | return mp; |
295 | } | 294 | } |
296 | 295 | ||
296 | static inline void capiminor_put(struct capiminor *mp) | ||
297 | { | ||
298 | kref_put(&mp->kref, capiminor_destroy); | ||
299 | } | ||
300 | |||
301 | static void capiminor_free(struct capiminor *mp) | ||
302 | { | ||
303 | unsigned long flags; | ||
304 | |||
305 | tty_unregister_device(capinc_tty_driver, mp->minor); | ||
306 | |||
307 | write_lock_irqsave(&capiminors_lock, flags); | ||
308 | capiminors[mp->minor] = NULL; | ||
309 | write_unlock_irqrestore(&capiminors_lock, flags); | ||
310 | |||
311 | capiminor_put(mp); | ||
312 | } | ||
313 | |||
297 | /* -------- struct capincci ----------------------------------------- */ | 314 | /* -------- struct capincci ----------------------------------------- */ |
298 | 315 | ||
299 | static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) | 316 | static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) |
@@ -1029,6 +1046,8 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file) | |||
1029 | #endif | 1046 | #endif |
1030 | if (mp->nccip == NULL) | 1047 | if (mp->nccip == NULL) |
1031 | capiminor_free(mp); | 1048 | capiminor_free(mp); |
1049 | |||
1050 | capiminor_put(mp); | ||
1032 | } | 1051 | } |
1033 | 1052 | ||
1034 | #ifdef _DEBUG_REFCOUNT | 1053 | #ifdef _DEBUG_REFCOUNT |