[PATCH 5/4] dma-fence: Have dma_fence_signal call signal_locked

Chris Wilson chris at chris-wilson.co.uk
Thu Aug 15 19:03:13 UTC 2019


Quoting Daniel Vetter (2019-08-15 19:48:42)
> On Thu, Aug 15, 2019 at 8:46 PM Chris Wilson <chris at chris-wilson.co.uk> wrote:
> > Quoting Daniel Vetter (2019-08-14 18:20:53)
> > > On Sun, Aug 11, 2019 at 10:15:23AM +0100, Chris Wilson wrote:
> > > > Now that dma_fence_signal always takes the spinlock to flush the
> > > > cb_list, simply take the spinlock and call dma_fence_signal_locked() to
> > > > avoid code repetition.
> > > >
> > > > Suggested-by: Christian König <christian.koenig at amd.com>
> > > > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> > > > Cc: Christian König <christian.koenig at amd.com>
> > >
> > > Hm, I think this largely defeats the point of having the lockless signal
> > > enabling trickery in dma_fence. Maybe that part isn't needed by anyone,
> > > but feels like a thing that needs a notch more thought. And if we need it,
> > > maybe a bit more cleanup.
> >
> > You mean dma_fence_enable_sw_signaling(). The only user appears to be to
> > flush fences, which is actually the intent of always notifying the signal
> > cb. By always doing the callbacks, we can avoid installing the interrupt
> > and completely saturating CPUs with irqs, instead doing a batch in a
> > leisurely timer callback if not flushed naturally.
> 
> Yeah I'm not against ditching this,

I was just thinking aloud working out what the current use case in ttm
was for.

> but can't we ditch a lot more if
> we just always take the spinlock in those paths now anyways? Kinda not
> worth having the complexity anymore.

You would be able to drop the was_set from dma_fence_add_callback. Say

diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index 59ac96ec7ba8..e566445134a2 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -345,38 +345,31 @@ int dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *cb,
                           dma_fence_func_t func)
 {
        unsigned long flags;
-       int ret = 0;
-       bool was_set;
+       int ret = -ENOENT;

        if (WARN_ON(!fence || !func))
                return -EINVAL;

-       if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
-               INIT_LIST_HEAD(&cb->node);
+       INIT_LIST_HEAD(&cb->node);
+       cb->func = func;
+
+       if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
                return -ENOENT;
-       }

        spin_lock_irqsave(fence->lock, flags);
-
-       was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
-                                  &fence->flags);
-
-       if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
-               ret = -ENOENT;
-       else if (!was_set && fence->ops->enable_signaling) {
+       if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) &&
+           !test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+                             &fence->flags)) {
                trace_dma_fence_enable_signal(fence);

-               if (!fence->ops->enable_signaling(fence)) {
+               if (!fence->ops->enable_signaling ||
+                   fence->ops->enable_signaling(fence)) {
+                       list_add_tail(&cb->node, &fence->cb_list);
+                       ret = 0;
+               } else {
                        dma_fence_signal_locked(fence);
-                       ret = -ENOENT;
                }
        }
-
-       if (!ret) {
-               cb->func = func;
-               list_add_tail(&cb->node, &fence->cb_list);
-       } else
-               INIT_LIST_HEAD(&cb->node);
        spin_unlock_irqrestore(fence->lock, flags);

        return ret;

Not a whole lot changes in terms of branches and serialising
instructions. One less baffling sequence to worry about.
-Chris


More information about the dri-devel mailing list