diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd.c | 37 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 16 | ||||
-rw-r--r-- | drivers/s390/char/tape.h | 2 | ||||
-rw-r--r-- | drivers/s390/char/tape_34xx.c | 8 | ||||
-rw-r--r-- | drivers/s390/char/tape_3590.c | 8 | ||||
-rw-r--r-- | drivers/s390/char/tape_core.c | 5 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 43 |
7 files changed, 46 insertions, 73 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 | ||
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 21254793c604..cb52da033f06 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -2019,15 +2019,23 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( | |||
2019 | ccw++; | 2019 | ccw++; |
2020 | recid += count; | 2020 | recid += count; |
2021 | new_track = 0; | 2021 | new_track = 0; |
2022 | /* first idaw for a ccw may start anywhere */ | ||
2023 | if (!idaw_dst) | ||
2024 | idaw_dst = dst; | ||
2022 | } | 2025 | } |
2023 | /* If we start a new idaw, everything is fine and the | 2026 | /* If we start a new idaw, we must make sure that it |
2024 | * start of the new idaw is the start of this segment. | 2027 | * starts on an IDA_BLOCK_SIZE boundary. |
2025 | * If we continue an idaw, we must make sure that the | 2028 | * If we continue an idaw, we must make sure that the |
2026 | * current segment begins where the so far accumulated | 2029 | * current segment begins where the so far accumulated |
2027 | * idaw ends | 2030 | * idaw ends |
2028 | */ | 2031 | */ |
2029 | if (!idaw_dst) | 2032 | if (!idaw_dst) { |
2030 | idaw_dst = dst; | 2033 | if (__pa(dst) & (IDA_BLOCK_SIZE-1)) { |
2034 | dasd_sfree_request(cqr, startdev); | ||
2035 | return ERR_PTR(-ERANGE); | ||
2036 | } else | ||
2037 | idaw_dst = dst; | ||
2038 | } | ||
2031 | if ((idaw_dst + idaw_len) != dst) { | 2039 | if ((idaw_dst + idaw_len) != dst) { |
2032 | dasd_sfree_request(cqr, startdev); | 2040 | dasd_sfree_request(cqr, startdev); |
2033 | return ERR_PTR(-ERANGE); | 2041 | return ERR_PTR(-ERANGE); |
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index c07809c8016a..5469e099597e 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h | |||
@@ -285,7 +285,7 @@ extern int tape_mtop(struct tape_device *, int, int); | |||
285 | extern void tape_state_set(struct tape_device *, enum tape_state); | 285 | extern void tape_state_set(struct tape_device *, enum tape_state); |
286 | 286 | ||
287 | extern int tape_generic_online(struct tape_device *, struct tape_discipline *); | 287 | extern int tape_generic_online(struct tape_device *, struct tape_discipline *); |
288 | extern int tape_generic_offline(struct tape_device *device); | 288 | extern int tape_generic_offline(struct ccw_device *); |
289 | 289 | ||
290 | /* Externals from tape_devmap.c */ | 290 | /* Externals from tape_devmap.c */ |
291 | extern int tape_generic_probe(struct ccw_device *); | 291 | extern int tape_generic_probe(struct ccw_device *); |
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 807ded5eb049..5f8e8ef43dd3 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c | |||
@@ -1294,12 +1294,6 @@ tape_34xx_online(struct ccw_device *cdev) | |||
1294 | ); | 1294 | ); |
1295 | } | 1295 | } |
1296 | 1296 | ||
1297 | static int | ||
1298 | tape_34xx_offline(struct ccw_device *cdev) | ||
1299 | { | ||
1300 | return tape_generic_offline(cdev->dev.driver_data); | ||
1301 | } | ||
1302 | |||
1303 | static struct ccw_driver tape_34xx_driver = { | 1297 | static struct ccw_driver tape_34xx_driver = { |
1304 | .name = "tape_34xx", | 1298 | .name = "tape_34xx", |
1305 | .owner = THIS_MODULE, | 1299 | .owner = THIS_MODULE, |
@@ -1307,7 +1301,7 @@ static struct ccw_driver tape_34xx_driver = { | |||
1307 | .probe = tape_generic_probe, | 1301 | .probe = tape_generic_probe, |
1308 | .remove = tape_generic_remove, | 1302 | .remove = tape_generic_remove, |
1309 | .set_online = tape_34xx_online, | 1303 | .set_online = tape_34xx_online, |
1310 | .set_offline = tape_34xx_offline, | 1304 | .set_offline = tape_generic_offline, |
1311 | }; | 1305 | }; |
1312 | 1306 | ||
1313 | static int | 1307 | static int |
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index fc1d91294143..823b05bd0dd7 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -1707,19 +1707,13 @@ tape_3590_online(struct ccw_device *cdev) | |||
1707 | &tape_discipline_3590); | 1707 | &tape_discipline_3590); |
1708 | } | 1708 | } |
1709 | 1709 | ||
1710 | static int | ||
1711 | tape_3590_offline(struct ccw_device *cdev) | ||
1712 | { | ||
1713 | return tape_generic_offline(cdev->dev.driver_data); | ||
1714 | } | ||
1715 | |||
1716 | static struct ccw_driver tape_3590_driver = { | 1710 | static struct ccw_driver tape_3590_driver = { |
1717 | .name = "tape_3590", | 1711 | .name = "tape_3590", |
1718 | .owner = THIS_MODULE, | 1712 | .owner = THIS_MODULE, |
1719 | .ids = tape_3590_ids, | 1713 | .ids = tape_3590_ids, |
1720 | .probe = tape_generic_probe, | 1714 | .probe = tape_generic_probe, |
1721 | .remove = tape_generic_remove, | 1715 | .remove = tape_generic_remove, |
1722 | .set_offline = tape_3590_offline, | 1716 | .set_offline = tape_generic_offline, |
1723 | .set_online = tape_3590_online, | 1717 | .set_online = tape_3590_online, |
1724 | }; | 1718 | }; |
1725 | 1719 | ||
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 08c09d3503cf..8a109f3b69c6 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c | |||
@@ -387,8 +387,11 @@ tape_cleanup_device(struct tape_device *device) | |||
387 | * Manual offline is only allowed while the drive is not in use. | 387 | * Manual offline is only allowed while the drive is not in use. |
388 | */ | 388 | */ |
389 | int | 389 | int |
390 | tape_generic_offline(struct tape_device *device) | 390 | tape_generic_offline(struct ccw_device *cdev) |
391 | { | 391 | { |
392 | struct tape_device *device; | ||
393 | |||
394 | device = cdev->dev.driver_data; | ||
392 | if (!device) { | 395 | if (!device) { |
393 | return -ENODEV; | 396 | return -ENODEV; |
394 | } | 397 | } |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 9e8a2914259b..accd957454e7 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -881,42 +881,6 @@ no_handler: | |||
881 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); | 881 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); |
882 | } | 882 | } |
883 | 883 | ||
884 | static void qdio_call_shutdown(struct work_struct *work) | ||
885 | { | ||
886 | struct ccw_device_private *priv; | ||
887 | struct ccw_device *cdev; | ||
888 | |||
889 | priv = container_of(work, struct ccw_device_private, kick_work); | ||
890 | cdev = priv->cdev; | ||
891 | qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); | ||
892 | put_device(&cdev->dev); | ||
893 | } | ||
894 | |||
895 | static void qdio_int_error(struct ccw_device *cdev) | ||
896 | { | ||
897 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
898 | |||
899 | switch (irq_ptr->state) { | ||
900 | case QDIO_IRQ_STATE_INACTIVE: | ||
901 | case QDIO_IRQ_STATE_CLEANUP: | ||
902 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); | ||
903 | break; | ||
904 | case QDIO_IRQ_STATE_ESTABLISHED: | ||
905 | case QDIO_IRQ_STATE_ACTIVE: | ||
906 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); | ||
907 | if (get_device(&cdev->dev)) { | ||
908 | /* Can't call shutdown from interrupt context. */ | ||
909 | PREPARE_WORK(&cdev->private->kick_work, | ||
910 | qdio_call_shutdown); | ||
911 | queue_work(ccw_device_work, &cdev->private->kick_work); | ||
912 | } | ||
913 | break; | ||
914 | default: | ||
915 | WARN_ON(1); | ||
916 | } | ||
917 | wake_up(&cdev->private->wait_q); | ||
918 | } | ||
919 | |||
920 | static int qdio_establish_check_errors(struct ccw_device *cdev, int cstat, | 884 | static int qdio_establish_check_errors(struct ccw_device *cdev, int cstat, |
921 | int dstat) | 885 | int dstat) |
922 | { | 886 | { |
@@ -973,10 +937,8 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
973 | switch (PTR_ERR(irb)) { | 937 | switch (PTR_ERR(irb)) { |
974 | case -EIO: | 938 | case -EIO: |
975 | DBF_ERROR("%4x IO error", irq_ptr->schid.sch_no); | 939 | DBF_ERROR("%4x IO error", irq_ptr->schid.sch_no); |
976 | return; | 940 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); |
977 | case -ETIMEDOUT: | 941 | wake_up(&cdev->private->wait_q); |
978 | DBF_ERROR("%4x IO timeout", irq_ptr->schid.sch_no); | ||
979 | qdio_int_error(cdev); | ||
980 | return; | 942 | return; |
981 | default: | 943 | default: |
982 | WARN_ON(1); | 944 | WARN_ON(1); |
@@ -1001,7 +963,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1001 | case QDIO_IRQ_STATE_ACTIVE: | 963 | case QDIO_IRQ_STATE_ACTIVE: |
1002 | if (cstat & SCHN_STAT_PCI) { | 964 | if (cstat & SCHN_STAT_PCI) { |
1003 | qdio_int_handler_pci(irq_ptr); | 965 | qdio_int_handler_pci(irq_ptr); |
1004 | /* no state change so no need to wake up wait_q */ | ||
1005 | return; | 966 | return; |
1006 | } | 967 | } |
1007 | if ((cstat & ~SCHN_STAT_PCI) || dstat) { | 968 | if ((cstat & ~SCHN_STAT_PCI) || dstat) { |