aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_fsm.c
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2006-07-12 10:40:19 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-07-12 10:40:19 -0400
commit7e560814de1972e1bfc780616841d7a0032ca467 (patch)
treef8d544454b54a0167f757cc945a3e29165f211f8 /drivers/s390/cio/device_fsm.c
parent5c898ba9d4b6c14fdd367b96e3641c2508b4a4a9 (diff)
[S390] path grouping and path verifications fixes.
1. Multipath devices for which SetPGID is not supported are not handled well. Use NOP ccws for path verification (sans path grouping) when SetPGID is not supported. 2. Check for PGIDs already set with SensePGID on _all_ paths (not just the first one) and try to find a common one. Moan if no common PGID can be found (and use NOP verification). If no PGIDs have been set, use the css global PGID (as before). (Rationale: SetPGID will get a command reject if the PGID it tries to set does not match the already set PGID.) 3. Immediately before reboot, issue RESET CHANNEL PATH (rcp) on all chpids. This will remove the old PGIDs. rcp will generate solicited CRWs which can be savely ignored by the machine check handler (all other actions create unsolicited CRWs). Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
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