diff options
author | Peter Oberparleiter <oberpar@linux.vnet.ibm.com> | 2013-11-26 08:55:56 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-12-16 08:37:40 -0500 |
commit | 449666dd1efacaf3f0eb020cc617dd702356575c (patch) | |
tree | 6c95cfa4ace2f56d87947e814fbbd2568351c22b /drivers/s390/cio | |
parent | 319e2e3f63c348a9b66db4667efa73178e18b17d (diff) |
s390/cio: More efficient handling of CHPID availability events
The CIO layer processes hardware events that indicate that a channel
path has become available 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.
This patch reduces the number of STSCH instructions performed while
processing a resource accessibility event and while varying a CHPID
online.
In both cases, Linux first performs a STSCH instruction on each unused
subchannel to see if the subchannel has become available. If the STSCH
instruction indicates that the subchannel is available, a full
evaluation of this subchannel is scheduled. Since the full evaluation
includes performing a STSCH instruction, the initial STSCH is
unnecessary and can be removed.
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>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r-- | drivers/s390/cio/chsc.c | 40 |
1 files changed, 4 insertions, 36 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 13299f902676..eee70cb8730b 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -237,26 +237,6 @@ void chsc_chp_offline(struct chp_id chpid) | |||
237 | for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link); | 237 | for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link); |
238 | } | 238 | } |
239 | 239 | ||
240 | static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data) | ||
241 | { | ||
242 | struct schib schib; | ||
243 | /* | ||
244 | * We don't know the device yet, but since a path | ||
245 | * may be available now to the device we'll have | ||
246 | * to do recognition again. | ||
247 | * Since we don't have any idea about which chpid | ||
248 | * that beast may be on we'll have to do a stsch | ||
249 | * on all devices, grr... | ||
250 | */ | ||
251 | if (stsch_err(schid, &schib)) | ||
252 | /* We're through */ | ||
253 | return -ENXIO; | ||
254 | |||
255 | /* Put it on the slow path. */ | ||
256 | css_schedule_eval(schid); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int __s390_process_res_acc(struct subchannel *sch, void *data) | 240 | static int __s390_process_res_acc(struct subchannel *sch, void *data) |
261 | { | 241 | { |
262 | spin_lock_irq(sch->lock); | 242 | spin_lock_irq(sch->lock); |
@@ -287,8 +267,8 @@ static void s390_process_res_acc(struct chp_link *link) | |||
287 | * The more information we have (info), the less scanning | 267 | * The more information we have (info), the less scanning |
288 | * will we have to do. | 268 | * will we have to do. |
289 | */ | 269 | */ |
290 | for_each_subchannel_staged(__s390_process_res_acc, | 270 | for_each_subchannel_staged(__s390_process_res_acc, NULL, link); |
291 | s390_process_res_acc_new_sch, link); | 271 | css_schedule_reprobe(); |
292 | } | 272 | } |
293 | 273 | ||
294 | static int | 274 | static int |
@@ -663,19 +643,6 @@ static int s390_subchannel_vary_chpid_on(struct subchannel *sch, void *data) | |||
663 | return 0; | 643 | return 0; |
664 | } | 644 | } |
665 | 645 | ||
666 | static int | ||
667 | __s390_vary_chpid_on(struct subchannel_id schid, void *data) | ||
668 | { | ||
669 | struct schib schib; | ||
670 | |||
671 | if (stsch_err(schid, &schib)) | ||
672 | /* We're through */ | ||
673 | return -ENXIO; | ||
674 | /* Put it on the slow path. */ | ||
675 | css_schedule_eval(schid); | ||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | /** | 646 | /** |
680 | * chsc_chp_vary - propagate channel-path vary operation to subchannels | 647 | * chsc_chp_vary - propagate channel-path vary operation to subchannels |
681 | * @chpid: channl-path ID | 648 | * @chpid: channl-path ID |
@@ -694,7 +661,8 @@ int chsc_chp_vary(struct chp_id chpid, int on) | |||
694 | /* Try to update the channel path description. */ | 661 | /* Try to update the channel path description. */ |
695 | chp_update_desc(chp); | 662 | chp_update_desc(chp); |
696 | for_each_subchannel_staged(s390_subchannel_vary_chpid_on, | 663 | for_each_subchannel_staged(s390_subchannel_vary_chpid_on, |
697 | __s390_vary_chpid_on, &chpid); | 664 | NULL, &chpid); |
665 | css_schedule_reprobe(); | ||
698 | } else | 666 | } else |
699 | for_each_subchannel_staged(s390_subchannel_vary_chpid_off, | 667 | for_each_subchannel_staged(s390_subchannel_vary_chpid_off, |
700 | NULL, &chpid); | 668 | NULL, &chpid); |