+ 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,
+};
+
+static int __devinit hvc_probe(
+ struct vio_dev *dev,
+ const struct vio_device_id *id)
+{
+ struct hvc_struct *hp;
+
+ /* probed with invalid parameters. */
+ if (!dev || !id)
+ return -EPERM;
+
+ hp = kmalloc(sizeof(*hp), GFP_KERNEL);
+ if (!hp)
+ return -ENOMEM;
+
+ memset(hp, 0x00, sizeof(*hp));
+ hp->vtermno = dev->unit_address;
+ hp->vdev = dev;
+ hp->vdev->dev.driver_data = hp;
+ hp->irq = dev->irq;
+
+ kobject_init(&hp->kobj);
+ hp->kobj.ktype = &hvc_kobj_type;
+
+ hp->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock(&hvc_structs_lock);
+ hp->index = ++hvc_count;
+ list_add_tail(&(hp->next), &hvc_structs);
+ spin_unlock(&hvc_structs_lock);
+
+ return 0;
+}
+
+static int __devexit hvc_remove(struct vio_dev *dev)
+{
+ struct hvc_struct *hp = dev->dev.driver_data;
+ 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;
+
+ /* Don't whack hp->irq because tty_hangup() will need to free the irq. */
+
+ spin_unlock_irqrestore(&hp->lock, flags);
+
+ /*
+ * We 'put' the instance that was grabbed when the kobject instance
+ * was intialized using kobject_init(). Let the last holder of this
+ * kobject cause it to be removed, which will probably be the tty_hangup
+ * below.
+ */
+ kobject_put(kobjp);
+
+ /*
+ * This function call will auto chain call hvc_hangup. The tty should
+ * always be valid at this time unless a simultaneous tty close already
+ * cleaned up the hvc_struct.
+ */
+ if (tty)
+ tty_hangup(tty);
+ return 0;
+}
+
+static struct vio_driver hvc_vio_driver = {
+ .name = hvc_driver_name,
+ .id_table = hvc_driver_table,
+ .probe = hvc_probe,
+ .remove = hvc_remove,
+};
+
+/* Driver initialization. Follow console initialization. This is where the TTY
+ * interfaces start to become available. */
+int __init hvc_init(void)
+{
+ int rc;
+
+ /* We need more than num_vterms adapters due to hotplug additions. */
+ hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
+ /* hvc_driver = alloc_tty_driver(num_vterms); */