From 1768beda4328b4832872d8484d08b5971b774260 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Tue, 22 Sep 2009 22:58:34 +0200 Subject: [PATCH] --- yaml --- r: 165332 b: refs/heads/master c: 255305536c1b56ad09590f1400fb2c788265e34e h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/s390/cio/css.c | 16 ++++++++++++++++ trunk/drivers/s390/cio/idset.c | 10 ++++++++++ trunk/drivers/s390/cio/idset.h | 1 + 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 1817ae2773c0..ebe0c1bb1fe1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 2f17644d1cd0121daa0a997ff4eca5b3b44d1fae +refs/heads/master: 255305536c1b56ad09590f1400fb2c788265e34e diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index 95805da2bb26..59c4b94cdb4b 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -409,10 +409,14 @@ static void css_evaluate_subchannel(struct subchannel_id schid, int slow) static struct idset *slow_subchannel_set; static spinlock_t slow_subchannel_lock; +static wait_queue_head_t css_eval_wq; +static atomic_t css_eval_scheduled; static int __init slow_subchannel_init(void) { spin_lock_init(&slow_subchannel_lock); + atomic_set(&css_eval_scheduled, 0); + init_waitqueue_head(&css_eval_wq); slow_subchannel_set = idset_sch_new(); if (!slow_subchannel_set) { CIO_MSG_EVENT(0, "could not allocate slow subchannel set\n"); @@ -468,9 +472,17 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data) static void css_slow_path_func(struct work_struct *unused) { + unsigned long flags; + CIO_TRACE_EVENT(4, "slowpath"); for_each_subchannel_staged(slow_eval_known_fn, slow_eval_unknown_fn, NULL); + spin_lock_irqsave(&slow_subchannel_lock, flags); + if (idset_is_empty(slow_subchannel_set)) { + atomic_set(&css_eval_scheduled, 0); + wake_up(&css_eval_wq); + } + spin_unlock_irqrestore(&slow_subchannel_lock, flags); } static DECLARE_WORK(slow_path_work, css_slow_path_func); @@ -482,6 +494,7 @@ void css_schedule_eval(struct subchannel_id schid) spin_lock_irqsave(&slow_subchannel_lock, flags); idset_sch_add(slow_subchannel_set, schid); + atomic_set(&css_eval_scheduled, 1); queue_work(slow_path_wq, &slow_path_work); spin_unlock_irqrestore(&slow_subchannel_lock, flags); } @@ -492,6 +505,7 @@ void css_schedule_eval_all(void) spin_lock_irqsave(&slow_subchannel_lock, flags); idset_fill(slow_subchannel_set); + atomic_set(&css_eval_scheduled, 1); queue_work(slow_path_wq, &slow_path_work); spin_unlock_irqrestore(&slow_subchannel_lock, flags); } @@ -1007,6 +1021,8 @@ static int __init channel_subsystem_init_sync(void) { /* Allocate and register subchannels. */ for_each_subchannel(setup_subchannel, NULL); + /* Wait for the evaluation of subchannels to finish. */ + wait_event(css_eval_wq, atomic_read(&css_eval_scheduled) == 0); /* Wait for the initialization of ccw devices to finish. */ wait_event(ccw_device_init_wq, diff --git a/trunk/drivers/s390/cio/idset.c b/trunk/drivers/s390/cio/idset.c index cf8f24a4b5eb..77e42cb127bb 100644 --- a/trunk/drivers/s390/cio/idset.c +++ b/trunk/drivers/s390/cio/idset.c @@ -110,3 +110,13 @@ int idset_sch_get_first(struct idset *set, struct subchannel_id *schid) } return rc; } + +int idset_is_empty(struct idset *set) +{ + int bitnum; + + bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id); + if (bitnum >= set->num_ssid * set->num_id) + return 1; + return 0; +} diff --git a/trunk/drivers/s390/cio/idset.h b/trunk/drivers/s390/cio/idset.h index 528065cb5021..ca1398aadc7e 100644 --- a/trunk/drivers/s390/cio/idset.h +++ b/trunk/drivers/s390/cio/idset.h @@ -21,5 +21,6 @@ void idset_sch_add(struct idset *set, struct subchannel_id id); void idset_sch_del(struct idset *set, struct subchannel_id id); int idset_sch_contains(struct idset *set, struct subchannel_id id); int idset_sch_get_first(struct idset *set, struct subchannel_id *id); +int idset_is_empty(struct idset *set); #endif /* S390_IDSET_H */