mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +00:00
Kernel: Don't reset AHCI ports during boot unless requested
Instead of blindly resetting every AHCI port, let's just reset only the controller by default. The user can still request to reset everything with a new kernel boot argument called ahci_reset_mode which is set by default to "controller", so the code will only invoke an HBA reset. This kernel boot argument can be set to 3 different values: 1. "controller" - reset the HBA and skip resetting AHCI ports 2. "none" - don't reset anything, so we rely on the firmware to initialize the AHCI HBA and ports for us. 3. "complete" - reset the AHCI HBA and ports.
This commit is contained in:
parent
a93dc8c8c9
commit
793d315994
Notes:
sideshowbarker
2024-07-18 21:26:58 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/793d3159948 Pull-request: https://github.com/SerenityOS/serenity/pull/5734
6 changed files with 58 additions and 5 deletions
|
@ -148,6 +148,19 @@ UNMAP_AFTER_INIT HPETMode CommandLine::hpet_mode() const
|
|||
PANIC("Unknown HPETMode: {}", hpet_mode);
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT AHCIResetMode CommandLine::ahci_reset_mode() const
|
||||
{
|
||||
const auto ahci_reset_mode = lookup("ahci_reset_mode").value_or("controller");
|
||||
if (ahci_reset_mode == "controller") {
|
||||
return AHCIResetMode::ControllerOnly;
|
||||
} else if (ahci_reset_mode == "none") {
|
||||
return AHCIResetMode::None;
|
||||
} else if (ahci_reset_mode == "complete") {
|
||||
return AHCIResetMode::Complete;
|
||||
}
|
||||
PANIC("Unknown AHCIResetMode: {}", ahci_reset_mode);
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT BootMode CommandLine::boot_mode() const
|
||||
{
|
||||
const auto boot_mode = lookup("boot_mode").value_or("graphical");
|
||||
|
|
|
@ -50,6 +50,12 @@ enum class AcpiFeatureLevel {
|
|||
Disabled,
|
||||
};
|
||||
|
||||
enum class AHCIResetMode {
|
||||
ControllerOnly,
|
||||
Complete,
|
||||
None
|
||||
};
|
||||
|
||||
class CommandLine {
|
||||
AK_MAKE_ETERNAL;
|
||||
|
||||
|
@ -72,6 +78,7 @@ public:
|
|||
[[nodiscard]] AcpiFeatureLevel acpi_feature_level() const;
|
||||
[[nodiscard]] BootMode boot_mode() const;
|
||||
[[nodiscard]] HPETMode hpet_mode() const;
|
||||
[[nodiscard]] AHCIResetMode ahci_reset_mode() const;
|
||||
[[nodiscard]] String userspace_init() const;
|
||||
[[nodiscard]] Vector<String> userspace_init_args() const;
|
||||
[[nodiscard]] String root_device() const;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <AK/OwnPtr.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/CommandLine.h>
|
||||
#include <Kernel/Storage/AHCIController.h>
|
||||
#include <Kernel/Storage/SATADiskDevice.h>
|
||||
#include <Kernel/VM/MemoryManager.h>
|
||||
|
@ -144,11 +145,13 @@ AHCIController::~AHCIController()
|
|||
|
||||
void AHCIController::initialize()
|
||||
{
|
||||
if (!reset()) {
|
||||
dmesgln("{}: AHCI controller reset failed", pci_address());
|
||||
return;
|
||||
if (kernel_command_line().ahci_reset_mode() != AHCIResetMode::None) {
|
||||
if (!reset()) {
|
||||
dmesgln("{}: AHCI controller reset failed", pci_address());
|
||||
return;
|
||||
}
|
||||
dmesgln("{}: AHCI controller reset", pci_address());
|
||||
}
|
||||
dmesgln("{}: AHCI controller reset", pci_address());
|
||||
dbgln("{}: AHCI command list entries count - {}", pci_address(), hba_capabilities().max_command_list_entries_count);
|
||||
hba().control_regs.ghc = 0x80000000; // Ensure that HBA knows we are AHCI aware.
|
||||
PCI::enable_interrupt_line(pci_address());
|
||||
|
|
|
@ -210,6 +210,22 @@ bool AHCIPort::reset()
|
|||
if (!initiate_sata_reset()) {
|
||||
return false;
|
||||
}
|
||||
return initialize();
|
||||
}
|
||||
|
||||
bool AHCIPort::initialize_without_reset()
|
||||
{
|
||||
ScopedSpinLock lock(m_lock);
|
||||
dmesgln("AHCI Port {}: {}", representative_port_index(), try_disambiguate_sata_status());
|
||||
return initialize();
|
||||
}
|
||||
|
||||
bool AHCIPort::initialize()
|
||||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: SIG {:x}", representative_port_index(), static_cast<u32>(m_port_registers.sig));
|
||||
if (!is_phy_enabled())
|
||||
return false;
|
||||
rebase();
|
||||
power_on();
|
||||
spin_up();
|
||||
|
|
|
@ -78,9 +78,13 @@ public:
|
|||
RefPtr<StorageDevice> connected_device() const { return m_connected_device; }
|
||||
|
||||
bool reset();
|
||||
UNMAP_AFTER_INIT bool initialize_without_reset();
|
||||
void handle_interrupt();
|
||||
|
||||
private:
|
||||
bool is_phy_enabled() const { return (m_port_registers.ssts & 0xf) == 3; }
|
||||
bool initialize();
|
||||
|
||||
UNMAP_AFTER_INIT AHCIPort(const AHCIPortHandler&, volatile AHCI::PortRegisters&, u32 port_index);
|
||||
|
||||
ALWAYS_INLINE void clear_sata_error_register() const;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <Kernel/CommandLine.h>
|
||||
#include <Kernel/Storage/AHCIPortHandler.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
@ -46,10 +47,19 @@ AHCIPortHandler::AHCIPortHandler(AHCIController& controller, u8 irq, AHCI::Maske
|
|||
// Clear pending interrupts, if there are any!
|
||||
m_pending_ports_interrupts.set_all();
|
||||
enable_irq();
|
||||
|
||||
if (kernel_command_line().ahci_reset_mode() == AHCIResetMode::Complete) {
|
||||
for (auto index : taken_ports.to_vector()) {
|
||||
auto port = AHCIPort::create(*this, static_cast<volatile AHCI::PortRegisters&>(controller.hba().port_regs[index]), index);
|
||||
m_handled_ports.set(index, port);
|
||||
port->reset();
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (auto index : taken_ports.to_vector()) {
|
||||
auto port = AHCIPort::create(*this, static_cast<volatile AHCI::PortRegisters&>(controller.hba().port_regs[index]), index);
|
||||
m_handled_ports.set(index, port);
|
||||
port->reset();
|
||||
port->initialize_without_reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue