Commit 12b20ded authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

kobject: convert hvc_console to use kref, not kobject



hvc_console is using a kobject only for reference counting, nothing
else.  So switch it to use a kref instead, which is all that is needed,
and is much smaller.

Cc: Anton Blanchard <anton@au.ibm.com>
Cc: Paul Mackerras <paulus@au.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Ryan S. Arnold <rsa@us.ibm.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a045171f
Loading
Loading
Loading
Loading
+33 −47
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@
#include <linux/init.h>
#include <linux/kbd_kern.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/kref.h>
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -89,7 +89,7 @@ struct hvc_struct {
	int irq_requested;
	int irq;
	struct list_head next;
	struct kobject kobj; /* ref count & hvc_struct lifetime */
	struct kref kref; /* ref count & hvc_struct lifetime */
};

/* dynamic list of hvc_struct instances */
@@ -110,7 +110,7 @@ static int last_hvc = -1;

/*
 * Do not call this function with either the hvc_structs_lock or the hvc_struct
 * lock held.  If successful, this function increments the kobject reference
 * lock held.  If successful, this function increments the kref reference
 * count against the target hvc_struct so it should be released when finished.
 */
static struct hvc_struct *hvc_get_by_index(int index)
@@ -123,7 +123,7 @@ static struct hvc_struct *hvc_get_by_index(int index)
	list_for_each_entry(hp, &hvc_structs, next) {
		spin_lock_irqsave(&hp->lock, flags);
		if (hp->index == index) {
			kobject_get(&hp->kobj);
			kref_get(&hp->kref);
			spin_unlock_irqrestore(&hp->lock, flags);
			spin_unlock(&hvc_structs_lock);
			return hp;
@@ -242,6 +242,23 @@ static int __init hvc_console_init(void)
}
console_initcall(hvc_console_init);

/* callback when the kboject ref count reaches zero. */
static void destroy_hvc_struct(struct kref *kref)
{
	struct hvc_struct *hp = container_of(kref, struct hvc_struct, kref);
	unsigned long flags;

	spin_lock(&hvc_structs_lock);

	spin_lock_irqsave(&hp->lock, flags);
	list_del(&(hp->next));
	spin_unlock_irqrestore(&hp->lock, flags);

	spin_unlock(&hvc_structs_lock);

	kfree(hp);
}

/*
 * hvc_instantiate() is an early console discovery method which locates
 * consoles * prior to the vio subsystem discovering them.  Hotplugged
@@ -261,7 +278,7 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
	/* make sure no no tty has been registered in this index */
	hp = hvc_get_by_index(index);
	if (hp) {
		kobject_put(&hp->kobj);
		kref_put(&hp->kref, destroy_hvc_struct);
		return -1;
	}

@@ -318,9 +335,8 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
	unsigned long flags;
	int irq = 0;
	int rc = 0;
	struct kobject *kobjp;

	/* Auto increments kobject reference if found. */
	/* Auto increments kref reference if found. */
	if (!(hp = hvc_get_by_index(tty->index)))
		return -ENODEV;

@@ -341,8 +357,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
	if (irq)
		hp->irq_requested = 1;

	kobjp = &hp->kobj;

	spin_unlock_irqrestore(&hp->lock, flags);
	/* check error, fallback to non-irq */
	if (irq)
@@ -352,7 +366,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
	 * If the request_irq() fails and we return an error.  The tty layer
	 * will call hvc_close() after a failed open but we don't want to clean
	 * up there so we'll clean up here and clear out the previously set
	 * tty fields and return the kobject reference.
	 * tty fields and return the kref reference.
	 */
	if (rc) {
		spin_lock_irqsave(&hp->lock, flags);
@@ -360,7 +374,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
		hp->irq_requested = 0;
		spin_unlock_irqrestore(&hp->lock, flags);
		tty->driver_data = NULL;
		kobject_put(kobjp);
		kref_put(&hp->kref, destroy_hvc_struct);
		printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
	}
	/* Force wakeup of the polling thread */
@@ -372,7 +386,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
static void hvc_close(struct tty_struct *tty, struct file * filp)
{
	struct hvc_struct *hp;
	struct kobject *kobjp;
	int irq = 0;
	unsigned long flags;

@@ -382,7 +395,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
	/*
	 * No driver_data means that this close was issued after a failed
	 * hvc_open by the tty layer's release_dev() function and we can just
	 * exit cleanly because the kobject reference wasn't made.
	 * exit cleanly because the kref reference wasn't made.
	 */
	if (!tty->driver_data)
		return;
@@ -390,7 +403,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
	hp = tty->driver_data;
	spin_lock_irqsave(&hp->lock, flags);

	kobjp = &hp->kobj;
	if (--hp->count == 0) {
		if (hp->irq_requested)
			irq = hp->irq;
@@ -417,7 +429,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
		spin_unlock_irqrestore(&hp->lock, flags);
	}

	kobject_put(kobjp);
	kref_put(&hp->kref, destroy_hvc_struct);
}

static void hvc_hangup(struct tty_struct *tty)
@@ -426,7 +438,6 @@ static void hvc_hangup(struct tty_struct *tty)
	unsigned long flags;
	int irq = 0;
	int temp_open_count;
	struct kobject *kobjp;

	if (!hp)
		return;
@@ -443,7 +454,6 @@ static void hvc_hangup(struct tty_struct *tty)
		return;
	}

	kobjp = &hp->kobj;
	temp_open_count = hp->count;
	hp->count = 0;
	hp->n_outbuf = 0;
@@ -457,7 +467,7 @@ static void hvc_hangup(struct tty_struct *tty)
		free_irq(irq, hp);
	while(temp_open_count) {
		--temp_open_count;
		kobject_put(kobjp);
		kref_put(&hp->kref, destroy_hvc_struct);
	}
}

@@ -729,27 +739,6 @@ static const struct tty_operations hvc_ops = {
	.chars_in_buffer = hvc_chars_in_buffer,
};

/* callback when the kboject ref count reaches zero. */
static void destroy_hvc_struct(struct kobject *kobj)
{
	struct hvc_struct *hp = container_of(kobj, struct hvc_struct, kobj);
	unsigned long flags;

	spin_lock(&hvc_structs_lock);

	spin_lock_irqsave(&hp->lock, flags);
	list_del(&(hp->next));
	spin_unlock_irqrestore(&hp->lock, flags);

	spin_unlock(&hvc_structs_lock);

	kfree(hp);
}

static struct kobj_type hvc_kobj_type = {
	.release = destroy_hvc_struct,
};

struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
					struct hv_ops *ops, int outbuf_size)
{
@@ -776,8 +765,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
	hp->outbuf_size = outbuf_size;
	hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];

	kobject_init(&hp->kobj);
	hp->kobj.ktype = &hvc_kobj_type;
	kref_init(&hp->kref);

	spin_lock_init(&hp->lock);
	spin_lock(&hvc_structs_lock);
@@ -806,12 +794,10 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
int __devexit hvc_remove(struct hvc_struct *hp)
{
	unsigned long flags;
	struct kobject *kobjp;
	struct tty_struct *tty;

	spin_lock_irqsave(&hp->lock, flags);
	tty = hp->tty;
	kobjp = &hp->kobj;

	if (hp->index < MAX_NR_HVC_CONSOLES)
		vtermnos[hp->index] = -1;
@@ -821,12 +807,12 @@ int __devexit hvc_remove(struct hvc_struct *hp)
	spin_unlock_irqrestore(&hp->lock, flags);

	/*
	 * We 'put' the instance that was grabbed when the kobject instance
	 * was initialized using kobject_init().  Let the last holder of this
	 * kobject cause it to be removed, which will probably be the tty_hangup
	 * We 'put' the instance that was grabbed when the kref instance
	 * was initialized using kref_init().  Let the last holder of this
	 * kref cause it to be removed, which will probably be the tty_hangup
	 * below.
	 */
	kobject_put(kobjp);
	kref_put(&hp->kref, destroy_hvc_struct);

	/*
	 * This function call will auto chain call hvc_hangup.  The tty should