aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>2009-12-07 06:51:18 -0500
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2009-12-07 06:51:30 -0500
commit390935acac21f3ea1a130bdca8eb9397cb293643 (patch)
treedafe0c1ff5c5d6946a024c05e5eedaa2731eaf20 /drivers/s390/cio/device.c
parent5d6e6b6f6f3eac10a7f5a15e961bac3b36824d9d (diff)
[S390] cio: introduce subchannel todos
Ensure that current and future users of sch->work do not overwrite each other by introducing a single mechanism for delayed subchannel work. Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r--drivers/s390/cio/device.c23
1 files changed, 5 insertions, 18 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 6097763f1035..0dcfc0ee3d81 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1051,23 +1051,6 @@ static void io_subchannel_init_fields(struct subchannel *sch)
1051 io_subchannel_init_config(sch); 1051 io_subchannel_init_config(sch);
1052} 1052}
1053 1053
1054static void io_subchannel_do_unreg(struct work_struct *work)
1055{
1056 struct subchannel *sch;
1057
1058 sch = container_of(work, struct subchannel, work);
1059 css_sch_device_unregister(sch);
1060 put_device(&sch->dev);
1061}
1062
1063/* Schedule unregister if we have no cdev. */
1064static void io_subchannel_schedule_removal(struct subchannel *sch)
1065{
1066 get_device(&sch->dev);
1067 INIT_WORK(&sch->work, io_subchannel_do_unreg);
1068 queue_work(slow_path_wq, &sch->work);
1069}
1070
1071/* 1054/*
1072 * Note: We always return 0 so that we bind to the device even on error. 1055 * Note: We always return 0 so that we bind to the device even on error.
1073 * This is needed so that our remove function is called on unregister. 1056 * This is needed so that our remove function is called on unregister.
@@ -1124,7 +1107,9 @@ static int io_subchannel_probe(struct subchannel *sch)
1124 return 0; 1107 return 0;
1125 1108
1126out_schedule: 1109out_schedule:
1127 io_subchannel_schedule_removal(sch); 1110 spin_lock_irq(sch->lock);
1111 css_sched_sch_todo(sch, SCH_TODO_UNREG);
1112 spin_unlock_irq(sch->lock);
1128 return 0; 1113 return 0;
1129} 1114}
1130 1115
@@ -1469,6 +1454,8 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
1469 spin_lock_irqsave(sch->lock, flags); 1454 spin_lock_irqsave(sch->lock, flags);
1470 if (!device_is_registered(&sch->dev)) 1455 if (!device_is_registered(&sch->dev))
1471 goto out_unlock; 1456 goto out_unlock;
1457 if (work_pending(&sch->todo_work))
1458 goto out_unlock;
1472 action = sch_get_action(sch); 1459 action = sch_get_action(sch);
1473 CIO_MSG_EVENT(2, "event: sch 0.%x.%04x, process=%d, action=%d\n", 1460 CIO_MSG_EVENT(2, "event: sch 0.%x.%04x, process=%d, action=%d\n",
1474 sch->schid.ssid, sch->schid.sch_no, process, 1461 sch->schid.ssid, sch->schid.sch_no, process,