|
@@ -57,11 +57,7 @@
|
|
|
* rescanning partner information upon a user's request.
|
|
|
*
|
|
|
* 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
|
|
|
- * 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.
|
|
|
+ * using the 2.6 Linux kernel kref construct.
|
|
|
*
|
|
|
* For direction on installation and usage of this driver please reference
|
|
|
* Documentation/powerpc/hvcs.txt.
|
|
@@ -71,7 +67,7 @@
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/interrupt.h>
|
|
|
#include <linux/kernel.h>
|
|
|
-#include <linux/kobject.h>
|
|
|
+#include <linux/kref.h>
|
|
|
#include <linux/kthread.h>
|
|
|
#include <linux/list.h>
|
|
|
#include <linux/major.h>
|
|
@@ -293,12 +289,12 @@ struct hvcs_struct {
|
|
|
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
|
|
|
* whacked until the koject refcount reaches zero though some entries
|
|
|
* 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? */
|
|
|
uint32_t p_unit_address; /* partner unit address */
|
|
|
uint32_t p_partition_ID; /* partner partition ID */
|
|
@@ -307,8 +303,8 @@ struct hvcs_struct {
|
|
|
struct vio_dev *vdev;
|
|
|
};
|
|
|
|
|
|
-/* Required to back map a kobject to its containing object */
|
|
|
-#define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj)
|
|
|
+/* Required to back map a kref to its containing object */
|
|
|
+#define from_kref(k) container_of(k, struct hvcs_struct, kref)
|
|
|
|
|
|
static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
|
|
|
static DEFINE_SPINLOCK(hvcs_structs_lock);
|
|
@@ -334,7 +330,6 @@ static void hvcs_partner_free(struct hvcs_struct *hvcsd);
|
|
|
static int hvcs_enable_device(struct hvcs_struct *hvcsd,
|
|
|
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 void hvcs_close(struct tty_struct *tty, struct file *filp);
|
|
|
static void hvcs_hangup(struct tty_struct * tty);
|
|
@@ -703,10 +698,10 @@ static void hvcs_return_index(int index)
|
|
|
hvcs_index_list[index] = -1;
|
|
|
}
|
|
|
|
|
|
-/* callback when the kboject ref count reaches zero */
|
|
|
-static void destroy_hvcs_struct(struct kobject *kobj)
|
|
|
+/* callback when the kref ref count reaches zero */
|
|
|
+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;
|
|
|
unsigned long flags;
|
|
|
|
|
@@ -743,10 +738,6 @@ static void destroy_hvcs_struct(struct kobject *kobj)
|
|
|
kfree(hvcsd);
|
|
|
}
|
|
|
|
|
|
-static struct kobj_type hvcs_kobj_type = {
|
|
|
- .release = destroy_hvcs_struct,
|
|
|
-};
|
|
|
-
|
|
|
static int hvcs_get_index(void)
|
|
|
{
|
|
|
int i;
|
|
@@ -791,9 +782,7 @@ static int __devinit hvcs_probe(
|
|
|
|
|
|
spin_lock_init(&hvcsd->lock);
|
|
|
/* Automatically incs the refcount the first time */
|
|
|
- kobject_init(&hvcsd->kobj);
|
|
|
- /* Set up the callback for terminating the hvcs_struct's life */
|
|
|
- hvcsd->kobj.ktype = &hvcs_kobj_type;
|
|
|
+ kref_init(&hvcsd->kref);
|
|
|
|
|
|
hvcsd->vdev = dev;
|
|
|
dev->dev.driver_data = hvcsd;
|
|
@@ -844,7 +833,6 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
|
|
|
{
|
|
|
struct hvcs_struct *hvcsd = dev->dev.driver_data;
|
|
|
unsigned long flags;
|
|
|
- struct kobject *kobjp;
|
|
|
struct tty_struct *tty;
|
|
|
|
|
|
if (!hvcsd)
|
|
@@ -856,15 +844,13 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
|
|
|
|
|
|
tty = hvcsd->tty;
|
|
|
|
|
|
- kobjp = &hvcsd->kobj;
|
|
|
-
|
|
|
spin_unlock_irqrestore(&hvcsd->lock, flags);
|
|
|
|
|
|
/*
|
|
|
* Let the last holder of this object cause it to be removed, which
|
|
|
* 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
|
|
@@ -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.
|
|
|
*
|
|
|
* 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)
|
|
|
list_for_each_entry(hvcsd, &hvcs_structs, next) {
|
|
|
spin_lock_irqsave(&hvcsd->lock, flags);
|
|
|
if (hvcsd->index == index) {
|
|
|
- kobject_get(&hvcsd->kobj);
|
|
|
+ kref_get(&hvcsd->kref);
|
|
|
spin_unlock_irqrestore(&hvcsd->lock, flags);
|
|
|
spin_unlock(&hvcs_structs_lock);
|
|
|
return hvcsd;
|
|
@@ -1129,14 +1115,13 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
|
|
|
unsigned int irq;
|
|
|
struct vio_dev *vdev;
|
|
|
unsigned long unit_address;
|
|
|
- struct kobject *kobjp;
|
|
|
|
|
|
if (tty->driver_data)
|
|
|
goto fast_open;
|
|
|
|
|
|
/*
|
|
|
* 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))) {
|
|
|
printk(KERN_WARNING "HVCS: open failed, no device associated"
|
|
@@ -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.
|
|
|
*/
|
|
|
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");
|
|
|
return rc;
|
|
|
}
|
|
@@ -1192,17 +1177,11 @@ fast_open:
|
|
|
hvcsd = tty->driver_data;
|
|
|
|
|
|
spin_lock_irqsave(&hvcsd->lock, flags);
|
|
|
- if (!kobject_get(&hvcsd->kobj)) {
|
|
|
- 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? */
|
|
|
- }
|
|
|
-
|
|
|
+ kref_get(&hvcsd->kref);
|
|
|
hvcsd->open_count++;
|
|
|
-
|
|
|
hvcsd->todo_mask |= HVCS_SCHED_READ;
|
|
|
spin_unlock_irqrestore(&hvcsd->lock, flags);
|
|
|
+
|
|
|
open_success:
|
|
|
hvcs_kick();
|
|
|
|
|
@@ -1212,9 +1191,8 @@ open_success:
|
|
|
return 0;
|
|
|
|
|
|
error_release:
|
|
|
- kobjp = &hvcsd->kobj;
|
|
|
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");
|
|
|
return retval;
|
|
@@ -1224,7 +1202,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
|
|
|
{
|
|
|
struct hvcs_struct *hvcsd;
|
|
|
unsigned long flags;
|
|
|
- struct kobject *kobjp;
|
|
|
int irq = NO_IRQ;
|
|
|
|
|
|
/*
|
|
@@ -1245,7 +1222,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
|
|
|
hvcsd = tty->driver_data;
|
|
|
|
|
|
spin_lock_irqsave(&hvcsd->lock, flags);
|
|
|
- kobjp = &hvcsd->kobj;
|
|
|
if (--hvcsd->open_count == 0) {
|
|
|
|
|
|
vio_disable_interrupts(hvcsd->vdev);
|
|
@@ -1270,7 +1246,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
|
|
|
tty->driver_data = NULL;
|
|
|
|
|
|
free_irq(irq, hvcsd);
|
|
|
- kobject_put(kobjp);
|
|
|
+ kref_put(&hvcsd->kref, destroy_hvcs_struct);
|
|
|
return;
|
|
|
} else if (hvcsd->open_count < 0) {
|
|
|
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)
|
|
|
}
|
|
|
|
|
|
spin_unlock_irqrestore(&hvcsd->lock, flags);
|
|
|
- kobject_put(kobjp);
|
|
|
+ kref_put(&hvcsd->kref, destroy_hvcs_struct);
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
unsigned long flags;
|
|
|
int temp_open_count;
|
|
|
- struct kobject *kobjp;
|
|
|
int irq = NO_IRQ;
|
|
|
|
|
|
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;
|
|
|
|
|
|
/*
|
|
|
- * 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
|
|
|
- * spinlock has been released. Get a pointer to the kobject and
|
|
|
- * kobject_put on that after releasing the spinlock.
|
|
|
+ * spinlock has been released.
|
|
|
*/
|
|
|
- kobjp = &hvcsd->kobj;
|
|
|
-
|
|
|
vio_disable_interrupts(hvcsd->vdev);
|
|
|
|
|
|
hvcsd->todo_mask = 0;
|
|
@@ -1324,7 +1296,7 @@ static void hvcs_hangup(struct tty_struct * tty)
|
|
|
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
|
|
|
* non-console device.
|
|
|
*/
|
|
@@ -1335,7 +1307,7 @@ static void hvcs_hangup(struct tty_struct * tty)
|
|
|
* NOTE: If this hangup was signaled from user space then the
|
|
|
* final put will never happen.
|
|
|
*/
|
|
|
- kobject_put(kobjp);
|
|
|
+ kref_put(&hvcsd->kref, destroy_hvcs_struct);
|
|
|
}
|
|
|
}
|
|
|
|