aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_fsm.c
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2010-10-25 10:10:34 -0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-10-25 10:10:19 -0400
commit585b954e1f2fa325d425b0786e4525ac7c9ae575 (patch)
treee79174793782e81820c7f6896284f7e341bf9e9d /drivers/s390/cio/device_fsm.c
parenteb4f5d93d70458ea644e0f46737f0bcf87280e83 (diff)
[S390] cio: notify drivers of channel path events
This patch adds a notification mechanism to inform ccw drivers about changes to channel paths, which occured while the device is online. Signed-off-by: Sebastian Ott <sebott@linux.vnet.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.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index c9b852647f01..4395c01a9dac 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -349,9 +349,13 @@ out:
349 349
350static void ccw_device_oper_notify(struct ccw_device *cdev) 350static void ccw_device_oper_notify(struct ccw_device *cdev)
351{ 351{
352 struct subchannel *sch = to_subchannel(cdev->dev.parent);
353
352 if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_OK) { 354 if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_OK) {
353 /* Reenable channel measurements, if needed. */ 355 /* Reenable channel measurements, if needed. */
354 ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF); 356 ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF);
357 /* Save indication for new paths. */
358 cdev->private->path_new_mask = sch->vpm;
355 return; 359 return;
356 } 360 }
357 /* Driver doesn't want device back. */ 361 /* Driver doesn't want device back. */
@@ -462,6 +466,32 @@ static void ccw_device_request_event(struct ccw_device *cdev, enum dev_event e)
462 } 466 }
463} 467}
464 468
469static void ccw_device_report_path_events(struct ccw_device *cdev)
470{
471 struct subchannel *sch = to_subchannel(cdev->dev.parent);
472 int path_event[8];
473 int chp, mask;
474
475 for (chp = 0, mask = 0x80; chp < 8; chp++, mask >>= 1) {
476 path_event[chp] = PE_NONE;
477 if (mask & cdev->private->path_gone_mask & ~(sch->vpm))
478 path_event[chp] |= PE_PATH_GONE;
479 if (mask & cdev->private->path_new_mask & sch->vpm)
480 path_event[chp] |= PE_PATH_AVAILABLE;
481 if (mask & cdev->private->pgid_reset_mask & sch->vpm)
482 path_event[chp] |= PE_PATHGROUP_ESTABLISHED;
483 }
484 if (cdev->online && cdev->drv->path_event)
485 cdev->drv->path_event(cdev, path_event);
486}
487
488static void ccw_device_reset_path_events(struct ccw_device *cdev)
489{
490 cdev->private->path_gone_mask = 0;
491 cdev->private->path_new_mask = 0;
492 cdev->private->pgid_reset_mask = 0;
493}
494
465void 495void
466ccw_device_verify_done(struct ccw_device *cdev, int err) 496ccw_device_verify_done(struct ccw_device *cdev, int err)
467{ 497{
@@ -498,6 +528,7 @@ callback:
498 &cdev->private->irb); 528 &cdev->private->irb);
499 memset(&cdev->private->irb, 0, sizeof(struct irb)); 529 memset(&cdev->private->irb, 0, sizeof(struct irb));
500 } 530 }
531 ccw_device_report_path_events(cdev);
501 break; 532 break;
502 case -ETIME: 533 case -ETIME:
503 case -EUSERS: 534 case -EUSERS:
@@ -516,6 +547,7 @@ callback:
516 ccw_device_done(cdev, DEV_STATE_NOT_OPER); 547 ccw_device_done(cdev, DEV_STATE_NOT_OPER);
517 break; 548 break;
518 } 549 }
550 ccw_device_reset_path_events(cdev);
519} 551}
520 552
521/* 553/*