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.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 8047800e9a0c..9bdb463765c7 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -114,11 +114,13 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
114 else 114 else
115 sch->lpm = 0; 115 sch->lpm = 0;
116 116
117 stsch (sch->schid, &sch->schib);
118
119 CIO_MSG_EVENT(2, "cio_start: 'not oper' status for " 117 CIO_MSG_EVENT(2, "cio_start: 'not oper' status for "
120 "subchannel 0.%x.%04x!\n", sch->schid.ssid, 118 "subchannel 0.%x.%04x!\n", sch->schid.ssid,
121 sch->schid.sch_no); 119 sch->schid.sch_no);
120
121 if (cio_update_schib(sch))
122 return -ENODEV;
123
122 sprintf(dbf_text, "no%s", dev_name(&sch->dev)); 124 sprintf(dbf_text, "no%s", dev_name(&sch->dev));
123 CIO_TRACE_EVENT(0, dbf_text); 125 CIO_TRACE_EVENT(0, dbf_text);
124 CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); 126 CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
@@ -316,7 +318,8 @@ cio_cancel (struct subchannel *sch)
316 switch (ccode) { 318 switch (ccode) {
317 case 0: /* success */ 319 case 0: /* success */
318 /* Update information in scsw. */ 320 /* Update information in scsw. */
319 stsch (sch->schid, &sch->schib); 321 if (cio_update_schib(sch))
322 return -ENODEV;
320 return 0; 323 return 0;
321 case 1: /* status pending */ 324 case 1: /* status pending */
322 return -EBUSY; 325 return -EBUSY;
@@ -358,6 +361,23 @@ cio_modify (struct subchannel *sch)
358} 361}
359 362
360/** 363/**
364 * cio_update_schib - Perform stsch and update schib if subchannel is valid.
365 * @sch: subchannel on which to perform stsch
366 * Return zero on success, -ENODEV otherwise.
367 */
368int cio_update_schib(struct subchannel *sch)
369{
370 struct schib schib;
371
372 if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib))
373 return -ENODEV;
374
375 memcpy(&sch->schib, &schib, sizeof(schib));
376 return 0;
377}
378EXPORT_SYMBOL_GPL(cio_update_schib);
379
380/**
361 * cio_enable_subchannel - enable a subchannel. 381 * cio_enable_subchannel - enable a subchannel.
362 * @sch: subchannel to be enabled 382 * @sch: subchannel to be enabled
363 * @intparm: interruption parameter to set 383 * @intparm: interruption parameter to set
@@ -365,7 +385,6 @@ cio_modify (struct subchannel *sch)
365int cio_enable_subchannel(struct subchannel *sch, u32 intparm) 385int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
366{ 386{
367 char dbf_txt[15]; 387 char dbf_txt[15];
368 int ccode;
369 int retry; 388 int retry;
370 int ret; 389 int ret;
371 390
@@ -374,8 +393,7 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
374 393
375 if (sch_is_pseudo_sch(sch)) 394 if (sch_is_pseudo_sch(sch))
376 return -EINVAL; 395 return -EINVAL;
377 ccode = stsch (sch->schid, &sch->schib); 396 if (cio_update_schib(sch))
378 if (ccode)
379 return -ENODEV; 397 return -ENODEV;
380 398
381 for (retry = 5, ret = 0; retry > 0; retry--) { 399 for (retry = 5, ret = 0; retry > 0; retry--) {
@@ -392,7 +410,10 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
392 */ 410 */
393 sch->schib.pmcw.csense = 0; 411 sch->schib.pmcw.csense = 0;
394 if (ret == 0) { 412 if (ret == 0) {
395 stsch (sch->schid, &sch->schib); 413 if (cio_update_schib(sch)) {
414 ret = -ENODEV;
415 break;
416 }
396 if (sch->schib.pmcw.ena) 417 if (sch->schib.pmcw.ena)
397 break; 418 break;
398 } 419 }
@@ -415,7 +436,6 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
415int cio_disable_subchannel(struct subchannel *sch) 436int cio_disable_subchannel(struct subchannel *sch)
416{ 437{
417 char dbf_txt[15]; 438 char dbf_txt[15];
418 int ccode;
419 int retry; 439 int retry;
420 int ret; 440 int ret;
421 441
@@ -424,8 +444,7 @@ int cio_disable_subchannel(struct subchannel *sch)
424 444
425 if (sch_is_pseudo_sch(sch)) 445 if (sch_is_pseudo_sch(sch))
426 return 0; 446 return 0;
427 ccode = stsch (sch->schid, &sch->schib); 447 if (cio_update_schib(sch))
428 if (ccode == 3) /* Not operational. */
429 return -ENODEV; 448 return -ENODEV;
430 449
431 if (scsw_actl(&sch->schib.scsw) != 0) 450 if (scsw_actl(&sch->schib.scsw) != 0)
@@ -448,7 +467,10 @@ int cio_disable_subchannel(struct subchannel *sch)
448 */ 467 */
449 break; 468 break;
450 if (ret == 0) { 469 if (ret == 0) {
451 stsch (sch->schid, &sch->schib); 470 if (cio_update_schib(sch)) {
471 ret = -ENODEV;
472 break;
473 }
452 if (!sch->schib.pmcw.ena) 474 if (!sch->schib.pmcw.ena)
453 break; 475 break;
454 } 476 }
@@ -851,7 +873,8 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
851 cc = msch(schid, schib); 873 cc = msch(schid, schib);
852 if (cc) 874 if (cc)
853 return (cc==3?-ENODEV:-EBUSY); 875 return (cc==3?-ENODEV:-EBUSY);
854 stsch(schid, schib); 876 if (stsch(schid, schib) || !css_sch_is_valid(schib))
877 return -ENODEV;
855 if (!schib->pmcw.ena) 878 if (!schib->pmcw.ena)
856 return 0; 879 return 0;
857 } 880 }