Commit ed04b892 authored by Cornelia Huck's avatar Cornelia Huck Committed by Martin Schwidefsky

[S390] cio: Try harder to disable subchannel.

Acting upon the assumption that cio_disable_subchannel()
is only called when we really want to disable the subchannel
(a) remove the check for activity (it is already done in
    ccw_device_offline(), which is the place where it matters)
(b) collect pending status via tsch() and ignore it (it
    can't matter anymore since the subchannel will be disabled).
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent eb32ae8d
...@@ -472,6 +472,7 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel); ...@@ -472,6 +472,7 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
int cio_disable_subchannel(struct subchannel *sch) int cio_disable_subchannel(struct subchannel *sch)
{ {
char dbf_txt[15]; char dbf_txt[15];
int retry;
int ret; int ret;
CIO_TRACE_EVENT (2, "dissch"); CIO_TRACE_EVENT (2, "dissch");
...@@ -482,16 +483,17 @@ int cio_disable_subchannel(struct subchannel *sch) ...@@ -482,16 +483,17 @@ int cio_disable_subchannel(struct subchannel *sch)
if (cio_update_schib(sch)) if (cio_update_schib(sch))
return -ENODEV; return -ENODEV;
if (scsw_actl(&sch->schib.scsw) != 0)
/*
* the disable function must not be called while there are
* requests pending for completion !
*/
return -EBUSY;
sch->config.ena = 0; sch->config.ena = 0;
ret = cio_commit_config(sch);
for (retry = 0; retry < 3; retry++) {
ret = cio_commit_config(sch);
if (ret == -EBUSY) {
struct irb irb;
if (tsch(sch->schid, &irb) != 0)
break;
} else
break;
}
sprintf (dbf_txt, "ret:%d", ret); sprintf (dbf_txt, "ret:%d", ret);
CIO_TRACE_EVENT (2, dbf_txt); CIO_TRACE_EVENT (2, dbf_txt);
return ret; return ret;
......
...@@ -1052,7 +1052,7 @@ ccw_device_offline_irq(struct ccw_device *cdev, enum dev_event dev_event) ...@@ -1052,7 +1052,7 @@ ccw_device_offline_irq(struct ccw_device *cdev, enum dev_event dev_event)
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
/* /*
* An interrupt in state offline means a previous disable was not * An interrupt in state offline means a previous disable was not
* successful. Try again. * successful - should not happen, but we try to disable again.
*/ */
cio_disable_subchannel(sch); cio_disable_subchannel(sch);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment