diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2010-10-25 10:10:34 -0400 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-10-25 10:10:19 -0400 |
commit | 585b954e1f2fa325d425b0786e4525ac7c9ae575 (patch) | |
tree | e79174793782e81820c7f6896284f7e341bf9e9d /drivers/s390/cio/device_fsm.c | |
parent | eb4f5d93d70458ea644e0f46737f0bcf87280e83 (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.c | 32 |
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 | ||
350 | static void ccw_device_oper_notify(struct ccw_device *cdev) | 350 | static 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 | ||
469 | static 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 | |||
488 | static 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 | |||
465 | void | 495 | void |
466 | ccw_device_verify_done(struct ccw_device *cdev, int err) | 496 | ccw_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 | /* |