Skip to content
Snippets Groups Projects
Commit be5a8cf3 authored by Philippe Mathieu-Daudé's avatar Philippe Mathieu-Daudé Committed by Thomas Huth
Browse files

hw/audio/intel-hda: Do not ignore DMA overrun errors


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: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20211218160912.1591633-2-philmd@redhat.com>
Signed-off-by: default avatarThomas Huth <thuth@redhat.com>
parent 3ab6fdc9
No related branches found
No related tags found
No related merge requests found
......@@ -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",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment