blob: e2eed14b5dbba5a504b6c7933c43e8d115a0604a [file]
/*
* SPDX-FileCopyrightText: Copyright OpenBMC Authors
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <MctpRequester.hpp>
#include <MessagePackUnpackUtils.hpp>
#include <NvidiaGpuMctpVdm.hpp>
#include <NvidiaLongRunningHandler.hpp>
#include <OcpMctpVdm.hpp>
#include <SerialQueue.hpp>
#include <boost/system/error_code.hpp>
#include <cstdint>
#include <functional>
#include <memory>
#include <span>
#include <string>
#include <system_error>
#include <vector>
// Helper that consolidates the long-running NSM command pipeline:
// queue submission, MCTP request/response, common-header decode,
// SUCCESS vs ACCEPTED branching, long-running response event handling.
//
// Per-command specifics (encode, payload decode) are supplied through
// Config callables. The helper has no knowledge of D-Bus, inventory,
// or which metric is calling it.
class NvidiaGpuLongRunningCommand :
public std::enable_shared_from_this<NvidiaGpuLongRunningCommand>
{
public:
struct Config
{
// Identifies the metric in log messages (e.g. "GPU Current
// Utilization").
std::string metricName;
gpu::MessageType messageType;
gpu::PlatformEnvironmentalCommands commandId;
// Size of the MCTP request buffer. The helper allocates a buffer of
// this size once at construction and reuses it across update() calls,
// so no per-request allocation occurs.
size_t requestSize;
// Fills the request bytes into `buf`. Returns 0 on success.
std::move_only_function<int(std::span<uint8_t> buf)> encodeRequest;
// Invoked when the device replies SUCCESS synchronously. `fullBuffer`
// is the entire MCTP response (including the common response header)
// so the caller can reuse the existing decodeGet*Response() helpers.
std::move_only_function<void(std::span<const uint8_t> fullBuffer)>
onImmediateSuccess;
// Invoked when the long-running response event arrives successfully.
// `payload` is the bytes the device returned for the command (no
// OCP/common header). The caller decodes via the matching
// decodeGet*Response() overload.
std::move_only_function<void(std::span<const uint8_t> payload)>
onLongRunningPayload;
};
NvidiaGpuLongRunningCommand(
uint8_t eid, mctp::MctpRequester& mctpRequester,
std::shared_ptr<SerialQueue> longRunningQueue,
std::shared_ptr<NvidiaLongRunningResponseHandler>
longRunningResponseHandler,
Config config);
void update();
private:
void doUpdate(SerialQueue::ReleaseHandle handle);
void processResponse(SerialQueue::ReleaseHandle handle,
const std::error_code& ec,
std::span<const uint8_t> buffer);
void processLongRunningResponse(
boost::system::error_code ec,
ocp::accelerator_management::CompletionCode cc, uint16_t reasonCode,
std::span<const uint8_t> responseData);
uint8_t eid;
mctp::MctpRequester& mctpRequester;
std::shared_ptr<SerialQueue> longRunningQueue;
std::shared_ptr<NvidiaLongRunningResponseHandler>
longRunningResponseHandler;
Config config;
std::vector<uint8_t> request;
bool requestEncoded{false};
};