diff options
Diffstat (limited to 'drivers/dma-buf')
-rw-r--r-- | drivers/dma-buf/dma-fence-unwrap.c | 11 | ||||
-rw-r--r-- | drivers/dma-buf/st-dma-fence-unwrap.c | 268 | ||||
-rw-r--r-- | drivers/dma-buf/st-dma-fence.c | 2 | ||||
-rw-r--r-- | drivers/dma-buf/sw_sync.c | 19 | ||||
-rw-r--r-- | drivers/dma-buf/udmabuf.c | 2 |
5 files changed, 290 insertions, 12 deletions
diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c index 6345062731f1..2a059ac0ed27 100644 --- a/drivers/dma-buf/dma-fence-unwrap.c +++ b/drivers/dma-buf/dma-fence-unwrap.c @@ -84,8 +84,8 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, struct dma_fence **fences, struct dma_fence_unwrap *iter) { + struct dma_fence *tmp, *unsignaled = NULL, **array; struct dma_fence_array *result; - struct dma_fence *tmp, **array; ktime_t timestamp; int i, j, count; @@ -94,6 +94,8 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, for (i = 0; i < num_fences; ++i) { dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) { if (!dma_fence_is_signaled(tmp)) { + dma_fence_put(unsignaled); + unsignaled = dma_fence_get(tmp); ++count; } else { ktime_t t = dma_fence_timestamp(tmp); @@ -107,9 +109,16 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, /* * If we couldn't find a pending fence just return a private signaled * fence with the timestamp of the last signaled one. + * + * Or if there was a single unsignaled fence left we can return it + * directly and early since that is a major path on many workloads. */ if (count == 0) return dma_fence_allocate_private_stub(timestamp); + else if (count == 1) + return unsignaled; + + dma_fence_put(unsignaled); array = kmalloc_array(count, sizeof(*array), GFP_KERNEL); if (!array) diff --git a/drivers/dma-buf/st-dma-fence-unwrap.c b/drivers/dma-buf/st-dma-fence-unwrap.c index f0cee984b6c7..a3be888ae2e8 100644 --- a/drivers/dma-buf/st-dma-fence-unwrap.c +++ b/drivers/dma-buf/st-dma-fence-unwrap.c @@ -28,7 +28,7 @@ static const struct dma_fence_ops mock_ops = { .get_timeline_name = mock_name, }; -static struct dma_fence *mock_fence(void) +static struct dma_fence *__mock_fence(u64 context, u64 seqno) { struct mock_fence *f; @@ -37,12 +37,16 @@ static struct dma_fence *mock_fence(void) return NULL; spin_lock_init(&f->lock); - dma_fence_init(&f->base, &mock_ops, &f->lock, - dma_fence_context_alloc(1), 1); + dma_fence_init(&f->base, &mock_ops, &f->lock, context, seqno); return &f->base; } +static struct dma_fence *mock_fence(void) +{ + return __mock_fence(dma_fence_context_alloc(1), 1); +} + static struct dma_fence *mock_array(unsigned int num_fences, ...) { struct dma_fence_array *array; @@ -304,6 +308,177 @@ error_put_f1: return err; } +static int unwrap_merge_duplicate(void *arg) +{ + struct dma_fence *fence, *f1, *f2; + struct dma_fence_unwrap iter; + int err = 0; + + f1 = mock_fence(); + if (!f1) + return -ENOMEM; + + dma_fence_enable_sw_signaling(f1); + + f2 = dma_fence_unwrap_merge(f1, f1); + if (!f2) { + err = -ENOMEM; + goto error_put_f1; + } + + dma_fence_unwrap_for_each(fence, &iter, f2) { + if (fence == f1) { + dma_fence_put(f1); + f1 = NULL; + } else { + pr_err("Unexpected fence!\n"); + err = -EINVAL; + } + } + + if (f1) { + pr_err("Not all fences seen!\n"); + err = -EINVAL; + } + + dma_fence_put(f2); +error_put_f1: + dma_fence_put(f1); + return err; +} + +static int unwrap_merge_seqno(void *arg) +{ + struct dma_fence *fence, *f1, *f2, *f3, *f4; + struct dma_fence_unwrap iter; + int err = 0; + u64 ctx[2]; + + ctx[0] = dma_fence_context_alloc(1); + ctx[1] = dma_fence_context_alloc(1); + + f1 = __mock_fence(ctx[1], 1); + if (!f1) + return -ENOMEM; + + dma_fence_enable_sw_signaling(f1); + + f2 = __mock_fence(ctx[1], 2); + if (!f2) { + err = -ENOMEM; + goto error_put_f1; + } + + dma_fence_enable_sw_signaling(f2); + + f3 = __mock_fence(ctx[0], 1); + if (!f3) { + err = -ENOMEM; + goto error_put_f2; + } + + dma_fence_enable_sw_signaling(f3); + + f4 = dma_fence_unwrap_merge(f1, f2, f3); + if (!f4) { + err = -ENOMEM; + goto error_put_f3; + } + + dma_fence_unwrap_for_each(fence, &iter, f4) { + if (fence == f3 && f2) { + dma_fence_put(f3); + f3 = NULL; + } else if (fence == f2 && !f3) { + dma_fence_put(f2); + f2 = NULL; + } else { + pr_err("Unexpected fence!\n"); + err = -EINVAL; + } + } + + if (f2 || f3) { + pr_err("Not all fences seen!\n"); + err = -EINVAL; + } + + dma_fence_put(f4); +error_put_f3: + dma_fence_put(f3); +error_put_f2: + dma_fence_put(f2); +error_put_f1: + dma_fence_put(f1); + return err; +} + +static int unwrap_merge_order(void *arg) +{ + struct dma_fence *fence, *f1, *f2, *a1, *a2, *c1, *c2; + struct dma_fence_unwrap iter; + int err = 0; + + f1 = mock_fence(); + if (!f1) + return -ENOMEM; + + dma_fence_enable_sw_signaling(f1); + + f2 = mock_fence(); + if (!f2) { + dma_fence_put(f1); + return -ENOMEM; + } + + dma_fence_enable_sw_signaling(f2); + + a1 = mock_array(2, f1, f2); + if (!a1) + return -ENOMEM; + + c1 = mock_chain(NULL, dma_fence_get(f1)); + if (!c1) + goto error_put_a1; + + c2 = mock_chain(c1, dma_fence_get(f2)); + if (!c2) + goto error_put_a1; + + /* + * The fences in the chain are the same as in a1 but in oposite order, + * the dma_fence_merge() function should be able to handle that. + */ + a2 = dma_fence_unwrap_merge(a1, c2); + + dma_fence_unwrap_for_each(fence, &iter, a2) { + if (fence == f1) { + f1 = NULL; + if (!f2) + pr_err("Unexpected order!\n"); + } else if (fence == f2) { + f2 = NULL; + if (f1) + pr_err("Unexpected order!\n"); + } else { + pr_err("Unexpected fence!\n"); + err = -EINVAL; + } + } + + if (f1 || f2) { + pr_err("Not all fences seen!\n"); + err = -EINVAL; + } + + dma_fence_put(a2); + return err; + +error_put_a1: + dma_fence_put(a1); + return -ENOMEM; +} + static int unwrap_merge_complex(void *arg) { struct dma_fence *fence, *f1, *f2, *f3, *f4, *f5; @@ -327,7 +502,7 @@ static int unwrap_merge_complex(void *arg) goto error_put_f2; /* The resulting array has the fences in reverse */ - f4 = dma_fence_unwrap_merge(f2, f1); + f4 = mock_array(2, dma_fence_get(f2), dma_fence_get(f1)); if (!f4) goto error_put_f3; @@ -367,6 +542,87 @@ error_put_f1: return err; } +static int unwrap_merge_complex_seqno(void *arg) +{ + struct dma_fence *fence, *f1, *f2, *f3, *f4, *f5, *f6, *f7; + struct dma_fence_unwrap iter; + int err = -ENOMEM; + u64 ctx[2]; + + ctx[0] = dma_fence_context_alloc(1); + ctx[1] = dma_fence_context_alloc(1); + + f1 = __mock_fence(ctx[0], 2); + if (!f1) + return -ENOMEM; + + dma_fence_enable_sw_signaling(f1); + + f2 = __mock_fence(ctx[1], 1); + if (!f2) + goto error_put_f1; + + dma_fence_enable_sw_signaling(f2); + + f3 = __mock_fence(ctx[0], 1); + if (!f3) + goto error_put_f2; + + dma_fence_enable_sw_signaling(f3); + + f4 = __mock_fence(ctx[1], 2); + if (!f4) + goto error_put_f3; + + dma_fence_enable_sw_signaling(f4); + + f5 = mock_array(2, dma_fence_get(f1), dma_fence_get(f2)); + if (!f5) + goto error_put_f4; + + f6 = mock_array(2, dma_fence_get(f3), dma_fence_get(f4)); + if (!f6) + goto error_put_f5; + + f7 = dma_fence_unwrap_merge(f5, f6); + if (!f7) + goto error_put_f6; + + err = 0; + dma_fence_unwrap_for_each(fence, &iter, f7) { + if (fence == f1 && f4) { + dma_fence_put(f1); + f1 = NULL; + } else if (fence == f4 && !f1) { + dma_fence_put(f4); + f4 = NULL; + } else { + pr_err("Unexpected fence!\n"); + err = -EINVAL; + } + } + + if (f1 || f4) { + pr_err("Not all fences seen!\n"); + err = -EINVAL; + } + + dma_fence_put(f7); +error_put_f6: + dma_fence_put(f6); +error_put_f5: + dma_fence_put(f5); +error_put_f4: + dma_fence_put(f4); +error_put_f3: + dma_fence_put(f3); +error_put_f2: + dma_fence_put(f2); +error_put_f1: + dma_fence_put(f1); + return err; +} + int dma_fence_unwrap(void) { static const struct subtest tests[] = { @@ -375,7 +631,11 @@ int dma_fence_unwrap(void) SUBTEST(unwrap_chain), SUBTEST(unwrap_chain_array), SUBTEST(unwrap_merge), + SUBTEST(unwrap_merge_duplicate), + SUBTEST(unwrap_merge_seqno), + SUBTEST(unwrap_merge_order), SUBTEST(unwrap_merge_complex), + SUBTEST(unwrap_merge_complex_seqno), }; return subtests(tests, NULL); diff --git a/drivers/dma-buf/st-dma-fence.c b/drivers/dma-buf/st-dma-fence.c index cf2ce3744ce6..9f80a45498f0 100644 --- a/drivers/dma-buf/st-dma-fence.c +++ b/drivers/dma-buf/st-dma-fence.c @@ -412,7 +412,7 @@ static int test_wait_timeout(void *arg) err = 0; err_free: - del_timer_sync(&wt.timer); + timer_delete_sync(&wt.timer); destroy_timer_on_stack(&wt.timer); dma_fence_signal(wt.f); dma_fence_put(wt.f); diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index f5905d67dedb..22a808995f10 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -438,15 +438,17 @@ static int sw_sync_ioctl_get_deadline(struct sync_timeline *obj, unsigned long a return -EINVAL; pt = dma_fence_to_sync_pt(fence); - if (!pt) - return -EINVAL; + if (!pt) { + ret = -EINVAL; + goto put_fence; + } spin_lock_irqsave(fence->lock, flags); - if (test_bit(SW_SYNC_HAS_DEADLINE_BIT, &fence->flags)) { - data.deadline_ns = ktime_to_ns(pt->deadline); - } else { + if (!test_bit(SW_SYNC_HAS_DEADLINE_BIT, &fence->flags)) { ret = -ENOENT; + goto unlock; } + data.deadline_ns = ktime_to_ns(pt->deadline); spin_unlock_irqrestore(fence->lock, flags); dma_fence_put(fence); @@ -458,6 +460,13 @@ static int sw_sync_ioctl_get_deadline(struct sync_timeline *obj, unsigned long a return -EFAULT; return 0; + +unlock: + spin_unlock_irqrestore(fence->lock, flags); +put_fence: + dma_fence_put(fence); + + return ret; } static long sw_sync_ioctl(struct file *file, unsigned int cmd, diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index cc7398cc17d6..e74e36a8ecda 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -393,7 +393,7 @@ static long udmabuf_create(struct miscdevice *device, if (!ubuf) return -ENOMEM; - pglimit = (size_limit_mb * 1024 * 1024) >> PAGE_SHIFT; + pglimit = ((u64)size_limit_mb * 1024 * 1024) >> PAGE_SHIFT; for (i = 0; i < head->count; i++) { pgoff_t subpgcnt; |