forked from Minki/linux
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:
parent
a045171f87
commit
12b20ded6f
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user