diff options
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 83da53c8e..92e03b42e 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -731,6 +731,44 @@ static void ccw_device_boxed_verify(struct ccw_device *cdev, } /* + * Pass interrupt to device driver. + */ +static int ccw_device_call_handler(struct ccw_device *cdev) +{ + unsigned int stctl; + int ending_status; + + /* + * we allow for the device action handler if . + * - we received ending status + * - the action handler requested to see all interrupts + * - we received an intermediate status + * - fast notification was requested (primary status) + * - unsolicited interrupts + */ + stctl = scsw_stctl(&cdev->private->irb.scsw); + ending_status = (stctl & SCSW_STCTL_SEC_STATUS) || + (stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) || + (stctl == SCSW_STCTL_STATUS_PEND); + if (!ending_status && + !cdev->private->options.repall && + !(stctl & SCSW_STCTL_INTER_STATUS) && + !(cdev->private->options.fast && + (stctl & SCSW_STCTL_PRIM_STATUS))) + return 0; + + if (ending_status) + ccw_device_set_timeout(cdev, 0); + + if (cdev->handler) + cdev->handler(cdev, cdev->private->intparm, + &cdev->private->irb); + + memset(&cdev->private->irb, 0, sizeof(struct irb)); + return 1; +} + +/* * Got an interrupt for a normal io (state online). */ static void |