aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/cio/device.c10
-rw-r--r--drivers/s390/cio/device.h2
-rw-r--r--drivers/s390/cio/device_fsm.c39
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:
1788static int resume_handle_boxed(struct ccw_device *cdev) 1788static 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)
1797static int resume_handle_disc(struct ccw_device *cdev) 1797static 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 */
316int ccw_device_notify(struct ccw_device *cdev, int event) 327int 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;
346out:
347 return ret;
326} 348}
327 349
328static void ccw_device_oper_notify(struct ccw_device *cdev) 350static 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)
586static void ccw_device_generic_notoper(struct ccw_device *cdev, 609static 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);