From ab79b0d5e099b0b1b5dff180a17d6f5836b84423 Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Thu, 12 Nov 2015 15:00:39 +0100 Subject: [PATCH] ahci: Reset port before access Also throw error if wakup from power safe mode failes. Fix #1776 --- repos/os/src/drivers/ahci/ahci.cc | 24 +++++++++++++++++++----- repos/os/src/drivers/ahci/ahci.h | 17 ++++++++++++++--- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/repos/os/src/drivers/ahci/ahci.cc b/repos/os/src/drivers/ahci/ahci.cc index 5b6d40a5d..32e2fe5ab 100644 --- a/repos/os/src/drivers/ahci/ahci.cc +++ b/repos/os/src/drivers/ahci/ahci.cc @@ -71,6 +71,11 @@ struct Ahci return sig == ATAPI_SIG_QEMU || sig == ATAPI_SIG; } + bool is_ata(unsigned sig) + { + return sig == ATA_SIG; + } + /** * Forward IRQs to ports */ @@ -121,12 +126,21 @@ struct Ahci continue; Port port(hba, platform_hba, i); - bool enabled = port.enable(); - unsigned sig = port.read(); - PINF("\t\t#%u: %s", i, enabled ? - (is_atapi(sig) ? "ATAPI" : "ATA") : - "off"); + /* check for ATA/ATAPI devices */ + unsigned sig = port.read(); + if (!is_atapi(sig) && !is_ata(sig)) { + PINF("\t\t#%u: off", i); + continue; + } + + port.reset(); + + bool enabled = false; + try { enabled = port.enable(); } + catch (Port::Not_ready) { PERR("Could not enable port %u", i); } + + PINF("\t\t#%u: %s", i, is_atapi(sig) ? "ATAPI" : "ATA"); if (!enabled) continue; diff --git a/repos/os/src/drivers/ahci/ahci.h b/repos/os/src/drivers/ahci/ahci.h index 15b019e79..b63fc0ace 100644 --- a/repos/os/src/drivers/ahci/ahci.h +++ b/repos/os/src/drivers/ahci/ahci.h @@ -16,6 +16,7 @@ #include #include +#include #include static bool constexpr verbose = false; @@ -389,6 +390,9 @@ struct Command_table */ struct Port : Genode::Mmio { + struct Not_ready : Genode::Exception { }; + + Hba &hba; Platform::Hba &platform_hba; unsigned cmd_slots = hba.command_slots(); @@ -639,9 +643,16 @@ struct Port : Genode::Mmio /* try to wake up device */ write(Ssts::Ipm::ACTIVE); - while ((Ssts::Dec::get(status) != Ssts::Dec::ESTABLISHED) || - !(Ssts::Ipm::get(status) & Ssts::Ipm::ACTIVE)) - status = read(); + Genode::retry( + [&] { + if ((Ssts::Dec::get(status) != Ssts::Dec::ESTABLISHED) || + !(Ssts::Ipm::get(status) & Ssts::Ipm::ACTIVE)) + throw Not_ready(); + }, + [&] { + hba.delayer().usleep(1000); + status = read(); + }, 10); } return ((Ssts::Dec::get(status) == Ssts::Dec::ESTABLISHED) &&