Commit 933fd5ff authored by Riana Tauro's avatar Riana Tauro Committed by Rodrigo Vivi

drm/xe: check pcode init status only on root gt of root tile

The root tile indicates the pcode initialization is complete
when all tiles have completed their initialization.
So the mailbox can be polled only on the root tile.
Check pcode init status only on root tile and move it to
device probe early as root tile is initialized there.
Also make similar changes in resume paths.

v2: add lock/unlocked version of pcode_mailbox_rw
    to allow pcode init to be called in device
    early probe (Rodrigo)

v3: add code description about using root tile
    change function names to xe_pcode_probe_early
    and xe_pcode_init (Rodrigo)
Signed-off-by: default avatarRiana Tauro <riana.tauro@intel.com>
Reviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: default avatarHimal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240410085005.1126343-2-riana.tauro@intel.comSigned-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent 3df49b2e
...@@ -422,8 +422,14 @@ static int xe_set_dma_info(struct xe_device *xe) ...@@ -422,8 +422,14 @@ static int xe_set_dma_info(struct xe_device *xe)
return err; return err;
} }
/* /**
* Initialize MMIO resources that don't require any knowledge about tile count. * xe_device_probe_early: Device early probe
* @xe: xe device instance
*
* Initialize MMIO resources that don't require any
* knowledge about tile count. Also initialize pcode
*
* Return: 0 on success, error code on failure
*/ */
int xe_device_probe_early(struct xe_device *xe) int xe_device_probe_early(struct xe_device *xe)
{ {
...@@ -439,6 +445,10 @@ int xe_device_probe_early(struct xe_device *xe) ...@@ -439,6 +445,10 @@ int xe_device_probe_early(struct xe_device *xe)
if (err) if (err)
return err; return err;
err = xe_pcode_probe_early(xe);
if (err)
return err;
return 0; return 0;
} }
...@@ -517,11 +527,8 @@ int xe_device_probe(struct xe_device *xe) ...@@ -517,11 +527,8 @@ int xe_device_probe(struct xe_device *xe)
if (err) if (err)
return err; return err;
for_each_gt(gt, xe, id) { for_each_gt(gt, xe, id)
err = xe_pcode_probe(gt); xe_pcode_init(gt);
if (err)
return err;
}
err = xe_display_init_noirq(xe); err = xe_display_init_noirq(xe);
if (err) if (err)
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <drm/drm_managed.h> #include <drm/drm_managed.h>
#include "xe_device.h"
#include "xe_gt.h" #include "xe_gt.h"
#include "xe_mmio.h" #include "xe_mmio.h"
#include "xe_pcode_api.h" #include "xe_pcode_api.h"
...@@ -43,8 +44,6 @@ static int pcode_mailbox_status(struct xe_gt *gt) ...@@ -43,8 +44,6 @@ static int pcode_mailbox_status(struct xe_gt *gt)
[PCODE_ERROR_MASK] = {-EPROTO, "Unknown"}, [PCODE_ERROR_MASK] = {-EPROTO, "Unknown"},
}; };
lockdep_assert_held(&gt->pcode.lock);
err = xe_mmio_read32(gt, PCODE_MAILBOX) & PCODE_ERROR_MASK; err = xe_mmio_read32(gt, PCODE_MAILBOX) & PCODE_ERROR_MASK;
if (err) { if (err) {
drm_err(&gt_to_xe(gt)->drm, "PCODE Mailbox failed: %d %s", err, drm_err(&gt_to_xe(gt)->drm, "PCODE Mailbox failed: %d %s", err,
...@@ -55,17 +54,15 @@ static int pcode_mailbox_status(struct xe_gt *gt) ...@@ -55,17 +54,15 @@ static int pcode_mailbox_status(struct xe_gt *gt)
return 0; return 0;
} }
static int pcode_mailbox_rw(struct xe_gt *gt, u32 mbox, u32 *data0, u32 *data1, static int __pcode_mailbox_rw(struct xe_gt *gt, u32 mbox, u32 *data0, u32 *data1,
unsigned int timeout_ms, bool return_data, unsigned int timeout_ms, bool return_data,
bool atomic) bool atomic)
{ {
int err; int err;
if (gt_to_xe(gt)->info.skip_pcode) if (gt_to_xe(gt)->info.skip_pcode)
return 0; return 0;
lockdep_assert_held(&gt->pcode.lock);
if ((xe_mmio_read32(gt, PCODE_MAILBOX) & PCODE_READY) != 0) if ((xe_mmio_read32(gt, PCODE_MAILBOX) & PCODE_READY) != 0)
return -EAGAIN; return -EAGAIN;
...@@ -87,6 +84,18 @@ static int pcode_mailbox_rw(struct xe_gt *gt, u32 mbox, u32 *data0, u32 *data1, ...@@ -87,6 +84,18 @@ static int pcode_mailbox_rw(struct xe_gt *gt, u32 mbox, u32 *data0, u32 *data1,
return pcode_mailbox_status(gt); return pcode_mailbox_status(gt);
} }
static int pcode_mailbox_rw(struct xe_gt *gt, u32 mbox, u32 *data0, u32 *data1,
unsigned int timeout_ms, bool return_data,
bool atomic)
{
if (gt_to_xe(gt)->info.skip_pcode)
return 0;
lockdep_assert_held(&gt->pcode.lock);
return __pcode_mailbox_rw(gt, mbox, data0, data1, timeout_ms, return_data, atomic);
}
int xe_pcode_write_timeout(struct xe_gt *gt, u32 mbox, u32 data, int timeout) int xe_pcode_write_timeout(struct xe_gt *gt, u32 mbox, u32 data, int timeout)
{ {
int err; int err;
...@@ -109,15 +118,19 @@ int xe_pcode_read(struct xe_gt *gt, u32 mbox, u32 *val, u32 *val1) ...@@ -109,15 +118,19 @@ int xe_pcode_read(struct xe_gt *gt, u32 mbox, u32 *val, u32 *val1)
return err; return err;
} }
static int xe_pcode_try_request(struct xe_gt *gt, u32 mbox, static int pcode_try_request(struct xe_gt *gt, u32 mbox,
u32 request, u32 reply_mask, u32 reply, u32 request, u32 reply_mask, u32 reply,
u32 *status, bool atomic, int timeout_us) u32 *status, bool atomic, int timeout_us, bool locked)
{ {
int slept, wait = 10; int slept, wait = 10;
for (slept = 0; slept < timeout_us; slept += wait) { for (slept = 0; slept < timeout_us; slept += wait) {
*status = pcode_mailbox_rw(gt, mbox, &request, NULL, 1, true, if (locked)
atomic); *status = pcode_mailbox_rw(gt, mbox, &request, NULL, 1, true,
atomic);
else
*status = __pcode_mailbox_rw(gt, mbox, &request, NULL, 1, true,
atomic);
if ((*status == 0) && ((request & reply_mask) == reply)) if ((*status == 0) && ((request & reply_mask) == reply))
return 0; return 0;
...@@ -158,8 +171,8 @@ int xe_pcode_request(struct xe_gt *gt, u32 mbox, u32 request, ...@@ -158,8 +171,8 @@ int xe_pcode_request(struct xe_gt *gt, u32 mbox, u32 request,
mutex_lock(&gt->pcode.lock); mutex_lock(&gt->pcode.lock);
ret = xe_pcode_try_request(gt, mbox, request, reply_mask, reply, &status, ret = pcode_try_request(gt, mbox, request, reply_mask, reply, &status,
false, timeout_base_ms * 1000); false, timeout_base_ms * 1000, true);
if (!ret) if (!ret)
goto out; goto out;
...@@ -177,8 +190,8 @@ int xe_pcode_request(struct xe_gt *gt, u32 mbox, u32 request, ...@@ -177,8 +190,8 @@ int xe_pcode_request(struct xe_gt *gt, u32 mbox, u32 request,
"PCODE timeout, retrying with preemption disabled\n"); "PCODE timeout, retrying with preemption disabled\n");
drm_WARN_ON_ONCE(&gt_to_xe(gt)->drm, timeout_base_ms > 1); drm_WARN_ON_ONCE(&gt_to_xe(gt)->drm, timeout_base_ms > 1);
preempt_disable(); preempt_disable();
ret = xe_pcode_try_request(gt, mbox, request, reply_mask, reply, &status, ret = pcode_try_request(gt, mbox, request, reply_mask, reply, &status,
true, timeout_base_ms * 1000); true, timeout_base_ms * 1000, true);
preempt_enable(); preempt_enable();
out: out:
...@@ -238,59 +251,71 @@ int xe_pcode_init_min_freq_table(struct xe_gt *gt, u32 min_gt_freq, ...@@ -238,59 +251,71 @@ int xe_pcode_init_min_freq_table(struct xe_gt *gt, u32 min_gt_freq,
} }
/** /**
* xe_pcode_init - Ensure PCODE is initialized * xe_pcode_ready - Ensure PCODE is initialized
* @gt: gt instance * @xe: xe instance
* @locked: true if lock held, false otherwise
* *
* This function ensures that PCODE is properly initialized. To be called during * PCODE init mailbox is polled only on root gt of root tile
* probe and resume paths. * as the root tile provides the initialization is complete only
* after all the tiles have completed the initialization.
* Called only on early probe without locks and with locks in
* resume path.
* *
* It returns 0 on success, and -error number on failure. * Returns 0 on success, and -error number on failure.
*/ */
int xe_pcode_init(struct xe_gt *gt) int xe_pcode_ready(struct xe_device *xe, bool locked)
{ {
u32 status, request = DGFX_GET_INIT_STATUS; u32 status, request = DGFX_GET_INIT_STATUS;
struct xe_gt *gt = xe_root_mmio_gt(xe);
int timeout_us = 180000000; /* 3 min */ int timeout_us = 180000000; /* 3 min */
int ret; int ret;
if (gt_to_xe(gt)->info.skip_pcode) if (xe->info.skip_pcode)
return 0; return 0;
if (!IS_DGFX(gt_to_xe(gt))) if (!IS_DGFX(xe))
return 0; return 0;
mutex_lock(&gt->pcode.lock); if (locked)
ret = xe_pcode_try_request(gt, DGFX_PCODE_STATUS, request, mutex_lock(&gt->pcode.lock);
DGFX_INIT_STATUS_COMPLETE,
DGFX_INIT_STATUS_COMPLETE, ret = pcode_try_request(gt, DGFX_PCODE_STATUS, request,
&status, false, timeout_us); DGFX_INIT_STATUS_COMPLETE,
mutex_unlock(&gt->pcode.lock); DGFX_INIT_STATUS_COMPLETE,
&status, false, timeout_us, locked);
if (locked)
mutex_unlock(&gt->pcode.lock);
if (ret) if (ret)
drm_err(&gt_to_xe(gt)->drm, drm_err(&xe->drm,
"PCODE initialization timedout after: 3 min\n"); "PCODE initialization timedout after: 3 min\n");
return ret; return ret;
} }
/** /**
* xe_pcode_probe - Prepare xe_pcode and also ensure PCODE is initialized. * xe_pcode_init: initialize components of PCODE
* @gt: gt instance * @gt: gt instance
* *
* This function initializes the xe_pcode component, and when needed, it ensures * This function initializes the xe_pcode component.
* that PCODE has properly performed its initialization and it is really ready * To be called once only during probe.
* to go. To be called once only during probe.
*
* It returns 0 on success, and -error number on failure.
*/ */
int xe_pcode_probe(struct xe_gt *gt) void xe_pcode_init(struct xe_gt *gt)
{ {
drmm_mutex_init(&gt_to_xe(gt)->drm, &gt->pcode.lock); drmm_mutex_init(&gt_to_xe(gt)->drm, &gt->pcode.lock);
}
if (gt_to_xe(gt)->info.skip_pcode) /**
return 0; * xe_pcode_probe_early: initializes PCODE
* @xe: xe instance
if (!IS_DGFX(gt_to_xe(gt))) *
return 0; * This function checks the initialization status of PCODE
* To be called once only during early probe without locks.
return xe_pcode_init(gt); *
* Returns 0 on success, error code otherwise
*/
int xe_pcode_probe_early(struct xe_device *xe)
{
return xe_pcode_ready(xe, false);
} }
...@@ -8,9 +8,11 @@ ...@@ -8,9 +8,11 @@
#include <linux/types.h> #include <linux/types.h>
struct xe_gt; struct xe_gt;
struct xe_device;
int xe_pcode_probe(struct xe_gt *gt); void xe_pcode_init(struct xe_gt *gt);
int xe_pcode_init(struct xe_gt *gt); int xe_pcode_probe_early(struct xe_device *xe);
int xe_pcode_ready(struct xe_device *xe, bool locked);
int xe_pcode_init_min_freq_table(struct xe_gt *gt, u32 min_gt_freq, int xe_pcode_init_min_freq_table(struct xe_gt *gt, u32 min_gt_freq,
u32 max_gt_freq); u32 max_gt_freq);
int xe_pcode_read(struct xe_gt *gt, u32 mbox, u32 *val, u32 *val1); int xe_pcode_read(struct xe_gt *gt, u32 mbox, u32 *val, u32 *val1);
......
...@@ -129,11 +129,9 @@ int xe_pm_resume(struct xe_device *xe) ...@@ -129,11 +129,9 @@ int xe_pm_resume(struct xe_device *xe)
for_each_tile(tile, xe, id) for_each_tile(tile, xe, id)
xe_wa_apply_tile_workarounds(tile); xe_wa_apply_tile_workarounds(tile);
for_each_gt(gt, xe, id) { err = xe_pcode_ready(xe, true);
err = xe_pcode_init(gt); if (err)
if (err) return err;
goto err;
}
xe_display_pm_resume_early(xe); xe_display_pm_resume_early(xe);
...@@ -386,11 +384,9 @@ int xe_pm_runtime_resume(struct xe_device *xe) ...@@ -386,11 +384,9 @@ int xe_pm_runtime_resume(struct xe_device *xe)
xe->d3cold.power_lost = xe_guc_in_reset(&gt->uc.guc); xe->d3cold.power_lost = xe_guc_in_reset(&gt->uc.guc);
if (xe->d3cold.allowed && xe->d3cold.power_lost) { if (xe->d3cold.allowed && xe->d3cold.power_lost) {
for_each_gt(gt, xe, id) { err = xe_pcode_ready(xe, true);
err = xe_pcode_init(gt); if (err)
if (err) goto out;
goto out;
}
/* /*
* This only restores pinned memory which is the memory * This only restores pinned memory which is the memory
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment