aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/cmf.c
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2008-12-25 07:39:12 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-12-25 07:39:10 -0500
commitcdb912a40df8b8507ab60b3d52f9980c0ba1f44d (patch)
tree52d693b3515b71b4f84b539d41571facb75498db /drivers/s390/cio/cmf.c
parentd6a30761d8116b8de8a5b5e79e68cce81d36414b (diff)
[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/cmf.c')
-rw-r--r--drivers/s390/cio/cmf.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index a90b28c0be57..288482b21048 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -195,7 +195,8 @@ static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc,
195 /* msch can silently fail, so do it again if necessary */ 195 /* msch can silently fail, so do it again if necessary */
196 for (retry = 0; retry < 3; retry++) { 196 for (retry = 0; retry < 3; retry++) {
197 /* prepare schib */ 197 /* prepare schib */
198 stsch(sch->schid, schib); 198 if (cio_update_schib(sch))
199 return -ENODEV;
199 schib->pmcw.mme = mme; 200 schib->pmcw.mme = mme;
200 schib->pmcw.mbfc = mbfc; 201 schib->pmcw.mbfc = mbfc;
201 /* address can be either a block address or a block index */ 202 /* address can be either a block address or a block index */
@@ -219,7 +220,8 @@ static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc,
219 ret = -EINVAL; 220 ret = -EINVAL;
220 break; 221 break;
221 } 222 }
222 stsch(sch->schid, schib); /* restore the schib */ 223 if (cio_update_schib(sch))
224 return -ENODEV;
223 225
224 if (ret) 226 if (ret)
225 break; 227 break;
@@ -338,7 +340,7 @@ static int cmf_copy_block(struct ccw_device *cdev)
338 340
339 sch = to_subchannel(cdev->dev.parent); 341 sch = to_subchannel(cdev->dev.parent);
340 342
341 if (stsch(sch->schid, &sch->schib)) 343 if (cio_update_schib(sch))
342 return -ENODEV; 344 return -ENODEV;
343 345
344 if (scsw_fctl(&sch->schib.scsw) & SCSW_FCTL_START_FUNC) { 346 if (scsw_fctl(&sch->schib.scsw) & SCSW_FCTL_START_FUNC) {