Commit f05d17b2 authored by Yuri Nudelman's avatar Yuri Nudelman Committed by Oded Gabbay
Browse files

habanalabs: take timestamp on wait for interrupt



Taking an accurate timestamp in a close proximity of the interrupt is
required for user side statistics management.

Signed-off-by: default avatarYuri Nudelman <ynudelman@habana.ai>
Reviewed-by: default avatarOded Gabbay <ogabbay@kernel.org>
Signed-off-by: default avatarOded Gabbay <ogabbay@kernel.org>
parent c1904127
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -2740,7 +2740,8 @@ static int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data)
static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
				u32 timeout_us, u64 user_address,
				u64 target_value, u16 interrupt_offset,
				enum hl_cs_wait_status *status)
				enum hl_cs_wait_status *status,
				bool take_timestamp, u64 *timestamp)
{
	struct hl_user_pending_interrupt *pend;
	struct hl_user_interrupt *interrupt;
@@ -2764,6 +2765,8 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,

	hl_fence_init(&pend->fence, ULONG_MAX);

	pend->fence.take_timestamp = take_timestamp;

	if (interrupt_offset == HL_COMMON_USER_INTERRUPT_ID)
		interrupt = &hdev->common_user_interrupt;
	else
@@ -2838,6 +2841,8 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
	list_del(&pend->wait_list_node);
	spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);

	*timestamp = ktime_to_ns(pend->fence.timestamp);

	kfree(pend);
	hl_ctx_put(ctx);

@@ -2851,6 +2856,7 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data)
	struct asic_fixed_properties *prop;
	union hl_wait_cs_args *args = data;
	enum hl_cs_wait_status status;
	u64 timestamp;
	int rc;

	prop = &hdev->asic_prop;
@@ -2880,7 +2886,9 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data)

	rc = _hl_interrupt_wait_ioctl(hdev, hpriv->ctx,
				args->in.interrupt_timeout_us, args->in.addr,
				args->in.target, interrupt_offset, &status);
				args->in.target, interrupt_offset, &status,
				args->in.flags & HL_CS_FLAGS_TIMESTAMP,
				&timestamp);

	if (rc) {
		if (rc != -EINTR)
@@ -2892,6 +2900,11 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data)

	memset(args, 0, sizeof(*args));

	if (timestamp) {
		args->out.timestamp_nsec = timestamp;
		args->out.flags |= HL_WAIT_CS_STATUS_FLAG_TIMESTAMP_VLD;
	}

	switch (status) {
	case CS_WAIT_STATUS_COMPLETED:
		args->out.status = HL_WAIT_CS_STATUS_COMPLETED;
+2 −0
Original line number Diff line number Diff line
@@ -601,6 +601,7 @@ struct asic_fixed_properties {
 *                         masters QIDs that multi cs is waiting on
 * @error: mark this fence with error
 * @timestamp: timestamp upon completion
 * @take_timestamp: timestamp shall be taken upon completion
 */
struct hl_fence {
	struct completion	completion;
@@ -609,6 +610,7 @@ struct hl_fence {
	u32			stream_master_qid_map;
	int			error;
	ktime_t			timestamp;
	u8			take_timestamp;
};

/**
+4 −1
Original line number Diff line number Diff line
@@ -143,8 +143,11 @@ static void handle_user_cq(struct hl_device *hdev,
	struct hl_user_pending_interrupt *pend;

	spin_lock(&user_cq->wait_list_lock);
	list_for_each_entry(pend, &user_cq->wait_list_head, wait_list_node)
	list_for_each_entry(pend, &user_cq->wait_list_head, wait_list_node) {
		if (pend->fence.take_timestamp)
			pend->fence.timestamp = ktime_get();
		complete_all(&pend->fence.completion);
	}
	spin_unlock(&user_cq->wait_list_lock);
}