diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2008-12-25 07:39:12 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-12-25 07:39:10 -0500 |
commit | cdb912a40df8b8507ab60b3d52f9980c0ba1f44d (patch) | |
tree | 52d693b3515b71b4f84b539d41571facb75498db /drivers/s390/cio/cmf.c | |
parent | d6a30761d8116b8de8a5b5e79e68cce81d36414b (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.c | 8 |
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) { |