#include "xe_configfs.h"
#include "xe_device.h"
#include "xe_drm_client.h"
+#include "xe_exec_queue.h"
#include "xe_exec_queue_types.h"
#include "xe_gt.h"
#include "xe_gt_clock.h"
return 0;
}
+static u64 get_queue_timestamp(struct xe_hw_engine *hwe)
+{
+ return xe_mmio_read64_2x32(&hwe->gt->mmio,
+ RING_QUEUE_TIMESTAMP(hwe->mmio_base));
+}
+
+static u32 get_multi_queue_active_queue_id(struct xe_hw_engine *hwe)
+{
+ u32 val = xe_mmio_read32(&hwe->gt->mmio,
+ RING_CSMQDEBUG(hwe->mmio_base));
+
+ return REG_FIELD_GET(CURRENT_ACTIVE_QUEUE_ID_MASK, val);
+}
+
static bool context_active(struct xe_lrc *lrc)
{
return xe_lrc_ctx_timestamp(lrc) == CONTEXT_ACTIVE;
}
-/**
- * xe_lrc_timestamp() - Current ctx timestamp
- * @lrc: Pointer to the lrc.
- *
- * Return latest ctx timestamp. With support for active contexts, the
- * calculation may be slightly racy, so follow a read-again logic to ensure that
- * the context is still active before returning the right timestamp.
- *
- * Returns: New ctx timestamp value
- */
-u64 xe_lrc_timestamp(struct xe_lrc *lrc)
+static u64 xe_lrc_multi_queue_timestamp(struct xe_lrc *lrc)
+{
+ struct xe_device *xe = lrc_to_xe(lrc);
+ struct xe_lrc *primary_lrc = lrc->multi_queue.primary_lrc;
+ struct xe_hw_engine *hwe;
+ u64 reg_queue_ts = lrc->queue_timestamp;
+
+ if (IS_SRIOV_VF(xe))
+ return xe_lrc_queue_timestamp(lrc);
+
+ xe_assert(xe, primary_lrc);
+
+ /* WA BB populates CONTEXT_ACTIVE cookie for primary context only */
+ if (!context_active(primary_lrc))
+ return xe_lrc_queue_timestamp(lrc);
+
+ /* WA BB populates engine id in PPHWSP of primary context only */
+ hwe = engine_id_to_hwe(primary_lrc->gt, xe_lrc_engine_id(primary_lrc));
+ if (!hwe)
+ return xe_lrc_queue_timestamp(lrc);
+
+ if (get_multi_queue_active_queue_id(hwe) != lrc->multi_queue.pos)
+ return xe_lrc_queue_timestamp(lrc);
+
+ /* queue is active, so store the queue timestamp register */
+ reg_queue_ts = get_queue_timestamp(hwe);
+
+ /* double check queue and primary queue are both still active */
+ if (get_multi_queue_active_queue_id(hwe) != lrc->multi_queue.pos ||
+ !context_active(primary_lrc))
+ return xe_lrc_queue_timestamp(lrc);
+
+ return reg_queue_ts;
+}
+
+static u64 xe_lrc_update_multi_queue_timestamp(struct xe_lrc *lrc, u64 *old_ts)
+{
+ *old_ts = lrc->queue_timestamp;
+ lrc->queue_timestamp = xe_lrc_multi_queue_timestamp(lrc);
+
+ return lrc->queue_timestamp;
+}
+
+static u64 xe_lrc_context_timestamp(struct xe_lrc *lrc)
{
u64 reg_ts, new_ts = lrc->ctx_timestamp;
return new_ts;
}
+static u64 xe_lrc_update_context_timestamp(struct xe_lrc *lrc, u64 *old_ts)
+{
+ *old_ts = lrc->ctx_timestamp;
+ lrc->ctx_timestamp = xe_lrc_context_timestamp(lrc);
+
+ trace_xe_lrc_update_timestamp(lrc, *old_ts);
+
+ return lrc->ctx_timestamp;
+}
+
+/**
+ * xe_lrc_timestamp() - Current lrc timestamp
+ * @lrc: Pointer to the lrc.
+ *
+ * Return latest lrc timestamp. With support for active contexts/queues, the
+ * calculation may be slightly racy, so follow a read-again logic to ensure that
+ * the context/queue is still active before returning the right timestamp.
+ *
+ * Returns: New lrc timestamp value
+ */
+u64 xe_lrc_timestamp(struct xe_lrc *lrc)
+{
+ if (xe_lrc_is_multi_queue(lrc))
+ return xe_lrc_multi_queue_timestamp(lrc);
+ else
+ return xe_lrc_context_timestamp(lrc);
+}
+
/**
- * xe_lrc_update_timestamp() - Update ctx timestamp
+ * xe_lrc_update_timestamp() - Update lrc timestamp
* @lrc: Pointer to the lrc.
* @old_ts: Old timestamp value
*
- * Populate @old_ts current saved ctx timestamp, read new ctx timestamp and
+ * Populate @old_ts with current saved lrc timestamp, read new lrc timestamp and
* update saved value.
*
- * Returns: New ctx timestamp value
+ * Returns: New lrc timestamp value
*/
u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts)
{
- *old_ts = lrc->ctx_timestamp;
- lrc->ctx_timestamp = xe_lrc_timestamp(lrc);
-
- trace_xe_lrc_update_timestamp(lrc, *old_ts);
-
- return lrc->ctx_timestamp;
+ if (xe_lrc_is_multi_queue(lrc))
+ return xe_lrc_update_multi_queue_timestamp(lrc, old_ts);
+ else
+ return xe_lrc_update_context_timestamp(lrc, old_ts);
}
/**