blob: 7a897845a67d0862eecd74d8883d1fdbb9d43af4 [file]
/*
* 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