From 0b6f02fea7716ec5752555ea44aafed214b58faa Mon Sep 17 00:00:00 2001 From: paulhsia Date: Fri, 4 Oct 2019 20:02:49 +0800 Subject: device: ac97: Cleanup interrupt logic - Send only one event while re-sampling. - Don't sent event if the new sr is identical to the old one This can reduce the rate to trigger the issue. BUG=chromium:937977 TEST=Build and run lots of aplay and arecord in guest vm Change-Id: Ibd21f363076c977ae256079e2615094b7ed2408b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1840752 Tested-by: Chih-Yang Hsia Tested-by: kokoro Reviewed-by: Daniel Verkamp Reviewed-by: Dylan Reid Commit-Queue: Chih-Yang Hsia --- devices/src/pci/ac97_bus_master.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/devices/src/pci/ac97_bus_master.rs b/devices/src/pci/ac97_bus_master.rs index 12a4f74..83c0021 100644 --- a/devices/src/pci/ac97_bus_master.rs +++ b/devices/src/pci/ac97_bus_master.rs @@ -235,19 +235,12 @@ impl Ac97BusMaster { { // Scope for the lock on thread_regs. let regs = thread_regs.lock(); - // Check output irq + // Check output and input irq let po_int_mask = regs.func_regs(Ac97Function::Output).int_mask(); - if regs.func_regs(Ac97Function::Output).sr & po_int_mask != 0 { - if let Some(irq_evt) = regs.irq_evt.as_ref() { - if let Err(e) = irq_evt.write(1) { - error!("Failed to set the irq from the resample thread: {}.", e); - break; - } - } - } - // Check input irq let pi_int_mask = regs.func_regs(Ac97Function::Input).int_mask(); - if regs.func_regs(Ac97Function::Input).sr & pi_int_mask != 0 { + if regs.func_regs(Ac97Function::Output).sr & po_int_mask != 0 + || regs.func_regs(Ac97Function::Input).sr & pi_int_mask != 0 + { if let Some(irq_evt) = regs.irq_evt.as_ref() { if let Err(e) = irq_evt.write(1) { error!("Failed to set the irq from the resample thread: {}.", e); @@ -753,14 +746,17 @@ fn update_sr(regs: &mut Ac97BusMasterRegs, func: Ac97Function, val: u16) { { let func_regs = regs.func_regs_mut(func); + let old_sr = func_regs.sr; func_regs.sr = val; - if val & SR_INT_MASK != 0 { + if (old_sr ^ val) & SR_INT_MASK != 0 { if (val & SR_LVBCI) != 0 && (func_regs.cr & CR_LVBIE) != 0 { interrupt_high = true; } if (val & SR_BCIS) != 0 && (func_regs.cr & CR_IOCE) != 0 { interrupt_high = true; } + } else { + return; } } -- cgit 1.4.1