diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2009-09-22 16:58:34 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-09-22 16:58:41 -0400 |
commit | 255305536c1b56ad09590f1400fb2c788265e34e (patch) | |
tree | 23c97143b3ffe1598f76bc01b94407fa0c7d79d4 | |
parent | 2f17644d1cd0121daa0a997ff4eca5b3b44d1fae (diff) |
[S390] cio: introduce css_eval_scheduled
Use css_eval_scheduled to determine if all scheduled subchannel
evaluation is finished. Wait for this value to be 0 in the
channel subsystem init function.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | drivers/s390/cio/css.c | 16 | ||||
-rw-r--r-- | drivers/s390/cio/idset.c | 10 | ||||
-rw-r--r-- | drivers/s390/cio/idset.h | 1 |
3 files changed, 27 insertions, 0 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 95805da2bb26..59c4b94cdb4b 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -409,10 +409,14 @@ static void css_evaluate_subchannel(struct subchannel_id schid, int slow) | |||
409 | 409 | ||
410 | static struct idset *slow_subchannel_set; | 410 | static struct idset *slow_subchannel_set; |
411 | static spinlock_t slow_subchannel_lock; | 411 | static spinlock_t slow_subchannel_lock; |
412 | static wait_queue_head_t css_eval_wq; | ||
413 | static atomic_t css_eval_scheduled; | ||
412 | 414 | ||
413 | static int __init slow_subchannel_init(void) | 415 | static int __init slow_subchannel_init(void) |
414 | { | 416 | { |
415 | spin_lock_init(&slow_subchannel_lock); | 417 | spin_lock_init(&slow_subchannel_lock); |
418 | atomic_set(&css_eval_scheduled, 0); | ||
419 | init_waitqueue_head(&css_eval_wq); | ||
416 | slow_subchannel_set = idset_sch_new(); | 420 | slow_subchannel_set = idset_sch_new(); |
417 | if (!slow_subchannel_set) { | 421 | if (!slow_subchannel_set) { |
418 | CIO_MSG_EVENT(0, "could not allocate slow subchannel set\n"); | 422 | 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) | |||
468 | 472 | ||
469 | static void css_slow_path_func(struct work_struct *unused) | 473 | static void css_slow_path_func(struct work_struct *unused) |
470 | { | 474 | { |
475 | unsigned long flags; | ||
476 | |||
471 | CIO_TRACE_EVENT(4, "slowpath"); | 477 | CIO_TRACE_EVENT(4, "slowpath"); |
472 | for_each_subchannel_staged(slow_eval_known_fn, slow_eval_unknown_fn, | 478 | for_each_subchannel_staged(slow_eval_known_fn, slow_eval_unknown_fn, |
473 | NULL); | 479 | NULL); |
480 | spin_lock_irqsave(&slow_subchannel_lock, flags); | ||
481 | if (idset_is_empty(slow_subchannel_set)) { | ||
482 | atomic_set(&css_eval_scheduled, 0); | ||
483 | wake_up(&css_eval_wq); | ||
484 | } | ||
485 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | ||
474 | } | 486 | } |
475 | 487 | ||
476 | static DECLARE_WORK(slow_path_work, css_slow_path_func); | 488 | static DECLARE_WORK(slow_path_work, css_slow_path_func); |
@@ -482,6 +494,7 @@ void css_schedule_eval(struct subchannel_id schid) | |||
482 | 494 | ||
483 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 495 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
484 | idset_sch_add(slow_subchannel_set, schid); | 496 | idset_sch_add(slow_subchannel_set, schid); |
497 | atomic_set(&css_eval_scheduled, 1); | ||
485 | queue_work(slow_path_wq, &slow_path_work); | 498 | queue_work(slow_path_wq, &slow_path_work); |
486 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 499 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
487 | } | 500 | } |
@@ -492,6 +505,7 @@ void css_schedule_eval_all(void) | |||
492 | 505 | ||
493 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 506 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
494 | idset_fill(slow_subchannel_set); | 507 | idset_fill(slow_subchannel_set); |
508 | atomic_set(&css_eval_scheduled, 1); | ||
495 | queue_work(slow_path_wq, &slow_path_work); | 509 | queue_work(slow_path_wq, &slow_path_work); |
496 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 510 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
497 | } | 511 | } |
@@ -1007,6 +1021,8 @@ static int __init channel_subsystem_init_sync(void) | |||
1007 | { | 1021 | { |
1008 | /* Allocate and register subchannels. */ | 1022 | /* Allocate and register subchannels. */ |
1009 | for_each_subchannel(setup_subchannel, NULL); | 1023 | for_each_subchannel(setup_subchannel, NULL); |
1024 | /* Wait for the evaluation of subchannels to finish. */ | ||
1025 | wait_event(css_eval_wq, atomic_read(&css_eval_scheduled) == 0); | ||
1010 | 1026 | ||
1011 | /* Wait for the initialization of ccw devices to finish. */ | 1027 | /* Wait for the initialization of ccw devices to finish. */ |
1012 | wait_event(ccw_device_init_wq, | 1028 | wait_event(ccw_device_init_wq, |
diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c index cf8f24a4b5eb..77e42cb127bb 100644 --- a/drivers/s390/cio/idset.c +++ b/drivers/s390/cio/idset.c | |||
@@ -110,3 +110,13 @@ int idset_sch_get_first(struct idset *set, struct subchannel_id *schid) | |||
110 | } | 110 | } |
111 | return rc; | 111 | return rc; |
112 | } | 112 | } |
113 | |||
114 | int idset_is_empty(struct idset *set) | ||
115 | { | ||
116 | int bitnum; | ||
117 | |||
118 | bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id); | ||
119 | if (bitnum >= set->num_ssid * set->num_id) | ||
120 | return 1; | ||
121 | return 0; | ||
122 | } | ||
diff --git a/drivers/s390/cio/idset.h b/drivers/s390/cio/idset.h index 528065cb5021..ca1398aadc7e 100644 --- a/drivers/s390/cio/idset.h +++ b/drivers/s390/cio/idset.h | |||
@@ -21,5 +21,6 @@ void idset_sch_add(struct idset *set, struct subchannel_id id); | |||
21 | void idset_sch_del(struct idset *set, struct subchannel_id id); | 21 | void idset_sch_del(struct idset *set, struct subchannel_id id); |
22 | int idset_sch_contains(struct idset *set, struct subchannel_id id); | 22 | int idset_sch_contains(struct idset *set, struct subchannel_id id); |
23 | int idset_sch_get_first(struct idset *set, struct subchannel_id *id); | 23 | int idset_sch_get_first(struct idset *set, struct subchannel_id *id); |
24 | int idset_is_empty(struct idset *set); | ||
24 | 25 | ||
25 | #endif /* S390_IDSET_H */ | 26 | #endif /* S390_IDSET_H */ |