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: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Greg Kroah-Hartman 2007-11-28 10:46:22 -08:00
Родитель a045171f87
Коммит 12b20ded6f
1 изменённых файлов: 33 добавлений и 47 удалений

Просмотреть файл

@ -27,7 +27,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kbd_kern.h> #include <linux/kbd_kern.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kobject.h> #include <linux/kref.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
@ -89,7 +89,7 @@ struct hvc_struct {
int irq_requested; int irq_requested;
int irq; int irq;
struct list_head next; 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 */ /* 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 * 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. * count against the target hvc_struct so it should be released when finished.
*/ */
static struct hvc_struct *hvc_get_by_index(int index) 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) { list_for_each_entry(hp, &hvc_structs, next) {
spin_lock_irqsave(&hp->lock, flags); spin_lock_irqsave(&hp->lock, flags);
if (hp->index == index) { if (hp->index == index) {
kobject_get(&hp->kobj); kref_get(&hp->kref);
spin_unlock_irqrestore(&hp->lock, flags); spin_unlock_irqrestore(&hp->lock, flags);
spin_unlock(&hvc_structs_lock); spin_unlock(&hvc_structs_lock);
return hp; return hp;
@ -242,6 +242,23 @@ static int __init hvc_console_init(void)
} }
console_initcall(hvc_console_init); 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 * hvc_instantiate() is an early console discovery method which locates
* consoles * prior to the vio subsystem discovering them. Hotplugged * 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 */ /* make sure no no tty has been registered in this index */
hp = hvc_get_by_index(index); hp = hvc_get_by_index(index);
if (hp) { if (hp) {
kobject_put(&hp->kobj); kref_put(&hp->kref, destroy_hvc_struct);
return -1; return -1;
} }
@ -318,9 +335,8 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
unsigned long flags; unsigned long flags;
int irq = 0; int irq = 0;
int rc = 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))) if (!(hp = hvc_get_by_index(tty->index)))
return -ENODEV; return -ENODEV;
@ -341,8 +357,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
if (irq) if (irq)
hp->irq_requested = 1; hp->irq_requested = 1;
kobjp = &hp->kobj;
spin_unlock_irqrestore(&hp->lock, flags); spin_unlock_irqrestore(&hp->lock, flags);
/* check error, fallback to non-irq */ /* check error, fallback to non-irq */
if (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 * 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 * 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 * 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) { if (rc) {
spin_lock_irqsave(&hp->lock, flags); 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; hp->irq_requested = 0;
spin_unlock_irqrestore(&hp->lock, flags); spin_unlock_irqrestore(&hp->lock, flags);
tty->driver_data = NULL; 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); printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
} }
/* Force wakeup of the polling thread */ /* 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) static void hvc_close(struct tty_struct *tty, struct file * filp)
{ {
struct hvc_struct *hp; struct hvc_struct *hp;
struct kobject *kobjp;
int irq = 0; int irq = 0;
unsigned long flags; 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 * 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 * 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) if (!tty->driver_data)
return; return;
@ -390,7 +403,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
hp = tty->driver_data; hp = tty->driver_data;
spin_lock_irqsave(&hp->lock, flags); spin_lock_irqsave(&hp->lock, flags);
kobjp = &hp->kobj;
if (--hp->count == 0) { if (--hp->count == 0) {
if (hp->irq_requested) if (hp->irq_requested)
irq = hp->irq; irq = hp->irq;
@ -417,7 +429,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
spin_unlock_irqrestore(&hp->lock, flags); spin_unlock_irqrestore(&hp->lock, flags);
} }
kobject_put(kobjp); kref_put(&hp->kref, destroy_hvc_struct);
} }
static void hvc_hangup(struct tty_struct *tty) static void hvc_hangup(struct tty_struct *tty)
@ -426,7 +438,6 @@ static void hvc_hangup(struct tty_struct *tty)
unsigned long flags; unsigned long flags;
int irq = 0; int irq = 0;
int temp_open_count; int temp_open_count;
struct kobject *kobjp;
if (!hp) if (!hp)
return; return;
@ -443,7 +454,6 @@ static void hvc_hangup(struct tty_struct *tty)
return; return;
} }
kobjp = &hp->kobj;
temp_open_count = hp->count; temp_open_count = hp->count;
hp->count = 0; hp->count = 0;
hp->n_outbuf = 0; hp->n_outbuf = 0;
@ -457,7 +467,7 @@ static void hvc_hangup(struct tty_struct *tty)
free_irq(irq, hp); free_irq(irq, hp);
while(temp_open_count) { while(temp_open_count) {
--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, .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 hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
struct hv_ops *ops, int outbuf_size) 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_size = outbuf_size;
hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
kobject_init(&hp->kobj); kref_init(&hp->kref);
hp->kobj.ktype = &hvc_kobj_type;
spin_lock_init(&hp->lock); spin_lock_init(&hp->lock);
spin_lock(&hvc_structs_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) int __devexit hvc_remove(struct hvc_struct *hp)
{ {
unsigned long flags; unsigned long flags;
struct kobject *kobjp;
struct tty_struct *tty; struct tty_struct *tty;
spin_lock_irqsave(&hp->lock, flags); spin_lock_irqsave(&hp->lock, flags);
tty = hp->tty; tty = hp->tty;
kobjp = &hp->kobj;
if (hp->index < MAX_NR_HVC_CONSOLES) if (hp->index < MAX_NR_HVC_CONSOLES)
vtermnos[hp->index] = -1; vtermnos[hp->index] = -1;
@ -821,12 +807,12 @@ int __devexit hvc_remove(struct hvc_struct *hp)
spin_unlock_irqrestore(&hp->lock, flags); spin_unlock_irqrestore(&hp->lock, flags);
/* /*
* We 'put' the instance that was grabbed when the kobject instance * We 'put' the instance that was grabbed when the kref instance
* was initialized using kobject_init(). Let the last holder of this * was initialized using kref_init(). Let the last holder of this
* kobject cause it to be removed, which will probably be the tty_hangup * kref cause it to be removed, which will probably be the tty_hangup
* below. * below.
*/ */
kobject_put(kobjp); kref_put(&hp->kref, destroy_hvc_struct);
/* /*
* This function call will auto chain call hvc_hangup. The tty should * This function call will auto chain call hvc_hangup. The tty should