aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd.c23
-rw-r--r--drivers/s390/block/dasd_eckd.c1
-rw-r--r--drivers/s390/block/dasd_int.h1
-rw-r--r--drivers/s390/cio/ccwgroup.c7
-rw-r--r--drivers/s390/cio/ccwreq.c15
-rw-r--r--drivers/s390/cio/ioasm.h15
6 files changed, 47 insertions, 15 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 0e86247d791e..33975e922d65 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1186,6 +1186,29 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1186 dasd_schedule_device_bh(device); 1186 dasd_schedule_device_bh(device);
1187} 1187}
1188 1188
1189enum uc_todo dasd_generic_uc_handler(struct ccw_device *cdev, struct irb *irb)
1190{
1191 struct dasd_device *device;
1192
1193 device = dasd_device_from_cdev_locked(cdev);
1194
1195 if (IS_ERR(device))
1196 goto out;
1197 if (test_bit(DASD_FLAG_OFFLINE, &device->flags) ||
1198 device->state != device->target ||
1199 !device->discipline->handle_unsolicited_interrupt){
1200 dasd_put_device(device);
1201 goto out;
1202 }
1203
1204 dasd_device_clear_timer(device);
1205 device->discipline->handle_unsolicited_interrupt(device, irb);
1206 dasd_put_device(device);
1207out:
1208 return UC_TODO_RETRY;
1209}
1210EXPORT_SYMBOL_GPL(dasd_generic_uc_handler);
1211
1189/* 1212/*
1190 * If we have an error on a dasd_block layer request then we cancel 1213 * If we have an error on a dasd_block layer request then we cancel
1191 * and return all further requests from the same dasd_block as well. 1214 * and return all further requests from the same dasd_block as well.
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 5b1cd8d6e971..ab84da5592e8 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -3436,6 +3436,7 @@ static struct ccw_driver dasd_eckd_driver = {
3436 .freeze = dasd_generic_pm_freeze, 3436 .freeze = dasd_generic_pm_freeze,
3437 .thaw = dasd_generic_restore_device, 3437 .thaw = dasd_generic_restore_device,
3438 .restore = dasd_generic_restore_device, 3438 .restore = dasd_generic_restore_device,
3439 .uc_handler = dasd_generic_uc_handler,
3439}; 3440};
3440 3441
3441/* 3442/*
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 32fac186ba3f..49b431d135e0 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -617,6 +617,7 @@ int dasd_generic_notify(struct ccw_device *, int);
617void dasd_generic_handle_state_change(struct dasd_device *); 617void dasd_generic_handle_state_change(struct dasd_device *);
618int dasd_generic_pm_freeze(struct ccw_device *); 618int dasd_generic_pm_freeze(struct ccw_device *);
619int dasd_generic_restore_device(struct ccw_device *); 619int dasd_generic_restore_device(struct ccw_device *);
620enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *);
620 621
621int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int); 622int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int);
622char *dasd_get_sense(struct irb *); 623char *dasd_get_sense(struct irb *);
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 5f97ea2ee6b1..97b25d68e3e7 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -123,8 +123,10 @@ ccwgroup_release (struct device *dev)
123 123
124 for (i = 0; i < gdev->count; i++) { 124 for (i = 0; i < gdev->count; i++) {
125 if (gdev->cdev[i]) { 125 if (gdev->cdev[i]) {
126 spin_lock_irq(gdev->cdev[i]->ccwlock);
126 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) 127 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
127 dev_set_drvdata(&gdev->cdev[i]->dev, NULL); 128 dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
129 spin_unlock_irq(gdev->cdev[i]->ccwlock);
128 put_device(&gdev->cdev[i]->dev); 130 put_device(&gdev->cdev[i]->dev);
129 } 131 }
130 } 132 }
@@ -262,11 +264,14 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
262 goto error; 264 goto error;
263 } 265 }
264 /* Don't allow a device to belong to more than one group. */ 266 /* Don't allow a device to belong to more than one group. */
267 spin_lock_irq(gdev->cdev[i]->ccwlock);
265 if (dev_get_drvdata(&gdev->cdev[i]->dev)) { 268 if (dev_get_drvdata(&gdev->cdev[i]->dev)) {
269 spin_unlock_irq(gdev->cdev[i]->ccwlock);
266 rc = -EINVAL; 270 rc = -EINVAL;
267 goto error; 271 goto error;
268 } 272 }
269 dev_set_drvdata(&gdev->cdev[i]->dev, gdev); 273 dev_set_drvdata(&gdev->cdev[i]->dev, gdev);
274 spin_unlock_irq(gdev->cdev[i]->ccwlock);
270 } 275 }
271 /* Check for sufficient number of bus ids. */ 276 /* Check for sufficient number of bus ids. */
272 if (i < num_devices && !curr_buf) { 277 if (i < num_devices && !curr_buf) {
@@ -303,8 +308,10 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
303error: 308error:
304 for (i = 0; i < num_devices; i++) 309 for (i = 0; i < num_devices; i++)
305 if (gdev->cdev[i]) { 310 if (gdev->cdev[i]) {
311 spin_lock_irq(gdev->cdev[i]->ccwlock);
306 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) 312 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
307 dev_set_drvdata(&gdev->cdev[i]->dev, NULL); 313 dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
314 spin_unlock_irq(gdev->cdev[i]->ccwlock);
308 put_device(&gdev->cdev[i]->dev); 315 put_device(&gdev->cdev[i]->dev);
309 gdev->cdev[i] = NULL; 316 gdev->cdev[i] = NULL;
310 } 317 }
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c
index 37df42af05ec..7f206ed44fdf 100644
--- a/drivers/s390/cio/ccwreq.c
+++ b/drivers/s390/cio/ccwreq.c
@@ -159,6 +159,7 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb)
159{ 159{
160 struct irb *irb = &cdev->private->irb; 160 struct irb *irb = &cdev->private->irb;
161 struct cmd_scsw *scsw = &irb->scsw.cmd; 161 struct cmd_scsw *scsw = &irb->scsw.cmd;
162 enum uc_todo todo;
162 163
163 /* Perform BASIC SENSE if needed. */ 164 /* Perform BASIC SENSE if needed. */
164 if (ccw_device_accumulate_and_sense(cdev, lcirb)) 165 if (ccw_device_accumulate_and_sense(cdev, lcirb))
@@ -178,6 +179,20 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb)
178 /* Check for command reject. */ 179 /* Check for command reject. */
179 if (irb->ecw[0] & SNS0_CMD_REJECT) 180 if (irb->ecw[0] & SNS0_CMD_REJECT)
180 return IO_REJECTED; 181 return IO_REJECTED;
182 /* Ask the driver what to do */
183 if (cdev->drv && cdev->drv->uc_handler) {
184 todo = cdev->drv->uc_handler(cdev, lcirb);
185 switch (todo) {
186 case UC_TODO_RETRY:
187 return IO_STATUS_ERROR;
188 case UC_TODO_RETRY_ON_NEW_PATH:
189 return IO_PATH_ERROR;
190 case UC_TODO_STOP:
191 return IO_REJECTED;
192 default:
193 return IO_STATUS_ERROR;
194 }
195 }
181 /* Assume that unexpected SENSE data implies an error. */ 196 /* Assume that unexpected SENSE data implies an error. */
182 return IO_STATUS_ERROR; 197 return IO_STATUS_ERROR;
183 } 198 }
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index 759262792633..fac06155773f 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -23,21 +23,6 @@ struct tpi_info {
23 * Some S390 specific IO instructions as inline 23 * Some S390 specific IO instructions as inline
24 */ 24 */
25 25
26static inline int stsch(struct subchannel_id schid, struct schib *addr)
27{
28 register struct subchannel_id reg1 asm ("1") = schid;
29 int ccode;
30
31 asm volatile(
32 " stsch 0(%3)\n"
33 " ipm %0\n"
34 " srl %0,28"
35 : "=d" (ccode), "=m" (*addr)
36 : "d" (reg1), "a" (addr)
37 : "cc");
38 return ccode;
39}
40
41static inline int stsch_err(struct subchannel_id schid, struct schib *addr) 26static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
42{ 27{
43 register struct subchannel_id reg1 asm ("1") = schid; 28 register struct subchannel_id reg1 asm ("1") = schid;