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