aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2009-09-22 16:58:34 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-09-22 16:58:41 -0400
commit255305536c1b56ad09590f1400fb2c788265e34e (patch)
tree23c97143b3ffe1598f76bc01b94407fa0c7d79d4 /drivers/s390
parent2f17644d1cd0121daa0a997ff4eca5b3b44d1fae (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>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/css.c16
-rw-r--r--drivers/s390/cio/idset.c10
-rw-r--r--drivers/s390/cio/idset.h1
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
410static struct idset *slow_subchannel_set; 410static struct idset *slow_subchannel_set;
411static spinlock_t slow_subchannel_lock; 411static spinlock_t slow_subchannel_lock;
412static wait_queue_head_t css_eval_wq;
413static atomic_t css_eval_scheduled;
412 414
413static int __init slow_subchannel_init(void) 415static 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
469static void css_slow_path_func(struct work_struct *unused) 473static 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
476static DECLARE_WORK(slow_path_work, css_slow_path_func); 488static 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
114int 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);
21void idset_sch_del(struct idset *set, struct subchannel_id id); 21void idset_sch_del(struct idset *set, struct subchannel_id id);
22int idset_sch_contains(struct idset *set, struct subchannel_id id); 22int idset_sch_contains(struct idset *set, struct subchannel_id id);
23int idset_sch_get_first(struct idset *set, struct subchannel_id *id); 23int idset_sch_get_first(struct idset *set, struct subchannel_id *id);
24int idset_is_empty(struct idset *set);
24 25
25#endif /* S390_IDSET_H */ 26#endif /* S390_IDSET_H */