diff options
-rw-r--r-- | drivers/s390/block/dasd.c | 11 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 32 |
2 files changed, 36 insertions, 7 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 6498d15f874f..0595c763dafd 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -2157,6 +2157,7 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible) | |||
2157 | test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && | 2157 | test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && |
2158 | (!dasd_eer_enabled(device))) { | 2158 | (!dasd_eer_enabled(device))) { |
2159 | cqr->status = DASD_CQR_FAILED; | 2159 | cqr->status = DASD_CQR_FAILED; |
2160 | cqr->intrc = -EAGAIN; | ||
2160 | continue; | 2161 | continue; |
2161 | } | 2162 | } |
2162 | /* Don't try to start requests if device is stopped */ | 2163 | /* Don't try to start requests if device is stopped */ |
@@ -3270,6 +3271,16 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event) | |||
3270 | dasd_schedule_device_bh(device); | 3271 | dasd_schedule_device_bh(device); |
3271 | } | 3272 | } |
3272 | if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) { | 3273 | if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) { |
3274 | if (!(device->path_data.opm & eventlpm) && | ||
3275 | !(device->path_data.tbvpm & eventlpm)) { | ||
3276 | /* | ||
3277 | * we can not establish a pathgroup on an | ||
3278 | * unavailable path, so trigger a path | ||
3279 | * verification first | ||
3280 | */ | ||
3281 | device->path_data.tbvpm |= eventlpm; | ||
3282 | dasd_schedule_device_bh(device); | ||
3283 | } | ||
3273 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 3284 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
3274 | "Pathgroup re-established\n"); | 3285 | "Pathgroup re-established\n"); |
3275 | if (device->discipline->kick_validate) | 3286 | if (device->discipline->kick_validate) |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 2fb2b9ea97ec..c48c72abbefc 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -1507,7 +1507,8 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device, | |||
1507 | * call might change behaviour of DASD devices. | 1507 | * call might change behaviour of DASD devices. |
1508 | */ | 1508 | */ |
1509 | static int | 1509 | static int |
1510 | dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) | 1510 | dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, |
1511 | unsigned long flags) | ||
1511 | { | 1512 | { |
1512 | struct dasd_ccw_req *cqr; | 1513 | struct dasd_ccw_req *cqr; |
1513 | int rc; | 1514 | int rc; |
@@ -1516,10 +1517,19 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) | |||
1516 | if (IS_ERR(cqr)) | 1517 | if (IS_ERR(cqr)) |
1517 | return PTR_ERR(cqr); | 1518 | return PTR_ERR(cqr); |
1518 | 1519 | ||
1520 | /* | ||
1521 | * set flags e.g. turn on failfast, to prevent blocking | ||
1522 | * the calling function should handle failed requests | ||
1523 | */ | ||
1524 | cqr->flags |= flags; | ||
1525 | |||
1519 | rc = dasd_sleep_on(cqr); | 1526 | rc = dasd_sleep_on(cqr); |
1520 | if (!rc) | 1527 | if (!rc) |
1521 | /* trigger CIO to reprobe devices */ | 1528 | /* trigger CIO to reprobe devices */ |
1522 | css_schedule_reprobe(); | 1529 | css_schedule_reprobe(); |
1530 | else if (cqr->intrc == -EAGAIN) | ||
1531 | rc = -EAGAIN; | ||
1532 | |||
1523 | dasd_sfree_request(cqr, cqr->memdev); | 1533 | dasd_sfree_request(cqr, cqr->memdev); |
1524 | return rc; | 1534 | return rc; |
1525 | } | 1535 | } |
@@ -1527,7 +1537,8 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) | |||
1527 | /* | 1537 | /* |
1528 | * Valide storage server of current device. | 1538 | * Valide storage server of current device. |
1529 | */ | 1539 | */ |
1530 | static void dasd_eckd_validate_server(struct dasd_device *device) | 1540 | static int dasd_eckd_validate_server(struct dasd_device *device, |
1541 | unsigned long flags) | ||
1531 | { | 1542 | { |
1532 | int rc; | 1543 | int rc; |
1533 | struct dasd_eckd_private *private; | 1544 | struct dasd_eckd_private *private; |
@@ -1536,17 +1547,18 @@ static void dasd_eckd_validate_server(struct dasd_device *device) | |||
1536 | private = (struct dasd_eckd_private *) device->private; | 1547 | private = (struct dasd_eckd_private *) device->private; |
1537 | if (private->uid.type == UA_BASE_PAV_ALIAS || | 1548 | if (private->uid.type == UA_BASE_PAV_ALIAS || |
1538 | private->uid.type == UA_HYPER_PAV_ALIAS) | 1549 | private->uid.type == UA_HYPER_PAV_ALIAS) |
1539 | return; | 1550 | return 0; |
1540 | if (dasd_nopav || MACHINE_IS_VM) | 1551 | if (dasd_nopav || MACHINE_IS_VM) |
1541 | enable_pav = 0; | 1552 | enable_pav = 0; |
1542 | else | 1553 | else |
1543 | enable_pav = 1; | 1554 | enable_pav = 1; |
1544 | rc = dasd_eckd_psf_ssc(device, enable_pav); | 1555 | rc = dasd_eckd_psf_ssc(device, enable_pav, flags); |
1545 | 1556 | ||
1546 | /* may be requested feature is not available on server, | 1557 | /* may be requested feature is not available on server, |
1547 | * therefore just report error and go ahead */ | 1558 | * therefore just report error and go ahead */ |
1548 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " | 1559 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " |
1549 | "returned rc=%d", private->uid.ssid, rc); | 1560 | "returned rc=%d", private->uid.ssid, rc); |
1561 | return rc; | ||
1550 | } | 1562 | } |
1551 | 1563 | ||
1552 | /* | 1564 | /* |
@@ -1556,7 +1568,13 @@ static void dasd_eckd_do_validate_server(struct work_struct *work) | |||
1556 | { | 1568 | { |
1557 | struct dasd_device *device = container_of(work, struct dasd_device, | 1569 | struct dasd_device *device = container_of(work, struct dasd_device, |
1558 | kick_validate); | 1570 | kick_validate); |
1559 | dasd_eckd_validate_server(device); | 1571 | if (dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST) |
1572 | == -EAGAIN) { | ||
1573 | /* schedule worker again if failed */ | ||
1574 | schedule_work(&device->kick_validate); | ||
1575 | return; | ||
1576 | } | ||
1577 | |||
1560 | dasd_put_device(device); | 1578 | dasd_put_device(device); |
1561 | } | 1579 | } |
1562 | 1580 | ||
@@ -1685,7 +1703,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1685 | if (rc) | 1703 | if (rc) |
1686 | goto out_err2; | 1704 | goto out_err2; |
1687 | 1705 | ||
1688 | dasd_eckd_validate_server(device); | 1706 | dasd_eckd_validate_server(device, 0); |
1689 | 1707 | ||
1690 | /* device may report different configuration data after LCU setup */ | 1708 | /* device may report different configuration data after LCU setup */ |
1691 | rc = dasd_eckd_read_conf(device); | 1709 | rc = dasd_eckd_read_conf(device); |
@@ -4153,7 +4171,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device) | |||
4153 | rc = dasd_alias_make_device_known_to_lcu(device); | 4171 | rc = dasd_alias_make_device_known_to_lcu(device); |
4154 | if (rc) | 4172 | if (rc) |
4155 | return rc; | 4173 | return rc; |
4156 | dasd_eckd_validate_server(device); | 4174 | dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST); |
4157 | 4175 | ||
4158 | /* RE-Read Configuration Data */ | 4176 | /* RE-Read Configuration Data */ |
4159 | rc = dasd_eckd_read_conf(device); | 4177 | rc = dasd_eckd_read_conf(device); |