aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/cio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r--drivers/s390/cio/cio.c40
1 files changed, 14 insertions, 26 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 88e35d85d205..8ee88c4ebd83 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -342,8 +342,9 @@ static int cio_check_config(struct subchannel *sch, struct schib *schib)
342 */ 342 */
343int cio_commit_config(struct subchannel *sch) 343int cio_commit_config(struct subchannel *sch)
344{ 344{
345 struct schib schib;
346 int ccode, retry, ret = 0; 345 int ccode, retry, ret = 0;
346 struct schib schib;
347 struct irb irb;
347 348
348 if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib)) 349 if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib))
349 return -ENODEV; 350 return -ENODEV;
@@ -367,7 +368,10 @@ int cio_commit_config(struct subchannel *sch)
367 ret = -EAGAIN; 368 ret = -EAGAIN;
368 break; 369 break;
369 case 1: /* status pending */ 370 case 1: /* status pending */
370 return -EBUSY; 371 ret = -EBUSY;
372 if (tsch(sch->schid, &irb))
373 return ret;
374 break;
371 case 2: /* busy */ 375 case 2: /* busy */
372 udelay(100); /* allow for recovery */ 376 udelay(100); /* allow for recovery */
373 ret = -EBUSY; 377 ret = -EBUSY;
@@ -403,7 +407,6 @@ EXPORT_SYMBOL_GPL(cio_update_schib);
403 */ 407 */
404int cio_enable_subchannel(struct subchannel *sch, u32 intparm) 408int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
405{ 409{
406 int retry;
407 int ret; 410 int ret;
408 411
409 CIO_TRACE_EVENT(2, "ensch"); 412 CIO_TRACE_EVENT(2, "ensch");
@@ -418,20 +421,14 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
418 sch->config.isc = sch->isc; 421 sch->config.isc = sch->isc;
419 sch->config.intparm = intparm; 422 sch->config.intparm = intparm;
420 423
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;
422 ret = cio_commit_config(sch); 431 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;
435 } 432 }
436 CIO_HEX_EVENT(2, &ret, sizeof(ret)); 433 CIO_HEX_EVENT(2, &ret, sizeof(ret));
437 return ret; 434 return ret;
@@ -444,7 +441,6 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
444 */ 441 */
445int cio_disable_subchannel(struct subchannel *sch) 442int cio_disable_subchannel(struct subchannel *sch)
446{ 443{
447 int retry;
448 int ret; 444 int ret;
449 445
450 CIO_TRACE_EVENT(2, "dissch"); 446 CIO_TRACE_EVENT(2, "dissch");
@@ -456,16 +452,8 @@ int cio_disable_subchannel(struct subchannel *sch)
456 return -ENODEV; 452 return -ENODEV;
457 453
458 sch->config.ena = 0; 454 sch->config.ena = 0;
455 ret = cio_commit_config(sch);
459 456
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 }
469 CIO_HEX_EVENT(2, &ret, sizeof(ret)); 457 CIO_HEX_EVENT(2, &ret, sizeof(ret));
470 return ret; 458 return ret;
471} 459}