blob: 1afc6caa830dae7fcfe64e1b0280a48c62b746bb [file] [log] [blame]
/*
* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION &
* AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
*/
#include "GpuMctpVdm.hpp"
#include "OcpMctpVdm.hpp"
#include <endian.h>
#include <cstdint>
#include <cstring>
namespace gpu
{
ocp::accelerator_management::CompletionCode packHeader(
const ocp::accelerator_management::BindingPciVidInfo& hdr,
ocp::accelerator_management::BindingPciVid& msg)
{
return ocp::accelerator_management::packHeader(nvidiaPciVendorId, hdr, msg);
}
ocp::accelerator_management::CompletionCode encodeReasonCode(
uint8_t cc, uint16_t reasonCode, uint8_t commandCode,
ocp::accelerator_management::Message& msg)
{
return ocp::accelerator_management::encodeReasonCode(cc, reasonCode,
commandCode, msg);
}
ocp::accelerator_management::CompletionCode decodeReasonCodeAndCC(
const ocp::accelerator_management::Message& msg, size_t msgLen, uint8_t& cc,
uint16_t& reasonCode)
{
if (be16toh(msg.hdr.pci_vendor_id) != nvidiaPciVendorId)
{
return ocp::accelerator_management::CompletionCode::ERR_INVALID_DATA;
}
return ocp::accelerator_management::decodeReasonCodeAndCC(
msg, msgLen, cc, reasonCode);
}
ocp::accelerator_management::CompletionCode
encodeQueryDeviceIdentificationRequest(
uint8_t instanceId, ocp::accelerator_management::Message& msg)
{
ocp::accelerator_management::BindingPciVidInfo header{};
header.ocp_accelerator_management_msg_type =
static_cast<uint8_t>(ocp::accelerator_management::MessageType::REQUEST);
header.instance_id = instanceId &
ocp::accelerator_management::instanceIdMask;
header.msg_type =
static_cast<uint8_t>(MessageType::DEVICE_CAPABILITY_DISCOVERY);
auto rc = packHeader(header, msg.hdr);
if (rc != ocp::accelerator_management::CompletionCode::SUCCESS)
{
return rc;
}
QueryDeviceIdentificationRequest request{};
request.hdr.command = static_cast<uint8_t>(
DeviceCapabilityDiscoveryCommands::QUERY_DEVICE_IDENTIFICATION);
request.hdr.data_size = 0;
std::memcpy(&msg.data, &request, sizeof(request));
return ocp::accelerator_management::CompletionCode::SUCCESS;
}
ocp::accelerator_management::CompletionCode
encodeQueryDeviceIdentificationResponse(
uint8_t instanceId, uint8_t cc, uint16_t reasonCode,
uint8_t deviceIdentification, uint8_t deviceInstance,
ocp::accelerator_management::Message& msg)
{
ocp::accelerator_management::BindingPciVidInfo header{};
header.ocp_accelerator_management_msg_type = static_cast<uint8_t>(
ocp::accelerator_management::MessageType::RESPONSE);
header.instance_id = instanceId &
ocp::accelerator_management::instanceIdMask;
header.msg_type =
static_cast<uint8_t>(MessageType::DEVICE_CAPABILITY_DISCOVERY);
auto rc = packHeader(header, msg.hdr);
if (rc != ocp::accelerator_management::CompletionCode::SUCCESS)
{
return rc;
}
if (cc != static_cast<uint8_t>(
ocp::accelerator_management::CompletionCode::SUCCESS))
{
return gpu::encodeReasonCode(
cc, reasonCode,
static_cast<uint8_t>(
DeviceCapabilityDiscoveryCommands::QUERY_DEVICE_IDENTIFICATION),
msg);
}
QueryDeviceIdentificationResponse response{};
response.hdr.command = static_cast<uint8_t>(
DeviceCapabilityDiscoveryCommands::QUERY_DEVICE_IDENTIFICATION);
response.hdr.completion_code = cc;
response.hdr.data_size = htole16(2);
response.device_identification = deviceIdentification;
response.instance_id = deviceInstance;
std::memcpy(&msg.data, &response, sizeof(response));
return ocp::accelerator_management::CompletionCode::SUCCESS;
}
ocp::accelerator_management::CompletionCode
decodeQueryDeviceIdentificationResponse(
const ocp::accelerator_management::Message& msg, size_t msgLen,
uint8_t& cc, uint16_t& reasonCode, uint8_t& deviceIdentification,
uint8_t& deviceInstance)
{
auto rc = gpu::decodeReasonCodeAndCC(msg, msgLen, cc, reasonCode);
if (rc != ocp::accelerator_management::CompletionCode::SUCCESS ||
cc != static_cast<uint8_t>(
ocp::accelerator_management::CompletionCode::SUCCESS))
{
return rc;
}
if (msgLen < sizeof(ocp::accelerator_management::BindingPciVid) +
sizeof(QueryDeviceIdentificationResponse))
{
return ocp::accelerator_management::CompletionCode::
ERR_INVALID_DATA_LENGTH;
}
QueryDeviceIdentificationResponse response{};
std::memcpy(&response, &msg.data, sizeof(response));
deviceIdentification = response.device_identification;
deviceInstance = response.instance_id;
return ocp::accelerator_management::CompletionCode::SUCCESS;
}
ocp::accelerator_management::CompletionCode encodeGetTemperatureReadingRequest(
uint8_t instanceId, uint8_t sensorId,
ocp::accelerator_management::Message& msg)
{
ocp::accelerator_management::BindingPciVidInfo header{};
header.ocp_accelerator_management_msg_type =
static_cast<uint8_t>(ocp::accelerator_management::MessageType::REQUEST);
header.instance_id = instanceId &
ocp::accelerator_management::instanceIdMask;
header.msg_type = static_cast<uint8_t>(MessageType::PLATFORM_ENVIRONMENTAL);
auto rc = packHeader(header, msg.hdr);
if (rc != ocp::accelerator_management::CompletionCode::SUCCESS)
{
return rc;
}
GetTemperatureReadingRequest request{};
request.hdr.command = static_cast<uint8_t>(
PlatformEnvironmentalCommands::GET_TEMPERATURE_READING);
request.hdr.data_size = sizeof(sensorId);
request.sensor_id = sensorId;
std::memcpy(&msg.data, &request, sizeof(request));
return ocp::accelerator_management::CompletionCode::SUCCESS;
}
ocp::accelerator_management::CompletionCode decodeGetTemperatureReadingRequest(
const ocp::accelerator_management::Message& msg, size_t msgLen,
uint8_t& sensorId)
{
if (msgLen < sizeof(ocp::accelerator_management::BindingPciVid) +
sizeof(GetTemperatureReadingRequest))
{
return ocp::accelerator_management::CompletionCode::
ERR_INVALID_DATA_LENGTH;
}
GetTemperatureReadingRequest request{};
std::memcpy(&request, &msg.data, sizeof(request));
if (request.hdr.data_size < sizeof(request.sensor_id))
{
return ocp::accelerator_management::CompletionCode::ERR_INVALID_DATA;
}
sensorId = request.sensor_id;
return ocp::accelerator_management::CompletionCode::SUCCESS;
}
ocp::accelerator_management::CompletionCode encodeGetTemperatureReadingResponse(
uint8_t instanceId, uint8_t cc, uint16_t reasonCode,
double temperatureReading, ocp::accelerator_management::Message& msg)
{
ocp::accelerator_management::BindingPciVidInfo header{};
header.ocp_accelerator_management_msg_type = static_cast<uint8_t>(
ocp::accelerator_management::MessageType::RESPONSE);
header.instance_id = instanceId &
ocp::accelerator_management::instanceIdMask;
header.msg_type = static_cast<uint8_t>(MessageType::PLATFORM_ENVIRONMENTAL);
auto rc = packHeader(header, msg.hdr);
if (rc != ocp::accelerator_management::CompletionCode::SUCCESS)
{
return rc;
}
if (cc != static_cast<uint8_t>(
ocp::accelerator_management::CompletionCode::SUCCESS))
{
return gpu::encodeReasonCode(
cc, reasonCode,
static_cast<uint8_t>(
PlatformEnvironmentalCommands::GET_TEMPERATURE_READING),
msg);
}
GetTemperatureReadingResponse response{};
response.hdr.command = static_cast<uint8_t>(
PlatformEnvironmentalCommands::GET_TEMPERATURE_READING);
response.hdr.completion_code = cc;
response.hdr.data_size = htole16(sizeof(uint32_t));
int32_t reading = static_cast<int32_t>(temperatureReading * (1 << 8));
response.reading = htole32(reading);
std::memcpy(&msg.data, &response, sizeof(response));
return ocp::accelerator_management::CompletionCode::SUCCESS;
}
ocp::accelerator_management::CompletionCode decodeGetTemperatureReadingResponse(
const ocp::accelerator_management::Message& msg, size_t msgLen, uint8_t& cc,
uint16_t& reasonCode, double& temperatureReading)
{
auto rc = gpu::decodeReasonCodeAndCC(msg, msgLen, cc, reasonCode);
if (rc != ocp::accelerator_management::CompletionCode::SUCCESS ||
cc != static_cast<uint8_t>(
ocp::accelerator_management::CompletionCode::SUCCESS))
{
return rc;
}
if (msgLen < sizeof(ocp::accelerator_management::BindingPciVid) +
sizeof(GetTemperatureReadingResponse))
{
return ocp::accelerator_management::CompletionCode::
ERR_INVALID_DATA_LENGTH;
}
GetTemperatureReadingResponse response{};
std::memcpy(&response, &msg.data, sizeof(response));
uint16_t dataSize = le16toh(response.hdr.data_size);
if (dataSize != sizeof(int32_t))
{
return ocp::accelerator_management::CompletionCode::ERR_INVALID_DATA;
}
int32_t reading = le32toh(response.reading);
temperatureReading = reading / static_cast<double>(1 << 8);
return ocp::accelerator_management::CompletionCode::SUCCESS;
}
} // namespace gpu