Commit be8f9f4c authored by Gustavo Sousa's avatar Gustavo Sousa Committed by Matt Roper

drm/xe/mmio: Use single logic for waiting functions

The implementations for xe_mmio_wait32() and xe_mmio_wait32_not() are
almost identical. Let us avoid duplication of logic by having them
calling a common __xe_mmio_wait32() function.
Signed-off-by: default avatarGustavo Sousa <gustavo.sousa@intel.com>
Reviewed-by: default avatarHimal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Signed-off-by: default avatarMatt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240723120120.5443-2-gustavo.sousa@intel.com
parent 641a118c
...@@ -333,37 +333,24 @@ u64 xe_mmio_read64_2x32(struct xe_gt *gt, struct xe_reg reg) ...@@ -333,37 +333,24 @@ u64 xe_mmio_read64_2x32(struct xe_gt *gt, struct xe_reg reg)
return (u64)udw << 32 | ldw; return (u64)udw << 32 | ldw;
} }
/** static int __xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
* xe_mmio_wait32() - Wait for a register to match the desired masked value u32 *out_val, bool atomic, bool expect_match)
* @gt: MMIO target GT
* @reg: register to read value from
* @mask: mask to be applied to the value read from the register
* @val: desired value after applying the mask
* @timeout_us: time out after this period of time. Wait logic tries to be
* smart, applying an exponential backoff until @timeout_us is reached.
* @out_val: if not NULL, points where to store the last unmasked value
* @atomic: needs to be true if calling from an atomic context
*
* This function polls for the desired masked value and returns zero on success
* or -ETIMEDOUT if timed out.
*
* Note that @timeout_us represents the minimum amount of time to wait before
* giving up. The actual time taken by this function can be a little more than
* @timeout_us for different reasons, specially in non-atomic contexts. Thus,
* it is possible that this function succeeds even after @timeout_us has passed.
*/
int xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 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);
int ret = -ETIMEDOUT; int ret = -ETIMEDOUT;
s64 wait = 10; s64 wait = 10;
u32 read; u32 read;
bool check;
for (;;) { for (;;) {
read = xe_mmio_read32(gt, reg); read = xe_mmio_read32(gt, reg);
if ((read & mask) == val) {
check = (read & mask) == val;
if (!expect_match)
check = !check;
if (check) {
ret = 0; ret = 0;
break; break;
} }
...@@ -384,7 +371,12 @@ int xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 t ...@@ -384,7 +371,12 @@ int xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 t
if (ret != 0) { if (ret != 0) {
read = xe_mmio_read32(gt, reg); read = xe_mmio_read32(gt, reg);
if ((read & mask) == val)
check = (read & mask) == val;
if (!expect_match)
check = !check;
if (check)
ret = 0; ret = 0;
} }
...@@ -395,62 +387,45 @@ int xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 t ...@@ -395,62 +387,45 @@ int xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 t
} }
/** /**
* xe_mmio_wait32_not() - Wait for a register to return anything other than the given masked value * xe_mmio_wait32() - Wait for a register to match the desired masked value
* @gt: MMIO target GT * @gt: MMIO target GT
* @reg: register to read value from * @reg: register to read value from
* @mask: mask to be applied to the value read from the register * @mask: mask to be applied to the value read from the register
* @val: value to match after applying the mask * @val: desired value after applying the mask
* @timeout_us: time out after this period of time. Wait logic tries to be * @timeout_us: time out after this period of time. Wait logic tries to be
* smart, applying an exponential backoff until @timeout_us is reached. * smart, applying an exponential backoff until @timeout_us is reached.
* @out_val: if not NULL, points where to store the last unmasked value * @out_val: if not NULL, points where to store the last unmasked value
* @atomic: needs to be true if calling from an atomic context * @atomic: needs to be true if calling from an atomic context
* *
* This function polls for a masked value to change from a given value and * This function polls for the desired masked value and returns zero on success
* returns zero on success or -ETIMEDOUT if timed out. * or -ETIMEDOUT if timed out.
* *
* Note that @timeout_us represents the minimum amount of time to wait before * Note that @timeout_us represents the minimum amount of time to wait before
* giving up. The actual time taken by this function can be a little more than * giving up. The actual time taken by this function can be a little more than
* @timeout_us for different reasons, specially in non-atomic contexts. Thus, * @timeout_us for different reasons, specially in non-atomic contexts. Thus,
* it is possible that this function succeeds even after @timeout_us has passed. * it is possible that this function succeeds even after @timeout_us has passed.
*/ */
int xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
u32 *out_val, bool atomic)
{
return __xe_mmio_wait32(gt, reg, mask, val, timeout_us, out_val, atomic, true);
}
/**
* xe_mmio_wait32_not() - Wait for a register to return anything other than the given masked value
* @gt: MMIO target GT
* @reg: register to read value from
* @mask: mask to be applied to the value read from the register
* @val: value not to be matched after applying the mask
* @timeout_us: time out after this period of time
* @out_val: if not NULL, points where to store the last unmasked value
* @atomic: needs to be true if calling from an atomic context
*
* This function works exactly like xe_mmio_wait32() with the exception that
* @val is expected not to be matched.
*/
int xe_mmio_wait32_not(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, int xe_mmio_wait32_not(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
u32 *out_val, bool atomic) u32 *out_val, bool atomic)
{ {
ktime_t cur = ktime_get_raw(); return __xe_mmio_wait32(gt, reg, mask, val, timeout_us, out_val, atomic, false);
const ktime_t end = ktime_add_us(cur, timeout_us);
int ret = -ETIMEDOUT;
s64 wait = 10;
u32 read;
for (;;) {
read = xe_mmio_read32(gt, reg);
if ((read & mask) != val) {
ret = 0;
break;
}
cur = ktime_get_raw();
if (!ktime_before(cur, end))
break;
if (ktime_after(ktime_add_us(cur, wait), end))
wait = ktime_us_delta(end, cur);
if (atomic)
udelay(wait);
else
usleep_range(wait, wait << 1);
wait <<= 1;
}
if (ret != 0) {
read = xe_mmio_read32(gt, reg);
if ((read & mask) != val)
ret = 0;
}
if (out_val)
*out_val = read;
return ret;
} }
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