Skip to content

Commit

Permalink
s390/cio: improve cio_commit_config
Browse files Browse the repository at this point in the history
The modify subchannel wrapper cio_commit_config can fail when
(unexpected) status is pending on the subchannel.

Callers of cio_commit_config (that operated on enabled subchannels)
needed to do error handling for that case (clear the unexpected
status with test subchannel and retry). This error handling is
missing in some code paths and caused online setting of devices to
fail.

Fix this for all callers by moving the error handling inside
cio_commit_config.

Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Sebastian Ott authored and Martin Schwidefsky committed Feb 6, 2014
1 parent 8d7f669 commit 1bc8927
Showing 1 changed file with 14 additions and 26 deletions.
40 changes: 14 additions & 26 deletions drivers/s390/cio/cio.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,9 @@ static int cio_check_config(struct subchannel *sch, struct schib *schib)
*/
int cio_commit_config(struct subchannel *sch)
{
struct schib schib;
int ccode, retry, ret = 0;
struct schib schib;
struct irb irb;

if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib))
return -ENODEV;
Expand All @@ -367,7 +368,10 @@ int cio_commit_config(struct subchannel *sch)
ret = -EAGAIN;
break;
case 1: /* status pending */
return -EBUSY;
ret = -EBUSY;
if (tsch(sch->schid, &irb))
return ret;
break;
case 2: /* busy */
udelay(100); /* allow for recovery */
ret = -EBUSY;
Expand Down Expand Up @@ -403,7 +407,6 @@ EXPORT_SYMBOL_GPL(cio_update_schib);
*/
int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
{
int retry;
int ret;

CIO_TRACE_EVENT(2, "ensch");
Expand All @@ -418,20 +421,14 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
sch->config.isc = sch->isc;
sch->config.intparm = intparm;

for (retry = 0; retry < 3; retry++) {
ret = cio_commit_config(sch);
if (ret == -EIO) {
/*
* Got a program check in msch. Try without
* the concurrent sense bit the next time.
*/
sch->config.csense = 0;
ret = cio_commit_config(sch);
if (ret == -EIO) {
/*
* Got a program check in msch. Try without
* the concurrent sense bit the next time.
*/
sch->config.csense = 0;
} else if (ret == -EBUSY) {
struct irb irb;
if (tsch(sch->schid, &irb) != 0)
break;
} else
break;
}
CIO_HEX_EVENT(2, &ret, sizeof(ret));
return ret;
Expand All @@ -444,7 +441,6 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
*/
int cio_disable_subchannel(struct subchannel *sch)
{
int retry;
int ret;

CIO_TRACE_EVENT(2, "dissch");
Expand All @@ -456,16 +452,8 @@ int cio_disable_subchannel(struct subchannel *sch)
return -ENODEV;

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;
}
CIO_HEX_EVENT(2, &ret, sizeof(ret));
return ret;
}
Expand Down

0 comments on commit 1bc8927

Please sign in to comment.