diff options
author | Konstantin Ozerkov <kozerkov@parallels.com> | 2011-10-26 11:11:01 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-10-31 05:03:28 -0400 |
commit | 228cf79376f13b98f2e1ac10586311312757675c (patch) | |
tree | d6855298c13b11deba6426b736d23d4aeeb1bdd3 /sound | |
parent | c09403dcc5698abf214329fbbf3cf8dbb5558bea (diff) |
ALSA: intel8x0: Improve performance in virtual environment
v3: detection code is x86 and KVM specific, hide it under ifdef
v2: add detection for virtual environments (KVM and Parallels)
This patch is intended to improve performance in virtualized environments
like Parallels Desktop or KVM/VirtualBox/QEMU (virtual ICH/AC97 audio).
I/O access is very time-expensive operation in virtual world: VCPU
can be rescheduled and in the worst case we get more than 10ms delay on
each I/O access.
In the virtual environment loop exit rule
(old_civ == current_civ && old_picb == current_picb) is never satisfied,
because old_picb is never the same as current_picb due to delay inspired
by reading current_civ. As a result loop ended by timeout and we get 10x
more I/O operations.
Experimental data from Prallels Desktop 7, RHEL6 guest (I/O ops per
second):
Original code:
In Port Counter Callback
f014 41550 fffff00000179d00 ac97_bm_read_civ+0x000
f018 41387 fffff0000017a580 ac97_bm_read_picb+0x000
With patch:
In Port Counter Callback
f014 4090 fffff00000179d00 ac97_bm_read_civ+0x000
f018 1964 fffff0000017a580 ac97_bm_read_picb+0x000
Signed-off-by: Konstantin Ozerkov <kozerkov@parallels.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/intel8x0.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 6a5b387b97fd..6dc302c3eb93 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -42,6 +42,12 @@ | |||
42 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
43 | #include <asm/cacheflush.h> | 43 | #include <asm/cacheflush.h> |
44 | 44 | ||
45 | #ifdef CONFIG_KVM_GUEST | ||
46 | #include <asm/kvm_para.h> | ||
47 | #else | ||
48 | #define kvm_para_available() (0) | ||
49 | #endif | ||
50 | |||
45 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 51 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
46 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); | 52 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); |
47 | MODULE_LICENSE("GPL"); | 53 | MODULE_LICENSE("GPL"); |
@@ -77,6 +83,7 @@ static int buggy_semaphore; | |||
77 | static int buggy_irq = -1; /* auto-check */ | 83 | static int buggy_irq = -1; /* auto-check */ |
78 | static int xbox; | 84 | static int xbox; |
79 | static int spdif_aclink = -1; | 85 | static int spdif_aclink = -1; |
86 | static int inside_vm = -1; | ||
80 | 87 | ||
81 | module_param(index, int, 0444); | 88 | module_param(index, int, 0444); |
82 | MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); | 89 | MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); |
@@ -94,6 +101,8 @@ module_param(xbox, bool, 0444); | |||
94 | MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection."); | 101 | MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection."); |
95 | module_param(spdif_aclink, int, 0444); | 102 | module_param(spdif_aclink, int, 0444); |
96 | MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); | 103 | MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); |
104 | module_param(inside_vm, bool, 0444); | ||
105 | MODULE_PARM_DESC(inside_vm, "KVM/Parallels optimization."); | ||
97 | 106 | ||
98 | /* just for backward compatibility */ | 107 | /* just for backward compatibility */ |
99 | static int enable; | 108 | static int enable; |
@@ -400,6 +409,7 @@ struct intel8x0 { | |||
400 | unsigned buggy_irq: 1; /* workaround for buggy mobos */ | 409 | unsigned buggy_irq: 1; /* workaround for buggy mobos */ |
401 | unsigned xbox: 1; /* workaround for Xbox AC'97 detection */ | 410 | unsigned xbox: 1; /* workaround for Xbox AC'97 detection */ |
402 | unsigned buggy_semaphore: 1; /* workaround for buggy codec semaphore */ | 411 | unsigned buggy_semaphore: 1; /* workaround for buggy codec semaphore */ |
412 | unsigned inside_vm: 1; /* enable VM optimization */ | ||
403 | 413 | ||
404 | int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */ | 414 | int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */ |
405 | unsigned int sdm_saved; /* SDM reg value */ | 415 | unsigned int sdm_saved; /* SDM reg value */ |
@@ -1065,8 +1075,11 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs | |||
1065 | udelay(10); | 1075 | udelay(10); |
1066 | continue; | 1076 | continue; |
1067 | } | 1077 | } |
1068 | if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) && | 1078 | if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV)) |
1069 | ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) | 1079 | continue; |
1080 | if (chip->inside_vm) | ||
1081 | break; | ||
1082 | if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) | ||
1070 | break; | 1083 | break; |
1071 | } while (timeout--); | 1084 | } while (timeout--); |
1072 | ptr = ichdev->last_pos; | 1085 | ptr = ichdev->last_pos; |
@@ -2984,6 +2997,10 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, | |||
2984 | if (xbox) | 2997 | if (xbox) |
2985 | chip->xbox = 1; | 2998 | chip->xbox = 1; |
2986 | 2999 | ||
3000 | chip->inside_vm = inside_vm; | ||
3001 | if (inside_vm) | ||
3002 | printk(KERN_INFO "intel8x0: enable KVM optimization\n"); | ||
3003 | |||
2987 | if (pci->vendor == PCI_VENDOR_ID_INTEL && | 3004 | if (pci->vendor == PCI_VENDOR_ID_INTEL && |
2988 | pci->device == PCI_DEVICE_ID_INTEL_440MX) | 3005 | pci->device == PCI_DEVICE_ID_INTEL_440MX) |
2989 | chip->fix_nocache = 1; /* enable workaround */ | 3006 | chip->fix_nocache = 1; /* enable workaround */ |
@@ -3226,6 +3243,14 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, | |||
3226 | buggy_irq = 0; | 3243 | buggy_irq = 0; |
3227 | } | 3244 | } |
3228 | 3245 | ||
3246 | if (inside_vm < 0) { | ||
3247 | /* detect KVM and Parallels virtual environments */ | ||
3248 | inside_vm = kvm_para_available(); | ||
3249 | #if defined(__i386__) || defined(__x86_64__) | ||
3250 | inside_vm = inside_vm || boot_cpu_has(X86_FEATURE_HYPERVISOR); | ||
3251 | #endif | ||
3252 | } | ||
3253 | |||
3229 | if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, | 3254 | if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, |
3230 | &chip)) < 0) { | 3255 | &chip)) < 0) { |
3231 | snd_card_free(card); | 3256 | snd_card_free(card); |