Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+28 −9
Original line number Original line Diff line number Diff line
@@ -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)
		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)
	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)


	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)
#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