diff options
| -rw-r--r-- | drivers/s390/block/dasd.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 0570794ccf1c..d1815272c435 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
| 22 | #include <linux/hdreg.h> | 22 | #include <linux/hdreg.h> |
| 23 | #include <linux/async.h> | ||
| 23 | 24 | ||
| 24 | #include <asm/ccwdev.h> | 25 | #include <asm/ccwdev.h> |
| 25 | #include <asm/ebcdic.h> | 26 | #include <asm/ebcdic.h> |
| @@ -480,8 +481,10 @@ static void dasd_change_state(struct dasd_device *device) | |||
| 480 | if (rc && rc != -EAGAIN) | 481 | if (rc && rc != -EAGAIN) |
| 481 | device->target = device->state; | 482 | device->target = device->state; |
| 482 | 483 | ||
| 483 | if (device->state == device->target) | 484 | if (device->state == device->target) { |
| 484 | wake_up(&dasd_init_waitq); | 485 | wake_up(&dasd_init_waitq); |
| 486 | dasd_put_device(device); | ||
| 487 | } | ||
| 485 | 488 | ||
| 486 | /* let user-space know that the device status changed */ | 489 | /* let user-space know that the device status changed */ |
| 487 | kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); | 490 | kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); |
| @@ -513,12 +516,15 @@ void dasd_kick_device(struct dasd_device *device) | |||
| 513 | */ | 516 | */ |
| 514 | void dasd_set_target_state(struct dasd_device *device, int target) | 517 | void dasd_set_target_state(struct dasd_device *device, int target) |
| 515 | { | 518 | { |
| 519 | dasd_get_device(device); | ||
| 516 | /* If we are in probeonly mode stop at DASD_STATE_READY. */ | 520 | /* If we are in probeonly mode stop at DASD_STATE_READY. */ |
| 517 | if (dasd_probeonly && target > DASD_STATE_READY) | 521 | if (dasd_probeonly && target > DASD_STATE_READY) |
| 518 | target = DASD_STATE_READY; | 522 | target = DASD_STATE_READY; |
| 519 | if (device->target != target) { | 523 | if (device->target != target) { |
| 520 | if (device->state == target) | 524 | if (device->state == target) { |
| 521 | wake_up(&dasd_init_waitq); | 525 | wake_up(&dasd_init_waitq); |
| 526 | dasd_put_device(device); | ||
| 527 | } | ||
| 522 | device->target = target; | 528 | device->target = target; |
| 523 | } | 529 | } |
| 524 | if (device->state != device->target) | 530 | if (device->state != device->target) |
| @@ -2148,6 +2154,22 @@ dasd_exit(void) | |||
| 2148 | * SECTION: common functions for ccw_driver use | 2154 | * SECTION: common functions for ccw_driver use |
| 2149 | */ | 2155 | */ |
| 2150 | 2156 | ||
| 2157 | static void dasd_generic_auto_online(void *data, async_cookie_t cookie) | ||
| 2158 | { | ||
| 2159 | struct ccw_device *cdev = data; | ||
| 2160 | int ret; | ||
| 2161 | |||
| 2162 | ret = ccw_device_set_online(cdev); | ||
| 2163 | if (ret) | ||
| 2164 | pr_warning("%s: Setting the DASD online failed with rc=%d\n", | ||
| 2165 | dev_name(&cdev->dev), ret); | ||
| 2166 | else { | ||
| 2167 | struct dasd_device *device = dasd_device_from_cdev(cdev); | ||
| 2168 | wait_event(dasd_init_waitq, _wait_for_device(device)); | ||
| 2169 | dasd_put_device(device); | ||
| 2170 | } | ||
| 2171 | } | ||
| 2172 | |||
| 2151 | /* | 2173 | /* |
| 2152 | * Initial attempt at a probe function. this can be simplified once | 2174 | * Initial attempt at a probe function. this can be simplified once |
| 2153 | * the other detection code is gone. | 2175 | * the other detection code is gone. |
| @@ -2180,10 +2202,7 @@ int dasd_generic_probe(struct ccw_device *cdev, | |||
| 2180 | */ | 2202 | */ |
| 2181 | if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) || | 2203 | if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) || |
| 2182 | (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0)) | 2204 | (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0)) |
| 2183 | ret = ccw_device_set_online(cdev); | 2205 | async_schedule(dasd_generic_auto_online, cdev); |
| 2184 | if (ret) | ||
| 2185 | pr_warning("%s: Setting the DASD online failed with rc=%d\n", | ||
| 2186 | dev_name(&cdev->dev), ret); | ||
| 2187 | return 0; | 2206 | return 0; |
| 2188 | } | 2207 | } |
| 2189 | 2208 | ||
| @@ -2290,13 +2309,7 @@ int dasd_generic_set_online(struct ccw_device *cdev, | |||
| 2290 | } else | 2309 | } else |
| 2291 | pr_debug("dasd_generic device %s found\n", | 2310 | pr_debug("dasd_generic device %s found\n", |
| 2292 | dev_name(&cdev->dev)); | 2311 | dev_name(&cdev->dev)); |
| 2293 | |||
| 2294 | /* FIXME: we have to wait for the root device but we don't want | ||
| 2295 | * to wait for each single device but for all at once. */ | ||
| 2296 | wait_event(dasd_init_waitq, _wait_for_device(device)); | ||
| 2297 | |||
| 2298 | dasd_put_device(device); | 2312 | dasd_put_device(device); |
| 2299 | |||
| 2300 | return rc; | 2313 | return rc; |
| 2301 | } | 2314 | } |
| 2302 | 2315 | ||
