From 5e1b5c329bc6b41be950cf7f78cae3f96366d05a Mon Sep 17 00:00:00 2001 From: Bananymous Date: Fri, 15 May 2026 21:30:41 +0300 Subject: [PATCH] Kernel: Allow HDA stream reset to timeout This was hanging on some version of qemu :^) --- .../kernel/Audio/HDAudio/AudioFunctionGroup.h | 2 +- .../Audio/HDAudio/AudioFunctionGroup.cpp | 23 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/kernel/include/kernel/Audio/HDAudio/AudioFunctionGroup.h b/kernel/include/kernel/Audio/HDAudio/AudioFunctionGroup.h index 2640745c..57a4da32 100644 --- a/kernel/include/kernel/Audio/HDAudio/AudioFunctionGroup.h +++ b/kernel/include/kernel/Audio/HDAudio/AudioFunctionGroup.h @@ -43,7 +43,7 @@ namespace Kernel BAN::ErrorOr enable_output_path(uint8_t index); BAN::ErrorOr disable_output_path(uint8_t index); - void reset_stream(); + BAN::ErrorOr reset_stream(); BAN::ErrorOr recurse_output_paths(const HDAudio::AFGWidget& widget, BAN::Vector& path); diff --git a/kernel/kernel/Audio/HDAudio/AudioFunctionGroup.cpp b/kernel/kernel/Audio/HDAudio/AudioFunctionGroup.cpp index c30e50de..3617ce2c 100644 --- a/kernel/kernel/Audio/HDAudio/AudioFunctionGroup.cpp +++ b/kernel/kernel/Audio/HDAudio/AudioFunctionGroup.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -202,12 +203,12 @@ namespace Kernel ASSERT(m_stream_index == 0xFF); m_stream_index = TRY(m_controller->allocate_stream(HDAudio::StreamType::Output, this)); - reset_stream(); + TRY(reset_stream()); return {}; } - void HDAudioFunctionGroup::reset_stream() + BAN::ErrorOr HDAudioFunctionGroup::reset_stream() { using Regs = HDAudio::Regs; @@ -219,13 +220,23 @@ namespace Kernel // stop stream bar.write8(base + Regs::SDCTL, bar.read8(base + Regs::SDCTL) & 0xFD); + const auto timeout_ms = SystemTimer::get().ms_since_boot() + 100; + // reset stream bar.write8(base + Regs::SDCTL, (bar.read8(base + Regs::SDCTL) & 0xFE) | 1); while (!(bar.read8(base + Regs::SDCTL) & 1)) + { + if (SystemTimer::get().ms_since_boot() > timeout_ms) + return BAN::Error::from_errno(ETIMEDOUT); Processor::pause(); + } bar.write8(base + Regs::SDCTL, (bar.read8(base + Regs::SDCTL) & 0xFE)); while ((bar.read8(base + Regs::SDCTL) & 1)) + { + if (SystemTimer::get().ms_since_boot() > timeout_ms) + return BAN::Error::from_errno(ETIMEDOUT); Processor::pause(); + } // set bdl address, total size and lvi const paddr_t bdl_paddr = m_bdl_region->paddr() + bdl_offset(); @@ -621,7 +632,13 @@ namespace Kernel m_bdl_tail = (m_bdl_tail + 1) % m_bdl_entry_count; if (m_bdl_tail == m_bdl_head) - reset_stream(); + { + if (auto ret = reset_stream(); ret.is_error()) + { + dwarnln("failed to reset HDA stream: {}", ret.error()); + return; + } + } queue_bdl_data(); }