[Intel-gfx] [PATCH 05/15] drm/i915: GuC-specific firmware loader

Dave Gordon david.s.gordon at intel.com
Mon Jul 6 09:37:57 PDT 2015


On 06/07/15 15:28, Daniel Vetter wrote:
> On Fri, Jul 03, 2015 at 01:30:27PM +0100, Dave Gordon wrote:
>> From: Alex Dai <yu.dai at intel.com>
>>
>> This uses the common firmware loader to fetch the firmware image,
>> 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. It has been reconstructed to accord
>> with the common firmware loading mechanism by Dave Gordon as well
>> as new firmware layout etc.
>>
>> v2:
>>      Various improvements per review comments by Chris Wilson
>>
>> v3:
>>      Removed 'wait' parameter to intel_guc_ucode_load() as prefetch
>>          is no longer supported in the common firmware loader, per
>> 	Daniel Vetter's request.
>>      F/w checker callback fn now returns errno rather than bool.
>>
>> Issue: VIZ-4884
>> Signed-off-by: Alex Dai <yu.dai at intel.com>
>> Signed-off-by: Dave Gordon <david.s.gordon at intel.com>
>> ---
>>   drivers/gpu/drm/i915/Makefile           |   3 +
>>   drivers/gpu/drm/i915/i915_dma.c         |   4 +
>>   drivers/gpu/drm/i915/i915_drv.h         |  11 +
>>   drivers/gpu/drm/i915/i915_gem.c         |   8 +
>>   drivers/gpu/drm/i915/i915_reg.h         |   4 +-
>>   drivers/gpu/drm/i915/intel_guc.h        |  49 ++++
>>   drivers/gpu/drm/i915/intel_guc_loader.c | 448 ++++++++++++++++++++++++++++++++
>>   7 files changed, 526 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/i915/intel_guc.h
>>   create mode 100644 drivers/gpu/drm/i915/intel_guc_loader.c
>>
>> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
>> index f1f80fc..62a8c83 100644
>> --- a/drivers/gpu/drm/i915/Makefile
>> +++ b/drivers/gpu/drm/i915/Makefile
>> @@ -42,6 +42,9 @@ i915-y += i915_cmd_parser.o \
>>   # generic ancilliary microcontroller support
>>   i915-y += intel_uc_loader.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 \
>> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
>> index c5349fa..730d91b 100644
>> --- a/drivers/gpu/drm/i915/i915_dma.c
>> +++ b/drivers/gpu/drm/i915/i915_dma.c
>> @@ -469,6 +469,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
>>
>>   cleanup_gem:
>>   	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);
>> @@ -866,6 +867,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>>
>>   	intel_uncore_init(dev);
>>
>> +	intel_guc_ucode_init(dev);
>> +
>>   	/* Load CSR Firmware for SKL */
>>   	intel_csr_ucode_init(dev);
>>
>> @@ -1117,6 +1120,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);
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index 9618f57..a7ccac5 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -50,6 +50,7 @@
>>   #include <linux/intel-iommu.h>
>>   #include <linux/kref.h>
>>   #include <linux/pm_qos.h>
>> +#include "intel_guc.h"
>>
>>   /* General customization:
>>    */
>> @@ -1687,6 +1688,8 @@ struct drm_i915_private {
>>
>>   	struct i915_virtual_gpu vgpu;
>>
>> +	struct intel_guc guc;
>> +
>>   	struct intel_csr csr;
>>
>>   	/* Display CSR-related protection */
>> @@ -1931,6 +1934,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__)++) \
>> @@ -2539,6 +2547,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 INTEL_PCH_DEVICE_ID_MASK		0xff00
>>   #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
>>   #define INTEL_PCH_CPT_DEVICE_ID_TYPE		0x1c00
>> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>> index aa8f4c3..80d7890 100644
>> --- a/drivers/gpu/drm/i915/i915_gem.c
>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>> @@ -5076,6 +5076,14 @@ i915_gem_init_hw(struct drm_device *dev)
>>   			goto out;
>>   	}
>>
>> +	/*
>> +	 * We can't enable contexts until all firmware is loaded; if this
>> +	 * fails, disable GuC submissions and fall back to execlist mode
>> +	 */
>> +	ret = intel_guc_ucode_load(dev);
>> +	if (ret)
>> +		i915.enable_guc_submission = false;
>
> I want an -EIO or similar here since runtime fallbacks to other modes
> really aren't great from a maintainance perspective, see my comments on
> the irq routing code.
>
> Yes we can make this work, but givin our stellar track record with keeping
> disabled features working it won't work for long. And it will impact us
> with additional constraints until we give up and rip it out again. Not
> worth it imo - if we decide to use the guc on a given platform we should
> imo require it and stick to that decision for at least as long as the
> driver is loaded. Developers can still change the option when reloading the
> driver, users won't have a chance to cause trouble.
> -Daniel

Again, this isn't really "runtime" -- we're still in the driver loading 
stage here. This is analogous to the various "sanitize" functions where 
we cross-check what options have been set and decide which to override, 
except that here we can't determine whether we're going to respect the 
default or user-specified request for GuC submission mode until we know 
whether we have valid firmware for the GuC.

At this point, we haven't submitted any batches, so the main point of 
use of this flag -- in the submission path, to switch between execlist 
and GuC modes -- has never yet been executed. So there should be no 
problem with changing the value before it's first used.

And this is a one-way switch; you (or the default config) asked for GuC 
submission, but we can't support it so we disable the option. There's no 
way to switch it back on without reloading the driver. So this /is/ the 
point at which we decide to use the GuC on a given platform and then 
stick to that decision for at least as long as the driver is loaded.

We have to support execlist mode for the foreseeable future anyway, so 
using it on a machine which (we think) ought to be GuC-capable doesn't 
add /any/ extra maintenance overhead at all.

Why break the user's machine unnecessarily? With real "end-users", 
especially those who have never used Linux before, you only get one 
chance. Sometimes I've installed Linux on a (Windows-using) friend's 
machine, and it hasn't worked first time. Then I switch to another VT, 
type some magic incantations, and 10 minutes later we have a usable 
login screen. Will they adopt Linux? Unlikely :( No matter how good it 
looks thereafter, if the machine's hardware doesn't work with the distro 
straight out of the box, they're just not going to believe it's 
something they can use. So it's very important that everything essential 
to the first-time experience works even when misconfigured -- and 
nothing is more essential than the display driver (networking and wi-fi 
are the next things that will put the user off if they don't work -- and 
they're also drivers that commonly rely on firmware blobs).

.Dave.


More information about the Intel-gfx mailing list