diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd.c | 23 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 1 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 1 | ||||
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 7 | ||||
-rw-r--r-- | drivers/s390/cio/ccwreq.c | 15 | ||||
-rw-r--r-- | drivers/s390/cio/ioasm.h | 15 |
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 | ||
1189 | enum 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); | ||
1207 | out: | ||
1208 | return UC_TODO_RETRY; | ||
1209 | } | ||
1210 | EXPORT_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); | |||
617 | void dasd_generic_handle_state_change(struct dasd_device *); | 617 | void dasd_generic_handle_state_change(struct dasd_device *); |
618 | int dasd_generic_pm_freeze(struct ccw_device *); | 618 | int dasd_generic_pm_freeze(struct ccw_device *); |
619 | int dasd_generic_restore_device(struct ccw_device *); | 619 | int dasd_generic_restore_device(struct ccw_device *); |
620 | enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *); | ||
620 | 621 | ||
621 | int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int); | 622 | int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int); |
622 | char *dasd_get_sense(struct irb *); | 623 | char *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, | |||
303 | error: | 308 | error: |
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 | ||
26 | static 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 | |||
41 | static inline int stsch_err(struct subchannel_id schid, struct schib *addr) | 26 | static 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; |