Skip to content

Commit 1bc8927

Browse files
Sebastian OttMartin Schwidefsky
authored andcommitted
s390/cio: improve cio_commit_config
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 <[email protected]> Signed-off-by: Sebastian Ott <[email protected]> Signed-off-by: Martin Schwidefsky <[email protected]>
1 parent 8d7f669 commit 1bc8927

File tree

1 file changed

+14
-26
lines changed

1 file changed

+14
-26
lines changed

drivers/s390/cio/cio.c

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,9 @@ static int cio_check_config(struct subchannel *sch, struct schib *schib)
342342
*/
343343
int cio_commit_config(struct subchannel *sch)
344344
{
345-
struct schib schib;
346345
int ccode, retry, ret = 0;
346+
struct schib schib;
347+
struct irb irb;
347348

348349
if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib))
349350
return -ENODEV;
@@ -367,7 +368,10 @@ int cio_commit_config(struct subchannel *sch)
367368
ret = -EAGAIN;
368369
break;
369370
case 1: /* status pending */
370-
return -EBUSY;
371+
ret = -EBUSY;
372+
if (tsch(sch->schid, &irb))
373+
return ret;
374+
break;
371375
case 2: /* busy */
372376
udelay(100); /* allow for recovery */
373377
ret = -EBUSY;
@@ -403,7 +407,6 @@ EXPORT_SYMBOL_GPL(cio_update_schib);
403407
*/
404408
int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
405409
{
406-
int retry;
407410
int ret;
408411

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

421-
for (retry = 0; retry < 3; retry++) {
424+
ret = cio_commit_config(sch);
425+
if (ret == -EIO) {
426+
/*
427+
* Got a program check in msch. Try without
428+
* the concurrent sense bit the next time.
429+
*/
430+
sch->config.csense = 0;
422431
ret = cio_commit_config(sch);
423-
if (ret == -EIO) {
424-
/*
425-
* Got a program check in msch. Try without
426-
* the concurrent sense bit the next time.
427-
*/
428-
sch->config.csense = 0;
429-
} else if (ret == -EBUSY) {
430-
struct irb irb;
431-
if (tsch(sch->schid, &irb) != 0)
432-
break;
433-
} else
434-
break;
435432
}
436433
CIO_HEX_EVENT(2, &ret, sizeof(ret));
437434
return ret;
@@ -444,7 +441,6 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
444441
*/
445442
int cio_disable_subchannel(struct subchannel *sch)
446443
{
447-
int retry;
448444
int ret;
449445

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

458454
sch->config.ena = 0;
455+
ret = cio_commit_config(sch);
459456

460-
for (retry = 0; retry < 3; retry++) {
461-
ret = cio_commit_config(sch);
462-
if (ret == -EBUSY) {
463-
struct irb irb;
464-
if (tsch(sch->schid, &irb) != 0)
465-
break;
466-
} else
467-
break;
468-
}
469457
CIO_HEX_EVENT(2, &ret, sizeof(ret));
470458
return ret;
471459
}

0 commit comments

Comments
 (0)