aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Oberparleiter <oberpar@linux.vnet.ibm.com>2013-11-26 08:58:08 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-12-16 08:37:41 -0500
commit175746eb06a8925274558793814d8c802dc48276 (patch)
tree353ba6f51e3e1a11c8f6619a9dedb8de2373a26f
parentb207f5a8f9a60fda4e995151af7d8670015e261d (diff)
s390/cio: Delay scan for newly available I/O devices
The CIO layer scans for newly available I/O devices by performing a scan of available subchannels using the Store Subchannel (STSCH) instruction. Performing too many STSCH instructions in a tight loop can cause high Hypervisor overhead which can negatively impact the performance of the virtual machine as a whole. A subchannel scan is triggered for example during a hardware event that indicates that a channel path has become available. It is also triggered by the DASD device driver for each device that is set online. This patch reduces the number of STSCH instructions being performed by delaying the start of the actual subchannel scan by 1 second. Multiple scan requests that are scheduled during this time will be merged into a single scan loop. The trade-off consists of a short delay that is introduced between the time that the event is processed and a newly available device becoming usable. This delay should be acceptable since it only affects devices that have not been in use before. Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Reviewed-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--drivers/s390/cio/blacklist.c2
-rw-r--r--drivers/s390/cio/css.c13
-rw-r--r--drivers/s390/cio/css.h1
3 files changed, 9 insertions, 7 deletions
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index a9fe3de2dec1..77ee4daec206 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -269,7 +269,7 @@ static int blacklist_parse_proc_parameters(char *buf)
269 else 269 else
270 return -EINVAL; 270 return -EINVAL;
271 271
272 css_schedule_reprobe(); 272 css_schedule_eval_all_unreg(0);
273 273
274 return rc; 274 return rc;
275} 275}
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index c1f9cc728c2d..604333ebf01e 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -575,7 +575,7 @@ static void css_slow_path_func(struct work_struct *unused)
575 spin_unlock_irqrestore(&slow_subchannel_lock, flags); 575 spin_unlock_irqrestore(&slow_subchannel_lock, flags);
576} 576}
577 577
578static DECLARE_WORK(slow_path_work, css_slow_path_func); 578static DECLARE_DELAYED_WORK(slow_path_work, css_slow_path_func);
579struct workqueue_struct *cio_work_q; 579struct workqueue_struct *cio_work_q;
580 580
581void css_schedule_eval(struct subchannel_id schid) 581void css_schedule_eval(struct subchannel_id schid)
@@ -585,7 +585,7 @@ void css_schedule_eval(struct subchannel_id schid)
585 spin_lock_irqsave(&slow_subchannel_lock, flags); 585 spin_lock_irqsave(&slow_subchannel_lock, flags);
586 idset_sch_add(slow_subchannel_set, schid); 586 idset_sch_add(slow_subchannel_set, schid);
587 atomic_set(&css_eval_scheduled, 1); 587 atomic_set(&css_eval_scheduled, 1);
588 queue_work(cio_work_q, &slow_path_work); 588 queue_delayed_work(cio_work_q, &slow_path_work, 0);
589 spin_unlock_irqrestore(&slow_subchannel_lock, flags); 589 spin_unlock_irqrestore(&slow_subchannel_lock, flags);
590} 590}
591 591
@@ -596,7 +596,7 @@ void css_schedule_eval_all(void)
596 spin_lock_irqsave(&slow_subchannel_lock, flags); 596 spin_lock_irqsave(&slow_subchannel_lock, flags);
597 idset_fill(slow_subchannel_set); 597 idset_fill(slow_subchannel_set);
598 atomic_set(&css_eval_scheduled, 1); 598 atomic_set(&css_eval_scheduled, 1);
599 queue_work(cio_work_q, &slow_path_work); 599 queue_delayed_work(cio_work_q, &slow_path_work, 0);
600 spin_unlock_irqrestore(&slow_subchannel_lock, flags); 600 spin_unlock_irqrestore(&slow_subchannel_lock, flags);
601} 601}
602 602
@@ -609,7 +609,7 @@ static int __unset_registered(struct device *dev, void *data)
609 return 0; 609 return 0;
610} 610}
611 611
612static void css_schedule_eval_all_unreg(void) 612void css_schedule_eval_all_unreg(unsigned long delay)
613{ 613{
614 unsigned long flags; 614 unsigned long flags;
615 struct idset *unreg_set; 615 struct idset *unreg_set;
@@ -627,7 +627,7 @@ static void css_schedule_eval_all_unreg(void)
627 spin_lock_irqsave(&slow_subchannel_lock, flags); 627 spin_lock_irqsave(&slow_subchannel_lock, flags);
628 idset_add_set(slow_subchannel_set, unreg_set); 628 idset_add_set(slow_subchannel_set, unreg_set);
629 atomic_set(&css_eval_scheduled, 1); 629 atomic_set(&css_eval_scheduled, 1);
630 queue_work(cio_work_q, &slow_path_work); 630 queue_delayed_work(cio_work_q, &slow_path_work, delay);
631 spin_unlock_irqrestore(&slow_subchannel_lock, flags); 631 spin_unlock_irqrestore(&slow_subchannel_lock, flags);
632 idset_free(unreg_set); 632 idset_free(unreg_set);
633} 633}
@@ -640,7 +640,8 @@ void css_wait_for_slow_path(void)
640/* Schedule reprobing of all unregistered subchannels. */ 640/* Schedule reprobing of all unregistered subchannels. */
641void css_schedule_reprobe(void) 641void css_schedule_reprobe(void)
642{ 642{
643 css_schedule_eval_all_unreg(); 643 /* Schedule with a delay to allow merging of subsequent calls. */
644 css_schedule_eval_all_unreg(1 * HZ);
644} 645}
645EXPORT_SYMBOL_GPL(css_schedule_reprobe); 646EXPORT_SYMBOL_GPL(css_schedule_reprobe);
646 647
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 29351321bad6..2c9107e20251 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -133,6 +133,7 @@ extern struct channel_subsystem *channel_subsystems[];
133/* Helper functions to build lists for the slow path. */ 133/* Helper functions to build lists for the slow path. */
134void css_schedule_eval(struct subchannel_id schid); 134void css_schedule_eval(struct subchannel_id schid);
135void css_schedule_eval_all(void); 135void css_schedule_eval_all(void);
136void css_schedule_eval_all_unreg(unsigned long delay);
136int css_complete_work(void); 137int css_complete_work(void);
137 138
138int sch_is_pseudo_sch(struct subchannel *); 139int sch_is_pseudo_sch(struct subchannel *);