On Fri, 9 Apr 2021 22:32:49 +0300 Claudiu Manoil wrote:
> On 09.04.2021 19:09, Jakub Kicinski wrote:
> > On Fri, 9 Apr 2021 06:37:53 +0000 Claudiu Manoil wrote:  
> >> Please try test_and_set_bit_lock()/ clear_bit_unlock() based on Jakub's
> >> suggestion, and see if it works for you / whether it can replace the 
> >> mutex.  
> > 
> > I was thinking that with multiple queues just a bit won't be sufficient
> > because:
> > 
> > xmit:                               work:
> > test_bit... // already set
> >                             dequeue // empty
> > enqueue
> >                             clear_bit()
> > 
> > That frame will never get sent, no?  
> 
> I don't see any issue with Yangbo's initial design actually, I was just
> suggesting him to replace the mutex with a bit lock, based on your comments.
> That means:
> xmit:         work:                           clean_tx_ring: //Tx conf
> skb_queue_tail()              
>               skb_dequeue()
>               test_and_set_bit_lock()
>                                               clear_bit_unlock()
> 
> The skb queue is one per device, as it needs to serialize ptp skbs
> for that device (due to the restriction that a ptp packet cannot be 
> enqueued for transmission if there's another ptp packet waiting
> for transmission in a h/w descriptor ring).
> 
> If multiple ptp skbs are coming in from different xmit queues at the 
> same time (same device), they are enqueued in the common priv->tx_skbs 
> queue (skb_queue_tail() is protected by locks), and the worker thread is 
> started.
> The worker dequeues the first ptp skb, and places the packet in the h/w 
> descriptor ring for transmission. Then dequeues the second skb and waits 
> at the lock (or mutex or whatever lock is preferred).
> Upon transmission of the ptp packet the lock is released by the Tx 
> confirmation napi thread (clean_tx_ring()) and the next PTP skb can be 
> placed in the corresponding descriptor ring for transmission by the 
> worker thread.

I see. I thought you were commenting on my scheme. Yes, if only the
worker is allowed to send there is no race, that should work well.

In my suggestion I was trying to allow the first frame to be sent
directly without going via the queue and requiring the worker to be
scheduled in.

> So the way I understood your comments is that you'd rather use a spin 
> lock in the worker thread instead of a mutex.

Not exactly, my main objection was that the mutex was used for wake up.
Worker locks it, completion path unlocks it.

Your suggestion of using a bit works well. Just Instead of a loop the
worker needs to send a single skb, and completion needs to schedule it
again.

> > Note that skb_queue already has a lock so you'd just need to make that
> > lock protect the flag/bit as well, overall the number of locks remains
> > the same. Take the queue's lock, check the flag, use
> > __skb_queue_tail(), release etc.
> 
> This is a good optimization idea indeed, to use the priv->tx_skb skb 
> list's spin lock, instead of adding another lock.

Reply via email to