| /* |
| * SPDX-FileCopyrightText: Copyright OpenBMC Authors |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include "NvidiaGpuMctpVdm.hpp" |
| |
| #include "MessagePackUnpackUtils.hpp" |
| #include "OcpMctpVdm.hpp" |
| |
| #include <array> |
| #include <bit> |
| #include <cerrno> |
| #include <cstddef> |
| #include <cstdint> |
| #include <functional> |
| #include <iterator> |
| #include <limits> |
| #include <span> |
| #include <string> |
| #include <string_view> |
| #include <utility> |
| #include <vector> |
| |
| namespace gpu |
| { |
| int encodeRequestCommonHeader(PackBuffer& buffer, gpu::MessageType msgType, |
| uint8_t command, uint8_t instanceId) |
| { |
| const int rc = ocp::accelerator_management::packHeader( |
| buffer, gpu::nvidiaPciVendorId, |
| ocp::accelerator_management::MessageType::REQUEST, instanceId, |
| static_cast<uint8_t>(msgType)); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| return buffer.pack(command); |
| } |
| |
| int decodeResponseCommonHeader( |
| UnpackBuffer& buffer, gpu::MessageType msgType, uint8_t command, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode) |
| { |
| ocp::accelerator_management::MessageType receivedMsgType{}; |
| uint8_t instanceId = 0; |
| uint8_t receivedMessageType = 0; |
| |
| int rc = ocp::accelerator_management::unpackHeader( |
| buffer, gpu::nvidiaPciVendorId, receivedMsgType, instanceId, |
| receivedMessageType); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (receivedMsgType != ocp::accelerator_management::MessageType::RESPONSE) |
| { |
| return EINVAL; |
| } |
| |
| if (receivedMessageType != static_cast<uint8_t>(msgType)) |
| { |
| return EINVAL; |
| } |
| |
| uint8_t receivedCommand = 0; |
| rc = buffer.unpack(receivedCommand); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (command != receivedCommand) |
| { |
| return EINVAL; |
| } |
| |
| rc = ocp::accelerator_management::unpackReasonCodeAndCC( |
| buffer, cc, reasonCode); |
| |
| return rc; |
| } |
| |
| int encodeSetEventSubscriptionRequest(uint8_t generationSetting, uint8_t eid, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::DEVICE_CAPABILITY_DISCOVERY, |
| static_cast<uint8_t>( |
| DeviceCapabilityDiscoveryCommands::SET_EVENT_SUBSCRIPTION), |
| 0); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 2; |
| buffer.pack(dataSize); |
| buffer.pack(generationSetting); |
| buffer.pack(eid); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeSetEventSubscriptionResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::DEVICE_CAPABILITY_DISCOVERY, |
| static_cast<uint8_t>( |
| DeviceCapabilityDiscoveryCommands::SET_EVENT_SUBSCRIPTION), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| return 0; |
| } |
| |
| int encodeSetEventSourcesRequest(uint64_t sources, uint8_t messageType, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::DEVICE_CAPABILITY_DISCOVERY, |
| static_cast<uint8_t>( |
| DeviceCapabilityDiscoveryCommands::SET_CURRENT_EVENT_SOURCES), |
| 0); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 9; |
| buffer.pack(dataSize); |
| buffer.pack(messageType); |
| buffer.pack(sources); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeSetEventSourcesResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::DEVICE_CAPABILITY_DISCOVERY, |
| static_cast<uint8_t>( |
| DeviceCapabilityDiscoveryCommands::SET_CURRENT_EVENT_SOURCES), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| return 0; |
| } |
| |
| int decodeLongRunningResponseEvent( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint8_t& instanceId, std::span<const uint8_t>& responseData) |
| { |
| UnpackBuffer buffer(buf); |
| |
| uint8_t completionCode = 0; |
| |
| buffer.unpack(instanceId); |
| buffer.unpack(completionCode); |
| buffer.unpack(reasonCode); |
| |
| if (buffer.getError() != 0) |
| { |
| return buffer.getError(); |
| } |
| |
| cc = static_cast<ocp::accelerator_management::CompletionCode>( |
| completionCode); |
| |
| responseData = buf.subspan(longRunningResponseEventSize); |
| |
| return 0; |
| } |
| |
| int decodeAggregateResponse( |
| UnpackBuffer& buffer, gpu::MessageType msgType, uint8_t command, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| std::move_only_function<int(const uint8_t tag, const uint8_t length, |
| UnpackBuffer& buffer)> |
| handler) |
| { |
| ocp::accelerator_management::MessageType receivedMsgType{}; |
| uint8_t instanceId = 0; |
| uint8_t receivedMessageType = 0; |
| |
| int rc = ocp::accelerator_management::unpackHeader( |
| buffer, gpu::nvidiaPciVendorId, receivedMsgType, instanceId, |
| receivedMessageType); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (receivedMsgType != ocp::accelerator_management::MessageType::RESPONSE) |
| { |
| return EINVAL; |
| } |
| |
| if (receivedMessageType != static_cast<uint8_t>(msgType)) |
| { |
| return EINVAL; |
| } |
| |
| uint8_t receivedCommand = 0; |
| rc = buffer.unpack(receivedCommand); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (command != receivedCommand) |
| { |
| return EINVAL; |
| } |
| |
| uint8_t completionCode = 0; |
| rc = buffer.unpack(completionCode); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| cc = static_cast<ocp::accelerator_management::CompletionCode>( |
| completionCode); |
| |
| if (cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| uint16_t receivedReasonCode = 0; |
| rc = buffer.unpack(receivedReasonCode); |
| if (rc != 0) |
| { |
| return rc; |
| } |
| reasonCode = receivedReasonCode; |
| return 0; |
| } |
| |
| reasonCode = 0; |
| |
| rc = ocp::accelerator_management::unpackAggregateResponse( |
| buffer, std::move(handler)); |
| |
| return rc; |
| } |
| |
| int encodeQueryDeviceIdentificationRequest(uint8_t instanceId, |
| const std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::DEVICE_CAPABILITY_DISCOVERY, |
| static_cast<uint8_t>( |
| DeviceCapabilityDiscoveryCommands::QUERY_DEVICE_IDENTIFICATION), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 0; |
| buffer.pack(dataSize); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeQueryDeviceIdentificationResponse( |
| const std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint8_t& deviceIdentification, uint8_t& deviceInstance) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::DEVICE_CAPABILITY_DISCOVERY, |
| static_cast<uint8_t>( |
| DeviceCapabilityDiscoveryCommands::QUERY_DEVICE_IDENTIFICATION), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(uint8_t) * 2) |
| { |
| return EINVAL; |
| } |
| |
| buffer.unpack(deviceIdentification); |
| buffer.unpack(deviceInstance); |
| |
| return buffer.getError(); |
| } |
| |
| int encodeGetSupportedMessageTypesRequest(uint8_t instanceId, |
| const std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::DEVICE_CAPABILITY_DISCOVERY, |
| static_cast<uint8_t>( |
| DeviceCapabilityDiscoveryCommands::GET_SUPPORTED_MESSAGE_TYPES), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 0; |
| buffer.pack(dataSize); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetSupportedMessageTypesResponse( |
| const std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| std::array<uint8_t, supportedListBitfieldSize>& supportedTypes) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::DEVICE_CAPABILITY_DISCOVERY, |
| static_cast<uint8_t>( |
| DeviceCapabilityDiscoveryCommands::GET_SUPPORTED_MESSAGE_TYPES), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != supportedTypes.size()) |
| { |
| return EINVAL; |
| } |
| |
| for (auto& byte : supportedTypes) |
| { |
| buffer.unpack(byte); |
| } |
| |
| return buffer.getError(); |
| } |
| |
| int encodeGetSupportedCommandCodesRequest( |
| uint8_t instanceId, uint8_t nvidiaMessageType, const std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::DEVICE_CAPABILITY_DISCOVERY, |
| static_cast<uint8_t>( |
| DeviceCapabilityDiscoveryCommands::GET_SUPPORTED_COMMAND_CODES), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 1; |
| buffer.pack(dataSize); |
| buffer.pack(nvidiaMessageType); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetSupportedCommandCodesResponse( |
| const std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| std::array<uint8_t, supportedListBitfieldSize>& supportedCommands) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::DEVICE_CAPABILITY_DISCOVERY, |
| static_cast<uint8_t>( |
| DeviceCapabilityDiscoveryCommands::GET_SUPPORTED_COMMAND_CODES), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != supportedCommands.size()) |
| { |
| return EINVAL; |
| } |
| |
| for (auto& byte : supportedCommands) |
| { |
| buffer.unpack(byte); |
| } |
| |
| return buffer.getError(); |
| } |
| |
| int encodeGetTemperatureReadingRequest(uint8_t instanceId, uint8_t sensorId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_TEMPERATURE_READING), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 1; |
| buffer.pack(dataSize); |
| buffer.pack(sensorId); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetTemperatureReadingResponse( |
| const std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| double& temperatureReading) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_TEMPERATURE_READING), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(int32_t)) |
| { |
| return EINVAL; |
| } |
| |
| int32_t reading = 0; |
| rc = buffer.unpack(reading); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| temperatureReading = reading / static_cast<double>(1 << 8); |
| |
| return 0; |
| } |
| |
| int encodeReadThermalParametersRequest(uint8_t instanceId, uint8_t sensorId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::READ_THERMAL_PARAMETERS), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 1; |
| buffer.pack(dataSize); |
| buffer.pack(sensorId); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeReadThermalParametersResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| int32_t& threshold) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::READ_THERMAL_PARAMETERS), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(int32_t)) |
| { |
| return EINVAL; |
| } |
| |
| rc = buffer.unpack(threshold); |
| |
| return rc; |
| } |
| |
| int encodeGetPowerDrawRequest(PlatformEnvironmentalCommands commandCode, |
| uint8_t instanceId, uint8_t sensorId, |
| uint8_t averagingInterval, std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(commandCode), instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = sizeof(sensorId) + sizeof(averagingInterval); |
| buffer.pack(dataSize); |
| buffer.pack(sensorId); |
| buffer.pack(averagingInterval); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetPowerDrawResponse(std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, |
| uint16_t& reasonCode, uint32_t& power) |
| { |
| UnpackBuffer buffer(buf); |
| |
| ocp::accelerator_management::MessageType receivedMsgType{}; |
| uint8_t instanceId = 0; |
| uint8_t receivedMessageType = 0; |
| |
| int rc = ocp::accelerator_management::unpackHeader( |
| buffer, gpu::nvidiaPciVendorId, receivedMsgType, instanceId, |
| receivedMessageType); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (receivedMsgType != ocp::accelerator_management::MessageType::RESPONSE) |
| { |
| return EINVAL; |
| } |
| |
| if (receivedMessageType != |
| static_cast<uint8_t>(MessageType::PLATFORM_ENVIRONMENTAL)) |
| { |
| return EINVAL; |
| } |
| |
| uint8_t receivedCommand = 0; |
| rc = buffer.unpack(receivedCommand); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| rc = ocp::accelerator_management::unpackReasonCodeAndCC( |
| buffer, cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(uint32_t)) |
| { |
| return EINVAL; |
| } |
| |
| rc = buffer.unpack(power); |
| |
| return rc; |
| } |
| |
| int encodeGetCurrentEnergyCounterRequest(uint8_t instanceId, uint8_t sensorId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_CURRENT_ENERGY_COUNTER), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 1; |
| buffer.pack(dataSize); |
| buffer.pack(sensorId); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetCurrentEnergyCounterResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint64_t& energy) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_CURRENT_ENERGY_COUNTER), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(uint64_t)) |
| { |
| return EINVAL; |
| } |
| |
| rc = buffer.unpack(energy); |
| |
| return rc; |
| } |
| |
| int encodeGetVoltageRequest(uint8_t instanceId, uint8_t sensorId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::GET_VOLTAGE), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 1; |
| buffer.pack(dataSize); |
| buffer.pack(sensorId); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetVoltageResponse(std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, |
| uint16_t& reasonCode, uint32_t& voltage) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::GET_VOLTAGE), cc, |
| reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(uint32_t)) |
| { |
| return EINVAL; |
| } |
| |
| rc = buffer.unpack(voltage); |
| |
| return rc; |
| } |
| |
| int encodeGetPowerLimitsRequest(uint8_t instanceId, uint32_t powerLimitId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::GET_POWER_LIMITS), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = sizeof(powerLimitId); |
| buffer.pack(dataSize); |
| buffer.pack(powerLimitId); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetPowerLimitsResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint32_t& persistentPowerLimitRequested, |
| uint32_t& oneshotPowerLimitRequested, uint32_t& powerLimitEnforced) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::GET_POWER_LIMITS), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(uint32_t) * 3) |
| { |
| return EINVAL; |
| } |
| |
| buffer.unpack(persistentPowerLimitRequested); |
| buffer.unpack(oneshotPowerLimitRequested); |
| buffer.unpack(powerLimitEnforced); |
| |
| return buffer.getError(); |
| } |
| |
| int encodeSetPowerLimitsRequest( |
| uint8_t instanceId, uint32_t powerLimitId, SetPowerLimitsAction action, |
| SetPowerLimitsPersistence persistence, uint32_t powerLimitMilliwatts, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::SET_POWER_LIMITS), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = sizeof(powerLimitId) + sizeof(uint8_t) + |
| sizeof(uint8_t) + sizeof(powerLimitMilliwatts); |
| buffer.pack(dataSize); |
| buffer.pack(powerLimitId); |
| buffer.pack(static_cast<uint8_t>(action)); |
| buffer.pack(static_cast<uint8_t>(persistence)); |
| buffer.pack(powerLimitMilliwatts); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeSetPowerLimitsResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::SET_POWER_LIMITS), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| return 0; |
| } |
| |
| int encodeGetDriverInformationRequest(uint8_t instanceId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_DRIVER_INFORMATION), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 0; |
| buffer.pack(dataSize); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetDriverInformationResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| DriverState& driverState, std::string& driverVersion) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_DRIVER_INFORMATION), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize < 2) |
| { |
| return EINVAL; |
| } |
| |
| uint8_t driverStateValue = 0; |
| rc = buffer.unpack(driverStateValue); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| driverState = static_cast<DriverState>(driverStateValue); |
| |
| std::span<const uint8_t> remainingBuffer = buffer.getRemaining(); |
| |
| if (remainingBuffer.empty()) |
| { |
| return EINVAL; |
| } |
| |
| driverVersion.clear(); |
| driverVersion.assign(remainingBuffer.begin(), |
| std::prev(remainingBuffer.end())); |
| |
| return 0; |
| } |
| |
| int encodeGetInventoryInformationRequest(uint8_t instanceId, uint8_t propertyId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_INVENTORY_INFORMATION), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 1; |
| buffer.pack(dataSize); |
| buffer.pack(propertyId); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetInventoryInformationResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| InventoryPropertyId propertyId, InventoryValue& value) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_INVENTORY_INFORMATION), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize == 0 || dataSize > maxInventoryDataSize) |
| { |
| return EINVAL; |
| } |
| |
| switch (propertyId) |
| { |
| case InventoryPropertyId::BOARD_PART_NUMBER: |
| case InventoryPropertyId::SERIAL_NUMBER: |
| case InventoryPropertyId::MARKETING_NAME: |
| case InventoryPropertyId::DEVICE_PART_NUMBER: |
| { |
| std::span<const uint8_t> remainingBuffer = buffer.getRemaining(); |
| |
| if (remainingBuffer.size() < dataSize) |
| { |
| return EINVAL; |
| } |
| |
| value = std::string(remainingBuffer.begin(), |
| remainingBuffer.begin() + dataSize); |
| break; |
| } |
| case InventoryPropertyId::DEVICE_GUID: |
| { |
| std::span<const uint8_t> remainingBuffer = buffer.getRemaining(); |
| |
| if (remainingBuffer.size() < dataSize) |
| { |
| return EINVAL; |
| } |
| |
| value = std::vector<uint8_t>(remainingBuffer.begin(), |
| remainingBuffer.begin() + dataSize); |
| break; |
| } |
| case InventoryPropertyId::DEFAULT_BOOST_CLOCKS: |
| case InventoryPropertyId::DEFAULT_BASE_CLOCKS: |
| case InventoryPropertyId::MIN_GRAPHICS_CLOCK: |
| case InventoryPropertyId::MAX_GRAPHICS_CLOCK: |
| case InventoryPropertyId::RATED_DEVICE_POWER_LIMIT: |
| case InventoryPropertyId::MIN_DEVICE_POWER_LIMIT: |
| case InventoryPropertyId::MAX_DEVICE_POWER_LIMIT: |
| case InventoryPropertyId::MAX_MEMORY_CAPACITY: |
| case InventoryPropertyId::MIN_MEMORY_CLOCK: |
| case InventoryPropertyId::MAX_MEMORY_CLOCK: |
| { |
| uint32_t intValue = 0; |
| rc = buffer.unpack(intValue); |
| if (rc != 0) |
| { |
| return rc; |
| } |
| value = intValue; |
| break; |
| } |
| default: |
| return EINVAL; |
| } |
| return 0; |
| } |
| |
| int encodeGetCurrentUtilizationModeRequest(uint8_t instanceId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_CURRENT_UTILIZATION), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 0; |
| buffer.pack(dataSize); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetCurrentUtilizationModeResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint32_t& gpuUtilization, uint32_t& memoryUtilization) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_CURRENT_UTILIZATION), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(uint32_t) * 2) |
| { |
| return EINVAL; |
| } |
| |
| buffer.unpack(gpuUtilization); |
| buffer.unpack(memoryUtilization); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetCurrentUtilizationModeResponse(std::span<const uint8_t> buf, |
| uint32_t& gpuUtilization, |
| uint32_t& memoryUtilization) |
| { |
| UnpackBuffer buffer(buf); |
| buffer.unpack(gpuUtilization); |
| buffer.unpack(memoryUtilization); |
| return buffer.getError(); |
| } |
| |
| int encodeGetClockLimitRequest(uint8_t instanceId, ClockType clockType, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::GET_CLOCK_LIMIT), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = sizeof(uint8_t); |
| buffer.pack(dataSize); |
| buffer.pack(static_cast<uint8_t>(clockType)); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetClockLimitResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint32_t& requestedLimitMin, uint32_t& requestedLimitMax, |
| uint32_t& presentLimitMin, uint32_t& presentLimitMax) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::GET_CLOCK_LIMIT), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != 4 * sizeof(uint32_t)) |
| { |
| return EINVAL; |
| } |
| |
| buffer.unpack(requestedLimitMin); |
| buffer.unpack(requestedLimitMax); |
| buffer.unpack(presentLimitMin); |
| buffer.unpack(presentLimitMax); |
| |
| return buffer.getError(); |
| } |
| |
| int encodeGetViolationDurationRequest(uint8_t instanceId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_VIOLATION_DURATION), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 0; |
| buffer.pack(dataSize); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetViolationDurationResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint64_t& hwViolationDuration, uint64_t& globalSwViolationDuration, |
| uint64_t& powerViolationDuration, uint64_t& thermalViolationDuration) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_VIOLATION_DURATION), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(uint64_t) * 4) |
| { |
| return EINVAL; |
| } |
| |
| buffer.unpack(hwViolationDuration); |
| buffer.unpack(globalSwViolationDuration); |
| buffer.unpack(powerViolationDuration); |
| buffer.unpack(thermalViolationDuration); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetViolationDurationResponse( |
| std::span<const uint8_t> buf, uint64_t& hwViolationDuration, |
| uint64_t& globalSwViolationDuration, uint64_t& powerViolationDuration, |
| uint64_t& thermalViolationDuration) |
| { |
| UnpackBuffer buffer(buf); |
| buffer.unpack(hwViolationDuration); |
| buffer.unpack(globalSwViolationDuration); |
| buffer.unpack(powerViolationDuration); |
| buffer.unpack(thermalViolationDuration); |
| return buffer.getError(); |
| } |
| |
| int encodeGetMemoryCapacityUtilizationRequest(uint8_t instanceId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_MEMORY_CAPACITY_UTILIZATION), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 0; |
| buffer.pack(dataSize); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetMemoryCapacityUtilizationResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint32_t& reservedMemory, uint32_t& usedMemory) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_MEMORY_CAPACITY_UTILIZATION), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(uint32_t) * 2) |
| { |
| return EINVAL; |
| } |
| |
| buffer.unpack(reservedMemory); |
| buffer.unpack(usedMemory); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetMemoryCapacityUtilizationResponse(std::span<const uint8_t> buf, |
| uint32_t& reservedMemory, |
| uint32_t& usedMemory) |
| { |
| UnpackBuffer buffer(buf); |
| buffer.unpack(reservedMemory); |
| buffer.unpack(usedMemory); |
| return buffer.getError(); |
| } |
| |
| int encodeSetClockLimitRequest(uint8_t instanceId, ClockType clockType, |
| ClockLimitFlag flag, uint32_t limitMinMHz, |
| uint32_t limitMaxMHz, std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::SET_CLOCK_LIMIT), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = sizeof(uint8_t) + sizeof(uint8_t) + |
| sizeof(limitMinMHz) + sizeof(limitMaxMHz); |
| buffer.pack(dataSize); |
| buffer.pack(static_cast<uint8_t>(clockType)); |
| buffer.pack(static_cast<uint8_t>(flag)); |
| buffer.pack(limitMinMHz); |
| buffer.pack(limitMaxMHz); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeSetClockLimitResponse(std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, |
| uint16_t& reasonCode) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::SET_CLOCK_LIMIT), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| return 0; |
| } |
| |
| int encodeQueryScalarGroupTelemetryV1Request( |
| uint8_t instanceId, uint8_t deviceIndex, PcieScalarGroupId groupId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PCIE_LINK, |
| static_cast<uint8_t>(PcieLinkCommands::QueryScalarGroupTelemetryV1), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 2; |
| buffer.pack(dataSize); |
| buffer.pack(deviceIndex); |
| buffer.pack(static_cast<uint8_t>(groupId)); |
| |
| return buffer.getError(); |
| } |
| |
| int encodeQueryScalarGroupTelemetryV2Request( |
| uint8_t instanceId, PciePortType portType, uint8_t upstreamPortNumber, |
| uint8_t portNumber, PcieScalarGroupId groupId, std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PCIE_LINK, |
| static_cast<uint8_t>(PcieLinkCommands::QueryScalarGroupTelemetryV2), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 3; |
| buffer.pack(dataSize); |
| const uint8_t encodedUpstreamPortNumber = |
| (static_cast<uint8_t>(portType) << 7) | (upstreamPortNumber & 0x7F); |
| buffer.pack(encodedUpstreamPortNumber); |
| buffer.pack(portNumber); |
| buffer.pack(static_cast<uint8_t>(groupId)); |
| |
| return buffer.getError(); |
| } |
| |
| static int decodeQueryScalarGroupTelemetryResponseImpl( |
| std::span<const uint8_t> buf, uint8_t expectedCommand, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| size_t& numTelemetryValues, std::vector<uint32_t>& telemetryValues) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader(buffer, MessageType::PCIE_LINK, |
| expectedCommand, cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| numTelemetryValues = dataSize / sizeof(uint32_t); |
| |
| if (telemetryValues.size() < numTelemetryValues) |
| { |
| telemetryValues.resize(numTelemetryValues); |
| } |
| |
| for (size_t i = 0; i < numTelemetryValues; i++) |
| { |
| rc = buffer.unpack(telemetryValues[i]); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| } |
| |
| return 0; |
| } |
| |
| int decodeQueryScalarGroupTelemetryV1Response( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| size_t& numTelemetryValues, std::vector<uint32_t>& telemetryValues) |
| { |
| return decodeQueryScalarGroupTelemetryResponseImpl( |
| buf, |
| static_cast<uint8_t>(PcieLinkCommands::QueryScalarGroupTelemetryV1), cc, |
| reasonCode, numTelemetryValues, telemetryValues); |
| } |
| |
| int decodeQueryScalarGroupTelemetryV2Response( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| size_t& numTelemetryValues, std::vector<uint32_t>& telemetryValues) |
| { |
| return decodeQueryScalarGroupTelemetryResponseImpl( |
| buf, |
| static_cast<uint8_t>(PcieLinkCommands::QueryScalarGroupTelemetryV2), cc, |
| reasonCode, numTelemetryValues, telemetryValues); |
| } |
| |
| int encodeListPciePortsRequest(uint8_t instanceId, std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PCIE_LINK, |
| static_cast<uint8_t>(PcieLinkCommands::ListPCIePorts), instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 0; |
| buffer.pack(dataSize); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeListPciePortsResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint16_t& numUpstreamPorts, std::vector<uint8_t>& numDownstreamPorts) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PCIE_LINK, |
| static_cast<uint8_t>(PcieLinkCommands::ListPCIePorts), cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize < sizeof(uint16_t)) |
| { |
| return EINVAL; |
| } |
| |
| uint16_t upstreamPorts = 0; |
| rc = buffer.unpack(upstreamPorts); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| numUpstreamPorts = 0; |
| numDownstreamPorts.clear(); |
| numDownstreamPorts.reserve(upstreamPorts); |
| |
| for (size_t i = 0; i < upstreamPorts; i++) |
| { |
| uint8_t isInternal = 0; |
| uint8_t count = 0; |
| |
| buffer.unpack(isInternal); |
| buffer.unpack(count); |
| |
| if (buffer.getError() != 0) |
| { |
| return EINVAL; |
| } |
| |
| // Count only external upstream ports |
| if (isInternal == 0) |
| { |
| ++numUpstreamPorts; |
| numDownstreamPorts.push_back(count); |
| } |
| } |
| |
| return 0; |
| } |
| |
| int encodeGetPortNetworkAddressesRequest( |
| uint8_t instanceId, uint16_t portNumber, std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::NETWORK_PORT, |
| static_cast<uint8_t>(NetworkPortCommands::GetPortNetworkAddresses), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = sizeof(portNumber); |
| buffer.pack(dataSize); |
| buffer.pack(portNumber); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetPortNetworkAddressesResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| NetworkPortLinkType& linkType, |
| std::vector<std::pair<uint8_t, uint64_t>>& addresses) |
| { |
| UnpackBuffer buffer(buf); |
| |
| addresses.clear(); |
| addresses.reserve(std::numeric_limits<uint8_t>::max()); |
| |
| const int rc = decodeAggregateResponse( |
| buffer, MessageType::NETWORK_PORT, |
| static_cast<uint8_t>(NetworkPortCommands::GetPortNetworkAddresses), cc, |
| reasonCode, |
| [&linkType, &addresses](const uint8_t tag, const uint8_t length, |
| UnpackBuffer& buffer) -> int { |
| if (tag == 0 && length == 1) |
| { |
| uint8_t linkTypeValue = 0; |
| int rc = buffer.unpack(linkTypeValue); |
| if (rc != 0) |
| { |
| return rc; |
| } |
| linkType = static_cast<NetworkPortLinkType>(linkTypeValue); |
| return 0; |
| } |
| |
| if (length == sizeof(uint64_t)) |
| { |
| uint64_t telemetryData = 0; |
| int rc = buffer.unpack(telemetryData); |
| if (rc != 0) |
| { |
| return rc; |
| } |
| addresses.emplace_back(tag, telemetryData); |
| return 0; |
| } |
| |
| buffer.skip(length); |
| return 0; |
| }); |
| |
| return rc; |
| } |
| |
| int encodeGetEthernetPortTelemetryCountersRequest( |
| uint8_t instanceId, uint16_t portNumber, std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::NETWORK_PORT, |
| static_cast<uint8_t>( |
| NetworkPortCommands::GetEthernetPortTelemetryCounters), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = sizeof(portNumber); |
| buffer.pack(dataSize); |
| buffer.pack(portNumber); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetEthernetPortTelemetryCountersResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| std::vector<std::pair<uint8_t, uint64_t>>& telemetryValues) |
| { |
| UnpackBuffer buffer(buf); |
| |
| telemetryValues.clear(); |
| telemetryValues.reserve(std::numeric_limits<uint8_t>::max()); |
| |
| const int rc = decodeAggregateResponse( |
| buffer, MessageType::NETWORK_PORT, |
| static_cast<uint8_t>( |
| NetworkPortCommands::GetEthernetPortTelemetryCounters), |
| cc, reasonCode, |
| [&telemetryValues](const uint8_t tag, const uint8_t length, |
| UnpackBuffer& buffer) -> int { |
| uint64_t telemetryData = 0; |
| |
| if (length == sizeof(uint32_t)) |
| { |
| uint32_t telemetryValue = 0; |
| int rc = buffer.unpack(telemetryValue); |
| if (rc != 0) |
| { |
| return rc; |
| } |
| telemetryData = telemetryValue; |
| } |
| else if (length == sizeof(uint64_t)) |
| { |
| int rc = buffer.unpack(telemetryData); |
| if (rc != 0) |
| { |
| return rc; |
| } |
| } |
| else |
| { |
| buffer.skip(length); |
| return 0; |
| } |
| |
| telemetryValues.emplace_back(tag, telemetryData); |
| |
| return 0; |
| }); |
| |
| return rc; |
| } |
| |
| int decodeXidEvent(std::span<const uint8_t> buf, uint8_t& flags, |
| uint32_t& eventMessageReason, uint32_t& sequenceNumber, |
| uint64_t& timestamp, std::string_view& messageTextString) |
| { |
| UnpackBuffer buffer(buf); |
| |
| buffer.unpack(flags); |
| |
| // Skip 3 reserved bytes |
| buffer.skip(3); |
| |
| buffer.unpack(eventMessageReason); |
| buffer.unpack(sequenceNumber); |
| buffer.unpack(timestamp); |
| |
| if (buffer.getError() != 0) |
| { |
| return buffer.getError(); |
| } |
| |
| std::span<const uint8_t> remainingData = buffer.getRemaining(); |
| messageTextString = std::string_view{ |
| std::bit_cast<const char*>(remainingData.data()), remainingData.size()}; |
| |
| return 0; |
| } |
| |
| int encodeGetCurrentClockFrequencyRequest(uint8_t instanceId, ClockType clockId, |
| std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_CURRENT_CLOCK_FREQUENCY), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = sizeof(uint8_t); |
| buffer.pack(dataSize); |
| buffer.pack(static_cast<uint8_t>(clockId)); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetCurrentClockFrequencyResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint32_t& clockFreqMHz) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_CURRENT_CLOCK_FREQUENCY), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(uint32_t)) |
| { |
| return EINVAL; |
| } |
| |
| rc = buffer.unpack(clockFreqMHz); |
| |
| return rc; |
| } |
| |
| int encodeGetEccErrorCountsRequest(uint8_t instanceId, std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| const int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_ECC_ERROR_COUNTS), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 0; |
| buffer.pack(dataSize); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetEccErrorCountsResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| uint16_t& flags, uint32_t& sramCorrected, uint32_t& sramUncorrectedSecded, |
| uint32_t& sramUncorrectedParity, uint32_t& dramCorrected, |
| uint32_t& dramUncorrected) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_ECC_ERROR_COUNTS), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| constexpr uint16_t expectedSize = sizeof(uint16_t) + sizeof(uint32_t) * 5; |
| if (dataSize != expectedSize) |
| { |
| return EINVAL; |
| } |
| |
| buffer.unpack(flags); |
| buffer.unpack(sramCorrected); |
| buffer.unpack(sramUncorrectedSecded); |
| buffer.unpack(sramUncorrectedParity); |
| buffer.unpack(dramCorrected); |
| buffer.unpack(dramUncorrected); |
| |
| return buffer.getError(); |
| } |
| |
| // GET_ECC_MODE returns a single flags byte: bit 0 is the ECC mode currently in |
| // effect, bit 1 is the mode that will apply after the next reset. |
| constexpr uint8_t eccModeCurrentEnabledMask = 0x01U; |
| constexpr uint8_t eccModePendingEnabledMask = 0x02U; |
| |
| int encodeGetEccModeRequest(uint8_t instanceId, std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::GET_ECC_MODE), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 0; |
| buffer.pack(dataSize); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetEccModeResponse(std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, |
| uint16_t& reasonCode, bool& currentEccModeEnabled, |
| bool& pendingEccModeEnabled) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>(PlatformEnvironmentalCommands::GET_ECC_MODE), cc, |
| reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| if (dataSize != sizeof(uint8_t)) |
| { |
| return EINVAL; |
| } |
| |
| uint8_t flags = 0; |
| rc = buffer.unpack(flags); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| currentEccModeEnabled = (flags & eccModeCurrentEnabledMask) != 0U; |
| pendingEccModeEnabled = (flags & eccModePendingEnabledMask) != 0U; |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetEccModeResponse(std::span<const uint8_t> buf, |
| bool& currentEccModeEnabled, |
| bool& pendingEccModeEnabled) |
| { |
| UnpackBuffer buffer(buf); |
| |
| uint8_t flags = 0; |
| const int rc = buffer.unpack(flags); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| currentEccModeEnabled = (flags & eccModeCurrentEnabledMask) != 0U; |
| pendingEccModeEnabled = (flags & eccModePendingEnabledMask) != 0U; |
| |
| return buffer.getError(); |
| } |
| |
| int encodeGetLeakDetectionInfoRequest(uint8_t instanceId, |
| const std::span<uint8_t> buf) |
| { |
| PackBuffer buffer(buf); |
| |
| int rc = encodeRequestCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_LEAK_DETECTION_INFO), |
| instanceId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| const uint8_t dataSize = 0; |
| buffer.pack(dataSize); |
| |
| return buffer.getError(); |
| } |
| |
| int decodeGetLeakDetectionInfoResponse( |
| std::span<const uint8_t> buf, |
| ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode, |
| std::vector<LeakSensorData>& parsedSensors) |
| { |
| UnpackBuffer buffer(buf); |
| |
| int rc = decodeResponseCommonHeader( |
| buffer, MessageType::PLATFORM_ENVIRONMENTAL, |
| static_cast<uint8_t>( |
| PlatformEnvironmentalCommands::GET_LEAK_DETECTION_INFO), |
| cc, reasonCode); |
| |
| if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS) |
| { |
| return rc; |
| } |
| |
| uint16_t dataSize = 0; |
| rc = buffer.unpack(dataSize); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| parsedSensors.clear(); |
| |
| uint8_t numSensors = 0; |
| rc = buffer.unpack(numSensors); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| uint8_t numThresholdLevels = 0; |
| rc = buffer.unpack(numThresholdLevels); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| for (uint8_t i = 0; i < numSensors; ++i) |
| { |
| LeakSensorData sensor; |
| |
| rc = buffer.unpack(sensor.sensorId); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| rc = buffer.unpack(sensor.leakState); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| for (uint8_t t = 0; t < numThresholdLevels; ++t) |
| { |
| uint16_t thresholdValue = 0; |
| rc = buffer.unpack(thresholdValue); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| sensor.thresholds.push_back(thresholdValue); |
| } |
| |
| uint16_t adcReadingValue = 0; |
| |
| rc = buffer.unpack(adcReadingValue); |
| |
| if (rc != 0) |
| { |
| return rc; |
| } |
| |
| sensor.adcReadingMv = adcReadingValue; |
| |
| parsedSensors.push_back(std::move(sensor)); |
| } |
| |
| return 0; |
| } |
| |
| } // namespace gpu |