71 lines
2.8 KiB
Diff
71 lines
2.8 KiB
Diff
From 2defe49a69b324499953c9b8c55f18e22ca74631 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
|
|
Date: Sat, 18 Dec 2021 17:09:10 +0100
|
|
Subject: [PATCH 23/25] hw/audio/intel-hda: Do not ignore DMA overrun errors
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Per the "High Definition Audio Specification" manual (rev. 1.0a),
|
|
section "3.3.30 Offset 5Dh: RIRBSTS - RIRB Status":
|
|
|
|
Response Overrun Interrupt Status (RIRBOIS):
|
|
|
|
Hardware sets this bit to a 1 when an overrun occurs in the RIRB.
|
|
An interrupt may be generated if the Response Overrun Interrupt
|
|
Control bit is set.
|
|
|
|
This bit will be set if the RIRB DMA engine is not able to write
|
|
the incoming responses to memory before additional incoming
|
|
responses overrun the internal FIFO.
|
|
|
|
When hardware detects an overrun, it will drop the responses which
|
|
overrun the buffer and set the RIRBOIS status bit to indicate the
|
|
error condition. Optionally, if the RIRBOIC is set, the hardware
|
|
will also generate an error to alert software to the problem.
|
|
|
|
QEMU emulates the DMA engine with the stl_le_pci_dma() calls. This
|
|
function returns a MemTxResult indicating whether the DMA access
|
|
was successful.
|
|
Handle any MemTxResult error as "DMA engine is not able to write the
|
|
incoming responses to memory" and raise the Overrun Interrupt flag
|
|
when this case occurs.
|
|
|
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
Message-Id: <20211218160912.1591633-2-philmd@redhat.com>
|
|
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
|
---
|
|
hw/audio/intel-hda.c | 9 +++++++--
|
|
1 file changed, 7 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
|
|
index 2b55d52150..0c1017edbb 100644
|
|
--- a/hw/audio/intel-hda.c
|
|
+++ b/hw/audio/intel-hda.c
|
|
@@ -350,6 +350,7 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res
|
|
IntelHDAState *d = container_of(bus, IntelHDAState, codecs);
|
|
hwaddr addr;
|
|
uint32_t wp, ex;
|
|
+ MemTxResult res = MEMTX_OK;
|
|
|
|
if (d->ics & ICH6_IRS_BUSY) {
|
|
dprint(d, 2, "%s: [irr] response 0x%x, cad 0x%x\n",
|
|
@@ -368,8 +369,12 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res
|
|
ex = (solicited ? 0 : (1 << 4)) | dev->cad;
|
|
wp = (d->rirb_wp + 1) & 0xff;
|
|
addr = intel_hda_addr(d->rirb_lbase, d->rirb_ubase);
|
|
- stl_le_pci_dma(&d->pci, addr + 8 * wp, response, attrs);
|
|
- stl_le_pci_dma(&d->pci, addr + 8 * wp + 4, ex, attrs);
|
|
+ res |= stl_le_pci_dma(&d->pci, addr + 8 * wp, response, attrs);
|
|
+ res |= stl_le_pci_dma(&d->pci, addr + 8 * wp + 4, ex, attrs);
|
|
+ if (res != MEMTX_OK && (d->rirb_ctl & ICH6_RBCTL_OVERRUN_EN)) {
|
|
+ d->rirb_sts |= ICH6_RBSTS_OVERRUN;
|
|
+ intel_hda_update_irq(d);
|
|
+ }
|
|
d->rirb_wp = wp;
|
|
|
|
dprint(d, 2, "%s: [wp 0x%x] response 0x%x, extra 0x%x\n",
|
|
--
|
|
2.27.0
|
|
|