diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2010-02-26 22:37:28 +0100 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-02-26 22:37:29 +0100 |
commit | 76e6fb4b86446e4605379b99ad3dd3f96bb1696f (patch) | |
tree | 0d123c6e1091d28ec87d98e76e037cfe8919942f | |
parent | b4c707214c987da021d4d5c4ed54612cf73d80d6 (diff) | |
download | lwn-76e6fb4b86446e4605379b99ad3dd3f96bb1696f.tar.gz lwn-76e6fb4b86446e4605379b99ad3dd3f96bb1696f.zip |
[S390] ccw_device_notify: improve return codes
Callers of ccw_device_notify could not distinguish between a driver
who has no notifier registered and a driver who doesn't want to keep
a device after a certain event. Change this by adding proper return
codes.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | drivers/s390/cio/device.c | 10 | ||||
-rw-r--r-- | drivers/s390/cio/device.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 39 |
3 files changed, 37 insertions, 14 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 6aa2f069c6be..c7b2b7b26b8b 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1338,7 +1338,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) /* Not operational. */ if (!cdev) return IO_SCH_UNREG; - if (!ccw_device_notify(cdev, CIO_GONE)) + if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) return IO_SCH_UNREG; return IO_SCH_ORPH_UNREG; } @@ -1346,12 +1346,12 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) if (!cdev) return IO_SCH_ATTACH; if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { - if (!ccw_device_notify(cdev, CIO_GONE)) + if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) return IO_SCH_UNREG_ATTACH; return IO_SCH_ORPH_ATTACH; } if ((sch->schib.pmcw.pam & sch->opm) == 0) { - if (!ccw_device_notify(cdev, CIO_NO_PATH)) + if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) return IO_SCH_UNREG; return IO_SCH_DISC; } @@ -1788,7 +1788,7 @@ out: static int resume_handle_boxed(struct ccw_device *cdev) { cdev->private->state = DEV_STATE_BOXED; - if (ccw_device_notify(cdev, CIO_BOXED)) + if (ccw_device_notify(cdev, CIO_BOXED) == NOTIFY_OK) return 0; ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); return -ENODEV; @@ -1797,7 +1797,7 @@ static int resume_handle_boxed(struct ccw_device *cdev) static int resume_handle_disc(struct ccw_device *cdev) { cdev->private->state = DEV_STATE_DISCONNECTED; - if (ccw_device_notify(cdev, CIO_GONE)) + if (ccw_device_notify(cdev, CIO_GONE) == NOTIFY_OK) return 0; ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); return -ENODEV; diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index ef60c8f5cd14..379de2d1ec49 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -4,7 +4,7 @@ #include <asm/ccwdev.h> #include <asm/atomic.h> #include <linux/wait.h> - +#include <linux/notifier.h> #include "io_sch.h" /* diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index ae760658a131..2cb01861ce34 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -313,21 +313,43 @@ ccw_device_sense_id_done(struct ccw_device *cdev, int err) } } +/** + * ccw_device_notify() - inform the device's driver about an event + * @cdev: device for which an event occured + * @event: event that occurred + * + * Returns: + * -%EINVAL if the device is offline or has no driver. + * -%EOPNOTSUPP if the device's driver has no notifier registered. + * %NOTIFY_OK if the driver wants to keep the device. + * %NOTIFY_BAD if the driver doesn't want to keep the device. + */ int ccw_device_notify(struct ccw_device *cdev, int event) { + int ret = -EINVAL; + if (!cdev->drv) - return 0; + goto out; if (!cdev->online) - return 0; + goto out; CIO_MSG_EVENT(2, "notify called for 0.%x.%04x, event=%d\n", cdev->private->dev_id.ssid, cdev->private->dev_id.devno, event); - return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0; + if (!cdev->drv->notify) { + ret = -EOPNOTSUPP; + goto out; + } + if (cdev->drv->notify(cdev, event)) + ret = NOTIFY_OK; + else + ret = NOTIFY_BAD; +out: + return ret; } static void ccw_device_oper_notify(struct ccw_device *cdev) { - if (ccw_device_notify(cdev, CIO_OPER)) { + if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_OK) { /* Reenable channel measurements, if needed. */ ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF); return; @@ -361,14 +383,15 @@ ccw_device_done(struct ccw_device *cdev, int state) case DEV_STATE_BOXED: CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n", cdev->private->dev_id.devno, sch->schid.sch_no); - if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED)) + if (cdev->online && + ccw_device_notify(cdev, CIO_BOXED) != NOTIFY_OK) ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); cdev->private->flags.donotify = 0; break; case DEV_STATE_NOT_OPER: CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n", cdev->private->dev_id.devno, sch->schid.sch_no); - if (!ccw_device_notify(cdev, CIO_GONE)) + if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); else ccw_device_set_disconnected(cdev); @@ -378,7 +401,7 @@ ccw_device_done(struct ccw_device *cdev, int state) CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel " "%04x\n", cdev->private->dev_id.devno, sch->schid.sch_no); - if (!ccw_device_notify(cdev, CIO_NO_PATH)) + if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); else ccw_device_set_disconnected(cdev); @@ -586,7 +609,7 @@ ccw_device_offline(struct ccw_device *cdev) static void ccw_device_generic_notoper(struct ccw_device *cdev, enum dev_event dev_event) { - if (!ccw_device_notify(cdev, CIO_GONE)) + if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); else ccw_device_set_disconnected(cdev); |