mirror of
https://github.com/torvalds/linux.git
synced 2024-11-06 03:51:48 +00:00
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>
This commit is contained in:
parent
c09403dcc5
commit
228cf79376
@ -42,6 +42,12 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#ifdef CONFIG_KVM_GUEST
|
||||
#include <asm/kvm_para.h>
|
||||
#else
|
||||
#define kvm_para_available() (0)
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
|
||||
MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455");
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -77,6 +83,7 @@ static int buggy_semaphore;
|
||||
static int buggy_irq = -1; /* auto-check */
|
||||
static int xbox;
|
||||
static int spdif_aclink = -1;
|
||||
static int inside_vm = -1;
|
||||
|
||||
module_param(index, int, 0444);
|
||||
MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
|
||||
@ -94,6 +101,8 @@ module_param(xbox, bool, 0444);
|
||||
MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
|
||||
module_param(spdif_aclink, int, 0444);
|
||||
MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
|
||||
module_param(inside_vm, bool, 0444);
|
||||
MODULE_PARM_DESC(inside_vm, "KVM/Parallels optimization.");
|
||||
|
||||
/* just for backward compatibility */
|
||||
static int enable;
|
||||
@ -400,6 +409,7 @@ struct intel8x0 {
|
||||
unsigned buggy_irq: 1; /* workaround for buggy mobos */
|
||||
unsigned xbox: 1; /* workaround for Xbox AC'97 detection */
|
||||
unsigned buggy_semaphore: 1; /* workaround for buggy codec semaphore */
|
||||
unsigned inside_vm: 1; /* enable VM optimization */
|
||||
|
||||
int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
|
||||
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
|
||||
udelay(10);
|
||||
continue;
|
||||
}
|
||||
if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
|
||||
ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
|
||||
if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV))
|
||||
continue;
|
||||
if (chip->inside_vm)
|
||||
break;
|
||||
if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
|
||||
break;
|
||||
} while (timeout--);
|
||||
ptr = ichdev->last_pos;
|
||||
@ -2984,6 +2997,10 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
|
||||
if (xbox)
|
||||
chip->xbox = 1;
|
||||
|
||||
chip->inside_vm = inside_vm;
|
||||
if (inside_vm)
|
||||
printk(KERN_INFO "intel8x0: enable KVM optimization\n");
|
||||
|
||||
if (pci->vendor == PCI_VENDOR_ID_INTEL &&
|
||||
pci->device == PCI_DEVICE_ID_INTEL_440MX)
|
||||
chip->fix_nocache = 1; /* enable workaround */
|
||||
@ -3226,6 +3243,14 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
|
||||
buggy_irq = 0;
|
||||
}
|
||||
|
||||
if (inside_vm < 0) {
|
||||
/* detect KVM and Parallels virtual environments */
|
||||
inside_vm = kvm_para_available();
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
inside_vm = inside_vm || boot_cpu_has(X86_FEATURE_HYPERVISOR);
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data,
|
||||
&chip)) < 0) {
|
||||
snd_card_free(card);
|
||||
|
Loading…
Reference in New Issue
Block a user