Skip to content

Commit b1cef13

Browse files
aalteresdceraolo
authored andcommitted
drm/i915/selftest/gsc: Ensure GSC Proxy init completes before selftests
On MTL, if the GSC Proxy init flows haven't completed, submissions to the GSC engine will fail. Those init flows are dependent on the mei's gsc_proxy component that is loaded in parallel with i915 and a worker that could potentially start after i915 driver init is done. That said, all subsytems that access the GSC engine today does check for such init flow completion before using the GSC engine. However, selftests currently don't wait on anything before starting. To fix this, add a waiter function at the start of __run_selftests that waits for gsc-proxy init flows to complete. Selftests shouldn't care if the proxy-init failed as that should be flagged elsewhere. Difference from prior versions: v7: - Change the fw status to INTEL_UC_FIRMWARE_LOAD_FAIL if the proxy-init fails so that intel_gsc_uc_fw_proxy_get_status catches it. (Daniele) v6: - Add a helper that returns something more than a boolean so we selftest can stop waiting if proxy-init hadn't completed but failed (Daniele). v5: - Move the call to __wait_gsc_proxy_completed from common __run_selftests dispatcher to the group-level selftest function (Trvtko). - change the pr_info to pr_warn if we hit the timeout. v4: - Remove generalized waiters function table framework (Tvrtko). - Remove mention of CI-framework-timeout from comments (Tvrtko). v3: - Rebase to latest drm-tip. v2: - Based on internal testing, increase the timeout for gsc-proxy specific case to 8 seconds. Signed-off-by: Alan Previn <[email protected]> Reviewed-by: Daniele Ceraolo Spurio <[email protected]> Signed-off-by: Daniele Ceraolo Spurio <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 76ff778 commit b1cef13

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,20 @@ bool intel_gsc_uc_fw_proxy_init_done(struct intel_gsc_uc *gsc, bool needs_wakere
4545
HECI1_FWSTS1_PROXY_STATE_NORMAL;
4646
}
4747

48+
int intel_gsc_uc_fw_proxy_get_status(struct intel_gsc_uc *gsc)
49+
{
50+
if (!(IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY)))
51+
return -ENODEV;
52+
if (!intel_uc_fw_is_loadable(&gsc->fw))
53+
return -ENODEV;
54+
if (__intel_uc_fw_status(&gsc->fw) == INTEL_UC_FIRMWARE_LOAD_FAIL)
55+
return -ENOLINK;
56+
if (!intel_gsc_uc_fw_proxy_init_done(gsc, true))
57+
return -EAGAIN;
58+
59+
return 0;
60+
}
61+
4862
bool intel_gsc_uc_fw_init_done(struct intel_gsc_uc *gsc)
4963
{
5064
return gsc_uc_get_fw_status(gsc_uc_to_gt(gsc)->uncore, false) &

drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ int intel_gsc_fw_get_binary_info(struct intel_uc_fw *gsc_fw, const void *data, s
1616
int intel_gsc_uc_fw_upload(struct intel_gsc_uc *gsc);
1717
bool intel_gsc_uc_fw_init_done(struct intel_gsc_uc *gsc);
1818
bool intel_gsc_uc_fw_proxy_init_done(struct intel_gsc_uc *gsc, bool needs_wakeref);
19+
int intel_gsc_uc_fw_proxy_get_status(struct intel_gsc_uc *gsc);
1920

2021
#endif

drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,18 @@ static void gsc_work(struct work_struct *work)
6262
}
6363

6464
ret = intel_gsc_proxy_request_handler(gsc);
65-
if (ret)
65+
if (ret) {
66+
if (actions & GSC_ACTION_FW_LOAD) {
67+
/*
68+
* A proxy failure right after firmware load means the proxy-init
69+
* step has failed so mark GSC as not usable after this
70+
*/
71+
drm_err(&gt->i915->drm,
72+
"GSC proxy handler failed to init\n");
73+
intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
74+
}
6675
goto out_put;
76+
}
6777

6878
/* mark the GSC FW init as done the first time we run this */
6979
if (actions & GSC_ACTION_FW_LOAD) {
@@ -78,6 +88,7 @@ static void gsc_work(struct work_struct *work)
7888
} else {
7989
drm_err(&gt->i915->drm,
8090
"GSC status reports proxy init not complete\n");
91+
intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
8192
}
8293
}
8394
}

drivers/gpu/drm/i915/selftests/i915_selftest.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include <linux/random.h>
2525

2626
#include "gt/intel_gt_pm.h"
27+
#include "gt/uc/intel_gsc_fw.h"
28+
2729
#include "i915_driver.h"
2830
#include "i915_drv.h"
2931
#include "i915_selftest.h"
@@ -127,6 +129,31 @@ static void set_default_test_all(struct selftest *st, unsigned int count)
127129
st[i].enabled = true;
128130
}
129131

132+
static bool
133+
__gsc_proxy_init_progressing(struct intel_gsc_uc *gsc)
134+
{
135+
return intel_gsc_uc_fw_proxy_get_status(gsc) == -EAGAIN;
136+
}
137+
138+
static void
139+
__wait_gsc_proxy_completed(struct drm_i915_private *i915)
140+
{
141+
bool need_to_wait = (IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY) &&
142+
i915->media_gt &&
143+
HAS_ENGINE(i915->media_gt, GSC0) &&
144+
intel_uc_fw_is_loadable(&i915->media_gt->uc.gsc.fw));
145+
/*
146+
* The gsc proxy component depends on the kernel component driver load ordering
147+
* and in corner cases (the first time after an IFWI flash), init-completion
148+
* firmware flows take longer.
149+
*/
150+
unsigned long timeout_ms = 8000;
151+
152+
if (need_to_wait && wait_for(!__gsc_proxy_init_progressing(&i915->media_gt->uc.gsc),
153+
timeout_ms))
154+
pr_warn(DRIVER_NAME "Timed out waiting for gsc_proxy_completion!\n");
155+
}
156+
130157
static int __run_selftests(const char *name,
131158
struct selftest *st,
132159
unsigned int count,
@@ -206,6 +233,8 @@ int i915_live_selftests(struct pci_dev *pdev)
206233
if (!i915_selftest.live)
207234
return 0;
208235

236+
__wait_gsc_proxy_completed(pdev_to_i915(pdev));
237+
209238
err = run_selftests(live, pdev_to_i915(pdev));
210239
if (err) {
211240
i915_selftest.live = err;
@@ -227,6 +256,8 @@ int i915_perf_selftests(struct pci_dev *pdev)
227256
if (!i915_selftest.perf)
228257
return 0;
229258

259+
__wait_gsc_proxy_completed(pdev_to_i915(pdev));
260+
230261
err = run_selftests(perf, pdev_to_i915(pdev));
231262
if (err) {
232263
i915_selftest.perf = err;

0 commit comments

Comments
 (0)