aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/capi
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@web.de>2010-02-08 05:12:27 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-16 19:01:28 -0500
commit0159d5491fef4acadd116a989b671e1cd350382f (patch)
tree2cc7d1567c18a6629ea641922880ece36ad765de /drivers/isdn/capi
parente95ac143868752ad30d93068a6fc0b39cf3a1bf4 (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.c37
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
85struct capiminor { 85struct 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
268static void capiminor_free(struct capiminor *mp) 272static 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
296static inline void capiminor_put(struct capiminor *mp)
297{
298 kref_put(&mp->kref, capiminor_destroy);
299}
300
301static 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
299static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) 316static 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