blob: 77e2cb30a18eb7bc1a1818387595d33a77a02065 [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "request_processor.h"
#include <lib/driver/logging/cpp/logger.h>
#include "src/devices/block/drivers/ufs/ufs.h"
namespace ufs {
template <typename Processor, typename Descriptor>
zx::result<std::unique_ptr<Processor>> RequestProcessor::Create(Ufs &ufs, zx::unowned_bti bti,
const fdf::MmioView mmio,
uint8_t entry_count) {
zx::result<RequestList> request_list =
RequestList::Create(bti->borrow(), sizeof(Descriptor), entry_count);
if (request_list.is_error()) {
return request_list.take_error();
}
fbl::AllocChecker ac;
auto request_processor = fbl::make_unique_checked<Processor>(
&ac, std::move(request_list.value()), ufs, std::move(bti), mmio, entry_count);
if (!ac.check()) {
fdf::error("Failed to allocate request processor.");
return zx::error(ZX_ERR_NO_MEMORY);
}
return zx::ok(std::move(request_processor));
}
template zx::result<std::unique_ptr<TransferRequestProcessor>>
RequestProcessor::Create<TransferRequestProcessor, TransferRequestDescriptor>(
Ufs &ufs, zx::unowned_bti bti, const fdf::MmioView mmio, uint8_t entry_count);
template zx::result<std::unique_ptr<TaskManagementRequestProcessor>>
RequestProcessor::Create<TaskManagementRequestProcessor, TaskManagementRequestDescriptor>(
Ufs &ufs, zx::unowned_bti bti, const fdf::MmioView mmio, uint8_t entry_count);
zx::result<uint8_t> RequestProcessor::ReserveSlot() {
for (uint8_t slot_num = 0; slot_num < request_list_.GetSlotCount(); ++slot_num) {
// Skip admin slot
zx::result<uint8_t> admin_slot_num = GetAdminCommandSlotNumber();
if (admin_slot_num.is_ok() && slot_num == admin_slot_num.value()) {
continue;
}
RequestSlot &slot = request_list_.GetSlot(slot_num);
if (slot.state == SlotState::kFree) {
slot.state = SlotState::kReserved;
return zx::ok(slot_num);
}
}
fdf::debug("Failed to reserve a request slot");
return zx::error(ZX_ERR_NO_RESOURCES);
}
zx::result<> RequestProcessor::ClearSlot(RequestSlot &request_slot) {
if (request_slot.pmt.is_valid()) {
if (zx_status_t status = request_slot.pmt.unpin(); status != ZX_OK) {
fdf::error("Failed to unpin IO buffer: {}", zx_status_get_string(status));
request_slot.result = status;
return zx::error(status);
}
}
request_slot.state = SlotState::kFree;
request_slot.io_cmd = nullptr;
request_slot.is_scsi_command = false;
request_slot.is_sync = false;
request_slot.result = ZX_OK;
request_slot.deadline = ZX_TIME_INFINITE;
return zx::ok();
}
zx::result<> RequestProcessor::RingRequestDoorbell(uint8_t slot_num) {
RequestSlot &request_slot = request_list_.GetSlot(slot_num);
sync_completion_t *complete = &request_slot.complete;
sync_completion_reset(complete);
ZX_DEBUG_ASSERT(request_slot.state == SlotState::kReserved);
request_slot.deadline = zx_deadline_after(GetTimeout().get());
request_slot.state = SlotState::kScheduled;
// TODO(https://fxbug.dev/42075643): Set the UtrInterruptAggregationControlReg.
SetDoorBellRegister(slot_num);
return zx::ok();
}
} // namespace ufs