On Fri, Nov 22, 2019 at 12:57:27PM -0800, Niranjana Vishwanathapura wrote:
+static inline bool +i915_range_done(struct hmm_range *range) +{
- bool ret = hmm_range_valid(range);
- hmm_range_unregister(range);
- return ret;
+}
This needs to be updated to follow the new API, but this pattern is generally wrong, failure if hmm_range_valid should retry the range_fault and so forth. See the hmm.rst.
+static int +i915_range_fault(struct i915_svm *svm, struct hmm_range *range) +{
- long ret;
- range->default_flags = 0;
- range->pfn_flags_mask = -1UL;
- ret = hmm_range_register(range, &svm->mirror);
- if (ret) {
up_read(&svm->mm->mmap_sem);
return (int)ret;
- }
Using a temporary range is the pattern from nouveau, is it really necessary in this driver?
+static u32 i915_svm_build_sg(struct i915_address_space *vm,
struct hmm_range *range,
struct sg_table *st)
+{
- struct scatterlist *sg;
- u32 sg_page_sizes = 0;
- u64 i, npages;
- sg = NULL;
- st->nents = 0;
- npages = (range->end - range->start) / PAGE_SIZE;
- /*
* No needd to dma map the host pages and later unmap it, as
* GPU is not allowed to access it with SVM. Hence, no need
* of any intermediate data strucutre to hold the mappings.
*/
- for (i = 0; i < npages; i++) {
u64 addr = range->pfns[i] & ~((1UL << range->pfn_shift) - 1);
if (sg && (addr == (sg_dma_address(sg) + sg->length))) {
sg->length += PAGE_SIZE;
sg_dma_len(sg) += PAGE_SIZE;
continue;
}
if (sg)
sg_page_sizes |= sg->length;
sg = sg ? __sg_next(sg) : st->sgl;
sg_dma_address(sg) = addr;
sg_dma_len(sg) = PAGE_SIZE;
sg->length = PAGE_SIZE;
st->nents++;
It is odd to build the range into a sgl.
IMHO it is not a good idea to use the sg_dma_address like this, that should only be filled in by a dma map. Where does it end up being used?
- range.pfn_shift = PAGE_SHIFT;
- range.start = args->start;
- range.flags = i915_range_flags;
- range.values = i915_range_values;
- range.end = range.start + args->length;
- for (i = 0; i < npages; ++i) {
range.pfns[i] = range.flags[HMM_PFN_VALID];
if (!(args->flags & I915_BIND_READONLY))
range.pfns[i] |= range.flags[HMM_PFN_WRITE];
- }
- down_read(&svm->mm->mmap_sem);
- vma = find_vma(svm->mm, range.start);
Why is find_vma needed?
- if (unlikely(!vma || vma->vm_end < range.end)) {
ret = -EFAULT;
goto vma_done;
- }
+again:
- ret = i915_range_fault(svm, &range);
- if (unlikely(ret))
goto vma_done;
- sg_page_sizes = i915_svm_build_sg(vm, &range, &st);
Keep in mind what can be done with the range values is limited until the lock is obtained. Reading the pfns and flags is OK though.
+int i915_svm_bind_mm(struct i915_address_space *vm) +{
- struct i915_svm *svm;
- struct mm_struct *mm;
- int ret = 0;
- mm = get_task_mm(current);
I don't think the get_task_mm(current) is needed, the mmget is already done for current->mm ?
Jason