Commit d5546d78 authored by Oded Gabbay's avatar Oded Gabbay

habanalabs: re-init completion object upon retry

In case user interrupt arrived but the completion value is less than
the target value, we want to retry the wait.

However, before the retry we must reinitialize the completion object,
under spin-lock, so the wait function won't exit immediately because
the completion object is already completed (from the previous
interrupt).
Signed-off-by: default avatarOded Gabbay <ogabbay@kernel.org>
parent 82629c71
...@@ -2046,7 +2046,8 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, ...@@ -2046,7 +2046,8 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
goto unlock_and_free_fence; goto unlock_and_free_fence;
} }
if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 4)) { if (copy_from_user(&completion_value, u64_to_user_ptr(user_address),
4)) {
dev_err(hdev->dev, dev_err(hdev->dev,
"Failed to copy completion value from user\n"); "Failed to copy completion value from user\n");
rc = -EFAULT; rc = -EFAULT;
...@@ -2077,18 +2078,28 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, ...@@ -2077,18 +2078,28 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx,
* If comparison fails, keep waiting until timeout expires * If comparison fails, keep waiting until timeout expires
*/ */
if (completion_rc > 0) { if (completion_rc > 0) {
spin_lock(&interrupt->wait_list_lock);
if (copy_from_user(&completion_value, if (copy_from_user(&completion_value,
u64_to_user_ptr(user_address), 4)) { u64_to_user_ptr(user_address), 4)) {
spin_unlock(&interrupt->wait_list_lock);
dev_err(hdev->dev, dev_err(hdev->dev,
"Failed to copy completion value from user\n"); "Failed to copy completion value from user\n");
rc = -EFAULT; rc = -EFAULT;
goto remove_pending_user_interrupt; goto remove_pending_user_interrupt;
} }
if (completion_value >= target_value) { if (completion_value >= target_value) {
spin_unlock(&interrupt->wait_list_lock);
*status = CS_WAIT_STATUS_COMPLETED; *status = CS_WAIT_STATUS_COMPLETED;
} else { } else {
reinit_completion(&pend->fence.completion);
timeout = completion_rc; timeout = completion_rc;
spin_unlock(&interrupt->wait_list_lock);
goto wait_again; goto wait_again;
} }
} else { } else {
......
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