aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r--drivers/s390/block/dasd.c314
1 files changed, 227 insertions, 87 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index fb613d70c2cb..794bfd962266 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -11,6 +11,7 @@
11#define KMSG_COMPONENT "dasd" 11#define KMSG_COMPONENT "dasd"
12#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 12#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
13 13
14#include <linux/kernel_stat.h>
14#include <linux/kmod.h> 15#include <linux/kmod.h>
15#include <linux/init.h> 16#include <linux/init.h>
16#include <linux/interrupt.h> 17#include <linux/interrupt.h>
@@ -368,6 +369,11 @@ dasd_state_ready_to_online(struct dasd_device * device)
368 device->state = DASD_STATE_ONLINE; 369 device->state = DASD_STATE_ONLINE;
369 if (device->block) { 370 if (device->block) {
370 dasd_schedule_block_bh(device->block); 371 dasd_schedule_block_bh(device->block);
372 if ((device->features & DASD_FEATURE_USERAW)) {
373 disk = device->block->gdp;
374 kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
375 return 0;
376 }
371 disk = device->block->bdev->bd_disk; 377 disk = device->block->bdev->bd_disk;
372 disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0); 378 disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
373 while ((part = disk_part_iter_next(&piter))) 379 while ((part = disk_part_iter_next(&piter)))
@@ -393,7 +399,7 @@ static int dasd_state_online_to_ready(struct dasd_device *device)
393 return rc; 399 return rc;
394 } 400 }
395 device->state = DASD_STATE_READY; 401 device->state = DASD_STATE_READY;
396 if (device->block) { 402 if (device->block && !(device->features & DASD_FEATURE_USERAW)) {
397 disk = device->block->bdev->bd_disk; 403 disk = device->block->bdev->bd_disk;
398 disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0); 404 disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
399 while ((part = disk_part_iter_next(&piter))) 405 while ((part = disk_part_iter_next(&piter)))
@@ -744,10 +750,6 @@ struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength,
744 char *data; 750 char *data;
745 int size; 751 int size;
746 752
747 /* Sanity checks */
748 BUG_ON(datasize > PAGE_SIZE ||
749 (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
750
751 size = (sizeof(struct dasd_ccw_req) + 7L) & -8L; 753 size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
752 if (cplength > 0) 754 if (cplength > 0)
753 size += cplength * sizeof(struct ccw1); 755 size += cplength * sizeof(struct ccw1);
@@ -853,7 +855,6 @@ int dasd_term_IO(struct dasd_ccw_req *cqr)
853 rc = ccw_device_clear(device->cdev, (long) cqr); 855 rc = ccw_device_clear(device->cdev, (long) cqr);
854 switch (rc) { 856 switch (rc) {
855 case 0: /* termination successful */ 857 case 0: /* termination successful */
856 cqr->retries--;
857 cqr->status = DASD_CQR_CLEAR_PENDING; 858 cqr->status = DASD_CQR_CLEAR_PENDING;
858 cqr->stopclk = get_clock(); 859 cqr->stopclk = get_clock();
859 cqr->starttime = 0; 860 cqr->starttime = 0;
@@ -905,6 +906,16 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
905 return rc; 906 return rc;
906 } 907 }
907 device = (struct dasd_device *) cqr->startdev; 908 device = (struct dasd_device *) cqr->startdev;
909 if (((cqr->block &&
910 test_bit(DASD_FLAG_LOCK_STOLEN, &cqr->block->base->flags)) ||
911 test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags)) &&
912 !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
913 DBF_DEV_EVENT(DBF_DEBUG, device, "start_IO: return request %p "
914 "because of stolen lock", cqr);
915 cqr->status = DASD_CQR_ERROR;
916 cqr->intrc = -EPERM;
917 return -EPERM;
918 }
908 if (cqr->retries < 0) { 919 if (cqr->retries < 0) {
909 /* internal error 14 - start_IO run out of retries */ 920 /* internal error 14 - start_IO run out of retries */
910 sprintf(errorstring, "14 %p", cqr); 921 sprintf(errorstring, "14 %p", cqr);
@@ -916,6 +927,11 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
916 cqr->startclk = get_clock(); 927 cqr->startclk = get_clock();
917 cqr->starttime = jiffies; 928 cqr->starttime = jiffies;
918 cqr->retries--; 929 cqr->retries--;
930 if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) {
931 cqr->lpm &= device->path_data.opm;
932 if (!cqr->lpm)
933 cqr->lpm = device->path_data.opm;
934 }
919 if (cqr->cpmode == 1) { 935 if (cqr->cpmode == 1) {
920 rc = ccw_device_tm_start(device->cdev, cqr->cpaddr, 936 rc = ccw_device_tm_start(device->cdev, cqr->cpaddr,
921 (long) cqr, cqr->lpm); 937 (long) cqr, cqr->lpm);
@@ -928,35 +944,53 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
928 cqr->status = DASD_CQR_IN_IO; 944 cqr->status = DASD_CQR_IN_IO;
929 break; 945 break;
930 case -EBUSY: 946 case -EBUSY:
931 DBF_DEV_EVENT(DBF_DEBUG, device, "%s", 947 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
932 "start_IO: device busy, retry later"); 948 "start_IO: device busy, retry later");
933 break; 949 break;
934 case -ETIMEDOUT: 950 case -ETIMEDOUT:
935 DBF_DEV_EVENT(DBF_DEBUG, device, "%s", 951 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
936 "start_IO: request timeout, retry later"); 952 "start_IO: request timeout, retry later");
937 break; 953 break;
938 case -EACCES: 954 case -EACCES:
939 /* -EACCES indicates that the request used only a 955 /* -EACCES indicates that the request used only a subset of the
940 * subset of the available pathes and all these 956 * available paths and all these paths are gone. If the lpm of
941 * pathes are gone. 957 * this request was only a subset of the opm (e.g. the ppm) then
942 * Do a retry with all available pathes. 958 * we just do a retry with all available paths.
959 * If we already use the full opm, something is amiss, and we
960 * need a full path verification.
943 */ 961 */
944 cqr->lpm = LPM_ANYPATH; 962 if (test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) {
945 DBF_DEV_EVENT(DBF_DEBUG, device, "%s", 963 DBF_DEV_EVENT(DBF_WARNING, device,
946 "start_IO: selected pathes gone," 964 "start_IO: selected paths gone (%x)",
947 " retry on all pathes"); 965 cqr->lpm);
966 } else if (cqr->lpm != device->path_data.opm) {
967 cqr->lpm = device->path_data.opm;
968 DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
969 "start_IO: selected paths gone,"
970 " retry on all paths");
971 } else {
972 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
973 "start_IO: all paths in opm gone,"
974 " do path verification");
975 dasd_generic_last_path_gone(device);
976 device->path_data.opm = 0;
977 device->path_data.ppm = 0;
978 device->path_data.npm = 0;
979 device->path_data.tbvpm =
980 ccw_device_get_path_mask(device->cdev);
981 }
948 break; 982 break;
949 case -ENODEV: 983 case -ENODEV:
950 DBF_DEV_EVENT(DBF_DEBUG, device, "%s", 984 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
951 "start_IO: -ENODEV device gone, retry"); 985 "start_IO: -ENODEV device gone, retry");
952 break; 986 break;
953 case -EIO: 987 case -EIO:
954 DBF_DEV_EVENT(DBF_DEBUG, device, "%s", 988 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
955 "start_IO: -EIO device gone, retry"); 989 "start_IO: -EIO device gone, retry");
956 break; 990 break;
957 case -EINVAL: 991 case -EINVAL:
958 /* most likely caused in power management context */ 992 /* most likely caused in power management context */
959 DBF_DEV_EVENT(DBF_DEBUG, device, "%s", 993 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
960 "start_IO: -EINVAL device currently " 994 "start_IO: -EINVAL device currently "
961 "not accessible"); 995 "not accessible");
962 break; 996 break;
@@ -1076,6 +1110,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1076 unsigned long long now; 1110 unsigned long long now;
1077 int expires; 1111 int expires;
1078 1112
1113 kstat_cpu(smp_processor_id()).irqs[IOINT_DAS]++;
1079 if (IS_ERR(irb)) { 1114 if (IS_ERR(irb)) {
1080 switch (PTR_ERR(irb)) { 1115 switch (PTR_ERR(irb)) {
1081 case -EIO: 1116 case -EIO:
@@ -1094,16 +1129,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1094 } 1129 }
1095 1130
1096 now = get_clock(); 1131 now = get_clock();
1097
1098 /* check for unsolicited interrupts */
1099 cqr = (struct dasd_ccw_req *) intparm; 1132 cqr = (struct dasd_ccw_req *) intparm;
1100 if (!cqr || ((scsw_cc(&irb->scsw) == 1) && 1133 /* check for conditions that should be handled immediately */
1101 (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) && 1134 if (!cqr ||
1102 ((scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND) || 1135 !(scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
1103 (scsw_stctl(&irb->scsw) == (SCSW_STCTL_STATUS_PEND | 1136 scsw_cstat(&irb->scsw) == 0)) {
1104 SCSW_STCTL_ALERT_STATUS))))) {
1105 if (cqr && cqr->status == DASD_CQR_IN_IO)
1106 cqr->status = DASD_CQR_QUEUED;
1107 if (cqr) 1137 if (cqr)
1108 memcpy(&cqr->irb, irb, sizeof(*irb)); 1138 memcpy(&cqr->irb, irb, sizeof(*irb));
1109 device = dasd_device_from_cdev_locked(cdev); 1139 device = dasd_device_from_cdev_locked(cdev);
@@ -1114,17 +1144,14 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1114 dasd_put_device(device); 1144 dasd_put_device(device);
1115 return; 1145 return;
1116 } 1146 }
1117 device->discipline->dump_sense_dbf(device, irb, 1147 device->discipline->dump_sense_dbf(device, irb, "int");
1118 "unsolicited"); 1148 if (device->features & DASD_FEATURE_ERPLOG)
1119 if ((device->features & DASD_FEATURE_ERPLOG)) 1149 device->discipline->dump_sense(device, cqr, irb);
1120 device->discipline->dump_sense(device, cqr, 1150 device->discipline->check_for_device_change(device, cqr, irb);
1121 irb);
1122 dasd_device_clear_timer(device);
1123 device->discipline->handle_unsolicited_interrupt(device,
1124 irb);
1125 dasd_put_device(device); 1151 dasd_put_device(device);
1126 return;
1127 } 1152 }
1153 if (!cqr)
1154 return;
1128 1155
1129 device = (struct dasd_device *) cqr->startdev; 1156 device = (struct dasd_device *) cqr->startdev;
1130 if (!device || 1157 if (!device ||
@@ -1164,25 +1191,19 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1164 struct dasd_ccw_req, devlist); 1191 struct dasd_ccw_req, devlist);
1165 } 1192 }
1166 } else { /* error */ 1193 } else { /* error */
1167 memcpy(&cqr->irb, irb, sizeof(struct irb));
1168 /* log sense for every failed I/O to s390 debugfeature */
1169 dasd_log_sense_dbf(cqr, irb);
1170 if (device->features & DASD_FEATURE_ERPLOG) {
1171 dasd_log_sense(cqr, irb);
1172 }
1173
1174 /* 1194 /*
1175 * If we don't want complex ERP for this request, then just 1195 * If we don't want complex ERP for this request, then just
1176 * reset this and retry it in the fastpath 1196 * reset this and retry it in the fastpath
1177 */ 1197 */
1178 if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) && 1198 if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) &&
1179 cqr->retries > 0) { 1199 cqr->retries > 0) {
1180 if (cqr->lpm == LPM_ANYPATH) 1200 if (cqr->lpm == device->path_data.opm)
1181 DBF_DEV_EVENT(DBF_DEBUG, device, 1201 DBF_DEV_EVENT(DBF_DEBUG, device,
1182 "default ERP in fastpath " 1202 "default ERP in fastpath "
1183 "(%i retries left)", 1203 "(%i retries left)",
1184 cqr->retries); 1204 cqr->retries);
1185 cqr->lpm = LPM_ANYPATH; 1205 if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))
1206 cqr->lpm = device->path_data.opm;
1186 cqr->status = DASD_CQR_QUEUED; 1207 cqr->status = DASD_CQR_QUEUED;
1187 next = cqr; 1208 next = cqr;
1188 } else 1209 } else
@@ -1210,13 +1231,13 @@ enum uc_todo dasd_generic_uc_handler(struct ccw_device *cdev, struct irb *irb)
1210 goto out; 1231 goto out;
1211 if (test_bit(DASD_FLAG_OFFLINE, &device->flags) || 1232 if (test_bit(DASD_FLAG_OFFLINE, &device->flags) ||
1212 device->state != device->target || 1233 device->state != device->target ||
1213 !device->discipline->handle_unsolicited_interrupt){ 1234 !device->discipline->check_for_device_change){
1214 dasd_put_device(device); 1235 dasd_put_device(device);
1215 goto out; 1236 goto out;
1216 } 1237 }
1217 1238 if (device->discipline->dump_sense_dbf)
1218 dasd_device_clear_timer(device); 1239 device->discipline->dump_sense_dbf(device, irb, "uc");
1219 device->discipline->handle_unsolicited_interrupt(device, irb); 1240 device->discipline->check_for_device_change(device, NULL, irb);
1220 dasd_put_device(device); 1241 dasd_put_device(device);
1221out: 1242out:
1222 return UC_TODO_RETRY; 1243 return UC_TODO_RETRY;
@@ -1366,8 +1387,14 @@ static void __dasd_device_start_head(struct dasd_device *device)
1366 cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist); 1387 cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist);
1367 if (cqr->status != DASD_CQR_QUEUED) 1388 if (cqr->status != DASD_CQR_QUEUED)
1368 return; 1389 return;
1369 /* when device is stopped, return request to previous layer */ 1390 /* when device is stopped, return request to previous layer
1370 if (device->stopped) { 1391 * exception: only the disconnect or unresumed bits are set and the
1392 * cqr is a path verification request
1393 */
1394 if (device->stopped &&
1395 !(!(device->stopped & ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM))
1396 && test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))) {
1397 cqr->intrc = -EAGAIN;
1371 cqr->status = DASD_CQR_CLEARED; 1398 cqr->status = DASD_CQR_CLEARED;
1372 dasd_schedule_device_bh(device); 1399 dasd_schedule_device_bh(device);
1373 return; 1400 return;
@@ -1383,6 +1410,23 @@ static void __dasd_device_start_head(struct dasd_device *device)
1383 dasd_device_set_timer(device, 50); 1410 dasd_device_set_timer(device, 50);
1384} 1411}
1385 1412
1413static void __dasd_device_check_path_events(struct dasd_device *device)
1414{
1415 int rc;
1416
1417 if (device->path_data.tbvpm) {
1418 if (device->stopped & ~(DASD_STOPPED_DC_WAIT |
1419 DASD_UNRESUMED_PM))
1420 return;
1421 rc = device->discipline->verify_path(
1422 device, device->path_data.tbvpm);
1423 if (rc)
1424 dasd_device_set_timer(device, 50);
1425 else
1426 device->path_data.tbvpm = 0;
1427 }
1428};
1429
1386/* 1430/*
1387 * Go through all request on the dasd_device request queue, 1431 * Go through all request on the dasd_device request queue,
1388 * terminate them on the cdev if necessary, and return them to the 1432 * terminate them on the cdev if necessary, and return them to the
@@ -1457,6 +1501,7 @@ static void dasd_device_tasklet(struct dasd_device *device)
1457 __dasd_device_check_expire(device); 1501 __dasd_device_check_expire(device);
1458 /* find final requests on ccw queue */ 1502 /* find final requests on ccw queue */
1459 __dasd_device_process_ccw_queue(device, &final_queue); 1503 __dasd_device_process_ccw_queue(device, &final_queue);
1504 __dasd_device_check_path_events(device);
1460 spin_unlock_irq(get_ccwdev_lock(device->cdev)); 1505 spin_unlock_irq(get_ccwdev_lock(device->cdev));
1461 /* Now call the callback function of requests with final status */ 1506 /* Now call the callback function of requests with final status */
1462 __dasd_device_process_final_queue(device, &final_queue); 1507 __dasd_device_process_final_queue(device, &final_queue);
@@ -1613,7 +1658,12 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
1613 continue; 1658 continue;
1614 if (cqr->status != DASD_CQR_FILLED) /* could be failed */ 1659 if (cqr->status != DASD_CQR_FILLED) /* could be failed */
1615 continue; 1660 continue;
1616 1661 if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags) &&
1662 !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
1663 cqr->status = DASD_CQR_FAILED;
1664 cqr->intrc = -EPERM;
1665 continue;
1666 }
1617 /* Non-temporary stop condition will trigger fail fast */ 1667 /* Non-temporary stop condition will trigger fail fast */
1618 if (device->stopped & ~DASD_STOPPED_PENDING && 1668 if (device->stopped & ~DASD_STOPPED_PENDING &&
1619 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && 1669 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
@@ -1621,7 +1671,6 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
1621 cqr->status = DASD_CQR_FAILED; 1671 cqr->status = DASD_CQR_FAILED;
1622 continue; 1672 continue;
1623 } 1673 }
1624
1625 /* Don't try to start requests if device is stopped */ 1674 /* Don't try to start requests if device is stopped */
1626 if (interruptible) { 1675 if (interruptible) {
1627 rc = wait_event_interruptible( 1676 rc = wait_event_interruptible(
@@ -1706,13 +1755,18 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
1706 int rc; 1755 int rc;
1707 1756
1708 device = cqr->startdev; 1757 device = cqr->startdev;
1758 if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags) &&
1759 !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
1760 cqr->status = DASD_CQR_FAILED;
1761 cqr->intrc = -EPERM;
1762 return -EIO;
1763 }
1709 spin_lock_irq(get_ccwdev_lock(device->cdev)); 1764 spin_lock_irq(get_ccwdev_lock(device->cdev));
1710 rc = _dasd_term_running_cqr(device); 1765 rc = _dasd_term_running_cqr(device);
1711 if (rc) { 1766 if (rc) {
1712 spin_unlock_irq(get_ccwdev_lock(device->cdev)); 1767 spin_unlock_irq(get_ccwdev_lock(device->cdev));
1713 return rc; 1768 return rc;
1714 } 1769 }
1715
1716 cqr->callback = dasd_wakeup_cb; 1770 cqr->callback = dasd_wakeup_cb;
1717 cqr->callback_data = DASD_SLEEPON_START_TAG; 1771 cqr->callback_data = DASD_SLEEPON_START_TAG;
1718 cqr->status = DASD_CQR_QUEUED; 1772 cqr->status = DASD_CQR_QUEUED;
@@ -2016,6 +2070,13 @@ static void __dasd_block_start_head(struct dasd_block *block)
2016 list_for_each_entry(cqr, &block->ccw_queue, blocklist) { 2070 list_for_each_entry(cqr, &block->ccw_queue, blocklist) {
2017 if (cqr->status != DASD_CQR_FILLED) 2071 if (cqr->status != DASD_CQR_FILLED)
2018 continue; 2072 continue;
2073 if (test_bit(DASD_FLAG_LOCK_STOLEN, &block->base->flags) &&
2074 !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
2075 cqr->status = DASD_CQR_FAILED;
2076 cqr->intrc = -EPERM;
2077 dasd_schedule_block_bh(block);
2078 continue;
2079 }
2019 /* Non-temporary stop condition will trigger fail fast */ 2080 /* Non-temporary stop condition will trigger fail fast */
2020 if (block->base->stopped & ~DASD_STOPPED_PENDING && 2081 if (block->base->stopped & ~DASD_STOPPED_PENDING &&
2021 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && 2082 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
@@ -2201,8 +2262,20 @@ static void dasd_setup_queue(struct dasd_block *block)
2201{ 2262{
2202 int max; 2263 int max;
2203 2264
2204 blk_queue_logical_block_size(block->request_queue, block->bp_block); 2265 if (block->base->features & DASD_FEATURE_USERAW) {
2205 max = block->base->discipline->max_blocks << block->s2b_shift; 2266 /*
2267 * the max_blocks value for raw_track access is 256
2268 * it is higher than the native ECKD value because we
2269 * only need one ccw per track
2270 * so the max_hw_sectors are
2271 * 2048 x 512B = 1024kB = 16 tracks
2272 */
2273 max = 2048;
2274 } else {
2275 max = block->base->discipline->max_blocks << block->s2b_shift;
2276 }
2277 blk_queue_logical_block_size(block->request_queue,
2278 block->bp_block);
2206 blk_queue_max_hw_sectors(block->request_queue, max); 2279 blk_queue_max_hw_sectors(block->request_queue, max);
2207 blk_queue_max_segments(block->request_queue, -1L); 2280 blk_queue_max_segments(block->request_queue, -1L);
2208 /* with page sized segments we can translate each segement into 2281 /* with page sized segments we can translate each segement into
@@ -2588,10 +2661,53 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
2588 return 0; 2661 return 0;
2589} 2662}
2590 2663
2664int dasd_generic_last_path_gone(struct dasd_device *device)
2665{
2666 struct dasd_ccw_req *cqr;
2667
2668 dev_warn(&device->cdev->dev, "No operational channel path is left "
2669 "for the device\n");
2670 DBF_DEV_EVENT(DBF_WARNING, device, "%s", "last path gone");
2671 /* First of all call extended error reporting. */
2672 dasd_eer_write(device, NULL, DASD_EER_NOPATH);
2673
2674 if (device->state < DASD_STATE_BASIC)
2675 return 0;
2676 /* Device is active. We want to keep it. */
2677 list_for_each_entry(cqr, &device->ccw_queue, devlist)
2678 if ((cqr->status == DASD_CQR_IN_IO) ||
2679 (cqr->status == DASD_CQR_CLEAR_PENDING)) {
2680 cqr->status = DASD_CQR_QUEUED;
2681 cqr->retries++;
2682 }
2683 dasd_device_set_stop_bits(device, DASD_STOPPED_DC_WAIT);
2684 dasd_device_clear_timer(device);
2685 dasd_schedule_device_bh(device);
2686 return 1;
2687}
2688EXPORT_SYMBOL_GPL(dasd_generic_last_path_gone);
2689
2690int dasd_generic_path_operational(struct dasd_device *device)
2691{
2692 dev_info(&device->cdev->dev, "A channel path to the device has become "
2693 "operational\n");
2694 DBF_DEV_EVENT(DBF_WARNING, device, "%s", "path operational");
2695 dasd_device_remove_stop_bits(device, DASD_STOPPED_DC_WAIT);
2696 if (device->stopped & DASD_UNRESUMED_PM) {
2697 dasd_device_remove_stop_bits(device, DASD_UNRESUMED_PM);
2698 dasd_restore_device(device);
2699 return 1;
2700 }
2701 dasd_schedule_device_bh(device);
2702 if (device->block)
2703 dasd_schedule_block_bh(device->block);
2704 return 1;
2705}
2706EXPORT_SYMBOL_GPL(dasd_generic_path_operational);
2707
2591int dasd_generic_notify(struct ccw_device *cdev, int event) 2708int dasd_generic_notify(struct ccw_device *cdev, int event)
2592{ 2709{
2593 struct dasd_device *device; 2710 struct dasd_device *device;
2594 struct dasd_ccw_req *cqr;
2595 int ret; 2711 int ret;
2596 2712
2597 device = dasd_device_from_cdev_locked(cdev); 2713 device = dasd_device_from_cdev_locked(cdev);
@@ -2602,41 +2718,64 @@ int dasd_generic_notify(struct ccw_device *cdev, int event)
2602 case CIO_GONE: 2718 case CIO_GONE:
2603 case CIO_BOXED: 2719 case CIO_BOXED:
2604 case CIO_NO_PATH: 2720 case CIO_NO_PATH:
2605 /* First of all call extended error reporting. */ 2721 device->path_data.opm = 0;
2606 dasd_eer_write(device, NULL, DASD_EER_NOPATH); 2722 device->path_data.ppm = 0;
2607 2723 device->path_data.npm = 0;
2608 if (device->state < DASD_STATE_BASIC) 2724 ret = dasd_generic_last_path_gone(device);
2609 break;
2610 /* Device is active. We want to keep it. */
2611 list_for_each_entry(cqr, &device->ccw_queue, devlist)
2612 if (cqr->status == DASD_CQR_IN_IO) {
2613 cqr->status = DASD_CQR_QUEUED;
2614 cqr->retries++;
2615 }
2616 dasd_device_set_stop_bits(device, DASD_STOPPED_DC_WAIT);
2617 dasd_device_clear_timer(device);
2618 dasd_schedule_device_bh(device);
2619 ret = 1;
2620 break; 2725 break;
2621 case CIO_OPER: 2726 case CIO_OPER:
2622 /* FIXME: add a sanity check. */
2623 dasd_device_remove_stop_bits(device, DASD_STOPPED_DC_WAIT);
2624 if (device->stopped & DASD_UNRESUMED_PM) {
2625 dasd_device_remove_stop_bits(device, DASD_UNRESUMED_PM);
2626 dasd_restore_device(device);
2627 ret = 1;
2628 break;
2629 }
2630 dasd_schedule_device_bh(device);
2631 if (device->block)
2632 dasd_schedule_block_bh(device->block);
2633 ret = 1; 2727 ret = 1;
2728 if (device->path_data.opm)
2729 ret = dasd_generic_path_operational(device);
2634 break; 2730 break;
2635 } 2731 }
2636 dasd_put_device(device); 2732 dasd_put_device(device);
2637 return ret; 2733 return ret;
2638} 2734}
2639 2735
2736void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
2737{
2738 int chp;
2739 __u8 oldopm, eventlpm;
2740 struct dasd_device *device;
2741
2742 device = dasd_device_from_cdev_locked(cdev);
2743 if (IS_ERR(device))
2744 return;
2745 for (chp = 0; chp < 8; chp++) {
2746 eventlpm = 0x80 >> chp;
2747 if (path_event[chp] & PE_PATH_GONE) {
2748 oldopm = device->path_data.opm;
2749 device->path_data.opm &= ~eventlpm;
2750 device->path_data.ppm &= ~eventlpm;
2751 device->path_data.npm &= ~eventlpm;
2752 if (oldopm && !device->path_data.opm)
2753 dasd_generic_last_path_gone(device);
2754 }
2755 if (path_event[chp] & PE_PATH_AVAILABLE) {
2756 device->path_data.opm &= ~eventlpm;
2757 device->path_data.ppm &= ~eventlpm;
2758 device->path_data.npm &= ~eventlpm;
2759 device->path_data.tbvpm |= eventlpm;
2760 dasd_schedule_device_bh(device);
2761 }
2762 }
2763 dasd_put_device(device);
2764}
2765EXPORT_SYMBOL_GPL(dasd_generic_path_event);
2766
2767int dasd_generic_verify_path(struct dasd_device *device, __u8 lpm)
2768{
2769 if (!device->path_data.opm && lpm) {
2770 device->path_data.opm = lpm;
2771 dasd_generic_path_operational(device);
2772 } else
2773 device->path_data.opm |= lpm;
2774 return 0;
2775}
2776EXPORT_SYMBOL_GPL(dasd_generic_verify_path);
2777
2778
2640int dasd_generic_pm_freeze(struct ccw_device *cdev) 2779int dasd_generic_pm_freeze(struct ccw_device *cdev)
2641{ 2780{
2642 struct dasd_ccw_req *cqr, *n; 2781 struct dasd_ccw_req *cqr, *n;
@@ -2646,6 +2785,10 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
2646 2785
2647 if (IS_ERR(device)) 2786 if (IS_ERR(device))
2648 return PTR_ERR(device); 2787 return PTR_ERR(device);
2788
2789 if (device->discipline->freeze)
2790 rc = device->discipline->freeze(device);
2791
2649 /* disallow new I/O */ 2792 /* disallow new I/O */
2650 dasd_device_set_stop_bits(device, DASD_STOPPED_PM); 2793 dasd_device_set_stop_bits(device, DASD_STOPPED_PM);
2651 /* clear active requests */ 2794 /* clear active requests */
@@ -2682,9 +2825,6 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
2682 list_splice_tail(&freeze_queue, &device->ccw_queue); 2825 list_splice_tail(&freeze_queue, &device->ccw_queue);
2683 spin_unlock_irq(get_ccwdev_lock(cdev)); 2826 spin_unlock_irq(get_ccwdev_lock(cdev));
2684 2827
2685 if (device->discipline->freeze)
2686 rc = device->discipline->freeze(device);
2687
2688 dasd_put_device(device); 2828 dasd_put_device(device);
2689 return rc; 2829 return rc;
2690} 2830}