summaryrefslogtreecommitdiff
path: root/drivers/s390/cio/device_fsm.c
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2008-12-25 12:39:12 (GMT)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-12-25 12:39:10 (GMT)
commitcdb912a40df8b8507ab60b3d52f9980c0ba1f44d (patch)
tree52d693b3515b71b4f84b539d41571facb75498db /drivers/s390/cio/device_fsm.c
parentd6a30761d8116b8de8a5b5e79e68cce81d36414b (diff)
downloadlinux-cdb912a40df8b8507ab60b3d52f9980c0ba1f44d.tar.xz
[S390] cio: introduce cio_update_schib
There is the chance that we get condition code 0 for a stsch but the resulting schib is not vaild. In the current code there are 2 cases: * we do a check for validity of the schib after stsch, but at this time we have already stored the invaild schib in the subchannel structure. This may lead to problems. * we don't do a check for validity, which is not that good either. The patch addresses both issues by introducing the stsch wrapper cio_update_schib which performs stsch on a local schib. This schib is only written back to the subchannel if it's valid. side note: For some functions (chp_events) the return codes are different now (-ENXIO vs -ENODEV) but this shouldn't do harm since the caller doesn't check for _specific_ errors. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r--drivers/s390/cio/device_fsm.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 01330cf..e1a3786 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -140,8 +140,7 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
int ret;
sch = to_subchannel(cdev->dev.parent);
- ret = stsch(sch->schid, &sch->schib);
- if (ret || !sch->schib.pmcw.dnv)
+ if (cio_update_schib(sch))
return -ENODEV;
if (!sch->schib.pmcw.ena)
/* Not operational -> done. */
@@ -245,11 +244,13 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
* through ssch() and the path information is up to date.
*/
old_lpm = sch->lpm;
- stsch(sch->schid, &sch->schib);
- sch->lpm = sch->schib.pmcw.pam & sch->opm;
+
/* Check since device may again have become not operational. */
- if (!sch->schib.pmcw.dnv)
+ if (cio_update_schib(sch))
state = DEV_STATE_NOT_OPER;
+ else
+ sch->lpm = sch->schib.pmcw.pam & sch->opm;
+
if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID)
/* Force reprobe on all chpids. */
old_lpm = 0;
@@ -549,7 +550,11 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
sch = to_subchannel(cdev->dev.parent);
/* Update schib - pom may have changed. */
- stsch(sch->schid, &sch->schib);
+ if (cio_update_schib(sch)) {
+ cdev->private->flags.donotify = 0;
+ ccw_device_done(cdev, DEV_STATE_NOT_OPER);
+ return;
+ }
/* Update lpm with verified path mask. */
sch->lpm = sch->vpm;
/* Repeat path verification? */
@@ -667,7 +672,7 @@ ccw_device_offline(struct ccw_device *cdev)
return 0;
}
sch = to_subchannel(cdev->dev.parent);
- if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv)
+ if (cio_update_schib(sch))
return -ENODEV;
if (scsw_actl(&sch->schib.scsw) != 0)
return -EBUSY;
@@ -745,7 +750,10 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
* Since we might not just be coming from an interrupt from the
* subchannel we have to update the schib.
*/
- stsch(sch->schid, &sch->schib);
+ if (cio_update_schib(sch)) {
+ ccw_device_verify_done(cdev, -ENODEV);
+ return;
+ }
if (scsw_actl(&sch->schib.scsw) != 0 ||
(scsw_stctl(&sch->schib.scsw) & SCSW_STCTL_STATUS_PEND) ||
@@ -1011,9 +1019,7 @@ void ccw_device_trigger_reprobe(struct ccw_device *cdev)
sch = to_subchannel(cdev->dev.parent);
/* Update some values. */
- if (stsch(sch->schid, &sch->schib))
- return;
- if (!sch->schib.pmcw.dnv)
+ if (cio_update_schib(sch))
return;
/*
* The pim, pam, pom values may not be accurate, but they are the best