class Ufs

Defined at line 174 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_

Public Methods

void ProcessIoSubmissions ()

Convert block operations to UPIU commands and submit them asynchronously.

Defined at line 128 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 60 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 67 of file ../../src/devices/block/drivers/ufs/ufs.cc

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

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

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

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

bool SuspendEnabled ()

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

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

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

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

scsi::Controller

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

std::string_view driver_name ()

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

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

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

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

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

async_dispatcher_t * driver_async_dispatcher ()

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

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

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

fdf::Logger & driver_logger ()

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

const ufs_config::Config & config ()

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

bool SupportsInlineEncryption ()

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

const fdf::MmioBuffer & GetMmio ()

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

DeviceManager & GetDeviceManager ()

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

TransferRequestProcessor & GetTransferRequestProcessor ()

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

TaskManagementRequestProcessor & GetTaskManagementRequestProcessor ()

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

fdf::Dispatcher & exception_event_dispatcher ()

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

fdf::UnownedDispatcher io_worker_dispatcher ()

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

fdf::UnownedDispatcher admin_worker_dispatcher ()

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

uint32_t GetLogicalUnitCount ()

for test

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

size_t GetPendingCommandsCount ()

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

bool HasWellKnownLun (WellKnownLuns lun)

Defined at line 284 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 293 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 296 of file ../../src/devices/block/drivers/ufs/ufs.h

bool SupportsPowerDownSuspend ()

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

bool IsHardwarePoweredOff ()

Defined at line 316 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 334 of file ../../src/devices/block/drivers/ufs/ufs.h

bool IsResumed ()

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

const inspect::Inspector & inspect ()

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

void Ufs ()

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

void ~Ufs ()

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

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

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

void Stop (fdf::StopCompleter completer)

Defined at line 1804 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 1535 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 1505 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 545 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 498 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 1676 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 1729 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 260 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 264 of file ../../src/devices/block/drivers/ufs/ufs.cc

void ProcessErrors ()

Recover errors in the request list.

Defined at line 266 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 37 of file ../../src/devices/block/drivers/ufs/ufs.cc

void SetHostControllerCallback (HostControllerCallback callback)

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

each host interface platform.

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

void DumpRegisters ()

Defined at line 1356 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 1089 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 1180 of file ../../src/devices/block/drivers/ufs/ufs.cc

zx::result<> ConfigureAutoHibernate ()

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

zx::result<> DisableAutoHibernate ()

Defined at line 1077 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 446 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 474 of file ../../src/devices/block/drivers/ufs/ufs.cc

void TriggerIoWork ()

Defined at line 403 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 347 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 685 of file ../../src/devices/block/drivers/ufs/ufs.cc

void OnDispatcherShutdown ()

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

void FinishStop (fdf::StopCompleter completer)

Defined at line 1759 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 1580 of file ../../src/devices/block/drivers/ufs/ufs.cc

void ScheduleResumeRetry ()

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

void CompletePendingResume ()

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

Friends

class RequestProcessor
class UfsTest