class Ufs

Defined at line 179 of file ../../src/devices/block/drivers/ufs/ufs.h

Base class for UFS drivers.

This class is the parent class for both UfsPci and UfsPdev drivers, which bind the UFS

controller via PCI and PDev respectively.

Protected Members

vmo mmio_buffer_vmo_
uint64_t mmio_buffer_size_
interrupt irq_
bti bti_
deque pending_commands_
Dispatcher irq_worker_dispatcher_
Dispatcher io_worker_dispatcher_
Dispatcher admin_worker_dispatcher_
Dispatcher exception_event_dispatcher_
IrqMethod irq_handler_
TaskMethod timeout_task_
unique_ptr device_manager_
unique_ptr transfer_request_processor_
unique_ptr task_management_request_processor_
unique_ptr rpmb_device_
uint32_t logical_unit_count_
unordered_set well_known_lun_set_
function_impl host_controller_callback_
bool shutdown_
uint32_t pending_dispatcher_shutdowns_
optional stop_completer_
uint32_t max_transfer_bytes_
bool qemu_quirk_
bool intel_quirk_
Config config_
InspectProperties properties_
shared_ptr incoming_
optional component_inspector_
optional node_name_
WireSyncClient parent_node_
WireSyncClient root_node_
WireSyncClient node_controller_
event power_element_token_
optional power_element_runner_
bool power_level_on_required_
optional pending_resume_completer_
bool stopping_
TaskMethod resume_retry_task_
duration resume_retry_delay_
atomic hardware_powered_off_
mutex uic_lock_
bool crypto_supported_
WireSyncClient inline_encryption_client_
array crypto_slot_data_unit_size_

Public Methods

void ProcessIoSubmissions ()

Convert block operations to UPIU commands and submit them asynchronously.

Defined at line 143 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<> NotifyEventCallback (NotifyEvent event, uint64_t data)

Defines a callback function to perform when an |event| occurs.

Defined at line 38 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<> Notify (NotifyEvent event, uint64_t data)

The controller notifies the host controller when it takes the action defined in |event|.

Defined at line 61 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx_status_t WaitWithTimeout (fit::function<bool ()> wait_for, zx::duration timeout, const fbl::String & timeout_message, zx::duration granularity)

Defined at line 68 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<uint16_t> TranslateUfsLunToScsiLun (uint8_t ufs_lun)

Defined at line 112 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<uint8_t> TranslateScsiLunToUfsLun (uint16_t scsi_lun)

Defined at line 126 of file ../../src/devices/block/drivers/ufs/ufs.cc

bool SuspendEnabled ()

Defined at line 202 of file ../../src/devices/block/drivers/ufs/ufs.h

std::optional<fidl::ServerEnd<fuchsia_power_broker::ElementRunner>> take_power_element_runner ()

Defined at line 205 of file ../../src/devices/block/drivers/ufs/ufs.h

fidl::WireSyncClient<fuchsia_driver_framework::Node> & root_node ()

scsi::Controller

Defined at line 210 of file ../../src/devices/block/drivers/ufs/ufs.h

std::string_view driver_name ()

Defined at line 211 of file ../../src/devices/block/drivers/ufs/ufs.h

const std::shared_ptr<fdf::Namespace> & driver_incoming ()

Defined at line 212 of file ../../src/devices/block/drivers/ufs/ufs.h

std::shared_ptr<fdf::OutgoingDirectory> & driver_outgoing ()

Defined at line 213 of file ../../src/devices/block/drivers/ufs/ufs.h

async_dispatcher_t * driver_async_dispatcher ()

Defined at line 214 of file ../../src/devices/block/drivers/ufs/ufs.h

const std::optional<std::string> & driver_node_name ()

Defined at line 215 of file ../../src/devices/block/drivers/ufs/ufs.h

fdf::Logger & driver_logger ()

Defined at line 216 of file ../../src/devices/block/drivers/ufs/ufs.h

const ufs_config::Config & config ()

Defined at line 217 of file ../../src/devices/block/drivers/ufs/ufs.h

bool SupportsInlineEncryption ()

Defined at line 223 of file ../../src/devices/block/drivers/ufs/ufs.h

const fdf::MmioBuffer & GetMmio ()

Defined at line 228 of file ../../src/devices/block/drivers/ufs/ufs.h

DeviceManager & GetDeviceManager ()

Defined at line 233 of file ../../src/devices/block/drivers/ufs/ufs.h

TransferRequestProcessor & GetTransferRequestProcessor ()

Defined at line 237 of file ../../src/devices/block/drivers/ufs/ufs.h

TaskManagementRequestProcessor & GetTaskManagementRequestProcessor ()

Defined at line 241 of file ../../src/devices/block/drivers/ufs/ufs.h

void SetHostControllerCallback (HostControllerCallback callback)

Used to register a platform-specific NotifyEventCallback, which handles variants and quirks for

each host interface platform.

Defined at line 257 of file ../../src/devices/block/drivers/ufs/ufs.h

fdf::Dispatcher & exception_event_dispatcher ()

Defined at line 273 of file ../../src/devices/block/drivers/ufs/ufs.h

fdf::UnownedDispatcher io_worker_dispatcher ()

Defined at line 275 of file ../../src/devices/block/drivers/ufs/ufs.h

fdf::UnownedDispatcher admin_worker_dispatcher ()

Defined at line 276 of file ../../src/devices/block/drivers/ufs/ufs.h

uint32_t GetLogicalUnitCount ()

for test

Defined at line 281 of file ../../src/devices/block/drivers/ufs/ufs.h

size_t GetPendingCommandsCount ()

Defined at line 282 of file ../../src/devices/block/drivers/ufs/ufs.h

bool HasWellKnownLun (WellKnownLuns lun)

Defined at line 289 of file ../../src/devices/block/drivers/ufs/ufs.h

bool intel_quirk ()

Host-controller quirks detected from the PCI vendor/device ID (see UfsPci::InitQuirk()).

Intel (Lakefield) UFSHCI: uses a 19.2 MHz reference clock instead of 38.4 MHz, needs the

peer's PA_TActivate raised by 200 us, and needs a 1250 us settle followed by a DME_PEER_GET to

clear a spurious DME error after a UIC power mode change.

Defined at line 298 of file ../../src/devices/block/drivers/ufs/ufs.h

bool qemu_quirk ()

QEMU's UFS host controller model does not implement UniPro attributes, UIC power mode

changes or Auto-Hibernate, so those steps are skipped and the link is assumed Active.

Defined at line 301 of file ../../src/devices/block/drivers/ufs/ufs.h

bool SupportsPowerDownSuspend ()

Defined at line 303 of file ../../src/devices/block/drivers/ufs/ufs.h

bool IsHardwarePoweredOff ()

Defined at line 326 of file ../../src/devices/block/drivers/ufs/ufs.h

std::mutex & uic_lock ()

Serialises register accesses that happen outside the I/O worker / ISR paths (UIC commands,

whether issued by this driver, by the PHY driver through fuchsia.hardware.ufs.phy/Ufshci, or

through fuchsia.hardware.ufs, and inline-crypto key-slot programming) against

StopHostControllerForPowerDown(). Must be acquired after DeviceManager::power_lock_ when both

are held, and must never be held across a Notify() callback into the PHY driver (its

Ufshci::DmeSet/DmeGet calls take this lock).

Defined at line 344 of file ../../src/devices/block/drivers/ufs/ufs.h

bool IsResumed ()

Defined at line 348 of file ../../src/devices/block/drivers/ufs/ufs.h

const inspect::Inspector & inspect ()

Defined at line 350 of file ../../src/devices/block/drivers/ufs/ufs.h

void Ufs ()

Defined at line 713 of file ../../src/devices/block/drivers/ufs/ufs.cc

void ~Ufs ()

Defined at line 1950 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<> Start (fdf::DriverContext context)

Defined at line 1640 of file ../../src/devices/block/drivers/ufs/ufs.cc

void Stop (fdf::StopCompleter completer)

Defined at line 1889 of file ../../src/devices/block/drivers/ufs/ufs.cc

void Suspend (fdf_power::SuspendCompleter completer)

fdf_power::Suspendable. Suspend()/Resume() are driven by Power Broker through the

framework-provided ElementRunner (level "off" -> Suspend, "on" -> Resume). The mixin

acknowledges the first "off" before any "on" on its own (first_activation_occurred_), so the

hardware initialized by Init() is not powered down just because the element is created without

a lease; Power Broker raises us to "on" as soon as the Execution State dependency is

registered.

Defined at line 1572 of file ../../src/devices/block/drivers/ufs/ufs.cc

void Resume (fdf_power::ResumeCompleter completer)

Power Broker treats a closed ElementRunner channel as "this element can never transition

again": it logs the error and stops driving the element, so storage would stay unusable until

reboot. A failed transition is therefore never answered by dropping the completer.

A failed "off" is logged and acknowledged: SuspendPower() has already rolled the device back or

recorded PowerDown, and the element genuinely no longer needs its dependencies. A failed "on" is

different: the completer is the signal that the level was reached, and Execution State depends

on it (ConfigurePowerManagement()), so acknowledging it early would let the rest of the system

come up and then stall on page faults against a device that is still down. Instead the completer

is held (pending_resume_completer_) while the driver keeps retrying ResumePower() in the

background (RetryResume()); Power Broker's watchdog reports the stuck element every 10 s, which

points at the real culprit. Power Broker does not send another SetLevel() while one is pending,

so the retry loop is the only path back to "on". DeviceManager keeps the truthful hardware state,

so every retry continues from where the failed attempt left off (see the comments in

SuspendPower()/ResumePower()).

The very first "off" that Power Broker issues when the element is created without a lease is

swallowed by fdf_power::Suspendable (first_activation_occurred_) and never reaches Suspend(), so

the hardware initialized by Init() stays active until the first "on" has been observed.

Defined at line 1542 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx_status_t ExecuteCommandSync (uint8_t target, uint16_t lun, iovec cdb, bool is_write, iovec data)

Defined at line 575 of file ../../src/devices/block/drivers/ufs/ufs.cc

void ExecuteCommandsAsync (uint8_t target, uint16_t lun, std::span<scsi::ScsiRequest> batch)

Defined at line 528 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<uint8_t> ProgramKeySlot (fidl::VectorView<uint8_t> wrapped_key, uint32_t data_unit_size)

Defined at line 1713 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<std::vector<uint8_t>> DeriveRawSecret (fidl::VectorView<uint8_t> wrapped_key)

Defined at line 1814 of file ../../src/devices/block/drivers/ufs/ufs.cc

void ProcessAdminCompletions ()

Find the completed Admin commands in the Request List and handle their completion.

Defined at line 290 of file ../../src/devices/block/drivers/ufs/ufs.cc

void ProcessIoCompletions ()

Find the completed IO commands in the Request List and handle their completion.

Defined at line 294 of file ../../src/devices/block/drivers/ufs/ufs.cc

void ProcessErrors ()

Recover errors in the request list.

Defined at line 296 of file ../../src/devices/block/drivers/ufs/ufs.cc

void DumpRegisters ()

Defined at line 1393 of file ../../src/devices/block/drivers/ufs/ufs.cc

bool HasProgrammedCryptoKeys ()

Returns true if any inline encryption key slot has been programmed. Key slot state (UFSHCI

CRYPTOCFG and, on platforms where the key table lives inside the host controller power domain,

the key material itself) does not survive a PowerDown suspend.

Defined at line 1775 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<> ReinitAfterPowerDown ()

Host-controller side of the power sequence, driven by DeviceManager::SuspendPower() /

ResumePower() (the device/link side lives in DeviceManager).

Defined at line 1119 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<> ClearUnitAttentions ()

After the device has been power-cycled (PowerDown suspend), every LU and well-known LU

reports a UNIT ATTENTION (POWER ON / RESET) on its first SCSI command. Clear them with

TEST UNIT READY so that the START STOP UNIT issued by ResumePower() and the first I/O to each

LU do not fail with ZX_ERR_UNAVAILABLE.

Defined at line 1217 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<> ConfigureAutoHibernate ()

Defined at line 1084 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<> DisableAutoHibernate ()

Defined at line 1107 of file ../../src/devices/block/drivers/ufs/ufs.cc

void SetHardwarePoweredOff (bool powered_off)

Marks the UFSHCI register space as inaccessible (power domains/clocks gated). While set, the

interrupt handler and I/O paths must not touch controller registers. Setting it also waits for

any in-progress interrupt handling to finish.

Defined at line 476 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx_status_t StopHostControllerForPowerDown ()

Masks interrupts, disables the host controller and marks the register space as powered off,

ahead of the PHY driver gating the UFSHCI power domains/clocks. Requires that no I/O slot is

allocated (RequestProcessor::BlockSlotAllocation() has run). Holds uic_lock() so that a UIC

command or key-slot write that has already passed its IsHardwarePoweredOff() check finishes

before the controller is stopped. Returns the status of the host controller disable; the

register space is marked powered off regardless.

Defined at line 504 of file ../../src/devices/block/drivers/ufs/ufs.cc

void TriggerIoWork ()

Defined at line 433 of file ../../src/devices/block/drivers/ufs/ufs.cc

Protected Methods

zx::result<fdf::MmioBuffer> CreateMmioBuffer (zx_off_t offset, size_t size, zx::vmo vmo)

Defined at line 357 of file ../../src/devices/block/drivers/ufs/ufs.h

zx_status_t Init ()

Initialize the UFS controller and bind the logical units.

Declare this as virtual to delay driver initialization in tests.

Defined at line 715 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<> ConfigureCryptoSlot (uint8_t slot, uint32_t data_unit_size)

Writes the UFSHCI CRYPTOCFG entry for |slot| and records the slot as programmed with

|data_unit_size|. Called by ProgramKeySlot() after the inline encryption provider has loaded

the key material into the hardware slot. Fails with ZX_ERR_BAD_STATE while the host

controller is powered down, in which case the slot is not recorded.

Defined at line 1745 of file ../../src/devices/block/drivers/ufs/ufs.cc

void OnDispatcherShutdown ()

Defined at line 1829 of file ../../src/devices/block/drivers/ufs/ufs.cc

void FinishStop (fdf::StopCompleter completer)

Defined at line 1844 of file ../../src/devices/block/drivers/ufs/ufs.cc

void RetryResume (async_dispatcher_t * dispatcher, async::TaskBase * task, zx_status_t status)

Runs on the default dispatcher, like Suspend()/Resume(), so they never overlap: Suspend() cancels

a pending retry and clears power_level_on_required_.

Defined at line 1617 of file ../../src/devices/block/drivers/ufs/ufs.cc

void ScheduleResumeRetry ()

Defined at line 1601 of file ../../src/devices/block/drivers/ufs/ufs.cc

void CompletePendingResume ()

Defined at line 1608 of file ../../src/devices/block/drivers/ufs/ufs.cc

Friends

class RequestProcessor
class UfsTest