[Intel-gfx] [CI 11/15] drm/i915/huc: track delayed HuC load with a fence

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Wed Oct 19 09:54:34 UTC 2022


Hi,

Don't know if this is real or not yet, hit it while running selftests a bit. Something to keep an eye on.

[ 2928.370577] ODEBUG: init destroyed (active state 0) object type: i915_sw_fence hint: sw_fence_dummy_notify+0x0/0x10 [i915]
[ 2928.370903] WARNING: CPU: 2 PID: 1113 at lib/debugobjects.c:502 debug_print_object+0x6b/0x90
[ 2928.370984] Modules linked in: i915(+) drm_display_helper drm_kms_helper netconsole cmac algif_hash algif_skcipher af_alg bnep nls_iso8859_1 snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio snd_intel_dspcfg snd_hda_codec snd_hwdep snd_hda_core snd_pcm intel_tcc_cooling x86_pkg_temp_thermal intel_powerclamp snd_seq_midi snd_seq_midi_event coretemp snd_rawmidi btusb btrtl btbcm kvm_intel btmtk btintel ath10k_pci snd_seq kvm ath10k_core bluetooth snd_timer rapl intel_cstate snd_seq_device input_leds mac80211 ecdh_generic libarc4 ath snd ecc serio_raw intel_wmi_thunderbolt at24 soundcore cfg80211 mei_me intel_xhci_usb_role_switch mei ideapad_laptop intel_pch_thermal platform_profile sparse_keymap acpi_pad sch_fq_codel msr efi_pstore ip_tables x_tables autofs4 crct10dif_pclmul crc32_pclmul ghash_clmulni_intel sha512_ssse3 aesni_intel prime_numbers crypto_simd atkbd drm_buddy cryptd vivaldi_fmap r8169 ttm i2c_i801 i2c_smbus cec realtek xhci_pci syscopyarea ahci
[ 2928.371145]  xhci_pci_renesas sysfillrect sysimgblt libahci fb_sys_fops video wmi [last unloaded: drm_kms_helper]
[ 2928.371489] CPU: 2 PID: 1113 Comm: modprobe Tainted: G     U  W          6.1.0-rc1 #196
[ 2928.371550] Hardware name: LENOVO 80MX/Lenovo E31-80, BIOS DCCN34WW(V2.03) 12/01/2015
[ 2928.371615] RIP: 0010:debug_print_object+0x6b/0x90
[ 2928.371664] Code: 49 89 c1 8b 43 10 83 c2 01 48 c7 c7 e8 be d6 bb 8b 4b 14 89 15 ca be b4 02 4c 8b 45 00 48 8b 14 c5 40 56 a8 bb e8 ec 5b 60 00 <0f> 0b 83 05 28 5a 3e 01 01 48 83 c4 08 5b 5d c3 83 05 1a 5a 3e 01
[ 2928.371782] RSP: 0018:ffff9ed841607a18 EFLAGS: 00010286
[ 2928.371841] RAX: 0000000000000000 RBX: ffff9208116a1d48 RCX: 0000000000000000
[ 2928.371909] RDX: 0000000000000001 RSI: ffffffffbbd277d2 RDI: 00000000ffffffff
[ 2928.372024] RBP: ffffffffc176a540 R08: 0000000000000000 R09: ffffffffbc07a1e0
[ 2928.372128] R10: 0000000000000001 R11: 0000000000000001 R12: ffff9208122da830
[ 2928.372192] R13: ffff92080089b000 R14: ffff9208122da770 R15: 0000000000000000
[ 2928.372259] FS:  00007f53e7617c40(0000) GS:ffff92086e500000(0000) knlGS:0000000000000000
[ 2928.372365] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 2928.372425] CR2: 000055cd28b33070 CR3: 0000000110dbd006 CR4: 00000000003706e0
[ 2928.372526] Call Trace:
[ 2928.372568]  <TASK>
[ 2928.372614]  ? intel_guc_hang_check+0xb0/0xb0 [i915]
[ 2928.373001]  __i915_sw_fence_init+0x2b/0x50 [i915]
[ 2928.373374]  intel_huc_init_early+0x75/0xb0 [i915]
[ 2928.373868]  intel_uc_init_early+0x4e/0x210 [i915]
[ 2928.374241]  intel_gt_common_init_early+0x16f/0x180 [i915]
[ 2928.374718]  intel_root_gt_init_early+0x49/0x60 [i915]
[ 2928.375074]  i915_driver_probe+0x917/0xed0 [i915]
[ 2928.375398]  ? drm_privacy_screen_get+0x163/0x1a0
[ 2928.375512]  i915_pci_probe+0xb0/0x230 [i915]
[ 2928.375823]  ? _raw_spin_unlock_irqrestore+0x38/0x50
[ 2928.375896]  pci_device_probe+0xa4/0x140
[ 2928.375930]  really_probe+0xd8/0x380
[ 2928.375992]  ? pm_runtime_barrier+0x50/0x80
[ 2928.376056]  __driver_probe_device+0x78/0x170
[ 2928.376103]  driver_probe_device+0x1e/0x80
[ 2928.376134]  __driver_attach+0x98/0x1e0
[ 2928.376161]  ? __device_attach_driver+0xf0/0xf0
[ 2928.376206]  ? __device_attach_driver+0xf0/0xf0
[ 2928.376237]  bus_for_each_dev+0x78/0xc0
[ 2928.376285]  bus_add_driver+0x1ad/0x200
[ 2928.376315]  driver_register+0x8f/0xe0
[ 2928.376344]  i915_init+0x1a/0x73 [i915]
[ 2928.376715]  ? 0xffffffffc04d0000
[ 2928.376766]  do_one_initcall+0x58/0x300
[ 2928.376824]  ? rcu_read_lock_sched_held+0x3f/0x70
[ 2928.376884]  ? trace_kmalloc+0x2c/0xd0
[ 2928.376951]  ? kmalloc_trace+0x44/0x50
[ 2928.377009]  do_init_module+0x4c/0x1e0
[ 2928.377069]  __do_sys_finit_module+0xb4/0x120
[ 2928.377156]  do_syscall_64+0x56/0x80
[ 2928.377210]  ? do_syscall_64+0x63/0x80
[ 2928.377264]  ? lockdep_hardirqs_on+0x79/0x100
[ 2928.377321]  ? do_syscall_64+0x63/0x80
[ 2928.377389]  ? lockdep_hardirqs_on+0x79/0x100
[ 2928.377464]  ? do_syscall_64+0x63/0x80
[ 2928.377516]  ? do_syscall_64+0x63/0x80
[ 2928.377566]  ? lockdep_hardirqs_on+0x79/0x100
[ 2928.377624]  ? do_syscall_64+0x63/0x80
[ 2928.377673]  ? lockdep_hardirqs_on+0x79/0x100
[ 2928.377728]  ? do_syscall_64+0x63/0x80
[ 2928.377779]  ? do_syscall_64+0x63/0x80
[ 2928.377830]  ? do_syscall_64+0x63/0x80
[ 2928.377882]  ? lockdep_hardirqs_on+0x79/0x100
[ 2928.377939]  entry_SYSCALL_64_after_hwframe+0x46/0xb0
[ 2928.378002] RIP: 0033:0x7f53e6d1ea3d
[ 2928.378054] Code: 5b 41 5c c3 66 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d c3 a3 0f 00 f7 d8 64 89 01 48
[ 2928.378184] RSP: 002b:00007ffee7d9bc08 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
[ 2928.378260] RAX: ffffffffffffffda RBX: 000055cd28b2cdf0 RCX: 00007f53e6d1ea3d
[ 2928.378327] RDX: 0000000000000000 RSI: 000055cd28b339f0 RDI: 0000000000000005
[ 2928.378392] RBP: 0000000000040000 R08: 0000000000000000 R09: 0000000000000002
[ 2928.378472] R10: 0000000000000005 R11: 0000000000000246 R12: 000055cd28b339f0
[ 2928.378539] R13: 000055cd28b2cf20 R14: 0000000000000000 R15: 000055cd28b33eb0
[ 2928.378634]  </TASK>
[ 2928.378675] irq event stamp: 133143
[ 2928.378738] hardirqs last  enabled at (133153): [<ffffffffbaafef92>] __up_console_sem+0x52/0x60
[ 2928.378833] hardirqs last disabled at (133162): [<ffffffffbaafef77>] __up_console_sem+0x37/0x60
[ 2928.378959] softirqs last  enabled at (132814): [<ffffffffbaa86bc1>] __irq_exit_rcu+0xc1/0x110
[ 2928.379037] softirqs last disabled at (132601): [<ffffffffbaa86bc1>] __irq_exit_rcu+0xc1/0x110
[ 2928.379126] ---[ end trace 0000000000000000 ]---

Regards,

Tvrtko

On 28/09/2022 01:41, Daniele Ceraolo Spurio wrote:
> Given that HuC load is delayed on DG2, this patch adds support for a fence
> that can be used to wait for load completion. No waiters are added in this
> patch (they're coming up in the next one), to keep the focus of the
> patch on the tracking logic.
> 
> The full HuC loading flow on boot DG2 is as follows:
> 1) i915 exports the GSC as an aux device;
> 2) the mei-gsc driver is loaded on the aux device;
> 3) the mei-pxp component is loaded;
> 4) mei-pxp calls back into i915 and we load the HuC.
> 
> Between steps 1 and 2 there can be several seconds of gap, mainly due to
> the kernel doing other work during the boot.
> The resume flow is slightly different, because we don't need to
> re-expose or re-probe the aux device, so we go directly to step 3 once
> i915 and mei-gsc have completed their resume flow.
> 
> Here's an example of the boot timing, captured with some logs added to
> i915:
> 
> [   17.908307] [drm] adding GSC device
> [   17.915717] [drm] i915 probe done
> [   22.282917] [drm] mei-gsc bound
> [   22.938153] [drm] HuC authenticated
> 
> Also to note is that if something goes wrong during GSC HW init the
> mei-gsc driver will still bind, but steps 3 and 4 will not happen.
> 
> The status tracking is done by registering a bus_notifier to receive a
> callback when the mei-gsc driver binds, with a large enough timeout to
> account for delays. Once mei-gsc is bound, we switch to a smaller
> timeout to wait for the mei-pxp component to load.
> The fence is signalled on HuC load complete or if anything goes wrong in
> any of the tracking steps. Timeout are enforced via hrtimer callbacks.
> 
> v2: fix includes (Jani)
> v5: gsc_notifier() remove unneeded ()
> 
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
> Reviewed-by: Alan Previn <alan.previn.teres.alexis at intel.com>
> ---
>   drivers/gpu/drm/i915/gt/intel_gsc.c    |  22 ++-
>   drivers/gpu/drm/i915/gt/uc/intel_huc.c | 199 +++++++++++++++++++++++++
>   drivers/gpu/drm/i915/gt/uc/intel_huc.h |  23 +++
>   3 files changed, 241 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_gsc.c b/drivers/gpu/drm/i915/gt/intel_gsc.c
> index d56f75b605d8..976fdf27e790 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gsc.c
> +++ b/drivers/gpu/drm/i915/gt/intel_gsc.c
> @@ -143,8 +143,14 @@ static void gsc_destroy_one(struct drm_i915_private *i915,
>   	struct intel_gsc_intf *intf = &gsc->intf[intf_id];
>   
>   	if (intf->adev) {
> -		auxiliary_device_delete(&intf->adev->aux_dev);
> -		auxiliary_device_uninit(&intf->adev->aux_dev);
> +		struct auxiliary_device *aux_dev = &intf->adev->aux_dev;
> +
> +		if (intf_id == 0)
> +			intel_huc_unregister_gsc_notifier(&gsc_to_gt(gsc)->uc.huc,
> +							  aux_dev->dev.bus);
> +
> +		auxiliary_device_delete(aux_dev);
> +		auxiliary_device_uninit(aux_dev);
>   		intf->adev = NULL;
>   	}
>   
> @@ -243,14 +249,24 @@ static void gsc_init_one(struct drm_i915_private *i915, struct intel_gsc *gsc,
>   		goto fail;
>   	}
>   
> +	intf->adev = adev; /* needed by the notifier */
> +
> +	if (intf_id == 0)
> +		intel_huc_register_gsc_notifier(&gsc_to_gt(gsc)->uc.huc,
> +						aux_dev->dev.bus);
> +
>   	ret = auxiliary_device_add(aux_dev);
>   	if (ret < 0) {
>   		drm_err(&i915->drm, "gsc aux add failed %d\n", ret);
> +		if (intf_id == 0)
> +			intel_huc_unregister_gsc_notifier(&gsc_to_gt(gsc)->uc.huc,
> +							  aux_dev->dev.bus);
> +		intf->adev = NULL;
> +
>   		/* adev will be freed with the put_device() and .release sequence */
>   		auxiliary_device_uninit(aux_dev);
>   		goto fail;
>   	}
> -	intf->adev = adev;
>   
>   	return;
>   fail:
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
> index f0188931d8e4..5f2144c78f8a 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
> @@ -10,6 +10,9 @@
>   #include "intel_huc.h"
>   #include "i915_drv.h"
>   
> +#include <linux/device/bus.h>
> +#include <linux/mei_aux.h>
> +
>   /**
>    * DOC: HuC
>    *
> @@ -42,6 +45,164 @@
>    * 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.
> + */
> +#define GSC_INIT_TIMEOUT_MS 10000
> +#define PXP_INIT_TIMEOUT_MS 2000
> +
> +static int sw_fence_dummy_notify(struct i915_sw_fence *sf,
> +				 enum i915_sw_fence_notify state)
> +{
> +	return NOTIFY_DONE;
> +}
> +
> +static void __delayed_huc_load_complete(struct intel_huc *huc)
> +{
> +	if (!i915_sw_fence_done(&huc->delayed_load.fence))
> +		i915_sw_fence_complete(&huc->delayed_load.fence);
> +}
> +
> +static void delayed_huc_load_complete(struct intel_huc *huc)
> +{
> +	hrtimer_cancel(&huc->delayed_load.timer);
> +	__delayed_huc_load_complete(huc);
> +}
> +
> +static void __gsc_init_error(struct intel_huc *huc)
> +{
> +	huc->delayed_load.status = INTEL_HUC_DELAYED_LOAD_ERROR;
> +	__delayed_huc_load_complete(huc);
> +}
> +
> +static void gsc_init_error(struct intel_huc *huc)
> +{
> +	hrtimer_cancel(&huc->delayed_load.timer);
> +	__gsc_init_error(huc);
> +}
> +
> +static void gsc_init_done(struct intel_huc *huc)
> +{
> +	hrtimer_cancel(&huc->delayed_load.timer);
> +
> +	/* MEI-GSC init is done, now we wait for MEI-PXP to bind */
> +	huc->delayed_load.status = INTEL_HUC_WAITING_ON_PXP;
> +	if (!i915_sw_fence_done(&huc->delayed_load.fence))
> +		hrtimer_start(&huc->delayed_load.timer,
> +			      ms_to_ktime(PXP_INIT_TIMEOUT_MS),
> +			      HRTIMER_MODE_REL);
> +}
> +
> +static enum hrtimer_restart huc_delayed_load_timer_callback(struct hrtimer *hrtimer)
> +{
> +	struct intel_huc *huc = container_of(hrtimer, struct intel_huc, delayed_load.timer);
> +
> +	if (!intel_huc_is_authenticated(huc)) {
> +		drm_err(&huc_to_gt(huc)->i915->drm,
> +			"timed out waiting for GSC init to load HuC\n");
> +
> +		__gsc_init_error(huc);
> +	}
> +
> +	return HRTIMER_NORESTART;
> +}
> +
> +static void huc_delayed_load_start(struct intel_huc *huc)
> +{
> +	ktime_t delay;
> +
> +	GEM_BUG_ON(intel_huc_is_authenticated(huc));
> +
> +	/*
> +	 * On resume we don't have to wait for MEI-GSC to be re-probed, but we
> +	 * do need to wait for MEI-PXP to reset & re-bind
> +	 */
> +	switch (huc->delayed_load.status) {
> +	case INTEL_HUC_WAITING_ON_GSC:
> +		delay = ms_to_ktime(GSC_INIT_TIMEOUT_MS);
> +		break;
> +	case INTEL_HUC_WAITING_ON_PXP:
> +		delay = ms_to_ktime(PXP_INIT_TIMEOUT_MS);
> +		break;
> +	default:
> +		gsc_init_error(huc);
> +		return;
> +	}
> +
> +	/*
> +	 * This fence is always complete unless we're waiting for the
> +	 * GSC device to come up to load the HuC. We arm the fence here
> +	 * and complete it when we confirm that the HuC is loaded from
> +	 * the PXP bind callback.
> +	 */
> +	GEM_BUG_ON(!i915_sw_fence_done(&huc->delayed_load.fence));
> +	i915_sw_fence_fini(&huc->delayed_load.fence);
> +	i915_sw_fence_reinit(&huc->delayed_load.fence);
> +	i915_sw_fence_await(&huc->delayed_load.fence);
> +	i915_sw_fence_commit(&huc->delayed_load.fence);
> +
> +	hrtimer_start(&huc->delayed_load.timer, delay, HRTIMER_MODE_REL);
> +}
> +
> +static int gsc_notifier(struct notifier_block *nb, unsigned long action, void *data)
> +{
> +	struct device *dev = data;
> +	struct intel_huc *huc = container_of(nb, struct intel_huc, delayed_load.nb);
> +	struct intel_gsc_intf *intf = &huc_to_gt(huc)->gsc.intf[0];
> +
> +	if (!intf->adev || &intf->adev->aux_dev.dev != dev)
> +		return 0;
> +
> +	switch (action) {
> +	case BUS_NOTIFY_BOUND_DRIVER: /* mei driver bound to aux device */
> +		gsc_init_done(huc);
> +		break;
> +
> +	case BUS_NOTIFY_DRIVER_NOT_BOUND: /* mei driver fails to be bound */
> +	case BUS_NOTIFY_UNBIND_DRIVER: /* mei driver about to be unbound */
> +		drm_info(&huc_to_gt(huc)->i915->drm,
> +			 "mei driver not bound, disabling HuC load\n");
> +		gsc_init_error(huc);
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +void intel_huc_register_gsc_notifier(struct intel_huc *huc, struct bus_type *bus)
> +{
> +	int ret;
> +
> +	if (!intel_huc_is_loaded_by_gsc(huc))
> +		return;
> +
> +	huc->delayed_load.nb.notifier_call = gsc_notifier;
> +	ret = bus_register_notifier(bus, &huc->delayed_load.nb);
> +	if (ret) {
> +		drm_err(&huc_to_gt(huc)->i915->drm,
> +			"failed to register GSC notifier\n");
> +		huc->delayed_load.nb.notifier_call = NULL;
> +		gsc_init_error(huc);
> +	}
> +}
> +
> +void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, struct bus_type *bus)
> +{
> +	if (!huc->delayed_load.nb.notifier_call)
> +		return;
> +
> +	delayed_huc_load_complete(huc);
> +
> +	bus_unregister_notifier(bus, &huc->delayed_load.nb);
> +	huc->delayed_load.nb.notifier_call = NULL;
> +}
> +
>   void intel_huc_init_early(struct intel_huc *huc)
>   {
>   	struct drm_i915_private *i915 = huc_to_gt(huc)->i915;
> @@ -57,6 +218,17 @@ void intel_huc_init_early(struct intel_huc *huc)
>   		huc->status.mask = HUC_FW_VERIFIED;
>   		huc->status.value = HUC_FW_VERIFIED;
>   	}
> +
> +	/*
> +	 * Initialize fence to be complete as this is expected to be complete
> +	 * unless there is a delayed HuC reload in progress.
> +	 */
> +	i915_sw_fence_init(&huc->delayed_load.fence,
> +			   sw_fence_dummy_notify);
> +	i915_sw_fence_commit(&huc->delayed_load.fence);
> +
> +	hrtimer_init(&huc->delayed_load.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +	huc->delayed_load.timer.function = huc_delayed_load_timer_callback;
>   }
>   
>   #define HUC_LOAD_MODE_STRING(x) (x ? "GSC" : "legacy")
> @@ -122,9 +294,25 @@ void intel_huc_fini(struct intel_huc *huc)
>   	if (!intel_uc_fw_is_loadable(&huc->fw))
>   		return;
>   
> +	delayed_huc_load_complete(huc);
> +
> +	i915_sw_fence_fini(&huc->delayed_load.fence);
>   	intel_uc_fw_fini(&huc->fw);
>   }
>   
> +void intel_huc_suspend(struct intel_huc *huc)
> +{
> +	if (!intel_uc_fw_is_loadable(&huc->fw))
> +		return;
> +
> +	/*
> +	 * in the unlikely case that we're suspending before the GSC has
> +	 * completed its loading sequence, just stop waiting. We'll restart
> +	 * on resume.
> +	 */
> +	delayed_huc_load_complete(huc);
> +}
> +
>   int intel_huc_wait_for_auth_complete(struct intel_huc *huc)
>   {
>   	struct intel_gt *gt = huc_to_gt(huc);
> @@ -136,6 +324,9 @@ int intel_huc_wait_for_auth_complete(struct intel_huc *huc)
>   					huc->status.value,
>   					2, 50, NULL);
>   
> +	/* mark the load process as complete even if the wait failed */
> +	delayed_huc_load_complete(huc);
> +
>   	if (ret) {
>   		drm_err(&gt->i915->drm, "HuC: Firmware not verified %d\n", ret);
>   		intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
> @@ -239,6 +430,12 @@ int intel_huc_check_status(struct intel_huc *huc)
>   	return intel_huc_is_authenticated(huc);
>   }
>   
> +static bool huc_has_delayed_load(struct intel_huc *huc)
> +{
> +	return intel_huc_is_loaded_by_gsc(huc) &&
> +	       (huc->delayed_load.status != INTEL_HUC_DELAYED_LOAD_ERROR);
> +}
> +
>   void intel_huc_update_auth_status(struct intel_huc *huc)
>   {
>   	if (!intel_uc_fw_is_loadable(&huc->fw))
> @@ -247,6 +444,8 @@ void intel_huc_update_auth_status(struct intel_huc *huc)
>   	if (intel_huc_is_authenticated(huc))
>   		intel_uc_fw_change_status(&huc->fw,
>   					  INTEL_UC_FIRMWARE_RUNNING);
> +	else if (huc_has_delayed_load(huc))
> +		huc_delayed_load_start(huc);
>   }
>   
>   /**
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.h b/drivers/gpu/drm/i915/gt/uc/intel_huc.h
> index 51f9d96a3ca3..915d281c1c72 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.h
> @@ -7,9 +7,21 @@
>   #define _INTEL_HUC_H_
>   
>   #include "i915_reg_defs.h"
> +#include "i915_sw_fence.h"
>   #include "intel_uc_fw.h"
>   #include "intel_huc_fw.h"
>   
> +#include <linux/notifier.h>
> +#include <linux/hrtimer.h>
> +
> +struct bus_type;
> +
> +enum intel_huc_delayed_load_status {
> +	INTEL_HUC_WAITING_ON_GSC = 0,
> +	INTEL_HUC_WAITING_ON_PXP,
> +	INTEL_HUC_DELAYED_LOAD_ERROR,
> +};
> +
>   struct intel_huc {
>   	/* Generic uC firmware management */
>   	struct intel_uc_fw fw;
> @@ -20,17 +32,28 @@ struct intel_huc {
>   		u32 mask;
>   		u32 value;
>   	} status;
> +
> +	struct {
> +		struct i915_sw_fence fence;
> +		struct hrtimer timer;
> +		struct notifier_block nb;
> +		enum intel_huc_delayed_load_status status;
> +	} delayed_load;
>   };
>   
>   void intel_huc_init_early(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);
>   int intel_huc_auth(struct intel_huc *huc);
>   int intel_huc_wait_for_auth_complete(struct intel_huc *huc);
>   int intel_huc_check_status(struct intel_huc *huc);
>   void intel_huc_update_auth_status(struct intel_huc *huc);
>   bool intel_huc_is_authenticated(struct intel_huc *huc);
>   
> +void intel_huc_register_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
> +void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
> +
>   static inline int intel_huc_sanitize(struct intel_huc *huc)
>   {
>   	intel_uc_fw_sanitize(&huc->fw);


More information about the Intel-gfx mailing list