Skip to content

Commit

Permalink
drm/i915/gsc: Fix race between HW init and GSC FW load
Browse files Browse the repository at this point in the history
The GSC FW load is a slow process (up to 250 ms), so we defer it to a
dedicated worker to avoid stalling the init flow for that long. However,
we currently start this worker before the HW init is complete, so there
is a chance that the GSC loading code submits to the HW before the
engine initialization has completed. We can easily fix this by starting
the thread later in the gt_resume flow.
From this later spot, the GSC code can still race with the default
submission code; we functionally don't care who wins the race (the GSC
load doesn't need any state), but since the whole point of the separate
worker is to make the main thread faster, we prefer the default
submission code to run first. Therefore, make an exception for driver
probe and only and start the gsc load from uc_init_late.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Reviewed-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230223172120.3304293-3-daniele.ceraolospurio@intel.com
  • Loading branch information
Daniele Ceraolo Spurio committed Mar 9, 2023
1 parent b09f967 commit 913e013
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 2 deletions.
19 changes: 19 additions & 0 deletions drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,25 @@ void intel_gsc_uc_flush_work(struct intel_gsc_uc *gsc)
flush_work(&gsc->work);
}

void intel_gsc_uc_resume(struct intel_gsc_uc *gsc)
{
if (!intel_uc_fw_is_loadable(&gsc->fw))
return;

/*
* we only want to start the GSC worker from here in the actual resume
* flow and not during driver load. This is because GSC load is slow and
* therefore we want to make sure that the default state init completes
* first to not slow down the init thread. A separate call to
* intel_gsc_uc_load_start will ensure that the GSC is loaded during
* driver load.
*/
if (!gsc_uc_to_gt(gsc)->engine[GSC0]->default_state)
return;

intel_gsc_uc_load_start(gsc);
}

void intel_gsc_uc_load_start(struct intel_gsc_uc *gsc)
{
if (!intel_uc_fw_is_loadable(&gsc->fw))
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ void intel_gsc_uc_init_early(struct intel_gsc_uc *gsc);
int intel_gsc_uc_init(struct intel_gsc_uc *gsc);
void intel_gsc_uc_fini(struct intel_gsc_uc *gsc);
void intel_gsc_uc_suspend(struct intel_gsc_uc *gsc);
void intel_gsc_uc_resume(struct intel_gsc_uc *gsc);
void intel_gsc_uc_flush_work(struct intel_gsc_uc *gsc);
void intel_gsc_uc_load_start(struct intel_gsc_uc *gsc);

Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/i915/gt/uc/intel_uc.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ void intel_uc_init_early(struct intel_uc *uc)
void intel_uc_init_late(struct intel_uc *uc)
{
intel_guc_init_late(&uc->guc);
intel_gsc_uc_load_start(&uc->gsc);
}

void intel_uc_driver_late_release(struct intel_uc *uc)
Expand Down Expand Up @@ -543,8 +544,6 @@ static int __uc_init_hw(struct intel_uc *uc)
intel_rps_lower_unslice(&uc_to_gt(uc)->rps);
}

intel_gsc_uc_load_start(&uc->gsc);

guc_info(guc, "submission %s\n", str_enabled_disabled(intel_uc_uses_guc_submission(uc)));
guc_info(guc, "SLPC %s\n", str_enabled_disabled(intel_uc_uses_guc_slpc(uc)));

Expand Down Expand Up @@ -714,6 +713,8 @@ static int __uc_resume(struct intel_uc *uc, bool enable_communication)
return err;
}

intel_gsc_uc_resume(&uc->gsc);

return 0;
}

Expand Down

0 comments on commit 913e013

Please sign in to comment.