summary refs log tree commit diff
diff options
context:
space:
mode:
authorpaulhsia <paulhsia@chromium.org>2019-11-20 17:47:12 +0800
committerCommit Bot <commit-bot@chromium.org>2019-11-21 23:45:13 +0000
commit5277958078b864401a8ca1e28e8bab3f7222322d (patch)
treeffa3fe0f40d1e714e5128e05be29d0fbf2c11690
parentc61d4d05ec7517749ac3becac6767ed75ba688a5 (diff)
downloadcrosvm-5277958078b864401a8ca1e28e8bab3f7222322d.tar
crosvm-5277958078b864401a8ca1e28e8bab3f7222322d.tar.gz
crosvm-5277958078b864401a8ca1e28e8bab3f7222322d.tar.bz2
crosvm-5277958078b864401a8ca1e28e8bab3f7222322d.tar.lz
crosvm-5277958078b864401a8ca1e28e8bab3f7222322d.tar.xz
crosvm-5277958078b864401a8ca1e28e8bab3f7222322d.tar.zst
crosvm-5277958078b864401a8ca1e28e8bab3f7222322d.zip
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 <paulhsia@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Dylan Reid <dgreid@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
-rw-r--r--devices/src/pci/ac97_bus_master.rs13
1 files changed, 7 insertions, 6 deletions
diff --git a/devices/src/pci/ac97_bus_master.rs b/devices/src/pci/ac97_bus_master.rs
index a3ad9af..a0a6344 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));