Commit 997a55ca authored by Daniele Ceraolo Spurio's avatar Daniele Ceraolo Spurio
Browse files

drm/xe/gsc: Initialize GSC proxy



The GSC uC needs to communicate with the CSME to perform certain
operations. Since the GSC can't perform this communication directly on
platforms where it is integrated in GT, the graphics driver needs to
transfer the messages from GSC to CSME and back. The proxy flow must be
manually started after the GSC is loaded to signal to GSC that we're
ready to handle its messages and allow it to query its init data from
CSME.

Note that the component must be removed before the pci_remove call
completes, so we can't use a drmm helper for it and we need to instead
perform the cleanup as part of the removal flow.

v2: add function documentation, more targeted memory clear, clearer logs
and variable names (Alan)

Signed-off-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Cc: Suraj Kandpal <suraj.kandpal@intel.com>
Reviewed-by: default avatarAlan Previn <alan.previn.teres.alexis@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240117182621.2653049-2-daniele.ceraolospurio@intel.com
parent 6af7ee08
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ xe-y += xe_bb.o \
	xe_ggtt.o \
	xe_gpu_scheduler.o \
	xe_gsc.o \
	xe_gsc_proxy.o \
	xe_gsc_submit.o \
	xe_gt.o \
	xe_gt_ccs_mode.o \
+44 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: MIT */
/*
 * Copyright © 2023 Intel Corporation
 */

#ifndef _ABI_GSC_PROXY_COMMANDS_ABI_H
#define _ABI_GSC_PROXY_COMMANDS_ABI_H

#include <linux/types.h>

/* Heci client ID for proxy commands */
#define HECI_MEADDRESS_PROXY 10

/* FW-defined proxy header */
struct xe_gsc_proxy_header {
	/*
	 * hdr:
	 * Bits 0-7: type of the proxy message (see enum xe_gsc_proxy_type)
	 * Bits 8-15: rsvd
	 * Bits 16-31: length in bytes of the payload following the proxy header
	 */
	u32 hdr;
#define GSC_PROXY_TYPE		 GENMASK(7, 0)
#define GSC_PROXY_PAYLOAD_LENGTH GENMASK(31, 16)

	u32 source;		/* Source of the Proxy message */
	u32 destination;	/* Destination of the Proxy message */
#define GSC_PROXY_ADDRESSING_KMD  0x10000
#define GSC_PROXY_ADDRESSING_GSC  0x20000
#define GSC_PROXY_ADDRESSING_CSME 0x30000

	u32 status;		/* Command status */
} __packed;

/* FW-defined proxy types */
enum xe_gsc_proxy_type {
	GSC_PROXY_MSG_TYPE_PROXY_INVALID = 0,
	GSC_PROXY_MSG_TYPE_PROXY_QUERY = 1,
	GSC_PROXY_MSG_TYPE_PROXY_PAYLOAD = 2,
	GSC_PROXY_MSG_TYPE_PROXY_END = 3,
	GSC_PROXY_MSG_TYPE_PROXY_NOTIFICATION = 4,
};

#endif
+20 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "xe_exec_queue.h"
#include "xe_exec.h"
#include "xe_ggtt.h"
#include "xe_gsc_proxy.h"
#include "xe_gt.h"
#include "xe_gt_mcr.h"
#include "xe_irq.h"
@@ -434,6 +435,7 @@ int xe_device_probe(struct xe_device *xe)
	struct xe_tile *tile;
	struct xe_gt *gt;
	int err;
	u8 last_gt;
	u8 id;

	xe_pat_init_early(xe);
@@ -521,16 +523,18 @@ int xe_device_probe(struct xe_device *xe)
		goto err_irq_shutdown;

	for_each_gt(gt, xe, id) {
		last_gt = id;

		err = xe_gt_init(gt);
		if (err)
			goto err_irq_shutdown;
			goto err_fini_gt;
	}

	xe_heci_gsc_init(xe);

	err = xe_display_init(xe);
	if (err)
		goto err_irq_shutdown;
		goto err_fini_gt;

	err = drm_dev_register(&xe->drm, 0);
	if (err)
@@ -551,6 +555,14 @@ int xe_device_probe(struct xe_device *xe)
err_fini_display:
	xe_display_driver_remove(xe);

err_fini_gt:
	for_each_gt(gt, xe, id) {
		if (id < last_gt)
			xe_gt_remove(gt);
		else
			break;
	}

err_irq_shutdown:
	xe_irq_shutdown(xe);
err:
@@ -568,12 +580,18 @@ static void xe_device_remove_display(struct xe_device *xe)

void xe_device_remove(struct xe_device *xe)
{
	struct xe_gt *gt;
	u8 id;

	xe_device_remove_display(xe);

	xe_display_fini(xe);

	xe_heci_gsc_fini(xe);

	for_each_gt(gt, xe, id)
		xe_gt_remove(gt);

	xe_irq_shutdown(xe);
}

+41 −11
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include "xe_bo.h"
#include "xe_device.h"
#include "xe_exec_queue.h"
#include "xe_gsc_proxy.h"
#include "xe_gsc_submit.h"
#include "xe_gt.h"
#include "xe_gt_printk.h"
@@ -242,8 +243,31 @@ static int gsc_upload(struct xe_gsc *gsc)
	if (err)
		return err;

	return 0;
}

static int gsc_upload_and_init(struct xe_gsc *gsc)
{
	struct xe_gt *gt = gsc_to_gt(gsc);
	int ret;

	ret = gsc_upload(gsc);
	if (ret)
		return ret;

	xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
	xe_gt_dbg(gt, "GSC FW async load completed\n");

	/* HuC auth failure is not fatal */
	if (xe_huc_is_authenticated(&gt->uc.huc, XE_HUC_AUTH_VIA_GUC))
		xe_huc_auth(&gt->uc.huc, XE_HUC_AUTH_VIA_GSC);

	ret = xe_gsc_proxy_start(gsc);
	if (ret)
		return ret;

	xe_gt_dbg(gt, "GSC proxy init completed\n");

	return 0;
}

@@ -257,19 +281,12 @@ static void gsc_work(struct work_struct *work)
	xe_device_mem_access_get(xe);
	xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC);

	ret = gsc_upload(gsc);
	if (ret && ret != -EEXIST) {
	ret = gsc_upload_and_init(gsc);
	if (ret && ret != -EEXIST)
		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
		goto out;
	}
	else
		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_RUNNING);

	xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);

	/* HuC auth failure is not fatal */
	if (xe_huc_is_authenticated(&gt->uc.huc, XE_HUC_AUTH_VIA_GUC))
		xe_huc_auth(&gt->uc.huc, XE_HUC_AUTH_VIA_GSC);

out:
	xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC);
	xe_device_mem_access_put(xe);
}
@@ -302,6 +319,10 @@ int xe_gsc_init(struct xe_gsc *gsc)
	else if (ret)
		goto out;

	ret = xe_gsc_proxy_init(gsc);
	if (ret && ret != -ENODEV)
		goto out;

	return 0;

out:
@@ -410,6 +431,15 @@ void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc)
		flush_work(&gsc->work);
}

/**
 * xe_gsc_remove() - Clean up the GSC structures before driver removal
 * @gsc: the GSC uC
 */
void xe_gsc_remove(struct xe_gsc *gsc)
{
	xe_gsc_proxy_remove(gsc);
}

/*
 * wa_14015076503: if the GSC FW is loaded, we need to alert it before doing a
 * GSC engine reset by writing a notification bit in the GS1 register and then
+1 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ int xe_gsc_init(struct xe_gsc *gsc);
int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc);
void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc);
void xe_gsc_load_start(struct xe_gsc *gsc);
void xe_gsc_remove(struct xe_gsc *gsc);

void xe_gsc_wa_14015076503(struct xe_gt *gt, bool prep);

Loading