summaryrefslogtreecommitdiff
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2013-04-13 15:06:27 +0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-04-17 16:07:33 +0400
commit0ad8f714a135cf993606c21fc1ed0e303ef17c0d (patch)
tree78ce400a47edecdce1921f2bb6cc536009778bb5 /drivers/s390/cio/device.c
parent4e5ebd51214a1851841f952e9e5b5072ce5f9da4 (diff)
downloadlinux-0ad8f714a135cf993606c21fc1ed0e303ef17c0d.tar.xz
s390/cio: fix early init counter usage
Via ccw_device_init_count we keep track of how many devices are in asynchronous device recognition/initialization. For early devices this variable was not only used prior to its initialization but used incorrectly (incremented but never decremented). Fix this by using static initialization for this variable (and friends), make them visible to device.c only, and decrement the counter after recognition of early devices is finished. Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> 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/device.c')
-rw-r--r--drivers/s390/cio/device.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 41a16785be29..1ab5f6c36d9b 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -44,6 +44,10 @@ static DEFINE_SPINLOCK(recovery_lock);
static int recovery_phase;
static const unsigned long recovery_delay[] = { 3, 30, 300 };
+static atomic_t ccw_device_init_count = ATOMIC_INIT(0);
+static DECLARE_WAIT_QUEUE_HEAD(ccw_device_init_wq);
+static struct bus_type ccw_bus_type;
+
/******************* bus type handling ***********************/
/* The Linux driver model distinguishes between a bus type and
@@ -128,8 +132,6 @@ static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env)
return ret;
}
-static struct bus_type ccw_bus_type;
-
static void io_subchannel_irq(struct subchannel *);
static int io_subchannel_probe(struct subchannel *);
static int io_subchannel_remove(struct subchannel *);
@@ -138,8 +140,6 @@ static int io_subchannel_sch_event(struct subchannel *, int);
static int io_subchannel_chp_event(struct subchannel *, struct chp_link *,
int);
static void recovery_func(unsigned long data);
-wait_queue_head_t ccw_device_init_wq;
-atomic_t ccw_device_init_count;
static struct css_device_id io_subchannel_ids[] = {
{ .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, },
@@ -192,10 +192,7 @@ int __init io_subchannel_init(void)
{
int ret;
- init_waitqueue_head(&ccw_device_init_wq);
- atomic_set(&ccw_device_init_count, 0);
setup_timer(&recovery_timer, recovery_func, 0);
-
ret = bus_register(&ccw_bus_type);
if (ret)
return ret;
@@ -1093,6 +1090,8 @@ static int io_subchannel_probe(struct subchannel *sch)
put_device(&cdev->dev);
goto out_schedule;
}
+ if (atomic_dec_and_test(&ccw_device_init_count))
+ wake_up(&ccw_device_init_wq);
return 0;
}
io_subchannel_init_fields(sch);