aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_fsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r--drivers/s390/cio/device_fsm.c88
1 files changed, 70 insertions, 18 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index cb1af0b6f033..7a39e0b0386c 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -152,7 +152,8 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
152 if (cdev->private->iretry) { 152 if (cdev->private->iretry) {
153 cdev->private->iretry--; 153 cdev->private->iretry--;
154 ret = cio_halt(sch); 154 ret = cio_halt(sch);
155 return (ret == 0) ? -EBUSY : ret; 155 if (ret != -EBUSY)
156 return (ret == 0) ? -EBUSY : ret;
156 } 157 }
157 /* halt io unsuccessful. */ 158 /* halt io unsuccessful. */
158 cdev->private->iretry = 255; /* 255 clear retries. */ 159 cdev->private->iretry = 255; /* 255 clear retries. */
@@ -378,6 +379,56 @@ ccw_device_done(struct ccw_device *cdev, int state)
378 put_device (&cdev->dev); 379 put_device (&cdev->dev);
379} 380}
380 381
382static inline int cmp_pgid(struct pgid *p1, struct pgid *p2)
383{
384 char *c1;
385 char *c2;
386
387 c1 = (char *)p1;
388 c2 = (char *)p2;
389
390 return memcmp(c1 + 1, c2 + 1, sizeof(struct pgid) - 1);
391}
392
393static void __ccw_device_get_common_pgid(struct ccw_device *cdev)
394{
395 int i;
396 int last;
397
398 last = 0;
399 for (i = 0; i < 8; i++) {
400 if (cdev->private->pgid[i].inf.ps.state1 == SNID_STATE1_RESET)
401 /* No PGID yet */
402 continue;
403 if (cdev->private->pgid[last].inf.ps.state1 ==
404 SNID_STATE1_RESET) {
405 /* First non-zero PGID */
406 last = i;
407 continue;
408 }
409 if (cmp_pgid(&cdev->private->pgid[i],
410 &cdev->private->pgid[last]) == 0)
411 /* Non-conflicting PGIDs */
412 continue;
413
414 /* PGID mismatch, can't pathgroup. */
415 CIO_MSG_EVENT(0, "SNID - pgid mismatch for device "
416 "0.%x.%04x, can't pathgroup\n",
417 cdev->private->ssid, cdev->private->devno);
418 cdev->private->options.pgroup = 0;
419 return;
420 }
421 if (cdev->private->pgid[last].inf.ps.state1 ==
422 SNID_STATE1_RESET)
423 /* No previous pgid found */
424 memcpy(&cdev->private->pgid[0], &css[0]->global_pgid,
425 sizeof(struct pgid));
426 else
427 /* Use existing pgid */
428 memcpy(&cdev->private->pgid[0], &cdev->private->pgid[last],
429 sizeof(struct pgid));
430}
431
381/* 432/*
382 * Function called from device_pgid.c after sense path ground has completed. 433 * Function called from device_pgid.c after sense path ground has completed.
383 */ 434 */
@@ -388,24 +439,26 @@ ccw_device_sense_pgid_done(struct ccw_device *cdev, int err)
388 439
389 sch = to_subchannel(cdev->dev.parent); 440 sch = to_subchannel(cdev->dev.parent);
390 switch (err) { 441 switch (err) {
391 case 0: 442 case -EOPNOTSUPP: /* path grouping not supported, use nop instead. */
392 /* Start Path Group verification. */ 443 cdev->private->options.pgroup = 0;
393 sch->vpm = 0; /* Start with no path groups set. */ 444 break;
394 cdev->private->state = DEV_STATE_VERIFY; 445 case 0: /* success */
395 ccw_device_verify_start(cdev); 446 case -EACCES: /* partial success, some paths not operational */
447 /* Check if all pgids are equal or 0. */
448 __ccw_device_get_common_pgid(cdev);
396 break; 449 break;
397 case -ETIME: /* Sense path group id stopped by timeout. */ 450 case -ETIME: /* Sense path group id stopped by timeout. */
398 case -EUSERS: /* device is reserved for someone else. */ 451 case -EUSERS: /* device is reserved for someone else. */
399 ccw_device_done(cdev, DEV_STATE_BOXED); 452 ccw_device_done(cdev, DEV_STATE_BOXED);
400 break; 453 return;
401 case -EOPNOTSUPP: /* path grouping not supported, just set online. */
402 cdev->private->options.pgroup = 0;
403 ccw_device_done(cdev, DEV_STATE_ONLINE);
404 break;
405 default: 454 default:
406 ccw_device_done(cdev, DEV_STATE_NOT_OPER); 455 ccw_device_done(cdev, DEV_STATE_NOT_OPER);
407 break; 456 return;
408 } 457 }
458 /* Start Path Group verification. */
459 sch->vpm = 0; /* Start with no path groups set. */
460 cdev->private->state = DEV_STATE_VERIFY;
461 ccw_device_verify_start(cdev);
409} 462}
410 463
411/* 464/*
@@ -562,8 +615,9 @@ ccw_device_online(struct ccw_device *cdev)
562 } 615 }
563 /* Do we want to do path grouping? */ 616 /* Do we want to do path grouping? */
564 if (!cdev->private->options.pgroup) { 617 if (!cdev->private->options.pgroup) {
565 /* No, set state online immediately. */ 618 /* Start initial path verification. */
566 ccw_device_done(cdev, DEV_STATE_ONLINE); 619 cdev->private->state = DEV_STATE_VERIFY;
620 ccw_device_verify_start(cdev);
567 return 0; 621 return 0;
568 } 622 }
569 /* Do a SensePGID first. */ 623 /* Do a SensePGID first. */
@@ -609,6 +663,7 @@ ccw_device_offline(struct ccw_device *cdev)
609 /* Are we doing path grouping? */ 663 /* Are we doing path grouping? */
610 if (!cdev->private->options.pgroup) { 664 if (!cdev->private->options.pgroup) {
611 /* No, set state offline immediately. */ 665 /* No, set state offline immediately. */
666 sch->vpm = 0;
612 ccw_device_done(cdev, DEV_STATE_OFFLINE); 667 ccw_device_done(cdev, DEV_STATE_OFFLINE);
613 return 0; 668 return 0;
614 } 669 }
@@ -705,8 +760,6 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
705{ 760{
706 struct subchannel *sch; 761 struct subchannel *sch;
707 762
708 if (!cdev->private->options.pgroup)
709 return;
710 if (cdev->private->state == DEV_STATE_W4SENSE) { 763 if (cdev->private->state == DEV_STATE_W4SENSE) {
711 cdev->private->flags.doverify = 1; 764 cdev->private->flags.doverify = 1;
712 return; 765 return;
@@ -995,8 +1048,7 @@ static void
995ccw_device_wait4io_verify(struct ccw_device *cdev, enum dev_event dev_event) 1048ccw_device_wait4io_verify(struct ccw_device *cdev, enum dev_event dev_event)
996{ 1049{
997 /* When the I/O has terminated, we have to start verification. */ 1050 /* When the I/O has terminated, we have to start verification. */
998 if (cdev->private->options.pgroup) 1051 cdev->private->flags.doverify = 1;
999 cdev->private->flags.doverify = 1;
1000} 1052}
1001 1053
1002static void 1054static void