diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2010-02-26 16:37:28 -0500 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-02-26 16:37:29 -0500 |
commit | 76e6fb4b86446e4605379b99ad3dd3f96bb1696f (patch) | |
tree | 0d123c6e1091d28ec87d98e76e037cfe8919942f /drivers/s390/cio | |
parent | b4c707214c987da021d4d5c4ed54612cf73d80d6 (diff) |
[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>
Diffstat (limited to 'drivers/s390/cio')
-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) | |||
1338 | /* Not operational. */ | 1338 | /* Not operational. */ |
1339 | if (!cdev) | 1339 | if (!cdev) |
1340 | return IO_SCH_UNREG; | 1340 | return IO_SCH_UNREG; |
1341 | if (!ccw_device_notify(cdev, CIO_GONE)) | 1341 | if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) |
1342 | return IO_SCH_UNREG; | 1342 | return IO_SCH_UNREG; |
1343 | return IO_SCH_ORPH_UNREG; | 1343 | return IO_SCH_ORPH_UNREG; |
1344 | } | 1344 | } |
@@ -1346,12 +1346,12 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) | |||
1346 | if (!cdev) | 1346 | if (!cdev) |
1347 | return IO_SCH_ATTACH; | 1347 | return IO_SCH_ATTACH; |
1348 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { | 1348 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { |
1349 | if (!ccw_device_notify(cdev, CIO_GONE)) | 1349 | if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) |
1350 | return IO_SCH_UNREG_ATTACH; | 1350 | return IO_SCH_UNREG_ATTACH; |
1351 | return IO_SCH_ORPH_ATTACH; | 1351 | return IO_SCH_ORPH_ATTACH; |
1352 | } | 1352 | } |
1353 | if ((sch->schib.pmcw.pam & sch->opm) == 0) { | 1353 | if ((sch->schib.pmcw.pam & sch->opm) == 0) { |
1354 | if (!ccw_device_notify(cdev, CIO_NO_PATH)) | 1354 | if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) |
1355 | return IO_SCH_UNREG; | 1355 | return IO_SCH_UNREG; |
1356 | return IO_SCH_DISC; | 1356 | return IO_SCH_DISC; |
1357 | } | 1357 | } |
@@ -1788,7 +1788,7 @@ out: | |||
1788 | static int resume_handle_boxed(struct ccw_device *cdev) | 1788 | static int resume_handle_boxed(struct ccw_device *cdev) |
1789 | { | 1789 | { |
1790 | cdev->private->state = DEV_STATE_BOXED; | 1790 | cdev->private->state = DEV_STATE_BOXED; |
1791 | if (ccw_device_notify(cdev, CIO_BOXED)) | 1791 | if (ccw_device_notify(cdev, CIO_BOXED) == NOTIFY_OK) |
1792 | return 0; | 1792 | return 0; |
1793 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 1793 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
1794 | return -ENODEV; | 1794 | return -ENODEV; |
@@ -1797,7 +1797,7 @@ static int resume_handle_boxed(struct ccw_device *cdev) | |||
1797 | static int resume_handle_disc(struct ccw_device *cdev) | 1797 | static int resume_handle_disc(struct ccw_device *cdev) |
1798 | { | 1798 | { |
1799 | cdev->private->state = DEV_STATE_DISCONNECTED; | 1799 | cdev->private->state = DEV_STATE_DISCONNECTED; |
1800 | if (ccw_device_notify(cdev, CIO_GONE)) | 1800 | if (ccw_device_notify(cdev, CIO_GONE) == NOTIFY_OK) |
1801 | return 0; | 1801 | return 0; |
1802 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 1802 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
1803 | return -ENODEV; | 1803 | 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 @@ | |||
4 | #include <asm/ccwdev.h> | 4 | #include <asm/ccwdev.h> |
5 | #include <asm/atomic.h> | 5 | #include <asm/atomic.h> |
6 | #include <linux/wait.h> | 6 | #include <linux/wait.h> |
7 | 7 | #include <linux/notifier.h> | |
8 | #include "io_sch.h" | 8 | #include "io_sch.h" |
9 | 9 | ||
10 | /* | 10 | /* |
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) | |||
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
316 | /** | ||
317 | * ccw_device_notify() - inform the device's driver about an event | ||
318 | * @cdev: device for which an event occured | ||
319 | * @event: event that occurred | ||
320 | * | ||
321 | * Returns: | ||
322 | * -%EINVAL if the device is offline or has no driver. | ||
323 | * -%EOPNOTSUPP if the device's driver has no notifier registered. | ||
324 | * %NOTIFY_OK if the driver wants to keep the device. | ||
325 | * %NOTIFY_BAD if the driver doesn't want to keep the device. | ||
326 | */ | ||
316 | int ccw_device_notify(struct ccw_device *cdev, int event) | 327 | int ccw_device_notify(struct ccw_device *cdev, int event) |
317 | { | 328 | { |
329 | int ret = -EINVAL; | ||
330 | |||
318 | if (!cdev->drv) | 331 | if (!cdev->drv) |
319 | return 0; | 332 | goto out; |
320 | if (!cdev->online) | 333 | if (!cdev->online) |
321 | return 0; | 334 | goto out; |
322 | CIO_MSG_EVENT(2, "notify called for 0.%x.%04x, event=%d\n", | 335 | CIO_MSG_EVENT(2, "notify called for 0.%x.%04x, event=%d\n", |
323 | cdev->private->dev_id.ssid, cdev->private->dev_id.devno, | 336 | cdev->private->dev_id.ssid, cdev->private->dev_id.devno, |
324 | event); | 337 | event); |
325 | return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0; | 338 | if (!cdev->drv->notify) { |
339 | ret = -EOPNOTSUPP; | ||
340 | goto out; | ||
341 | } | ||
342 | if (cdev->drv->notify(cdev, event)) | ||
343 | ret = NOTIFY_OK; | ||
344 | else | ||
345 | ret = NOTIFY_BAD; | ||
346 | out: | ||
347 | return ret; | ||
326 | } | 348 | } |
327 | 349 | ||
328 | static void ccw_device_oper_notify(struct ccw_device *cdev) | 350 | static void ccw_device_oper_notify(struct ccw_device *cdev) |
329 | { | 351 | { |
330 | if (ccw_device_notify(cdev, CIO_OPER)) { | 352 | if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_OK) { |
331 | /* Reenable channel measurements, if needed. */ | 353 | /* Reenable channel measurements, if needed. */ |
332 | ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF); | 354 | ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF); |
333 | return; | 355 | return; |
@@ -361,14 +383,15 @@ ccw_device_done(struct ccw_device *cdev, int state) | |||
361 | case DEV_STATE_BOXED: | 383 | case DEV_STATE_BOXED: |
362 | CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n", | 384 | CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n", |
363 | cdev->private->dev_id.devno, sch->schid.sch_no); | 385 | cdev->private->dev_id.devno, sch->schid.sch_no); |
364 | if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED)) | 386 | if (cdev->online && |
387 | ccw_device_notify(cdev, CIO_BOXED) != NOTIFY_OK) | ||
365 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 388 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
366 | cdev->private->flags.donotify = 0; | 389 | cdev->private->flags.donotify = 0; |
367 | break; | 390 | break; |
368 | case DEV_STATE_NOT_OPER: | 391 | case DEV_STATE_NOT_OPER: |
369 | CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n", | 392 | CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n", |
370 | cdev->private->dev_id.devno, sch->schid.sch_no); | 393 | cdev->private->dev_id.devno, sch->schid.sch_no); |
371 | if (!ccw_device_notify(cdev, CIO_GONE)) | 394 | if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) |
372 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 395 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
373 | else | 396 | else |
374 | ccw_device_set_disconnected(cdev); | 397 | ccw_device_set_disconnected(cdev); |
@@ -378,7 +401,7 @@ ccw_device_done(struct ccw_device *cdev, int state) | |||
378 | CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel " | 401 | CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel " |
379 | "%04x\n", cdev->private->dev_id.devno, | 402 | "%04x\n", cdev->private->dev_id.devno, |
380 | sch->schid.sch_no); | 403 | sch->schid.sch_no); |
381 | if (!ccw_device_notify(cdev, CIO_NO_PATH)) | 404 | if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) |
382 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 405 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
383 | else | 406 | else |
384 | ccw_device_set_disconnected(cdev); | 407 | ccw_device_set_disconnected(cdev); |
@@ -586,7 +609,7 @@ ccw_device_offline(struct ccw_device *cdev) | |||
586 | static void ccw_device_generic_notoper(struct ccw_device *cdev, | 609 | static void ccw_device_generic_notoper(struct ccw_device *cdev, |
587 | enum dev_event dev_event) | 610 | enum dev_event dev_event) |
588 | { | 611 | { |
589 | if (!ccw_device_notify(cdev, CIO_GONE)) | 612 | if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) |
590 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 613 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
591 | else | 614 | else |
592 | ccw_device_set_disconnected(cdev); | 615 | ccw_device_set_disconnected(cdev); |