Commit f3445a1a authored by Cornelia Huck's avatar Cornelia Huck Committed by Martin Schwidefsky

[S390] dasd: Use the new async framework for autoonlining.

The dasd driver can automatically online detected dasds, which
especially important for finding the root device. Currently,
it will wait for each online operation to finish individually,
which may take long if many dasds need to be onlined. When using
the new async framework, these onlining operations can run in
parallel and presence of the root device is ensured by the fact
that prepare_namespace() waits for all async threads to finish.
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarStefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 75cb71f3
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/async.h>
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
...@@ -480,8 +481,10 @@ static void dasd_change_state(struct dasd_device *device) ...@@ -480,8 +481,10 @@ static void dasd_change_state(struct dasd_device *device)
if (rc && rc != -EAGAIN) if (rc && rc != -EAGAIN)
device->target = device->state; device->target = device->state;
if (device->state == device->target) if (device->state == device->target) {
wake_up(&dasd_init_waitq); wake_up(&dasd_init_waitq);
dasd_put_device(device);
}
/* let user-space know that the device status changed */ /* let user-space know that the device status changed */
kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE);
...@@ -513,12 +516,15 @@ void dasd_kick_device(struct dasd_device *device) ...@@ -513,12 +516,15 @@ void dasd_kick_device(struct dasd_device *device)
*/ */
void dasd_set_target_state(struct dasd_device *device, int target) void dasd_set_target_state(struct dasd_device *device, int target)
{ {
dasd_get_device(device);
/* If we are in probeonly mode stop at DASD_STATE_READY. */ /* If we are in probeonly mode stop at DASD_STATE_READY. */
if (dasd_probeonly && target > DASD_STATE_READY) if (dasd_probeonly && target > DASD_STATE_READY)
target = DASD_STATE_READY; target = DASD_STATE_READY;
if (device->target != target) { if (device->target != target) {
if (device->state == target) if (device->state == target) {
wake_up(&dasd_init_waitq); wake_up(&dasd_init_waitq);
dasd_put_device(device);
}
device->target = target; device->target = target;
} }
if (device->state != device->target) if (device->state != device->target)
...@@ -2148,6 +2154,22 @@ dasd_exit(void) ...@@ -2148,6 +2154,22 @@ dasd_exit(void)
* SECTION: common functions for ccw_driver use * SECTION: common functions for ccw_driver use
*/ */
static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
{
struct ccw_device *cdev = data;
int ret;
ret = ccw_device_set_online(cdev);
if (ret)
pr_warning("%s: Setting the DASD online failed with rc=%d\n",
dev_name(&cdev->dev), ret);
else {
struct dasd_device *device = dasd_device_from_cdev(cdev);
wait_event(dasd_init_waitq, _wait_for_device(device));
dasd_put_device(device);
}
}
/* /*
* Initial attempt at a probe function. this can be simplified once * Initial attempt at a probe function. this can be simplified once
* the other detection code is gone. * the other detection code is gone.
...@@ -2180,10 +2202,7 @@ int dasd_generic_probe(struct ccw_device *cdev, ...@@ -2180,10 +2202,7 @@ int dasd_generic_probe(struct ccw_device *cdev,
*/ */
if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) || if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) ||
(dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0)) (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0))
ret = ccw_device_set_online(cdev); async_schedule(dasd_generic_auto_online, cdev);
if (ret)
pr_warning("%s: Setting the DASD online failed with rc=%d\n",
dev_name(&cdev->dev), ret);
return 0; return 0;
} }
...@@ -2290,13 +2309,7 @@ int dasd_generic_set_online(struct ccw_device *cdev, ...@@ -2290,13 +2309,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
} else } else
pr_debug("dasd_generic device %s found\n", pr_debug("dasd_generic device %s found\n",
dev_name(&cdev->dev)); dev_name(&cdev->dev));
/* FIXME: we have to wait for the root device but we don't want
* to wait for each single device but for all at once. */
wait_event(dasd_init_waitq, _wait_for_device(device));
dasd_put_device(device); dasd_put_device(device);
return rc; return rc;
} }
......
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