ih->rptr_addr = adev->wb.gpu_addr + rptr_offs * 4;
ih->rptr_cpu = &adev->wb.wb[rptr_offs];
}
+
+ init_waitqueue_head(&ih->wait_process);
return 0;
}
}
}
+/* Waiter helper that checks current rptr matches or passes checkpoint wptr */
+static bool amdgpu_ih_has_checkpoint_processed(struct amdgpu_device *adev,
+ struct amdgpu_ih_ring *ih,
+ uint32_t checkpoint_wptr,
+ uint32_t *prev_rptr)
+{
+ uint32_t cur_rptr = ih->rptr | (*prev_rptr & ~ih->ptr_mask);
+
+ /* rptr has wrapped. */
+ if (cur_rptr < *prev_rptr)
+ cur_rptr += ih->ptr_mask + 1;
+ *prev_rptr = cur_rptr;
+
+ return cur_rptr >= checkpoint_wptr;
+}
+
+/**
+ * amdgpu_ih_wait_on_checkpoint_process - wait to process IVs up to checkpoint
+ *
+ * @adev: amdgpu_device pointer
+ * @ih: ih ring to process
+ *
+ * Used to ensure ring has processed IVs up to the checkpoint write pointer.
+ */
+int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device *adev,
+ struct amdgpu_ih_ring *ih)
+{
+ uint32_t checkpoint_wptr, rptr;
+
+ if (!ih->enabled || adev->shutdown)
+ return -ENODEV;
+
+ checkpoint_wptr = amdgpu_ih_get_wptr(adev, ih);
+ /* Order wptr with rptr. */
+ rmb();
+ rptr = READ_ONCE(ih->rptr);
+
+ /* wptr has wrapped. */
+ if (rptr > checkpoint_wptr)
+ checkpoint_wptr += ih->ptr_mask + 1;
+
+ return wait_event_interruptible(ih->wait_process,
+ amdgpu_ih_has_checkpoint_processed(adev, ih,
+ checkpoint_wptr, &rptr));
+}
+
/**
* amdgpu_ih_process - interrupt handler
*
}
amdgpu_ih_set_rptr(adev, ih);
+ wake_up_all(&ih->wait_process);
atomic_set(&ih->lock, 0);
/* make sure wptr hasn't changed while processing */
unsigned rptr;
atomic_t lock;
struct amdgpu_ih_regs ih_regs;
+
+ /* For waiting on IH processing at checkpoint. */
+ wait_queue_head_t wait_process;
};
/* provided by the ih block */
void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
unsigned int num_dw);
+int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device *adev,
+ struct amdgpu_ih_ring *ih);
int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
void amdgpu_ih_decode_iv_helper(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih,