diff mbox

[net-next,2/2] net: bcmgenet: add support for xmit_more

Message ID 1425937937-26955-3-git-send-email-f.fainelli@gmail.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Florian Fainelli March 9, 2015, 9:52 p.m. UTC
Delay the update of the TDMA producer index unless this is the last SKB in a
batch, or the queue is already stopped.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/ethernet/broadcom/genet/bcmgenet.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

Comments

Eric Dumazet March 9, 2015, 10:10 p.m. UTC | #1
On Mon, 2015-03-09 at 14:52 -0700, Florian Fainelli wrote:
> Delay the update of the TDMA producer index unless this is the last SKB in a
> batch, or the queue is already stopped.
> 
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
>  drivers/net/ethernet/broadcom/genet/bcmgenet.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> index 9b3b8a3db59b..8419826da6a7 100644
> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
> @@ -1316,8 +1316,10 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
>  	ring->prod_index += nr_frags + 1;
>  	ring->prod_index &= DMA_P_INDEX_MASK;
>  
> -	bcmgenet_tdma_ring_writel(priv, ring->index,
> -				  ring->prod_index, TDMA_PROD_INDEX);
> +	if (!skb->xmit_more || netif_xmit_stopped(txq))
> +		/* Packets are ready, update producer index */
> +		bcmgenet_tdma_ring_writel(priv, ring->index,
> +					  ring->prod_index, TDMA_PROD_INDEX);
>  
>  	if (ring->free_bds <= (MAX_SKB_FRAGS + 1))
>  		netif_tx_stop_queue(txq);

It seems you have a race here, if you stop the queue right now, while
this skb had skb->xmit_more set.





--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Florian Fainelli March 9, 2015, 10:13 p.m. UTC | #2
2015-03-09 15:10 GMT-07:00 Eric Dumazet <eric.dumazet@gmail.com>:
> On Mon, 2015-03-09 at 14:52 -0700, Florian Fainelli wrote:
>> Delay the update of the TDMA producer index unless this is the last SKB in a
>> batch, or the queue is already stopped.
>>
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>>  drivers/net/ethernet/broadcom/genet/bcmgenet.c | 6 ++++--
>>  1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> index 9b3b8a3db59b..8419826da6a7 100644
>> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> @@ -1316,8 +1316,10 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
>>       ring->prod_index += nr_frags + 1;
>>       ring->prod_index &= DMA_P_INDEX_MASK;
>>
>> -     bcmgenet_tdma_ring_writel(priv, ring->index,
>> -                               ring->prod_index, TDMA_PROD_INDEX);
>> +     if (!skb->xmit_more || netif_xmit_stopped(txq))
>> +             /* Packets are ready, update producer index */
>> +             bcmgenet_tdma_ring_writel(priv, ring->index,
>> +                                       ring->prod_index, TDMA_PROD_INDEX);
>>
>>       if (ring->free_bds <= (MAX_SKB_FRAGS + 1))
>>               netif_tx_stop_queue(txq);
>
> It seems you have a race here, if you stop the queue right now, while
> this skb had skb->xmit_more set.

bcmgenet_xmit() and bcmgenet_tx_reclaim() are the only two functions
that can stop a queue, and they are using a spinlock to avoid that.
--
Florian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Eric Dumazet March 9, 2015, 10:36 p.m. UTC | #3
On Mon, 2015-03-09 at 15:13 -0700, Florian Fainelli wrote:

> bcmgenet_xmit() and bcmgenet_tx_reclaim() are the only two functions
> that can stop a queue, and they are using a spinlock to avoid that.

It does not matter.

If you hit the condition :

if (ring->free_bds <= (MAX_SKB_FRAGS + 1))
     netif_tx_stop_queue(txq);

Then maybe you filled the ring buffer with skb having xmit_more set, and
you never did a bcmgenet_tdma_ring_writel()

Look at other drivers using xmit_more, because you have to reverse
things.

The skeleton is :

maybe_stop_tx();

if (netif_xmit_stopped(txring_txq(tx_ring)) || !skb->xmit_more) {
    mmiiowb();
    ...
}



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Florian Fainelli March 9, 2015, 10:49 p.m. UTC | #4
2015-03-09 15:36 GMT-07:00 Eric Dumazet <eric.dumazet@gmail.com>:
> On Mon, 2015-03-09 at 15:13 -0700, Florian Fainelli wrote:
>
>> bcmgenet_xmit() and bcmgenet_tx_reclaim() are the only two functions
>> that can stop a queue, and they are using a spinlock to avoid that.
>
> It does not matter.
>
> If you hit the condition :
>
> if (ring->free_bds <= (MAX_SKB_FRAGS + 1))
>      netif_tx_stop_queue(txq);
>
> Then maybe you filled the ring buffer with skb having xmit_more set, and
> you never did a bcmgenet_tdma_ring_writel()

Right, thanks for pointing that out.

>
> Look at other drivers using xmit_more, because you have to reverse
> things.
>
> The skeleton is :
>
> maybe_stop_tx();
>
> if (netif_xmit_stopped(txring_txq(tx_ring)) || !skb->xmit_more) {
>     mmiiowb();
>     ...
> }
>

Will fix that, thanks
diff mbox

Patch

diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 9b3b8a3db59b..8419826da6a7 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1316,8 +1316,10 @@  static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
 	ring->prod_index += nr_frags + 1;
 	ring->prod_index &= DMA_P_INDEX_MASK;
 
-	bcmgenet_tdma_ring_writel(priv, ring->index,
-				  ring->prod_index, TDMA_PROD_INDEX);
+	if (!skb->xmit_more || netif_xmit_stopped(txq))
+		/* Packets are ready, update producer index */
+		bcmgenet_tdma_ring_writel(priv, ring->index,
+					  ring->prod_index, TDMA_PROD_INDEX);
 
 	if (ring->free_bds <= (MAX_SKB_FRAGS + 1))
 		netif_tx_stop_queue(txq);