| // Copyright 2019 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 "msd_img_device.h" |
| |
| #include "fuchsia_sys_info.h" |
| |
| #if defined(NO_HARDWARE) |
| #include "mock/mock_bus_mapper.h" |
| #include "mock/mock_mmio.h" |
| #endif |
| |
| extern "C" |
| { |
| #include "process_stats.h" |
| #include "pvrsrv.h" |
| #include "pvrsrv_error.h" |
| #include "rgxdevice.h" |
| #include "rgxinit.h" |
| #include "srvcore.h" |
| } |
| |
| namespace |
| { |
| static uint64_t registers_physical_address_s = 0u; |
| static void* registers_cpu_address_s = nullptr; |
| } // namespace |
| |
| |
| |
| MsdImgDevice::MsdImgDevice(std::unique_ptr<magma::PlatformDevice> platform_device, |
| ImgSysDevice* sys_device) |
| : sys_device_(sys_device), |
| platform_device_(std::move(platform_device)) |
| { |
| magic_ = kMagic; |
| sys_info_ = std::make_unique<FuchsiaSysInfo>(); |
| } |
| |
| MsdImgDevice::~MsdImgDevice() |
| { |
| registers_physical_address_s = 0u; |
| registers_cpu_address_s = nullptr; |
| #if !defined(NO_HARDWARE) |
| if (stats_user_) |
| { |
| SORgxGpuUtilStatsUnregister(stats_user_); |
| } |
| #endif |
| if (device_node_) |
| { |
| PVRSRVDeviceDestroy(device_node_); |
| } |
| } |
| |
| bool |
| MsdImgDevice::Init() |
| { |
| #if defined(NO_HARDWARE) |
| bus_mapper_ = std::make_unique<MockBusMapper>(); |
| registers_physical_address_s = PAGE_SIZE; |
| // The address doesn't matter (functions that read/write registers are |
| // no-ops), but this needs to be non-zero to avoid hitting asserts. |
| registers_cpu_address_s = reinterpret_cast<void*>(PAGE_SIZE); |
| mmio_ = MockMmio::Create(PAGE_SIZE * 10); |
| #else |
| bus_mapper_ = magma::PlatformBusMapper::Create(platform_device_->GetBusTransactionInitiator()); |
| if (!bus_mapper_) |
| { |
| return DRETF(false, "Failed to create bus transaction initiator"); |
| } |
| mmio_ = platform_device_->CpuMapMmio(0u, magma::PlatformMmio::CACHE_POLICY_UNCACHED_DEVICE); |
| if (!mmio_) |
| { |
| return DRETF(false, "Failed to get mmio"); |
| } |
| registers_physical_address_s = mmio_->physical_address(); |
| registers_cpu_address_s = mmio_->addr(); |
| |
| #endif |
| PVRSRV_ERROR srv_err; |
| srv_err = PVRSRVDeviceCreate(this, 1u, &device_node_); |
| if (srv_err != PVRSRV_OK) |
| { |
| return DRETF(false, "Failed to create device: %d", srv_err); |
| } |
| |
| srv_err = PVRSRVDeviceInitialise(device_node_); |
| if (srv_err != PVRSRV_OK) |
| { |
| return DRETF(false, "Failed to initialize device: %d", srv_err); |
| } |
| #if !defined(NO_HARDWARE) |
| srv_err = SORgxGpuUtilStatsRegister(&stats_user_); |
| if (srv_err != PVRSRV_OK) |
| { |
| return DRETF(false, "Failed to initialize stats: %d", srv_err); |
| } |
| #endif |
| return true; |
| } |
| |
| std::unique_ptr<magma::PlatformInterrupt> |
| MsdImgDevice::interrupt() |
| { |
| return platform_device_->RegisterInterrupt(0); |
| } |
| |
| void |
| MsdImgDevice::DumpStatus(uint32_t dump_state) |
| { |
| PVRSRVDebugRequest(device_node_, DEBUG_REQUEST_VERBOSITY_HIGH, NULL, NULL); |
| #if !defined(NO_HARDWARE) |
| PVRSRV_RGXDEV_INFO* psDevInfo = (PVRSRV_RGXDEV_INFO*)device_node_->pvDevice; |
| RGXFWIF_GPU_UTIL_STATS stats; |
| PVRSRV_ERROR eError = psDevInfo->pfnGetGpuUtilStats(device_node_, stats_user_, &stats); |
| if (eError == PVRSRV_OK) |
| { |
| // ui64Timestamp is garbage. |
| magma::log(magma::LOG_INFO, |
| "Times since last dump (microseconds):\n Active high: %lu, Active low: %lu, Blocked: %lu, Idle: " |
| "%lu, Total: %lu", |
| stats.ui64GpuStatActiveHigh, stats.ui64GpuStatActiveLow, stats.ui64GpuStatBlocked, |
| stats.ui64GpuStatIdle, stats.ui64GpuStatCumulative); |
| } |
| else |
| { |
| magma::log(magma::LOG_WARNING, "Unable to retrieve GPU utilization stats, error: %d", eError); |
| } |
| #endif |
| } |
| |
| zx_status_t |
| MsdImgDevice::PowerUp() |
| { |
| return sys_device_->PowerUp(); |
| } |
| |
| zx_status_t |
| MsdImgDevice::PowerDown() |
| { |
| return sys_device_->PowerDown(); |
| } |
| |
| // static |
| std::unique_ptr<MsdImgDevice> |
| MsdImgDevice::Create(msd_driver_t* drv, void* device) |
| { |
| ImgSysDevice* sys_device = reinterpret_cast<ImgSysDevice*>(device); |
| |
| std::unique_ptr<magma::PlatformDevice> platform_device = |
| magma::PlatformDevice::Create(sys_device->device()); |
| if (!platform_device) |
| { |
| return DRETP(nullptr, "Failed to create platform device"); |
| } |
| |
| auto msd_device = std::unique_ptr<MsdImgDevice>( |
| new MsdImgDevice(std::move(platform_device), sys_device)); |
| if (!msd_device->Init()) |
| { |
| return DRETP(nullptr, "Failed to create msd device"); |
| } |
| return msd_device; |
| } |
| |
| // static |
| void |
| MsdImgDevice::Destroy(MsdImgDevice* device) |
| { |
| delete device; |
| } |
| |
| // static |
| uint64_t |
| MsdImgDevice::GetRegistersPhysicalAddress() |
| { |
| DASSERT(registers_physical_address_s); |
| return registers_physical_address_s; |
| } |
| |
| // static |
| void* |
| MsdImgDevice::GetRegistersCpuAddress() |
| { |
| DASSERT(registers_cpu_address_s); |
| return registers_cpu_address_s; |
| } |