Commit b086c8a3 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] dynamic addition of virtual disks on PPC64 iSeries

From: Stephen Rothwell <sfr@canb.auug.org.au>

This patch allows us to dynamically add virtual disks to an iSeries partition.
 It works like this: after you have created the virtual disk file on OS/400
and attached it to the Linux partition, you need to write to
/sys/bus/vio/drivers/viodasd/probe (it doesn't matter what you write).  This
will do the probe.  It calls add_disk() for each new disk, so we get hotplug
events as a side effect.

This was the nicest way I could think of doing this as the interface to the
hypervisor is polled ...
parent bb0d0927
...@@ -40,8 +40,11 @@ ...@@ -40,8 +40,11 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/vio.h>
#include <asm/iSeries/HvTypes.h> #include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/HvLpEvent.h> #include <asm/iSeries/HvLpEvent.h>
#include <asm/iSeries/HvLpConfig.h> #include <asm/iSeries/HvLpConfig.h>
...@@ -519,13 +522,6 @@ static void probe_disk(struct viodasd_device *d) ...@@ -519,13 +522,6 @@ static void probe_disk(struct viodasd_device *d)
"bad rc sending event to OS/400 %d\n", (int)hvrc); "bad rc sending event to OS/400 %d\n", (int)hvrc);
return; return;
} }
printk(VIOD_KERN_INFO "disk %d: %lu sectors (%lu MB) "
"CHS=%d/%d/%d sector size %d%s\n",
dev_no, (unsigned long)(d->size >> 9),
(unsigned long)(d->size >> 20),
(int)d->cylinders, (int)d->tracks,
(int)d->sectors, (int)d->bytes_per_sector,
d->read_only ? " (RO)" : "");
/* create the request queue for the disk */ /* create the request queue for the disk */
spin_lock_init(&d->q_lock); spin_lock_init(&d->q_lock);
q = blk_init_queue(do_viodasd_request, &d->q_lock); q = blk_init_queue(do_viodasd_request, &d->q_lock);
...@@ -563,6 +559,14 @@ static void probe_disk(struct viodasd_device *d) ...@@ -563,6 +559,14 @@ static void probe_disk(struct viodasd_device *d)
g->private_data = d; g->private_data = d;
set_capacity(g, d->size >> 9); set_capacity(g, d->size >> 9);
printk(VIOD_KERN_INFO "disk %d: %lu sectors (%lu MB) "
"CHS=%d/%d/%d sector size %d%s\n",
dev_no, (unsigned long)(d->size >> 9),
(unsigned long)(d->size >> 20),
(int)d->cylinders, (int)d->tracks,
(int)d->sectors, (int)d->bytes_per_sector,
d->read_only ? " (RO)" : "");
/* register us in the global list */ /* register us in the global list */
add_disk(g); add_disk(g);
} }
...@@ -724,6 +728,26 @@ static void handle_block_event(struct HvLpEvent *event) ...@@ -724,6 +728,26 @@ static void handle_block_event(struct HvLpEvent *event)
} }
} }
/*
* Get the driver to reprobe for more disks.
*/
static ssize_t probe_disks(struct device_driver *drv, const char *buf,
size_t count)
{
struct viodasd_device *d;
for (d = viodasd_devices; d < &viodasd_devices[MAX_DISKNO]; d++) {
if (d->disk == NULL)
probe_disk(d);
}
return count;
}
static DRIVER_ATTR(probe, S_IWUSR, NULL, probe_disks)
static struct vio_driver viodasd_driver = {
.name = "viodasd"
};
/* /*
* Initialize the whole device driver. Handle module and non-module * Initialize the whole device driver. Handle module and non-module
* versions * versions
...@@ -767,6 +791,9 @@ static int __init viodasd_init(void) ...@@ -767,6 +791,9 @@ static int __init viodasd_init(void)
for (i = 0; i < MAX_DISKNO; i++) for (i = 0; i < MAX_DISKNO; i++)
probe_disk(&viodasd_devices[i]); probe_disk(&viodasd_devices[i]);
vio_register_driver(&viodasd_driver); /* FIX ME - error checking */
driver_create_file(&viodasd_driver.driver, &driver_attr_probe);
return 0; return 0;
} }
module_init(viodasd_init); module_init(viodasd_init);
...@@ -776,6 +803,9 @@ void viodasd_exit(void) ...@@ -776,6 +803,9 @@ void viodasd_exit(void)
int i; int i;
struct viodasd_device *d; struct viodasd_device *d;
driver_remove_file(&viodasd_driver.driver, &driver_attr_probe);
vio_unregister_driver(&viodasd_driver);
for (i = 0; i < MAX_DISKNO; i++) { for (i = 0; i < MAX_DISKNO; i++) {
d = &viodasd_devices[i]; d = &viodasd_devices[i];
if (d->disk) { if (d->disk) {
......
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