linux/drivers/gpu/drm/i915/gt/uc/intel_huc.c

// SPDX-License-Identifier: MIT
/*
 * Copyright © 2016-2019 Intel Corporation
 */

#include <linux/types.h>

#include "gt/intel_gt.h"
#include "gt/intel_rps.h"
#include "intel_guc_reg.h"
#include "intel_huc.h"
#include "intel_huc_print.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "pxp/intel_pxp_cmd_interface_43.h"

#include <linux/device/bus.h>
#include <linux/mei_aux.h>

/**
 * DOC: HuC
 *
 * The HuC is a dedicated microcontroller for usage in media HEVC (High
 * Efficiency Video Coding) operations. Userspace can directly use the firmware
 * capabilities by adding HuC specific commands to batch buffers.
 *
 * The kernel driver is only responsible for loading the HuC firmware and
 * triggering its security authentication. This is done differently depending
 * on the platform:
 *
 * - older platforms (from Gen9 to most Gen12s): the load is performed via DMA
 *   and the authentication via GuC
 * - DG2: load and authentication are both performed via GSC.
 * - MTL and newer platforms: the load is performed via DMA (same as with
 *   not-DG2 older platforms), while the authentication is done in 2-steps,
 *   a first auth for clear-media workloads via GuC and a second one for all
 *   workloads via GSC.
 *
 * On platforms where the GuC does the authentication, to correctly do so the
 * HuC binary must be loaded before the GuC one.
 * Loading the HuC is optional; however, not using the HuC might negatively
 * impact power usage and/or performance of media workloads, depending on the
 * use-cases.
 * HuC must be reloaded on events that cause the WOPCM to lose its contents
 * (S3/S4, FLR); on older platforms the HuC must also be reloaded on GuC/GT
 * reset, while on newer ones it will survive that.
 *
 * See https://github.com/intel/media-driver for the latest details on HuC
 * functionality.
 */

/**
 * DOC: HuC Memory Management
 *
 * Similarly to the GuC, the HuC can't do any memory allocations on its own,
 * with the difference being that the allocations for HuC usage are handled by
 * the userspace driver instead of the kernel one. The HuC accesses the memory
 * via the PPGTT belonging to the context loaded on the VCS executing the
 * HuC-specific commands.
 */

/*
 * MEI-GSC load is an async process. The probing of the exposed aux device
 * (see intel_gsc.c) usually happens a few seconds after i915 probe, depending
 * on when the kernel schedules it. Unless something goes terribly wrong, we're
 * guaranteed for this to happen during boot, so the big timeout is a safety net
 * that we never expect to need.
 * MEI-PXP + HuC load usually takes ~300ms, but if the GSC needs to be resumed
 * and/or reset, this can take longer. Note that the kernel might schedule
 * other work between the i915 init/resume and the MEI one, which can add to
 * the delay.
 */
#define GSC_INIT_TIMEOUT_MS
#define PXP_INIT_TIMEOUT_MS

static int sw_fence_dummy_notify(struct i915_sw_fence *sf,
				 enum i915_sw_fence_notify state)
{}

static void __delayed_huc_load_complete(struct intel_huc *huc)
{}

static void delayed_huc_load_complete(struct intel_huc *huc)
{}

static void __gsc_init_error(struct intel_huc *huc)
{}

static void gsc_init_error(struct intel_huc *huc)
{}

static void gsc_init_done(struct intel_huc *huc)
{}

static enum hrtimer_restart huc_delayed_load_timer_callback(struct hrtimer *hrtimer)
{}

static void huc_delayed_load_start(struct intel_huc *huc)
{}

static int gsc_notifier(struct notifier_block *nb, unsigned long action, void *data)
{}

void intel_huc_register_gsc_notifier(struct intel_huc *huc, const struct bus_type *bus)
{}

void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, const struct bus_type *bus)
{}

static void delayed_huc_load_init(struct intel_huc *huc)
{}

static void delayed_huc_load_fini(struct intel_huc *huc)
{}

int intel_huc_sanitize(struct intel_huc *huc)
{}

static bool vcs_supported(struct intel_gt *gt)
{}

void intel_huc_init_early(struct intel_huc *huc)
{}

#define HUC_LOAD_MODE_STRING(x)
static int check_huc_loading_mode(struct intel_huc *huc)
{}

int intel_huc_init(struct intel_huc *huc)
{}

void intel_huc_fini(struct intel_huc *huc)
{}

void intel_huc_suspend(struct intel_huc *huc)
{}

static const char *auth_mode_string(struct intel_huc *huc,
				    enum intel_huc_authentication_type type)
{}

/*
 * Use a longer timeout for debug builds so that problems can be detected
 * and analysed. But a shorter timeout for releases so that user's don't
 * wait forever to find out there is a problem. Note that the only reason
 * an end user should hit the timeout is in case of extreme thermal throttling.
 * And a system that is that hot during boot is probably dead anyway!
 */
#if defined(CONFIG_DRM_I915_DEBUG_GEM)
#define HUC_LOAD_RETRY_LIMIT
#else
#define HUC_LOAD_RETRY_LIMIT
#endif

int intel_huc_wait_for_auth_complete(struct intel_huc *huc,
				     enum intel_huc_authentication_type type)
{}

/**
 * intel_huc_auth() - Authenticate HuC uCode
 * @huc: intel_huc structure
 * @type: authentication type (via GuC or via GSC)
 *
 * Called after HuC and GuC firmware loading during intel_uc_init_hw().
 *
 * This function invokes the GuC action to authenticate the HuC firmware,
 * passing the offset of the RSA signature to intel_guc_auth_huc(). It then
 * waits for up to 50ms for firmware verification ACK.
 */
int intel_huc_auth(struct intel_huc *huc, enum intel_huc_authentication_type type)
{}

bool intel_huc_is_authenticated(struct intel_huc *huc,
				enum intel_huc_authentication_type type)
{}

static bool huc_is_fully_authenticated(struct intel_huc *huc)
{}

/**
 * intel_huc_check_status() - check HuC status
 * @huc: intel_huc structure
 *
 * This function reads status register to verify if HuC
 * firmware was successfully loaded.
 *
 * The return values match what is expected for the I915_PARAM_HUC_STATUS
 * getparam.
 */
int intel_huc_check_status(struct intel_huc *huc)
{}

static bool huc_has_delayed_load(struct intel_huc *huc)
{}

void intel_huc_update_auth_status(struct intel_huc *huc)
{}

/**
 * intel_huc_load_status - dump information about HuC load status
 * @huc: the HuC
 * @p: the &drm_printer
 *
 * Pretty printer for HuC load status.
 */
void intel_huc_load_status(struct intel_huc *huc, struct drm_printer *p)
{}