drm/xe: Remove i915_utils dependency from xe_pcode.
Expand xe_mmio_wait32 to accept atomic and then use that directly when possible, and create own routine to wait for the pcode status. Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Reviewed-by: Matthew Brost <matthew.brost@intel.com>
This commit is contained in:
parent
81593af6c8
commit
7dc9b92dcf
8 changed files with 57 additions and 69 deletions
|
@ -125,7 +125,7 @@ static int domain_wake_wait(struct xe_gt *gt,
|
||||||
{
|
{
|
||||||
return xe_mmio_wait32(gt, domain->reg_ack, domain->val, domain->val,
|
return xe_mmio_wait32(gt, domain->reg_ack, domain->val, domain->val,
|
||||||
XE_FORCE_WAKE_ACK_TIMEOUT_MS * USEC_PER_MSEC,
|
XE_FORCE_WAKE_ACK_TIMEOUT_MS * USEC_PER_MSEC,
|
||||||
NULL);
|
NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void domain_sleep(struct xe_gt *gt, struct xe_force_wake_domain *domain)
|
static void domain_sleep(struct xe_gt *gt, struct xe_force_wake_domain *domain)
|
||||||
|
@ -138,7 +138,7 @@ static int domain_sleep_wait(struct xe_gt *gt,
|
||||||
{
|
{
|
||||||
return xe_mmio_wait32(gt, domain->reg_ack, 0, domain->val,
|
return xe_mmio_wait32(gt, domain->reg_ack, 0, domain->val,
|
||||||
XE_FORCE_WAKE_ACK_TIMEOUT_MS * USEC_PER_MSEC,
|
XE_FORCE_WAKE_ACK_TIMEOUT_MS * USEC_PER_MSEC,
|
||||||
NULL);
|
NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define for_each_fw_domain_masked(domain__, mask__, fw__, tmp__) \
|
#define for_each_fw_domain_masked(domain__, mask__, fw__, tmp__) \
|
||||||
|
|
|
@ -600,7 +600,7 @@ int do_gt_reset(struct xe_gt *gt)
|
||||||
|
|
||||||
xe_mmio_write32(gt, GEN6_GDRST.reg, GEN11_GRDOM_FULL);
|
xe_mmio_write32(gt, GEN6_GDRST.reg, GEN11_GRDOM_FULL);
|
||||||
err = xe_mmio_wait32(gt, GEN6_GDRST.reg, 0, GEN11_GRDOM_FULL, 5000,
|
err = xe_mmio_wait32(gt, GEN6_GDRST.reg, 0, GEN11_GRDOM_FULL, 5000,
|
||||||
NULL);
|
NULL, false);
|
||||||
if (err)
|
if (err)
|
||||||
drm_err(&xe->drm,
|
drm_err(&xe->drm,
|
||||||
"GT reset failed to clear GEN11_GRDOM_FULL\n");
|
"GT reset failed to clear GEN11_GRDOM_FULL\n");
|
||||||
|
|
|
@ -376,7 +376,8 @@ static void mcr_lock(struct xe_gt *gt)
|
||||||
* shares the same steering control register.
|
* shares the same steering control register.
|
||||||
*/
|
*/
|
||||||
if (GRAPHICS_VERx100(xe) >= 1270)
|
if (GRAPHICS_VERx100(xe) >= 1270)
|
||||||
ret = xe_mmio_wait32(gt, STEER_SEMAPHORE, 0, 0x1, 10, NULL);
|
ret = xe_mmio_wait32(gt, STEER_SEMAPHORE, 0, 0x1, 10, NULL,
|
||||||
|
false);
|
||||||
|
|
||||||
drm_WARN_ON_ONCE(&xe->drm, ret == -ETIMEDOUT);
|
drm_WARN_ON_ONCE(&xe->drm, ret == -ETIMEDOUT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -325,7 +325,7 @@ int xe_guc_reset(struct xe_guc *guc)
|
||||||
xe_mmio_write32(gt, GEN6_GDRST.reg, GEN11_GRDOM_GUC);
|
xe_mmio_write32(gt, GEN6_GDRST.reg, GEN11_GRDOM_GUC);
|
||||||
|
|
||||||
ret = xe_mmio_wait32(gt, GEN6_GDRST.reg, 0, GEN11_GRDOM_GUC, 5000,
|
ret = xe_mmio_wait32(gt, GEN6_GDRST.reg, 0, GEN11_GRDOM_GUC, 5000,
|
||||||
&gdrst);
|
&gdrst, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
drm_err(&xe->drm, "GuC reset timed out, GEN6_GDRST=0x%8x\n",
|
drm_err(&xe->drm, "GuC reset timed out, GEN6_GDRST=0x%8x\n",
|
||||||
gdrst);
|
gdrst);
|
||||||
|
@ -423,7 +423,7 @@ static int guc_wait_ucode(struct xe_guc *guc)
|
||||||
ret = xe_mmio_wait32(guc_to_gt(guc), GUC_STATUS.reg,
|
ret = xe_mmio_wait32(guc_to_gt(guc), GUC_STATUS.reg,
|
||||||
FIELD_PREP(GS_UKERNEL_MASK,
|
FIELD_PREP(GS_UKERNEL_MASK,
|
||||||
XE_GUC_LOAD_STATUS_READY),
|
XE_GUC_LOAD_STATUS_READY),
|
||||||
GS_UKERNEL_MASK, 200000, &status);
|
GS_UKERNEL_MASK, 200000, &status, false);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
struct drm_device *drm = &xe->drm;
|
struct drm_device *drm = &xe->drm;
|
||||||
|
@ -671,7 +671,7 @@ retry:
|
||||||
ret = xe_mmio_wait32(gt, reply_reg,
|
ret = xe_mmio_wait32(gt, reply_reg,
|
||||||
FIELD_PREP(GUC_HXG_MSG_0_ORIGIN,
|
FIELD_PREP(GUC_HXG_MSG_0_ORIGIN,
|
||||||
GUC_HXG_ORIGIN_GUC),
|
GUC_HXG_ORIGIN_GUC),
|
||||||
GUC_HXG_MSG_0_ORIGIN, 50000, &reply);
|
GUC_HXG_MSG_0_ORIGIN, 50000, &reply, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
timeout:
|
timeout:
|
||||||
drm_err(&xe->drm, "mmio request 0x%08x: no reply 0x%08x\n",
|
drm_err(&xe->drm, "mmio request 0x%08x: no reply 0x%08x\n",
|
||||||
|
@ -686,7 +686,8 @@ timeout:
|
||||||
ret = xe_mmio_wait32(gt, reply_reg,
|
ret = xe_mmio_wait32(gt, reply_reg,
|
||||||
FIELD_PREP(GUC_HXG_MSG_0_TYPE,
|
FIELD_PREP(GUC_HXG_MSG_0_TYPE,
|
||||||
GUC_HXG_TYPE_RESPONSE_SUCCESS),
|
GUC_HXG_TYPE_RESPONSE_SUCCESS),
|
||||||
GUC_HXG_MSG_0_TYPE, 1000000, &header);
|
GUC_HXG_MSG_0_TYPE, 1000000, &header,
|
||||||
|
false);
|
||||||
|
|
||||||
if (unlikely(FIELD_GET(GUC_HXG_MSG_0_ORIGIN, header) !=
|
if (unlikely(FIELD_GET(GUC_HXG_MSG_0_ORIGIN, header) !=
|
||||||
GUC_HXG_ORIGIN_GUC))
|
GUC_HXG_ORIGIN_GUC))
|
||||||
|
|
|
@ -85,7 +85,7 @@ int xe_huc_auth(struct xe_huc *huc)
|
||||||
|
|
||||||
ret = xe_mmio_wait32(gt, GEN11_HUC_KERNEL_LOAD_INFO.reg,
|
ret = xe_mmio_wait32(gt, GEN11_HUC_KERNEL_LOAD_INFO.reg,
|
||||||
HUC_LOAD_SUCCESSFUL,
|
HUC_LOAD_SUCCESSFUL,
|
||||||
HUC_LOAD_SUCCESSFUL, 100000, NULL);
|
HUC_LOAD_SUCCESSFUL, 100000, NULL, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
drm_err(&xe->drm, "HuC: Firmware not verified %d\n", ret);
|
drm_err(&xe->drm, "HuC: Firmware not verified %d\n", ret);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -82,8 +82,8 @@ static inline int xe_mmio_write32_and_verify(struct xe_gt *gt,
|
||||||
return (reg_val & mask) != eval ? -EINVAL : 0;
|
return (reg_val & mask) != eval ? -EINVAL : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int xe_mmio_wait32(struct xe_gt *gt, u32 reg, u32 val,
|
static inline int xe_mmio_wait32(struct xe_gt *gt, u32 reg, u32 val, u32 mask,
|
||||||
u32 mask, u32 timeout_us, u32 *out_val)
|
u32 timeout_us, u32 *out_val, bool atomic)
|
||||||
{
|
{
|
||||||
ktime_t cur = ktime_get_raw();
|
ktime_t cur = ktime_get_raw();
|
||||||
const ktime_t end = ktime_add_us(cur, timeout_us);
|
const ktime_t end = ktime_add_us(cur, timeout_us);
|
||||||
|
@ -108,7 +108,10 @@ static inline int xe_mmio_wait32(struct xe_gt *gt, u32 reg, u32 val,
|
||||||
if (ktime_after(ktime_add_us(cur, wait), end))
|
if (ktime_after(ktime_add_us(cur, wait), end))
|
||||||
wait = ktime_us_delta(end, cur);
|
wait = ktime_us_delta(end, cur);
|
||||||
|
|
||||||
usleep_range(wait, wait << 1);
|
if (atomic)
|
||||||
|
udelay(wait);
|
||||||
|
else
|
||||||
|
usleep_range(wait, wait << 1);
|
||||||
wait <<= 1;
|
wait <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,6 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
/*
|
|
||||||
* FIXME: This header has been deemed evil and we need to kill it. Temporarily
|
|
||||||
* including so we can use 'wait_for'.
|
|
||||||
*/
|
|
||||||
#include "i915_utils.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DOC: PCODE
|
* DOC: PCODE
|
||||||
|
@ -59,28 +54,24 @@ static int pcode_mailbox_status(struct xe_gt *gt)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pcode_mailbox_done(struct xe_gt *gt)
|
|
||||||
{
|
|
||||||
lockdep_assert_held(>->pcode.lock);
|
|
||||||
return (xe_mmio_read32(gt, PCODE_MAILBOX.reg) & PCODE_READY) == 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, bool return_data, bool atomic)
|
unsigned int timeout_ms, bool return_data,
|
||||||
|
bool atomic)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
lockdep_assert_held(>->pcode.lock);
|
lockdep_assert_held(>->pcode.lock);
|
||||||
|
|
||||||
if (!pcode_mailbox_done(gt))
|
if ((xe_mmio_read32(gt, PCODE_MAILBOX.reg) & PCODE_READY) != 0)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
xe_mmio_write32(gt, PCODE_DATA0.reg, *data0);
|
xe_mmio_write32(gt, PCODE_DATA0.reg, *data0);
|
||||||
xe_mmio_write32(gt, PCODE_DATA1.reg, data1 ? *data1 : 0);
|
xe_mmio_write32(gt, PCODE_DATA1.reg, data1 ? *data1 : 0);
|
||||||
xe_mmio_write32(gt, PCODE_MAILBOX.reg, PCODE_READY | mbox);
|
xe_mmio_write32(gt, PCODE_MAILBOX.reg, PCODE_READY | mbox);
|
||||||
|
|
||||||
if (atomic)
|
err = xe_mmio_wait32(gt, PCODE_MAILBOX.reg, 0, PCODE_READY,
|
||||||
_wait_for_atomic(pcode_mailbox_done(gt), timeout * 1000, 1);
|
timeout_ms * 1000, NULL, atomic);
|
||||||
else
|
if (err)
|
||||||
wait_for(pcode_mailbox_done(gt), timeout);
|
return err;
|
||||||
|
|
||||||
if (return_data) {
|
if (return_data) {
|
||||||
*data0 = xe_mmio_read32(gt, PCODE_DATA0.reg);
|
*data0 = xe_mmio_read32(gt, PCODE_DATA0.reg);
|
||||||
|
@ -113,13 +104,26 @@ int xe_pcode_read(struct xe_gt *gt, u32 mbox, u32 *val, u32 *val1)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool xe_pcode_try_request(struct xe_gt *gt, u32 mbox,
|
static int xe_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)
|
u32 *status, bool atomic, int timeout_us)
|
||||||
{
|
{
|
||||||
*status = pcode_mailbox_rw(gt, mbox, &request, NULL, 1, true, atomic);
|
int slept, wait = 10;
|
||||||
|
|
||||||
return (*status == 0) && ((request & reply_mask) == reply);
|
for (slept = 0; slept < timeout_us; slept += wait) {
|
||||||
|
*status = pcode_mailbox_rw(gt, mbox, &request, NULL, 1, true,
|
||||||
|
atomic);
|
||||||
|
if ((*status == 0) && ((request & reply_mask) == reply))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (atomic)
|
||||||
|
udelay(wait);
|
||||||
|
else
|
||||||
|
usleep_range(wait, wait << 1);
|
||||||
|
wait <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,25 +150,12 @@ int xe_pcode_request(struct xe_gt *gt, u32 mbox, u32 request,
|
||||||
{
|
{
|
||||||
u32 status;
|
u32 status;
|
||||||
int ret;
|
int ret;
|
||||||
bool atomic = false;
|
|
||||||
|
|
||||||
mutex_lock(>->pcode.lock);
|
mutex_lock(>->pcode.lock);
|
||||||
|
|
||||||
#define COND \
|
ret = xe_pcode_try_request(gt, mbox, request, reply_mask, reply, &status,
|
||||||
xe_pcode_try_request(gt, mbox, request, reply_mask, reply, &status, atomic)
|
false, timeout_base_ms * 1000);
|
||||||
|
if (ret)
|
||||||
/*
|
|
||||||
* Prime the PCODE by doing a request first. Normally it guarantees
|
|
||||||
* that a subsequent request, at most @timeout_base_ms later, succeeds.
|
|
||||||
* _wait_for() doesn't guarantee when its passed condition is evaluated
|
|
||||||
* first, so send the first request explicitly.
|
|
||||||
*/
|
|
||||||
if (COND) {
|
|
||||||
ret = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
ret = _wait_for(COND, timeout_base_ms * 1000, 10, 10);
|
|
||||||
if (!ret)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -181,15 +172,13 @@ 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(>_to_xe(gt)->drm, timeout_base_ms > 1);
|
drm_WARN_ON_ONCE(>_to_xe(gt)->drm, timeout_base_ms > 1);
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
atomic = true;
|
ret = xe_pcode_try_request(gt, mbox, request, reply_mask, reply, &status,
|
||||||
ret = wait_for_atomic(COND, 50);
|
true, timeout_base_ms * 1000);
|
||||||
atomic = false;
|
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(>->pcode.lock);
|
mutex_unlock(>->pcode.lock);
|
||||||
return status ? status : ret;
|
return status ? status : ret;
|
||||||
#undef COND
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* xe_pcode_init_min_freq_table - Initialize PCODE's QOS frequency table
|
* xe_pcode_init_min_freq_table - Initialize PCODE's QOS frequency table
|
||||||
|
@ -243,16 +232,6 @@ unlock:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pcode_dgfx_status_complete(struct xe_gt *gt)
|
|
||||||
{
|
|
||||||
u32 data = DGFX_GET_INIT_STATUS;
|
|
||||||
int status = pcode_mailbox_rw(gt, DGFX_PCODE_STATUS,
|
|
||||||
&data, NULL, 1, true, false);
|
|
||||||
|
|
||||||
return status == 0 &&
|
|
||||||
(data & DGFX_INIT_STATUS_COMPLETE) == DGFX_INIT_STATUS_COMPLETE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xe_pcode_init - Ensure PCODE is initialized
|
* xe_pcode_init - Ensure PCODE is initialized
|
||||||
* @gt: gt instance
|
* @gt: gt instance
|
||||||
|
@ -264,20 +243,23 @@ static bool pcode_dgfx_status_complete(struct xe_gt *gt)
|
||||||
*/
|
*/
|
||||||
int xe_pcode_init(struct xe_gt *gt)
|
int xe_pcode_init(struct xe_gt *gt)
|
||||||
{
|
{
|
||||||
int timeout = 180000; /* 3 min */
|
u32 status, request = DGFX_GET_INIT_STATUS;
|
||||||
|
int timeout_us = 180000000; /* 3 min */
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!IS_DGFX(gt_to_xe(gt)))
|
if (!IS_DGFX(gt_to_xe(gt)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mutex_lock(>->pcode.lock);
|
mutex_lock(>->pcode.lock);
|
||||||
ret = wait_for(pcode_dgfx_status_complete(gt), timeout);
|
ret = xe_pcode_try_request(gt, DGFX_PCODE_STATUS, request,
|
||||||
|
DGFX_INIT_STATUS_COMPLETE,
|
||||||
|
DGFX_INIT_STATUS_COMPLETE,
|
||||||
|
&status, false, timeout_us);
|
||||||
mutex_unlock(>->pcode.lock);
|
mutex_unlock(>->pcode.lock);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
drm_err(>_to_xe(gt)->drm,
|
drm_err(>_to_xe(gt)->drm,
|
||||||
"PCODE initialization timedout after: %d min\n",
|
"PCODE initialization timedout after: 3 min\n");
|
||||||
timeout / 60000);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,7 +352,8 @@ static int uc_fw_xfer(struct xe_uc_fw *uc_fw, u32 offset, u32 dma_flags)
|
||||||
_MASKED_BIT_ENABLE(dma_flags | START_DMA));
|
_MASKED_BIT_ENABLE(dma_flags | START_DMA));
|
||||||
|
|
||||||
/* Wait for DMA to finish */
|
/* Wait for DMA to finish */
|
||||||
ret = xe_mmio_wait32(gt, DMA_CTRL.reg, 0, START_DMA, 100000, &dma_ctrl);
|
ret = xe_mmio_wait32(gt, DMA_CTRL.reg, 0, START_DMA, 100000, &dma_ctrl,
|
||||||
|
false);
|
||||||
if (ret)
|
if (ret)
|
||||||
drm_err(&xe->drm, "DMA for %s fw failed, DMA_CTRL=%u\n",
|
drm_err(&xe->drm, "DMA for %s fw failed, DMA_CTRL=%u\n",
|
||||||
xe_uc_fw_type_repr(uc_fw->type), dma_ctrl);
|
xe_uc_fw_type_repr(uc_fw->type), dma_ctrl);
|
||||||
|
|
Loading…
Add table
Reference in a new issue