Commit f7eb12c6 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

kobject: convert hvcs to use kref, not kobject

hvcs 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 12b20ded
...@@ -57,11 +57,7 @@ ...@@ -57,11 +57,7 @@
* rescanning partner information upon a user's request. * rescanning partner information upon a user's request.
* *
* Each vty-server, prior to being exposed to this driver is reference counted * Each vty-server, prior to being exposed to this driver is reference counted
* using the 2.6 Linux kernel kobject construct. This kobject is also used by * using the 2.6 Linux kernel kref construct.
* the vio bus to provide a vio device sysfs entry that this driver attaches
* device specific attributes to, including partner information. The vio bus
* framework also provides a sysfs entry for each vio driver. The hvcs driver
* provides driver attributes in this entry.
* *
* For direction on installation and usage of this driver please reference * For direction on installation and usage of this driver please reference
* Documentation/powerpc/hvcs.txt. * Documentation/powerpc/hvcs.txt.
...@@ -71,7 +67,7 @@ ...@@ -71,7 +67,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.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/major.h> #include <linux/major.h>
...@@ -293,12 +289,12 @@ struct hvcs_struct { ...@@ -293,12 +289,12 @@ struct hvcs_struct {
int chars_in_buffer; int chars_in_buffer;
/* /*
* Any variable below the kobject is valid before a tty is connected and * Any variable below the kref is valid before a tty is connected and
* stays valid after the tty is disconnected. These shouldn't be * stays valid after the tty is disconnected. These shouldn't be
* whacked until the koject refcount reaches zero though some entries * whacked until the koject refcount reaches zero though some entries
* may be changed via sysfs initiatives. * may be changed via sysfs initiatives.
*/ */
struct kobject kobj; /* ref count & hvcs_struct lifetime */ struct kref kref; /* ref count & hvcs_struct lifetime */
int connected; /* is the vty-server currently connected to a vty? */ int connected; /* is the vty-server currently connected to a vty? */
uint32_t p_unit_address; /* partner unit address */ uint32_t p_unit_address; /* partner unit address */
uint32_t p_partition_ID; /* partner partition ID */ uint32_t p_partition_ID; /* partner partition ID */
...@@ -307,8 +303,8 @@ struct hvcs_struct { ...@@ -307,8 +303,8 @@ struct hvcs_struct {
struct vio_dev *vdev; struct vio_dev *vdev;
}; };
/* Required to back map a kobject to its containing object */ /* Required to back map a kref to its containing object */
#define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj) #define from_kref(k) container_of(k, struct hvcs_struct, kref)
static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs); static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
static DEFINE_SPINLOCK(hvcs_structs_lock); static DEFINE_SPINLOCK(hvcs_structs_lock);
...@@ -334,7 +330,6 @@ static void hvcs_partner_free(struct hvcs_struct *hvcsd); ...@@ -334,7 +330,6 @@ static void hvcs_partner_free(struct hvcs_struct *hvcsd);
static int hvcs_enable_device(struct hvcs_struct *hvcsd, static int hvcs_enable_device(struct hvcs_struct *hvcsd,
uint32_t unit_address, unsigned int irq, struct vio_dev *dev); uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
static void destroy_hvcs_struct(struct kobject *kobj);
static int hvcs_open(struct tty_struct *tty, struct file *filp); static int hvcs_open(struct tty_struct *tty, struct file *filp);
static void hvcs_close(struct tty_struct *tty, struct file *filp); static void hvcs_close(struct tty_struct *tty, struct file *filp);
static void hvcs_hangup(struct tty_struct * tty); static void hvcs_hangup(struct tty_struct * tty);
...@@ -703,10 +698,10 @@ static void hvcs_return_index(int index) ...@@ -703,10 +698,10 @@ static void hvcs_return_index(int index)
hvcs_index_list[index] = -1; hvcs_index_list[index] = -1;
} }
/* callback when the kboject ref count reaches zero */ /* callback when the kref ref count reaches zero */
static void destroy_hvcs_struct(struct kobject *kobj) static void destroy_hvcs_struct(struct kref *kref)
{ {
struct hvcs_struct *hvcsd = from_kobj(kobj); struct hvcs_struct *hvcsd = from_kref(kref);
struct vio_dev *vdev; struct vio_dev *vdev;
unsigned long flags; unsigned long flags;
...@@ -743,10 +738,6 @@ static void destroy_hvcs_struct(struct kobject *kobj) ...@@ -743,10 +738,6 @@ static void destroy_hvcs_struct(struct kobject *kobj)
kfree(hvcsd); kfree(hvcsd);
} }
static struct kobj_type hvcs_kobj_type = {
.release = destroy_hvcs_struct,
};
static int hvcs_get_index(void) static int hvcs_get_index(void)
{ {
int i; int i;
...@@ -791,9 +782,7 @@ static int __devinit hvcs_probe( ...@@ -791,9 +782,7 @@ static int __devinit hvcs_probe(
spin_lock_init(&hvcsd->lock); spin_lock_init(&hvcsd->lock);
/* Automatically incs the refcount the first time */ /* Automatically incs the refcount the first time */
kobject_init(&hvcsd->kobj); kref_init(&hvcsd->kref);
/* Set up the callback for terminating the hvcs_struct's life */
hvcsd->kobj.ktype = &hvcs_kobj_type;
hvcsd->vdev = dev; hvcsd->vdev = dev;
dev->dev.driver_data = hvcsd; dev->dev.driver_data = hvcsd;
...@@ -844,7 +833,6 @@ static int __devexit hvcs_remove(struct vio_dev *dev) ...@@ -844,7 +833,6 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
{ {
struct hvcs_struct *hvcsd = dev->dev.driver_data; struct hvcs_struct *hvcsd = dev->dev.driver_data;
unsigned long flags; unsigned long flags;
struct kobject *kobjp;
struct tty_struct *tty; struct tty_struct *tty;
if (!hvcsd) if (!hvcsd)
...@@ -856,15 +844,13 @@ static int __devexit hvcs_remove(struct vio_dev *dev) ...@@ -856,15 +844,13 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
tty = hvcsd->tty; tty = hvcsd->tty;
kobjp = &hvcsd->kobj;
spin_unlock_irqrestore(&hvcsd->lock, flags); spin_unlock_irqrestore(&hvcsd->lock, flags);
/* /*
* Let the last holder of this object cause it to be removed, which * Let the last holder of this object cause it to be removed, which
* would probably be tty_hangup below. * would probably be tty_hangup below.
*/ */
kobject_put (kobjp); kref_put(&hvcsd->kref, destroy_hvcs_struct);
/* /*
* The hangup is a scheduled function which will auto chain call * The hangup is a scheduled function which will auto chain call
...@@ -1086,7 +1072,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, ...@@ -1086,7 +1072,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
} }
/* /*
* This always increments the kobject ref count if the call is successful. * This always increments the kref ref count if the call is successful.
* Please remember to dec when you are done with the instance. * Please remember to dec when you are done with the instance.
* *
* NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when
...@@ -1103,7 +1089,7 @@ static struct hvcs_struct *hvcs_get_by_index(int index) ...@@ -1103,7 +1089,7 @@ static struct hvcs_struct *hvcs_get_by_index(int index)
list_for_each_entry(hvcsd, &hvcs_structs, next) { list_for_each_entry(hvcsd, &hvcs_structs, next) {
spin_lock_irqsave(&hvcsd->lock, flags); spin_lock_irqsave(&hvcsd->lock, flags);
if (hvcsd->index == index) { if (hvcsd->index == index) {
kobject_get(&hvcsd->kobj); kref_get(&hvcsd->kref);
spin_unlock_irqrestore(&hvcsd->lock, flags); spin_unlock_irqrestore(&hvcsd->lock, flags);
spin_unlock(&hvcs_structs_lock); spin_unlock(&hvcs_structs_lock);
return hvcsd; return hvcsd;
...@@ -1129,14 +1115,13 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) ...@@ -1129,14 +1115,13 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
unsigned int irq; unsigned int irq;
struct vio_dev *vdev; struct vio_dev *vdev;
unsigned long unit_address; unsigned long unit_address;
struct kobject *kobjp;
if (tty->driver_data) if (tty->driver_data)
goto fast_open; goto fast_open;
/* /*
* Is there a vty-server that shares the same index? * Is there a vty-server that shares the same index?
* This function increments the kobject index. * This function increments the kref index.
*/ */
if (!(hvcsd = hvcs_get_by_index(tty->index))) { if (!(hvcsd = hvcs_get_by_index(tty->index))) {
printk(KERN_WARNING "HVCS: open failed, no device associated" printk(KERN_WARNING "HVCS: open failed, no device associated"
...@@ -1181,7 +1166,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) ...@@ -1181,7 +1166,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
* and will grab the spinlock and free the connection if it fails. * and will grab the spinlock and free the connection if it fails.
*/ */
if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) { if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
kobject_put(&hvcsd->kobj); kref_put(&hvcsd->kref, destroy_hvcs_struct);
printk(KERN_WARNING "HVCS: enable device failed.\n"); printk(KERN_WARNING "HVCS: enable device failed.\n");
return rc; return rc;
} }
...@@ -1192,17 +1177,11 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) ...@@ -1192,17 +1177,11 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
hvcsd = tty->driver_data; hvcsd = tty->driver_data;
spin_lock_irqsave(&hvcsd->lock, flags); spin_lock_irqsave(&hvcsd->lock, flags);
if (!kobject_get(&hvcsd->kobj)) { kref_get(&hvcsd->kref);
spin_unlock_irqrestore(&hvcsd->lock, flags);
printk(KERN_ERR "HVCS: Kobject of open"
" hvcs doesn't exist.\n");
return -EFAULT; /* Is this the right return value? */
}
hvcsd->open_count++; hvcsd->open_count++;
hvcsd->todo_mask |= HVCS_SCHED_READ; hvcsd->todo_mask |= HVCS_SCHED_READ;
spin_unlock_irqrestore(&hvcsd->lock, flags); spin_unlock_irqrestore(&hvcsd->lock, flags);
open_success: open_success:
hvcs_kick(); hvcs_kick();
...@@ -1212,9 +1191,8 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) ...@@ -1212,9 +1191,8 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
return 0; return 0;
error_release: error_release:
kobjp = &hvcsd->kobj;
spin_unlock_irqrestore(&hvcsd->lock, flags); spin_unlock_irqrestore(&hvcsd->lock, flags);
kobject_put(&hvcsd->kobj); kref_put(&hvcsd->kref, destroy_hvcs_struct);
printk(KERN_WARNING "HVCS: partner connect failed.\n"); printk(KERN_WARNING "HVCS: partner connect failed.\n");
return retval; return retval;
...@@ -1224,7 +1202,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) ...@@ -1224,7 +1202,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
{ {
struct hvcs_struct *hvcsd; struct hvcs_struct *hvcsd;
unsigned long flags; unsigned long flags;
struct kobject *kobjp;
int irq = NO_IRQ; int irq = NO_IRQ;
/* /*
...@@ -1245,7 +1222,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) ...@@ -1245,7 +1222,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
hvcsd = tty->driver_data; hvcsd = tty->driver_data;
spin_lock_irqsave(&hvcsd->lock, flags); spin_lock_irqsave(&hvcsd->lock, flags);
kobjp = &hvcsd->kobj;
if (--hvcsd->open_count == 0) { if (--hvcsd->open_count == 0) {
vio_disable_interrupts(hvcsd->vdev); vio_disable_interrupts(hvcsd->vdev);
...@@ -1270,7 +1246,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) ...@@ -1270,7 +1246,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
tty->driver_data = NULL; tty->driver_data = NULL;
free_irq(irq, hvcsd); free_irq(irq, hvcsd);
kobject_put(kobjp); kref_put(&hvcsd->kref, destroy_hvcs_struct);
return; return;
} else if (hvcsd->open_count < 0) { } else if (hvcsd->open_count < 0) {
printk(KERN_ERR "HVCS: vty-server@%X open_count: %d" printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
...@@ -1279,7 +1255,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) ...@@ -1279,7 +1255,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
} }
spin_unlock_irqrestore(&hvcsd->lock, flags); spin_unlock_irqrestore(&hvcsd->lock, flags);
kobject_put(kobjp); kref_put(&hvcsd->kref, destroy_hvcs_struct);
} }
static void hvcs_hangup(struct tty_struct * tty) static void hvcs_hangup(struct tty_struct * tty)
...@@ -1287,21 +1263,17 @@ static void hvcs_hangup(struct tty_struct * tty) ...@@ -1287,21 +1263,17 @@ static void hvcs_hangup(struct tty_struct * tty)
struct hvcs_struct *hvcsd = tty->driver_data; struct hvcs_struct *hvcsd = tty->driver_data;
unsigned long flags; unsigned long flags;
int temp_open_count; int temp_open_count;
struct kobject *kobjp;
int irq = NO_IRQ; int irq = NO_IRQ;
spin_lock_irqsave(&hvcsd->lock, flags); spin_lock_irqsave(&hvcsd->lock, flags);
/* Preserve this so that we know how many kobject refs to put */ /* Preserve this so that we know how many kref refs to put */
temp_open_count = hvcsd->open_count; temp_open_count = hvcsd->open_count;
/* /*
* Don't kobject put inside the spinlock because the destruction * Don't kref put inside the spinlock because the destruction
* callback may use the spinlock and it may get called before the * callback may use the spinlock and it may get called before the
* spinlock has been released. Get a pointer to the kobject and * spinlock has been released.
* kobject_put on that after releasing the spinlock.
*/ */
kobjp = &hvcsd->kobj;
vio_disable_interrupts(hvcsd->vdev); vio_disable_interrupts(hvcsd->vdev);
hvcsd->todo_mask = 0; hvcsd->todo_mask = 0;
...@@ -1324,7 +1296,7 @@ static void hvcs_hangup(struct tty_struct * tty) ...@@ -1324,7 +1296,7 @@ static void hvcs_hangup(struct tty_struct * tty)
free_irq(irq, hvcsd); free_irq(irq, hvcsd);
/* /*
* We need to kobject_put() for every open_count we have since the * We need to kref_put() for every open_count we have since the
* tty_hangup() function doesn't invoke a close per open connection on a * tty_hangup() function doesn't invoke a close per open connection on a
* non-console device. * non-console device.
*/ */
...@@ -1335,7 +1307,7 @@ static void hvcs_hangup(struct tty_struct * tty) ...@@ -1335,7 +1307,7 @@ static void hvcs_hangup(struct tty_struct * tty)
* NOTE: If this hangup was signaled from user space then the * NOTE: If this hangup was signaled from user space then the
* final put will never happen. * final put will never happen.
*/ */
kobject_put(kobjp); kref_put(&hvcsd->kref, destroy_hvcs_struct);
} }
} }
......
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