summaryrefslogtreecommitdiff
path: root/Kernel/Storage/ATA
diff options
context:
space:
mode:
authorLiav A <liavalb@gmail.com>2021-11-13 14:20:48 +0200
committerAndreas Kling <kling@serenityos.org>2021-11-13 23:35:27 +0100
commit0e5983e6033cad65e86e74489e519c185a4c5116 (patch)
tree869d4f9ba9807878f71eeee24829acdfd8558f3d /Kernel/Storage/ATA
parent557351724addeff2e6b1ffe602ef2c94ffbbcc03 (diff)
downloadserenity-0e5983e6033cad65e86e74489e519c185a4c5116.zip
Kernel/AHCI: Simplify wait and timeout pattern significantly
Instead of repeating ourselves with the pattern of waiting for some condition to be met, we can have a general method for this task, and then we can provide the retry count, the required delay and a lambda function for the checked condition.
Diffstat (limited to 'Kernel/Storage/ATA')
-rw-r--r--Kernel/Storage/ATA/AHCIPort.cpp46
-rw-r--r--Kernel/Storage/ATA/AHCIPort.h2
2 files changed, 26 insertions, 22 deletions
diff --git a/Kernel/Storage/ATA/AHCIPort.cpp b/Kernel/Storage/ATA/AHCIPort.cpp
index eed1a075fe..82baef929a 100644
--- a/Kernel/Storage/ATA/AHCIPort.cpp
+++ b/Kernel/Storage/ATA/AHCIPort.cpp
@@ -405,14 +405,11 @@ void AHCIPort::rebase()
stop_command_list_processing();
stop_fis_receiving();
full_memory_barrier();
- size_t retry = 0;
+
// Try to wait 1 second for HBA to clear Command List Running and FIS Receive Running
- while (retry < 1000) {
- if (!(m_port_registers.cmd & (1 << 15)) && !(m_port_registers.cmd & (1 << 14)))
- break;
- IO::delay(1000);
- retry++;
- }
+ wait_until_condition_met_or_timeout(1000, 1000, [this]() -> bool {
+ return !(m_port_registers.cmd & (1 << 15)) && !(m_port_registers.cmd & (1 << 14));
+ });
full_memory_barrier();
m_port_registers.clbu = 0;
m_port_registers.clb = m_command_list_page->paddr().get();
@@ -690,6 +687,17 @@ bool AHCIPort::identify_device()
return success;
}
+void AHCIPort::wait_until_condition_met_or_timeout(size_t delay_in_microseconds, size_t retries, Function<bool(void)> condition_being_met) const
+{
+ size_t retry = 0;
+ while (retry < retries) {
+ if (condition_being_met())
+ break;
+ IO::delay(delay_in_microseconds);
+ retry++;
+ }
+}
+
bool AHCIPort::shutdown()
{
MutexLocker locker(m_lock);
@@ -786,15 +794,13 @@ bool AHCIPort::initiate_sata_reset()
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Initiate SATA reset", representative_port_index());
stop_command_list_processing();
full_memory_barrier();
- size_t retry = 0;
+
+ // Note: The AHCI specification says to wait now a 500 milliseconds
// Try to wait 1 second for HBA to clear Command List Running
- while (retry < 5000) {
- if (!(m_port_registers.cmd & (1 << 15)))
- break;
- // The AHCI specification says to wait now a 500 milliseconds
- IO::delay(100);
- retry++;
- }
+ wait_until_condition_met_or_timeout(100, 5000, [this]() -> bool {
+ return !(m_port_registers.cmd & (1 << 15));
+ });
+
full_memory_barrier();
spin_up();
full_memory_barrier();
@@ -804,14 +810,10 @@ bool AHCIPort::initiate_sata_reset()
full_memory_barrier();
set_interface_state(AHCI::DeviceDetectionInitialization::NoActionRequested);
full_memory_barrier();
- retry = 0;
- while (retry < 1000) {
- if (is_phy_enabled())
- break;
- IO::delay(10);
- retry++;
- }
+ wait_until_condition_met_or_timeout(10, 1000, [this]() -> bool {
+ return is_phy_enabled();
+ });
dmesgln("AHCI Port {}: {}", representative_port_index(), try_disambiguate_sata_status());
diff --git a/Kernel/Storage/ATA/AHCIPort.h b/Kernel/Storage/ATA/AHCIPort.h
index 78dd5a91e9..5d000cc462 100644
--- a/Kernel/Storage/ATA/AHCIPort.h
+++ b/Kernel/Storage/ATA/AHCIPort.h
@@ -99,6 +99,8 @@ private:
ALWAYS_INLINE bool is_interface_disabled() const { return (m_port_registers.ssts & 0xf) == 4; };
+ ALWAYS_INLINE void wait_until_condition_met_or_timeout(size_t delay_in_microseconds, size_t retries, Function<bool(void)> condition_being_met) const;
+
// Data members
EntropySource m_entropy_source;