Commit 0159d549 authored by Jan Kiszka's avatar Jan Kiszka Committed by David S. Miller

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: default avatarJan Kiszka <jan.kiszka@web.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e95ac143
...@@ -83,6 +83,8 @@ struct datahandle_queue { ...@@ -83,6 +83,8 @@ struct datahandle_queue {
}; };
struct capiminor { struct capiminor {
struct kref kref;
struct capincci *nccip; struct capincci *nccip;
unsigned int minor; unsigned int minor;
struct dentry *capifs_dentry; struct dentry *capifs_dentry;
...@@ -223,6 +225,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) ...@@ -223,6 +225,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
return NULL; return NULL;
} }
kref_init(&mp->kref);
mp->ap = ap; mp->ap = ap;
mp->ncci = ncci; mp->ncci = ncci;
mp->msgid = 0; mp->msgid = 0;
...@@ -265,18 +269,11 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) ...@@ -265,18 +269,11 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
return NULL; return NULL;
} }
static void capiminor_free(struct capiminor *mp) static void capiminor_destroy(struct kref *kref)
{ {
unsigned long flags; struct capiminor *mp = container_of(kref, struct capiminor, kref);
tty_unregister_device(capinc_tty_driver, mp->minor);
write_lock_irqsave(&capiminors_lock, flags);
capiminors[mp->minor] = NULL;
write_unlock_irqrestore(&capiminors_lock, flags);
kfree_skb(mp->ttyskb); kfree_skb(mp->ttyskb);
mp->ttyskb = NULL;
skb_queue_purge(&mp->inqueue); skb_queue_purge(&mp->inqueue);
skb_queue_purge(&mp->outqueue); skb_queue_purge(&mp->outqueue);
capiminor_del_all_ack(mp); capiminor_del_all_ack(mp);
...@@ -289,11 +286,31 @@ static struct capiminor *capiminor_get(unsigned int minor) ...@@ -289,11 +286,31 @@ static struct capiminor *capiminor_get(unsigned int minor)
read_lock(&capiminors_lock); read_lock(&capiminors_lock);
mp = capiminors[minor]; mp = capiminors[minor];
if (mp)
kref_get(&mp->kref);
read_unlock(&capiminors_lock); read_unlock(&capiminors_lock);
return mp; return mp;
} }
static inline void capiminor_put(struct capiminor *mp)
{
kref_put(&mp->kref, capiminor_destroy);
}
static void capiminor_free(struct capiminor *mp)
{
unsigned long flags;
tty_unregister_device(capinc_tty_driver, mp->minor);
write_lock_irqsave(&capiminors_lock, flags);
capiminors[mp->minor] = NULL;
write_unlock_irqrestore(&capiminors_lock, flags);
capiminor_put(mp);
}
/* -------- struct capincci ----------------------------------------- */ /* -------- struct capincci ----------------------------------------- */
static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) 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,6 +1046,8 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file)
#endif #endif
if (mp->nccip == NULL) if (mp->nccip == NULL)
capiminor_free(mp); capiminor_free(mp);
capiminor_put(mp);
} }
#ifdef _DEBUG_REFCOUNT #ifdef _DEBUG_REFCOUNT
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment