From 5277958078b864401a8ca1e28e8bab3f7222322d Mon Sep 17 00:00:00 2001 From: paulhsia Date: Wed, 20 Nov 2019 17:47:12 +0800 Subject: [PATCH] ac97: bus_master: Sync SR_CELV with civ == lvi From ac97 spec, SR_CELV should be synced with civ == lvi in bus_master. intel8x0 is not using the bit but some other driver or system might be using it. Remove checking if new_sr equals to old_sr since update_sr will do nothing if the input value equals to the old sr value. Add unit tests steps to test the expected results. BUG=chromium:1026538 TEST=Unit tests Change-Id: I3dc9f42e2beed8e635a65dbefba44677c73fcc5b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1925917 Tested-by: Chih-Yang Hsia Tested-by: kokoro Commit-Queue: Dylan Reid Reviewed-by: Dylan Reid --- devices/src/pci/ac97_bus_master.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/devices/src/pci/ac97_bus_master.rs b/devices/src/pci/ac97_bus_master.rs index a3ad9af8ad..a0a6344e80 100644 --- a/devices/src/pci/ac97_bus_master.rs +++ b/devices/src/pci/ac97_bus_master.rs @@ -416,7 +416,7 @@ impl Ac97BusMaster { && func_regs.sr & SR_DCH == SR_DCH && func_regs.civ != func_regs.lvi { - func_regs.sr &= !SR_DCH; + func_regs.sr &= !(SR_DCH | SR_CELV); } } @@ -664,8 +664,7 @@ fn buffer_completed( .read_obj_from_addr(GuestAddress(u64::from(descriptor_addr) + 4)) .map_err(GuestMemoryError::ReadingGuestBufferAddress)?; - let mut new_sr = regs.func_regs(func).sr; - + let mut new_sr = regs.func_regs(func).sr & !SR_CELV; if control_reg & BD_IOC != 0 { new_sr |= SR_BCIS; } @@ -681,9 +680,7 @@ fn buffer_completed( func_regs.piv = (func_regs.piv + 1) % 32; // move piv to the next buffer. } - if new_sr != regs.func_regs(func).sr { - update_sr(regs, func, new_sr); - } + update_sr(regs, func, new_sr); if func == Ac97Function::Output { regs.po_pointer_update_time = Instant::now(); @@ -941,6 +938,7 @@ mod test { std::thread::sleep(time::Duration::from_millis(500)); assert!(bm.readw(PO_SR_16) & SR_LVBCI != 0); // Hit last buffer assert!(bm.readw(PO_SR_16) & SR_DCH == SR_DCH); // DMA stopped because of lack of buffers. + assert_eq!(bm.readw(PO_SR_16) & SR_CELV, SR_CELV); assert_eq!(bm.readb(PO_LVI_15), bm.readb(PO_CIV_14)); assert!( bm.readl(GLOB_STA_30) & GS_POINT != 0, @@ -952,6 +950,7 @@ mod test { // Reset the LVI to the last buffer and check that playback resumes bm.writeb(PO_LVI_15, LVI_MASK, &mixer); assert!(bm.readw(PO_SR_16) & SR_DCH == 0); // DMA restarts. + assert_eq!(bm.readw(PO_SR_16) & SR_CELV, 0); let (restart_civ, restart_picb) = (bm.readb(PO_CIV_14), bm.readw(PO_PICB_18)); std::thread::sleep(time::Duration::from_millis(20)); @@ -1022,6 +1021,7 @@ mod test { std::thread::sleep(time::Duration::from_millis(5000)); assert_ne!(bm.readw(PI_SR_06) & SR_LVBCI, 0); // Hit last buffer assert_eq!(bm.readw(PI_SR_06) & SR_DCH, SR_DCH); // DMA stopped because of lack of buffers. + assert_eq!(bm.readw(PI_SR_06) & SR_CELV, SR_CELV); assert_eq!(bm.readb(PI_LVI_05), bm.readb(PI_CIV_04)); assert!( bm.readl(GLOB_STA_30) & GS_PIINT != 0, @@ -1034,6 +1034,7 @@ mod test { // Reset the LVI to the last buffer and check that playback resumes bm.writeb(PI_LVI_05, LVI_MASK, &mixer); assert!(bm.readw(PI_SR_06) & SR_DCH == 0); // DMA restarts. + assert_eq!(bm.readw(PI_SR_06) & SR_CELV, 0); let restart_civ = bm.readb(PI_CIV_04); std::thread::sleep(time::Duration::from_millis(200));