diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-12-06 06:42:35 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-12-06 06:43:49 +0100 |
commit | d6c1c49de577fa292af2449817364b7d89b574d8 (patch) | |
tree | e97cf88a318f50eb23c18d790e8b0bcf7bb47169 /sound/pci/intel8x0.c | |
parent | 9dde9dc0a81c7aeb863b35121d09011f09b4897c (diff) | |
parent | ddf6e0e50723b62ac76ed18eb53e9417c6eefba7 (diff) |
Merge branch 'perf/urgent' into perf/core
Merge reason: Add these cherry-picked commits so that future changes
on perf/core don't conflict.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'sound/pci/intel8x0.c')
-rw-r--r-- | sound/pci/intel8x0.c | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 29e312597f2..11718b49b2e 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1077,6 +1077,13 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs } if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV)) continue; + + /* IO read operation is very expensive inside virtual machine + * as it is emulated. The probability that subsequent PICB read + * will return different result is high enough to loop till + * timeout here. + * Same CIV is strict enough condition to be sure that PICB + * is valid inside VM on emulated card. */ if (chip->inside_vm) break; if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) @@ -2930,6 +2937,45 @@ static unsigned int sis_codec_bits[3] = { ICH_PCR, ICH_SCR, ICH_SIS_TCR }; +static int __devinit snd_intel8x0_inside_vm(struct pci_dev *pci) +{ + int result = inside_vm; + char *msg = NULL; + + /* check module parameter first (override detection) */ + if (result >= 0) { + msg = result ? "enable (forced) VM" : "disable (forced) VM"; + goto fini; + } + + /* detect KVM and Parallels virtual environments */ + result = kvm_para_available(); +#ifdef X86_FEATURE_HYPERVISOR + result = result || boot_cpu_has(X86_FEATURE_HYPERVISOR); +#endif + if (!result) + goto fini; + + /* check for known (emulated) devices */ + if (pci->subsystem_vendor == 0x1af4 && + pci->subsystem_device == 0x1100) { + /* KVM emulated sound, PCI SSID: 1af4:1100 */ + msg = "enable KVM"; + } else if (pci->subsystem_vendor == 0x1ab8) { + /* Parallels VM emulated sound, PCI SSID: 1ab8:xxxx */ + msg = "enable Parallels VM"; + } else { + msg = "disable (unknown or VT-d) VM"; + result = 0; + } + +fini: + if (msg != NULL) + printk(KERN_INFO "intel8x0: %s optimization\n", msg); + + return result; +} + static int __devinit snd_intel8x0_create(struct snd_card *card, struct pci_dev *pci, unsigned long device_type, @@ -2997,9 +3043,7 @@ 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"); + chip->inside_vm = snd_intel8x0_inside_vm(pci); if (pci->vendor == PCI_VENDOR_ID_INTEL && pci->device == PCI_DEVICE_ID_INTEL_440MX) @@ -3243,14 +3287,6 @@ 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); |