Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33a732f4 authored by Alex Dai's avatar Alex Dai Committed by Daniel Vetter
Browse files

drm/i915: GuC-specific firmware loader



This fetches the required firmware image from the filesystem,
then loads it into the GuC's memory via a dedicated DMA engine.

This patch is derived from GuC loading work originally done by
Vinit Azad and Ben Widawsky.

v2:
    Various improvements per review comments by Chris Wilson

v3:
    Removed 'wait' parameter to intel_guc_ucode_load() as firmware
        prefetch is no longer supported in the common firmware loader,
	per Daniel Vetter's request.
    Firmware checker callback fn now returns errno rather than bool.

v4:
    Squash uC-independent code into GuC-specifc loader [Daniel Vetter]
    Don't keep the driver working (by falling back to execlist mode)
        if GuC firmware loading fails [Daniel Vetter]

v5:
    Clarify WOPCM-related #defines [Tom O'Rourke]
    Delete obsolete code no longer required with current h/w & f/w
        [Tom O'Rourke]
    Move the call to intel_guc_ucode_init() later, so that it can
        allocate GEM objects, and have it fetch the firmware; then
	intel_guc_ucode_load() doesn't need to fetch it later.
        [Daniel Vetter].

v6:
    Update comment describing intel_guc_ucode_load() [Tom O'Rourke]

Issue: VIZ-4884
Signed-off-by: default avatarAlex Dai <yu.dai@intel.com>
Signed-off-by: default avatarDave Gordon <david.s.gordon@intel.com>
Reviewed-by: default avatarTom O'Rourke <Tom.O'Rourke@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 04a60f9f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -40,6 +40,9 @@ i915-y += i915_cmd_parser.o \
	  intel_ringbuffer.o \
	  intel_uncore.o

# general-purpose microcontroller (GuC) support
i915-y += intel_guc_loader.o

# autogenerated null render state
i915-y += intel_renderstate_gen6.o \
	  intel_renderstate_gen7.o \
+9 −0
Original line number Diff line number Diff line
@@ -435,6 +435,11 @@ static int i915_load_modeset_init(struct drm_device *dev)
	 * working irqs for e.g. gmbus and dp aux transfers. */
	intel_modeset_init(dev);

	/* intel_guc_ucode_init() needs the mutex to allocate GEM objects */
	mutex_lock(&dev->struct_mutex);
	intel_guc_ucode_init(dev);
	mutex_unlock(&dev->struct_mutex);

	ret = i915_gem_init(dev);
	if (ret)
		goto cleanup_irq;
@@ -476,6 +481,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
	i915_gem_context_fini(dev);
	mutex_unlock(&dev->struct_mutex);
cleanup_irq:
	mutex_lock(&dev->struct_mutex);
	intel_guc_ucode_fini(dev);
	mutex_unlock(&dev->struct_mutex);
	drm_irq_uninstall(dev);
cleanup_gem_stolen:
	i915_gem_cleanup_stolen(dev);
@@ -1128,6 +1136,7 @@ int i915_driver_unload(struct drm_device *dev)
	flush_workqueue(dev_priv->wq);

	mutex_lock(&dev->struct_mutex);
	intel_guc_ucode_fini(dev);
	i915_gem_cleanup_ringbuffer(dev);
	i915_gem_context_fini(dev);
	mutex_unlock(&dev->struct_mutex);
+11 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@
#include <linux/intel-iommu.h>
#include <linux/kref.h>
#include <linux/pm_qos.h>
#include "intel_guc.h"

/* General customization:
 */
@@ -1709,6 +1710,8 @@ struct drm_i915_private {

	struct i915_virtual_gpu vgpu;

	struct intel_guc guc;

	struct intel_csr csr;

	/* Display CSR-related protection */
@@ -1953,6 +1956,11 @@ static inline struct drm_i915_private *dev_to_i915(struct device *dev)
	return to_i915(dev_get_drvdata(dev));
}

static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
{
	return container_of(guc, struct drm_i915_private, guc);
}

/* Iterate over initialised rings */
#define for_each_ring(ring__, dev_priv__, i__) \
	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
@@ -2557,6 +2565,9 @@ struct drm_i915_cmd_table {

#define HAS_CSR(dev)	(IS_SKYLAKE(dev))

#define HAS_GUC_UCODE(dev)	(IS_GEN9(dev))
#define HAS_GUC_SCHED(dev)	(IS_GEN9(dev))

#define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
				    INTEL_INFO(dev)->gen >= 8)

+16 −0
Original line number Diff line number Diff line
@@ -4681,6 +4681,22 @@ i915_gem_init_hw(struct drm_device *dev)
			goto out;
	}

	/* We can't enable contexts until all firmware is loaded */
	ret = intel_guc_ucode_load(dev);
	if (ret) {
		/*
		 * If we got an error and GuC submission is enabled, map
		 * the error to -EIO so the GPU will be declared wedged.
		 * OTOH, if we didn't intend to use the GuC anyway, just
		 * discard the error and carry on.
		 */
		DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret,
			i915.enable_guc_submission ? "" : " (ignored)");
		ret = i915.enable_guc_submission ? -EIO : 0;
		if (ret)
			goto out;
	}

	/* Now it is safe to go back round and do everything else: */
	for_each_ring(ring, dev_priv, i) {
		struct drm_i915_gem_request *req;
+11 −6
Original line number Diff line number Diff line
@@ -38,10 +38,6 @@
#define   GS_MIA_SHIFT			16
#define   GS_MIA_MASK			  (0x07 << GS_MIA_SHIFT)

#define GUC_WOPCM_SIZE			0xc050
#define   GUC_WOPCM_SIZE_VALUE  	  (0x80 << 12)	/* 512KB */
#define GUC_WOPCM_OFFSET		0x80000		/* 512KB */

#define SOFT_SCRATCH(n)			(0xc180 + ((n) * 4))

#define UOS_RSA_SCRATCH_0		0xc200
@@ -56,10 +52,18 @@
#define   UOS_MOVE			  (1<<4)
#define   START_DMA			  (1<<0)
#define DMA_GUC_WOPCM_OFFSET		0xc340
#define   GUC_WOPCM_OFFSET_VALUE	  0x80000	/* 512KB */

#define GUC_WOPCM_SIZE			0xc050
#define   GUC_WOPCM_SIZE_VALUE  	  (0x80 << 12)	/* 512KB */

/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */
#define	GUC_WOPCM_TOP			(GUC_WOPCM_SIZE_VALUE)

#define GEN8_GT_PM_CONFIG		0x138140
#define GEN9LP_GT_PM_CONFIG		0x138140
#define GEN9_GT_PM_CONFIG		0x13816c
#define   GEN8_GT_DOORBELL_ENABLE	  (1<<0)
#define   GT_DOORBELL_ENABLE		  (1<<0)

#define GEN8_GTCR			0x4274
#define   GEN8_GTCR_INVALIDATE		  (1<<0)
@@ -80,7 +84,8 @@
				 GUC_ENABLE_READ_CACHE_LOGIC		| \
				 GUC_ENABLE_MIA_CACHING			| \
				 GUC_ENABLE_READ_CACHE_FOR_SRAM_DATA	| \
				 GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA)
				 GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA	| \
				 GUC_ENABLE_MIA_CLOCK_GATING)

#define HOST2GUC_INTERRUPT		0xc4c8
#define   HOST2GUC_TRIGGER		  (1<<0)
Loading