aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Weinhuber <wein@de.ibm.com>2011-01-05 06:48:04 -0500
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2011-01-05 06:47:30 -0500
commit5a27e60dec59a95bd7f8ae9a19ae2ede4f76395b (patch)
tree20595cba0caebf7a8a5f0afac9785c7d717f3e8c
parenta4d26c6aeceea330ee5e0fb6b017d57e3b252d29 (diff)
[S390] dasd: Improve handling of stolen DASD reservation
If a DASD device has been reserved by a Linux system, and later this reservation is ‘stolen’ by a second system by means of an unconditional reserve, then the first system receives a notification about this fact. With this patch such an event can be either ignored, as before, or it can be used to let the device fail all I/O request, so that the device will not block anymore. Signed-off-by: Stefan Weinhuber <wein@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/dasd.h1
-rw-r--r--drivers/s390/block/dasd.c75
-rw-r--r--drivers/s390/block/dasd_devmap.c99
-rw-r--r--drivers/s390/block/dasd_eckd.c51
-rw-r--r--drivers/s390/block/dasd_eer.c1
-rw-r--r--drivers/s390/block/dasd_fba.c18
-rw-r--r--drivers/s390/block/dasd_int.h13
7 files changed, 189 insertions, 69 deletions
diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h
index b604a9186f8e..47fcdada5d25 100644
--- a/arch/s390/include/asm/dasd.h
+++ b/arch/s390/include/asm/dasd.h
@@ -80,6 +80,7 @@ typedef struct dasd_information2_t {
80#define DASD_FEATURE_INITIAL_ONLINE 0x04 80#define DASD_FEATURE_INITIAL_ONLINE 0x04
81#define DASD_FEATURE_ERPLOG 0x08 81#define DASD_FEATURE_ERPLOG 0x08
82#define DASD_FEATURE_FAILFAST 0x10 82#define DASD_FEATURE_FAILFAST 0x10
83#define DASD_FEATURE_FAILONSLCK 0x20
83 84
84#define DASD_PARTN_BITS 2 85#define DASD_PARTN_BITS 2
85 86
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 8f2067bc88c0..f16afe74464f 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -902,6 +902,16 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
902 return rc; 902 return rc;
903 } 903 }
904 device = (struct dasd_device *) cqr->startdev; 904 device = (struct dasd_device *) cqr->startdev;
905 if (((cqr->block &&
906 test_bit(DASD_FLAG_LOCK_STOLEN, &cqr->block->base->flags)) ||
907 test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags)) &&
908 !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
909 DBF_DEV_EVENT(DBF_DEBUG, device, "start_IO: return request %p "
910 "because of stolen lock", cqr);
911 cqr->status = DASD_CQR_ERROR;
912 cqr->intrc = -EPERM;
913 return -EPERM;
914 }
905 if (cqr->retries < 0) { 915 if (cqr->retries < 0) {
906 /* internal error 14 - start_IO run out of retries */ 916 /* internal error 14 - start_IO run out of retries */
907 sprintf(errorstring, "14 %p", cqr); 917 sprintf(errorstring, "14 %p", cqr);
@@ -1115,16 +1125,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1115 } 1125 }
1116 1126
1117 now = get_clock(); 1127 now = get_clock();
1118
1119 /* check for unsolicited interrupts */
1120 cqr = (struct dasd_ccw_req *) intparm; 1128 cqr = (struct dasd_ccw_req *) intparm;
1121 if (!cqr || ((scsw_cc(&irb->scsw) == 1) && 1129 /* check for conditions that should be handled immediately */
1122 (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) && 1130 if (!cqr ||
1123 ((scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND) || 1131 !(scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
1124 (scsw_stctl(&irb->scsw) == (SCSW_STCTL_STATUS_PEND | 1132 scsw_cstat(&irb->scsw) == 0)) {
1125 SCSW_STCTL_ALERT_STATUS))))) {
1126 if (cqr && cqr->status == DASD_CQR_IN_IO)
1127 cqr->status = DASD_CQR_QUEUED;
1128 if (cqr) 1133 if (cqr)
1129 memcpy(&cqr->irb, irb, sizeof(*irb)); 1134 memcpy(&cqr->irb, irb, sizeof(*irb));
1130 device = dasd_device_from_cdev_locked(cdev); 1135 device = dasd_device_from_cdev_locked(cdev);
@@ -1135,17 +1140,14 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1135 dasd_put_device(device); 1140 dasd_put_device(device);
1136 return; 1141 return;
1137 } 1142 }
1138 device->discipline->dump_sense_dbf(device, irb, 1143 device->discipline->dump_sense_dbf(device, irb, "int");
1139 "unsolicited"); 1144 if (device->features & DASD_FEATURE_ERPLOG)
1140 if ((device->features & DASD_FEATURE_ERPLOG)) 1145 device->discipline->dump_sense(device, cqr, irb);
1141 device->discipline->dump_sense(device, cqr, 1146 device->discipline->check_for_device_change(device, cqr, irb);
1142 irb);
1143 dasd_device_clear_timer(device);
1144 device->discipline->handle_unsolicited_interrupt(device,
1145 irb);
1146 dasd_put_device(device); 1147 dasd_put_device(device);
1147 return;
1148 } 1148 }
1149 if (!cqr)
1150 return;
1149 1151
1150 device = (struct dasd_device *) cqr->startdev; 1152 device = (struct dasd_device *) cqr->startdev;
1151 if (!device || 1153 if (!device ||
@@ -1185,13 +1187,6 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1185 struct dasd_ccw_req, devlist); 1187 struct dasd_ccw_req, devlist);
1186 } 1188 }
1187 } else { /* error */ 1189 } else { /* error */
1188 memcpy(&cqr->irb, irb, sizeof(struct irb));
1189 /* log sense for every failed I/O to s390 debugfeature */
1190 dasd_log_sense_dbf(cqr, irb);
1191 if (device->features & DASD_FEATURE_ERPLOG) {
1192 dasd_log_sense(cqr, irb);
1193 }
1194
1195 /* 1190 /*
1196 * If we don't want complex ERP for this request, then just 1191 * If we don't want complex ERP for this request, then just
1197 * reset this and retry it in the fastpath 1192 * reset this and retry it in the fastpath
@@ -1232,13 +1227,13 @@ enum uc_todo dasd_generic_uc_handler(struct ccw_device *cdev, struct irb *irb)
1232 goto out; 1227 goto out;
1233 if (test_bit(DASD_FLAG_OFFLINE, &device->flags) || 1228 if (test_bit(DASD_FLAG_OFFLINE, &device->flags) ||
1234 device->state != device->target || 1229 device->state != device->target ||
1235 !device->discipline->handle_unsolicited_interrupt){ 1230 !device->discipline->check_for_device_change){
1236 dasd_put_device(device); 1231 dasd_put_device(device);
1237 goto out; 1232 goto out;
1238 } 1233 }
1239 1234 if (device->discipline->dump_sense_dbf)
1240 dasd_device_clear_timer(device); 1235 device->discipline->dump_sense_dbf(device, irb, "uc");
1241 device->discipline->handle_unsolicited_interrupt(device, irb); 1236 device->discipline->check_for_device_change(device, NULL, irb);
1242 dasd_put_device(device); 1237 dasd_put_device(device);
1243out: 1238out:
1244 return UC_TODO_RETRY; 1239 return UC_TODO_RETRY;
@@ -1659,7 +1654,12 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
1659 continue; 1654 continue;
1660 if (cqr->status != DASD_CQR_FILLED) /* could be failed */ 1655 if (cqr->status != DASD_CQR_FILLED) /* could be failed */
1661 continue; 1656 continue;
1662 1657 if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags) &&
1658 !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
1659 cqr->status = DASD_CQR_FAILED;
1660 cqr->intrc = -EPERM;
1661 continue;
1662 }
1663 /* Non-temporary stop condition will trigger fail fast */ 1663 /* Non-temporary stop condition will trigger fail fast */
1664 if (device->stopped & ~DASD_STOPPED_PENDING && 1664 if (device->stopped & ~DASD_STOPPED_PENDING &&
1665 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && 1665 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
@@ -1667,7 +1667,6 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
1667 cqr->status = DASD_CQR_FAILED; 1667 cqr->status = DASD_CQR_FAILED;
1668 continue; 1668 continue;
1669 } 1669 }
1670
1671 /* Don't try to start requests if device is stopped */ 1670 /* Don't try to start requests if device is stopped */
1672 if (interruptible) { 1671 if (interruptible) {
1673 rc = wait_event_interruptible( 1672 rc = wait_event_interruptible(
@@ -1752,13 +1751,18 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
1752 int rc; 1751 int rc;
1753 1752
1754 device = cqr->startdev; 1753 device = cqr->startdev;
1754 if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags) &&
1755 !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
1756 cqr->status = DASD_CQR_FAILED;
1757 cqr->intrc = -EPERM;
1758 return -EIO;
1759 }
1755 spin_lock_irq(get_ccwdev_lock(device->cdev)); 1760 spin_lock_irq(get_ccwdev_lock(device->cdev));
1756 rc = _dasd_term_running_cqr(device); 1761 rc = _dasd_term_running_cqr(device);
1757 if (rc) { 1762 if (rc) {
1758 spin_unlock_irq(get_ccwdev_lock(device->cdev)); 1763 spin_unlock_irq(get_ccwdev_lock(device->cdev));
1759 return rc; 1764 return rc;
1760 } 1765 }
1761
1762 cqr->callback = dasd_wakeup_cb; 1766 cqr->callback = dasd_wakeup_cb;
1763 cqr->callback_data = DASD_SLEEPON_START_TAG; 1767 cqr->callback_data = DASD_SLEEPON_START_TAG;
1764 cqr->status = DASD_CQR_QUEUED; 1768 cqr->status = DASD_CQR_QUEUED;
@@ -2062,6 +2066,13 @@ static void __dasd_block_start_head(struct dasd_block *block)
2062 list_for_each_entry(cqr, &block->ccw_queue, blocklist) { 2066 list_for_each_entry(cqr, &block->ccw_queue, blocklist) {
2063 if (cqr->status != DASD_CQR_FILLED) 2067 if (cqr->status != DASD_CQR_FILLED)
2064 continue; 2068 continue;
2069 if (test_bit(DASD_FLAG_LOCK_STOLEN, &block->base->flags) &&
2070 !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
2071 cqr->status = DASD_CQR_FAILED;
2072 cqr->intrc = -EPERM;
2073 dasd_schedule_block_bh(block);
2074 continue;
2075 }
2065 /* Non-temporary stop condition will trigger fail fast */ 2076 /* Non-temporary stop condition will trigger fail fast */
2066 if (block->base->stopped & ~DASD_STOPPED_PENDING && 2077 if (block->base->stopped & ~DASD_STOPPED_PENDING &&
2067 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && 2078 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 0001df8ad3e6..47fc88692494 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -1127,6 +1127,103 @@ dasd_expires_store(struct device *dev, struct device_attribute *attr,
1127 1127
1128static DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store); 1128static DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store);
1129 1129
1130static ssize_t dasd_reservation_policy_show(struct device *dev,
1131 struct device_attribute *attr,
1132 char *buf)
1133{
1134 struct dasd_devmap *devmap;
1135 int rc = 0;
1136
1137 devmap = dasd_find_busid(dev_name(dev));
1138 if (IS_ERR(devmap)) {
1139 rc = snprintf(buf, PAGE_SIZE, "ignore\n");
1140 } else {
1141 spin_lock(&dasd_devmap_lock);
1142 if (devmap->features & DASD_FEATURE_FAILONSLCK)
1143 rc = snprintf(buf, PAGE_SIZE, "fail\n");
1144 else
1145 rc = snprintf(buf, PAGE_SIZE, "ignore\n");
1146 spin_unlock(&dasd_devmap_lock);
1147 }
1148 return rc;
1149}
1150
1151static ssize_t dasd_reservation_policy_store(struct device *dev,
1152 struct device_attribute *attr,
1153 const char *buf, size_t count)
1154{
1155 struct dasd_devmap *devmap;
1156 int rc;
1157
1158 devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
1159 if (IS_ERR(devmap))
1160 return PTR_ERR(devmap);
1161 rc = 0;
1162 spin_lock(&dasd_devmap_lock);
1163 if (sysfs_streq("ignore", buf))
1164 devmap->features &= ~DASD_FEATURE_FAILONSLCK;
1165 else if (sysfs_streq("fail", buf))
1166 devmap->features |= DASD_FEATURE_FAILONSLCK;
1167 else
1168 rc = -EINVAL;
1169 if (devmap->device)
1170 devmap->device->features = devmap->features;
1171 spin_unlock(&dasd_devmap_lock);
1172 if (rc)
1173 return rc;
1174 else
1175 return count;
1176}
1177
1178static DEVICE_ATTR(reservation_policy, 0644,
1179 dasd_reservation_policy_show, dasd_reservation_policy_store);
1180
1181static ssize_t dasd_reservation_state_show(struct device *dev,
1182 struct device_attribute *attr,
1183 char *buf)
1184{
1185 struct dasd_device *device;
1186 int rc = 0;
1187
1188 device = dasd_device_from_cdev(to_ccwdev(dev));
1189 if (IS_ERR(device))
1190 return snprintf(buf, PAGE_SIZE, "none\n");
1191
1192 if (test_bit(DASD_FLAG_IS_RESERVED, &device->flags))
1193 rc = snprintf(buf, PAGE_SIZE, "reserved\n");
1194 else if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags))
1195 rc = snprintf(buf, PAGE_SIZE, "lost\n");
1196 else
1197 rc = snprintf(buf, PAGE_SIZE, "none\n");
1198 dasd_put_device(device);
1199 return rc;
1200}
1201
1202static ssize_t dasd_reservation_state_store(struct device *dev,
1203 struct device_attribute *attr,
1204 const char *buf, size_t count)
1205{
1206 struct dasd_device *device;
1207 int rc = 0;
1208
1209 device = dasd_device_from_cdev(to_ccwdev(dev));
1210 if (IS_ERR(device))
1211 return -ENODEV;
1212 if (sysfs_streq("reset", buf))
1213 clear_bit(DASD_FLAG_LOCK_STOLEN, &device->flags);
1214 else
1215 rc = -EINVAL;
1216 dasd_put_device(device);
1217
1218 if (rc)
1219 return rc;
1220 else
1221 return count;
1222}
1223
1224static DEVICE_ATTR(last_known_reservation_state, 0644,
1225 dasd_reservation_state_show, dasd_reservation_state_store);
1226
1130static struct attribute * dasd_attrs[] = { 1227static struct attribute * dasd_attrs[] = {
1131 &dev_attr_readonly.attr, 1228 &dev_attr_readonly.attr,
1132 &dev_attr_discipline.attr, 1229 &dev_attr_discipline.attr,
@@ -1139,6 +1236,8 @@ static struct attribute * dasd_attrs[] = {
1139 &dev_attr_erplog.attr, 1236 &dev_attr_erplog.attr,
1140 &dev_attr_failfast.attr, 1237 &dev_attr_failfast.attr,
1141 &dev_attr_expires.attr, 1238 &dev_attr_expires.attr,
1239 &dev_attr_reservation_policy.attr,
1240 &dev_attr_last_known_reservation_state.attr,
1142 NULL, 1241 NULL,
1143}; 1242};
1144 1243
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index a1ebf5722ae5..46eafce3a0a6 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -817,6 +817,7 @@ static int dasd_eckd_read_conf_immediately(struct dasd_device *device,
817 817
818 dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buffer, lpm); 818 dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buffer, lpm);
819 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); 819 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
820 set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
820 cqr->retries = 5; 821 cqr->retries = 5;
821 rc = dasd_sleep_on_immediatly(cqr); 822 rc = dasd_sleep_on_immediatly(cqr);
822 return rc; 823 return rc;
@@ -1947,9 +1948,9 @@ dasd_eckd_erp_postaction(struct dasd_ccw_req * cqr)
1947 return dasd_default_erp_postaction; 1948 return dasd_default_erp_postaction;
1948} 1949}
1949 1950
1950 1951static void dasd_eckd_check_for_device_change(struct dasd_device *device,
1951static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, 1952 struct dasd_ccw_req *cqr,
1952 struct irb *irb) 1953 struct irb *irb)
1953{ 1954{
1954 char mask; 1955 char mask;
1955 char *sense = NULL; 1956 char *sense = NULL;
@@ -1973,40 +1974,41 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
1973 /* schedule worker to reload device */ 1974 /* schedule worker to reload device */
1974 dasd_reload_device(device); 1975 dasd_reload_device(device);
1975 } 1976 }
1976
1977 dasd_generic_handle_state_change(device); 1977 dasd_generic_handle_state_change(device);
1978 return; 1978 return;
1979 } 1979 }
1980 1980
1981 /* summary unit check */
1982 sense = dasd_get_sense(irb); 1981 sense = dasd_get_sense(irb);
1983 if (sense && (sense[7] == 0x0D) && 1982 if (!sense)
1983 return;
1984
1985 /* summary unit check */
1986 if ((sense[7] == 0x0D) &&
1984 (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK)) { 1987 (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK)) {
1985 dasd_alias_handle_summary_unit_check(device, irb); 1988 dasd_alias_handle_summary_unit_check(device, irb);
1986 return; 1989 return;
1987 } 1990 }
1988 1991
1989 /* service information message SIM */ 1992 /* service information message SIM */
1990 if (sense && !(sense[27] & DASD_SENSE_BIT_0) && 1993 if (!cqr && !(sense[27] & DASD_SENSE_BIT_0) &&
1991 ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) { 1994 ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) {
1992 dasd_3990_erp_handle_sim(device, sense); 1995 dasd_3990_erp_handle_sim(device, sense);
1993 dasd_schedule_device_bh(device);
1994 return; 1996 return;
1995 } 1997 }
1996 1998
1997 if ((scsw_cc(&irb->scsw) == 1) && !sense && 1999 /* loss of device reservation is handled via base devices only
1998 (scsw_fctl(&irb->scsw) == SCSW_FCTL_START_FUNC) && 2000 * as alias devices may be used with several bases
1999 (scsw_actl(&irb->scsw) == SCSW_ACTL_START_PEND) && 2001 */
2000 (scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND)) { 2002 if (device->block && (sense[7] == 0x3F) &&
2001 /* fake irb do nothing, they are handled elsewhere */ 2003 (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) &&
2002 dasd_schedule_device_bh(device); 2004 test_bit(DASD_FLAG_IS_RESERVED, &device->flags)) {
2003 return; 2005 if (device->features & DASD_FEATURE_FAILONSLCK)
2006 set_bit(DASD_FLAG_LOCK_STOLEN, &device->flags);
2007 clear_bit(DASD_FLAG_IS_RESERVED, &device->flags);
2008 dev_err(&device->cdev->dev,
2009 "The device reservation was lost\n");
2004 } 2010 }
2005 2011}
2006 dasd_schedule_device_bh(device);
2007 return;
2008};
2009
2010 2012
2011static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( 2013static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
2012 struct dasd_device *startdev, 2014 struct dasd_device *startdev,
@@ -2931,6 +2933,8 @@ dasd_eckd_release(struct dasd_device *device)
2931 cqr->status = DASD_CQR_FILLED; 2933 cqr->status = DASD_CQR_FILLED;
2932 2934
2933 rc = dasd_sleep_on_immediatly(cqr); 2935 rc = dasd_sleep_on_immediatly(cqr);
2936 if (!rc)
2937 clear_bit(DASD_FLAG_IS_RESERVED, &device->flags);
2934 2938
2935 if (useglobal) 2939 if (useglobal)
2936 mutex_unlock(&dasd_reserve_mutex); 2940 mutex_unlock(&dasd_reserve_mutex);
@@ -2984,6 +2988,8 @@ dasd_eckd_reserve(struct dasd_device *device)
2984 cqr->status = DASD_CQR_FILLED; 2988 cqr->status = DASD_CQR_FILLED;
2985 2989
2986 rc = dasd_sleep_on_immediatly(cqr); 2990 rc = dasd_sleep_on_immediatly(cqr);
2991 if (!rc)
2992 set_bit(DASD_FLAG_IS_RESERVED, &device->flags);
2987 2993
2988 if (useglobal) 2994 if (useglobal)
2989 mutex_unlock(&dasd_reserve_mutex); 2995 mutex_unlock(&dasd_reserve_mutex);
@@ -3036,6 +3042,8 @@ dasd_eckd_steal_lock(struct dasd_device *device)
3036 cqr->status = DASD_CQR_FILLED; 3042 cqr->status = DASD_CQR_FILLED;
3037 3043
3038 rc = dasd_sleep_on_immediatly(cqr); 3044 rc = dasd_sleep_on_immediatly(cqr);
3045 if (!rc)
3046 set_bit(DASD_FLAG_IS_RESERVED, &device->flags);
3039 3047
3040 if (useglobal) 3048 if (useglobal)
3041 mutex_unlock(&dasd_reserve_mutex); 3049 mutex_unlock(&dasd_reserve_mutex);
@@ -3088,6 +3096,7 @@ static int dasd_eckd_snid(struct dasd_device *device,
3088 cqr->memdev = device; 3096 cqr->memdev = device;
3089 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); 3097 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
3090 set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); 3098 set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
3099 set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
3091 cqr->retries = 5; 3100 cqr->retries = 5;
3092 cqr->expires = 10 * HZ; 3101 cqr->expires = 10 * HZ;
3093 cqr->buildclk = get_clock(); 3102 cqr->buildclk = get_clock();
@@ -3832,7 +3841,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
3832 .format_device = dasd_eckd_format_device, 3841 .format_device = dasd_eckd_format_device,
3833 .erp_action = dasd_eckd_erp_action, 3842 .erp_action = dasd_eckd_erp_action,
3834 .erp_postaction = dasd_eckd_erp_postaction, 3843 .erp_postaction = dasd_eckd_erp_postaction,
3835 .handle_unsolicited_interrupt = dasd_eckd_handle_unsolicited_interrupt, 3844 .check_for_device_change = dasd_eckd_check_for_device_change,
3836 .build_cp = dasd_eckd_build_alias_cp, 3845 .build_cp = dasd_eckd_build_alias_cp,
3837 .free_cp = dasd_eckd_free_alias_cp, 3846 .free_cp = dasd_eckd_free_alias_cp,
3838 .dump_sense = dasd_eckd_dump_sense, 3847 .dump_sense = dasd_eckd_dump_sense,
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 83b4615a3b62..77f778b7b070 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -473,6 +473,7 @@ int dasd_eer_enable(struct dasd_device *device)
473 cqr->retries = 255; 473 cqr->retries = 255;
474 cqr->expires = 10 * HZ; 474 cqr->expires = 10 * HZ;
475 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); 475 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
476 set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
476 477
477 ccw = cqr->cpaddr; 478 ccw = cqr->cpaddr;
478 ccw->cmd_code = DASD_ECKD_CCW_SNSS; 479 ccw->cmd_code = DASD_ECKD_CCW_SNSS;
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 86bacda2c5f6..be89b3a893da 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -233,24 +233,16 @@ dasd_fba_erp_postaction(struct dasd_ccw_req * cqr)
233 return NULL; 233 return NULL;
234} 234}
235 235
236static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device, 236static void dasd_fba_check_for_device_change(struct dasd_device *device,
237 struct irb *irb) 237 struct dasd_ccw_req *cqr,
238 struct irb *irb)
238{ 239{
239 char mask; 240 char mask;
240 241
241 /* first of all check for state change pending interrupt */ 242 /* first of all check for state change pending interrupt */
242 mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; 243 mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
243 if ((irb->scsw.cmd.dstat & mask) == mask) { 244 if ((irb->scsw.cmd.dstat & mask) == mask)
244 dasd_generic_handle_state_change(device); 245 dasd_generic_handle_state_change(device);
245 return;
246 }
247
248 /* check for unsolicited interrupts */
249 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
250 "unsolicited interrupt received");
251 device->discipline->dump_sense_dbf(device, irb, "unsolicited");
252 dasd_schedule_device_bh(device);
253 return;
254}; 246};
255 247
256static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev, 248static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
@@ -605,7 +597,7 @@ static struct dasd_discipline dasd_fba_discipline = {
605 .handle_terminated_request = dasd_fba_handle_terminated_request, 597 .handle_terminated_request = dasd_fba_handle_terminated_request,
606 .erp_action = dasd_fba_erp_action, 598 .erp_action = dasd_fba_erp_action,
607 .erp_postaction = dasd_fba_erp_postaction, 599 .erp_postaction = dasd_fba_erp_postaction,
608 .handle_unsolicited_interrupt = dasd_fba_handle_unsolicited_interrupt, 600 .check_for_device_change = dasd_fba_check_for_device_change,
609 .build_cp = dasd_fba_build_cp, 601 .build_cp = dasd_fba_build_cp,
610 .free_cp = dasd_fba_free_cp, 602 .free_cp = dasd_fba_free_cp,
611 .dump_sense = dasd_fba_dump_sense, 603 .dump_sense = dasd_fba_dump_sense,
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index ba038ef57606..df9f6999411d 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -232,6 +232,10 @@ struct dasd_ccw_req {
232#define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */ 232#define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */
233#define DASD_CQR_FLAGS_FAILFAST 1 /* FAILFAST */ 233#define DASD_CQR_FLAGS_FAILFAST 1 /* FAILFAST */
234#define DASD_CQR_VERIFY_PATH 2 /* path verification request */ 234#define DASD_CQR_VERIFY_PATH 2 /* path verification request */
235#define DASD_CQR_ALLOW_SLOCK 3 /* Try this request even when lock was
236 * stolen. Should not be combined with
237 * DASD_CQR_FLAGS_USE_ERP
238 */
235 239
236/* Signature for error recovery functions. */ 240/* Signature for error recovery functions. */
237typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); 241typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);
@@ -334,9 +338,9 @@ struct dasd_discipline {
334 void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *, 338 void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *,
335 struct irb *); 339 struct irb *);
336 void (*dump_sense_dbf) (struct dasd_device *, struct irb *, char *); 340 void (*dump_sense_dbf) (struct dasd_device *, struct irb *, char *);
337 341 void (*check_for_device_change) (struct dasd_device *,
338 void (*handle_unsolicited_interrupt) (struct dasd_device *, 342 struct dasd_ccw_req *,
339 struct irb *); 343 struct irb *);
340 344
341 /* i/o control functions. */ 345 /* i/o control functions. */
342 int (*fill_geometry) (struct dasd_block *, struct hd_geometry *); 346 int (*fill_geometry) (struct dasd_block *, struct hd_geometry *);
@@ -473,6 +477,9 @@ struct dasd_block {
473 * confuse this with the user specified 477 * confuse this with the user specified
474 * read-only feature. 478 * read-only feature.
475 */ 479 */
480#define DASD_FLAG_IS_RESERVED 7 /* The device is reserved */
481#define DASD_FLAG_LOCK_STOLEN 8 /* The device lock was stolen */
482
476 483
477void dasd_put_device_wake(struct dasd_device *); 484void dasd_put_device_wake(struct dasd_device *);
478 485