net: stmmac: adding multiple buffers
Subsystems (4)
cover net: stmmac: adding multiple buffers
This patch adds multiple buffers to stmmac in a more fragmented way, in order to make problem debug easier.
I would kindly request to people to test this patch in their HWs in order to check if everything's functional. Thank you.
Joao Pinto (4):
net: stmmac: break some functions into RX and TX scopes
net: stmmac: adding multiple buffers for rx
net: stmmac: adding multiple buffers for TX
net: stmmac: adding multiple napi mechanism
drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 45 +- drivers/net/ethernet/stmicro/stmmac/ring_mode.c | 46 +- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 49 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1295 ++++++++++++++------- 4 files changed, 969 insertions(+), 466 deletions(-)
Signature · 1 line
2.9.3
PATCH 1/4 net: stmmac: break some functions into RX and TX scopes
This patch breaks several functions into RX and TX scopes, which will be useful when adding multiple buffers mechanism.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 350 +++++++++++++++++----- 1 file changed, 268 insertions(+), 82 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +268 -82
@@ -889,24 +889,41 @@ static int stmmac_init_phy(struct net_device *dev)return 0 ; } -static void stmmac_display_rings (struct stmmac_priv *priv) +static void stmmac_display_rx_rings (struct stmmac_priv *priv) { -void *head_rx, *head_tx; +void *head_rx; -if (priv->extend_desc) { +if (priv->extend_desc) head_rx = (void *)priv->dma_erx; - head_tx = (void *)priv->dma_etx; - }else { +else head_rx = (void *)priv->dma_rx; - head_tx = (void *)priv->dma_tx; - } -/* Display Rx ring */ +/* Display RX ring */ priv->hw->desc->display_ring (head_rx,DMA_RX_SIZE , true); -/* Display Tx ring */ +} + +static void stmmac_display_tx_rings (struct stmmac_priv *priv) +{ +void *head_tx; + +if (priv->extend_desc) + head_tx = (void *)priv->dma_etx; +else + head_tx = (void *)priv->dma_tx; + +/* Display TX ring */ priv->hw->desc->display_ring (head_tx,DMA_TX_SIZE , false); } +static void stmmac_display_rings (struct stmmac_priv *priv) +{ +/* Display RX ring */ +stmmac_display_rx_rings (priv); + +/* Display TX ring */ +stmmac_display_tx_rings (priv); +} +static int stmmac_set_bfsize (int mtu,int bufsize) {int ret = bufsize;
@@ -924,16 +941,16 @@ static int stmmac_set_bfsize(int mtu, int bufsize) }/** -* stmmac_clear_descriptors - clear descriptors +* stmmac_clear_rx_descriptors - clear RX descriptors * @priv: driver private structure -* Description: this function is called to clear the tx and rx descriptors +* Description: this function is called to clear the rx descriptors * in case of both basic and extended descriptors are used. */ -static void stmmac_clear_descriptors (struct stmmac_priv *priv) +static void stmmac_clear_rx_descriptors (struct stmmac_priv *priv) {int i; -/* Clear the Rx/Tx descriptors */ +/* Clear the RX descriptors */ for (i =0 ; i <DMA_RX_SIZE ; i++)if (priv->extend_desc) priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
@@ -943,6 +960,19 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) priv->hw->desc->init_rx_desc (&priv->dma_rx[i], priv->use_riwt, priv->mode, (i ==DMA_RX_SIZE -1 )); +} + +/** +* stmmac_clear_tx_descriptors - clear tx descriptors +* @priv: driver private structure +* Description: this function is called to clear the tx descriptors +* in case of both basic and extended descriptors are used. +*/ +static void stmmac_clear_tx_descriptors (struct stmmac_priv *priv) +{ +int i; + +/* Clear the TX descriptors */ for (i =0 ; i <DMA_TX_SIZE ; i++)if (priv->extend_desc) priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
@@ -955,6 +985,21 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) }/** +* stmmac_clear_descriptors - clear descriptors +* @priv: driver private structure +* Description: this function is called to clear the tx and rx descriptors +* in case of both basic and extended descriptors are used. +*/ +static void stmmac_clear_descriptors (struct stmmac_priv *priv) +{ +/* Clear the RX descriptors */ +stmmac_clear_rx_descriptors (priv); + +/* Clear the TX descriptors */ +stmmac_clear_tx_descriptors (priv); +} + +/** * stmmac_init_rx_buffers - init the RX descriptor buffer. * @priv: driver private structure * @p: descriptor pointer
@@ -996,6 +1041,11 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,return 0 ; } +/** +* stmmac_free_rx_buffers - free RX dma buffers +* @priv: private structure +* @i: buffer index. +*/ static void stmmac_free_rx_buffers (struct stmmac_priv *priv,int i) {if (priv->rx_skbuff[i]) {
@@ -1007,14 +1057,42 @@ static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i) }/** -* init_dma_desc_rings - init the RX/TX descriptor rings +* stmmac_free_tx_buffers - free RX dma buffers +* @priv: private structure +* @i: buffer index. +*/ +static void stmmac_free_tx_buffers (struct stmmac_priv *priv,int i) +{ +if (priv->tx_skbuff_dma[i].buf) { +if (priv->tx_skbuff_dma[i].map_as_page) +dma_unmap_page (priv->device, + priv->tx_skbuff_dma[i].buf, + priv->tx_skbuff_dma[i].len, +DMA_TO_DEVICE ); +else +dma_unmap_single (priv->device, + priv->tx_skbuff_dma[i].buf, + priv->tx_skbuff_dma[i].len, +DMA_TO_DEVICE ); + } + +if (priv->tx_skbuff[i]) { +dev_kfree_skb_any (priv->tx_skbuff[i]); + priv->tx_skbuff[i] =NULL ; + priv->tx_skbuff_dma[i].buf =0 ; + priv->tx_skbuff_dma[i].map_as_page = false; + } +} + +/** +* init_dma_rx_desc_rings - init the RX descriptor rings * @dev: net device structure * @flags: gfp flag. -* Description: this function initializes the DMA RX/TX descriptors +* Description: this function initializes the DMA RX descriptors * and allocates the socket buffers. It supports the chained and ring * modes. */ -static int init_dma_desc_rings (struct net_device *dev,gfp_t flags) +static int init_dma_rx_desc_rings (struct net_device *dev,gfp_t flags) {int i;struct stmmac_priv *priv =netdev_priv (dev);
@@ -1030,8 +1108,7 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) priv->dma_buf_sz = bfsize;netif_dbg (priv, probe, priv->dev, -"(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n" , - __func__, (u32 )priv->dma_rx_phy, (u32 )priv->dma_tx_phy); +"(%s) dma_rx_phy=0x%08x\n" , __func__, (u32 )priv->dma_rx_phy);/* RX INITIALIZATION */ netif_dbg(priv, probe, priv->dev,
@@ -1058,17 +1135,44 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)/* Setup the chained descriptor addresses */ if (priv->mode ==STMMAC_CHAIN_MODE ) { -if (priv->extend_desc) { +if (priv->extend_desc) priv->hw->mode->init (priv->dma_erx, priv->dma_rx_phy,DMA_RX_SIZE ,1 ); - priv->hw->mode->init (priv->dma_etx, priv->dma_tx_phy, -DMA_TX_SIZE ,1 ); - }else { +else priv->hw->mode->init (priv->dma_rx, priv->dma_rx_phy,DMA_RX_SIZE ,0 ); + } + +return 0 ; +err_init_rx_buffers: +while (--i >=0 ) +stmmac_free_rx_buffers (priv, i); +return ret; +} + +/** +* init_dma_tx_desc_rings - init the TX descriptor rings +* @dev: net device structure. +* Description: this function initializes the DMA TX descriptors +* and allocates the socket buffers. It supports the chained and ring +* modes. +*/ +static int init_dma_tx_desc_rings (struct net_device *dev) +{ +struct stmmac_priv *priv =netdev_priv (dev); +int i; + +netif_dbg (priv, probe, priv->dev, +"(%s) dma_tx_phy=0x%08x\n" , __func__, (u32 )priv->dma_rx_phy); + +/* Setup the chained descriptor addresses */ +if (priv->mode ==STMMAC_CHAIN_MODE ) { +if (priv->extend_desc) + priv->hw->mode->init (priv->dma_etx, priv->dma_tx_phy, +DMA_TX_SIZE ,1 ); +else priv->hw->mode->init (priv->dma_tx, priv->dma_tx_phy,DMA_TX_SIZE ,0 ); - } }/* TX INITIALIZATION */
@@ -1099,18 +1203,42 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) priv->cur_tx =0 ;netdev_reset_queue (priv->dev); +return 0 ; +} + +/** +* init_dma_desc_rings - init the RX/TX descriptor rings +* @dev: net device structure +* @flags: gfp flag. +* Description: this function initializes the DMA RX/TX descriptors +* and allocates the socket buffers. It supports the chained and ring +* modes. +*/ +static int init_dma_desc_rings (struct net_device *dev,gfp_t flags) +{ +struct stmmac_priv *priv =netdev_priv (dev); +int ret; + +/* RX INITIALIZATION */ + ret =init_dma_rx_desc_rings (dev, flags); +if (ret) +return ret; + +/* TX INITIALIZATION */ + ret =init_dma_tx_desc_rings (dev); +stmmac_clear_descriptors (priv);if (netif_msg_hw (priv))stmmac_display_rings (priv); -return 0 ; -err_init_rx_buffers: -while (--i >=0 ) -stmmac_free_rx_buffers (priv, i);return ret; } +/** +* dma_free_rx_skbufs - free RX dma buffers +* @priv: private structure +*/ static void dma_free_rx_skbufs (struct stmmac_priv *priv) {int i;
@@ -1119,42 +1247,27 @@ static void dma_free_rx_skbufs(struct stmmac_priv *priv)stmmac_free_rx_buffers (priv, i); } +/** +* dma_free_tx_skbufs - free TX dma buffers +* @priv: private structure +*/ static void dma_free_tx_skbufs (struct stmmac_priv *priv) {int i; -for (i =0 ; i <DMA_TX_SIZE ; i++) { -if (priv->tx_skbuff_dma[i].buf) { -if (priv->tx_skbuff_dma[i].map_as_page) -dma_unmap_page (priv->device, - priv->tx_skbuff_dma[i].buf, - priv->tx_skbuff_dma[i].len, -DMA_TO_DEVICE ); -else -dma_unmap_single (priv->device, - priv->tx_skbuff_dma[i].buf, - priv->tx_skbuff_dma[i].len, -DMA_TO_DEVICE ); - } - -if (priv->tx_skbuff[i]) { -dev_kfree_skb_any (priv->tx_skbuff[i]); - priv->tx_skbuff[i] =NULL ; - priv->tx_skbuff_dma[i].buf =0 ; - priv->tx_skbuff_dma[i].map_as_page = false; - } - } +for (i =0 ; i <DMA_TX_SIZE ; i++) +stmmac_free_tx_buffers (priv, i); }/** -* alloc_dma_desc_resources - alloc TX/RX resources. +* alloc_dma_rx_desc_resources - alloc RX resources. * @priv: private structure * Description: according to which descriptor can be used (extend or basic) * this function allocates the resources for TX and RX paths. In case of * reception, for example, it pre-allocated the RX socket buffer in order to * allow zero-copy mechanism. */ -static int alloc_dma_desc_resources (struct stmmac_priv *priv) +static int alloc_dma_rx_desc_resources (struct stmmac_priv *priv) {int ret = -ENOMEM ;
@@ -1168,11 +1281,50 @@ static int alloc_dma_desc_resources(struct stmmac_priv *priv)if (!priv->rx_skbuff) goto err_rx_skbuff; +if (priv->extend_desc) { + priv->dma_erx =dma_zalloc_coherent (priv->device,DMA_RX_SIZE * +sizeof (struct +dma_extended_desc ), + &priv->dma_rx_phy, +GFP_KERNEL ); +if (!priv->dma_erx) + goto err_dma; + + }else { + priv->dma_rx =dma_zalloc_coherent (priv->device,DMA_RX_SIZE * +sizeof (struct dma_desc ), + &priv->dma_rx_phy, +GFP_KERNEL ); +if (!priv->dma_rx) + goto err_dma; + } + +return 0 ; + +err_dma: +kfree (priv->rx_skbuff); +err_rx_skbuff: +kfree (priv->rx_skbuff_dma); +return ret; +} + +/** +* alloc_dma_tx_desc_resources - alloc TX resources. +* @priv: private structure +* Description: according to which descriptor can be used (extend or basic) +* this function allocates the resources for TX and RX paths. In case of +* reception, for example, it pre-allocated the RX socket buffer in order to +* allow zero-copy mechanism. +*/ +static int alloc_dma_tx_desc_resources (struct stmmac_priv *priv) +{ +int ret = -ENOMEM ; + priv->tx_skbuff_dma =kmalloc_array (DMA_TX_SIZE ,sizeof (*priv->tx_skbuff_dma),GFP_KERNEL );if (!priv->tx_skbuff_dma) - goto err_tx_skbuff_dma; +return -ENOMEM ; priv->tx_skbuff =kmalloc_array (DMA_TX_SIZE ,sizeof (struct sk_buff *),GFP_KERNEL );
@@ -1180,14 +1332,6 @@ static int alloc_dma_desc_resources(struct stmmac_priv *priv) goto err_tx_skbuff;if (priv->extend_desc) { - priv->dma_erx =dma_zalloc_coherent (priv->device,DMA_RX_SIZE * -sizeof (struct -dma_extended_desc ), - &priv->dma_rx_phy, -GFP_KERNEL ); -if (!priv->dma_erx) - goto err_dma; - priv->dma_etx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE * sizeof(struct dma_extended_desc),
@@ -1200,13 +1344,6 @@ static int alloc_dma_desc_resources(struct stmmac_priv *priv) goto err_dma; } }else { - priv->dma_rx =dma_zalloc_coherent (priv->device,DMA_RX_SIZE * -sizeof (struct dma_desc ), - &priv->dma_rx_phy, -GFP_KERNEL ); -if (!priv->dma_rx) - goto err_dma; - priv->dma_tx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE * sizeof(struct dma_desc), &priv->dma_tx_phy,
@@ -1225,42 +1362,91 @@ static int alloc_dma_desc_resources(struct stmmac_priv *priv)kfree (priv->tx_skbuff); err_tx_skbuff:kfree (priv->tx_skbuff_dma); -err_tx_skbuff_dma: -kfree (priv->rx_skbuff); -err_rx_skbuff: -kfree (priv->rx_skbuff_dma);return ret; } -static void free_dma_desc_resources (struct stmmac_priv *priv) +/** +* alloc_dma_desc_resources - alloc TX/RX resources. +* @priv: private structure +* Description: according to which descriptor can be used (extend or basic) +* this function allocates the resources for TX and RX paths. In case of +* reception, for example, it pre-allocated the RX socket buffer in order to +* allow zero-copy mechanism. +*/ +static int alloc_dma_desc_resources (struct stmmac_priv *priv) +{ +/* RX Allocation */ +int ret =alloc_dma_rx_desc_resources (priv); + +if (ret) +return ret; + +/* TX Allocation */ + ret =alloc_dma_tx_desc_resources (priv); + +return ret; +} + +/** +* free_dma_rx_desc_resources - free RX dma desc resources +* @priv: private structure +*/ +static void free_dma_rx_desc_resources (struct stmmac_priv *priv) { -/* Release the DMA TX/RX socket buffers */ +/* Release the DMA RX socket buffers */ dma_free_rx_skbufs (priv); -dma_free_tx_skbufs (priv);/* Free DMA regions of consistent memory previously allocated */ -if (!priv->extend_desc) { -dma_free_coherent (priv->device, -DMA_TX_SIZE *sizeof (struct dma_desc ), - priv->dma_tx, priv->dma_tx_phy); +if (!priv->extend_desc)dma_free_coherent (priv->device,DMA_RX_SIZE *sizeof (struct dma_desc ), priv->dma_rx, priv->dma_rx_phy); - }else { -dma_free_coherent (priv->device,DMA_TX_SIZE * -sizeof (struct dma_extended_desc ), - priv->dma_etx, priv->dma_tx_phy); +else dma_free_coherent (priv->device,DMA_RX_SIZE *sizeof (struct dma_extended_desc ), priv->dma_erx, priv->dma_rx_phy); - } +kfree (priv->rx_skbuff_dma);kfree (priv->rx_skbuff); +} + +/** +* free_dma_tx_desc_resources - free TX dma desc resources +* @priv: private structure +*/ +static void free_dma_tx_desc_resources (struct stmmac_priv *priv) +{ +/* Release the DMA TX socket buffers */ +dma_free_tx_skbufs (priv); + +/* Free DMA regions of consistent memory previously allocated */ +if (!priv->extend_desc) +dma_free_coherent (priv->device, +DMA_TX_SIZE *sizeof (struct dma_desc ), + priv->dma_tx, priv->dma_tx_phy); +else +dma_free_coherent (priv->device,DMA_TX_SIZE * +sizeof (struct dma_extended_desc ), + priv->dma_etx, priv->dma_tx_phy); +kfree (priv->tx_skbuff_dma);kfree (priv->tx_skbuff); }/** +* free_dma_desc_resources - free dma desc resources +* @priv: private structure +*/ +static void free_dma_desc_resources (struct stmmac_priv *priv) +{ +/* Release the DMA RX socket buffers */ +free_dma_rx_desc_resources (priv); + +/* Release the DMA TX socket buffers */ +free_dma_tx_desc_resources (priv); +} + +/** * stmmac_mac_enable_rx_queues - Enable MAC rx queues * @priv: driver private structure * Description: It is used for enabling the rx queues in the MAC
Signature · 1 line
2.9.3
Re: [PATCH 1/4] net: stmmac: break some functions into RX and TX scopes
Quoted 7 lines · Joao Pinto
This patch breaks several functions into RX and TX scopes, which will be useful when adding multiple buffers mechanism.
Signed-off-by Joao Pinto <[email protected]>--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 350 +++++++++++++++++----- 1 file changed, 268 insertions(+), 82 deletions(-)
A couple of small nits below.
Quoted 1 line
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0
-0
[...]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int stmmac_set_bfsize(int mtu, int bufsize) · line 946
Quoted 9 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2
-2@@ -924,16 +941,16 @@ static int stmmac_set_bfsize(int mtu, int bufsize) }/** -* stmmac_clear_descriptors - clear descriptors +* stmmac_clear_rx_descriptors - clear RX descriptors * @priv: driver private structure -* Description: this function is called to clear the tx and rx descriptors +* Description: this function is called to clear the rx descriptors
You seem to be transitioning to "RX" and "TX" everywhere, maybe do the same in this comment for consistency?
Also, on a general note: there's no need for "Description:" here. The kerneldoc format mandates that you leave a blank line after the block of parameter descriptions, and the paragraph that follows becomes the description. I know that these are static functions and are therefore not parsed by kerneldoc, but since you already use the syntax anyway, you might as well get it right.
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int stmmac_set_bfsize(int mtu, int bufsize) · line 951
Quoted 6 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1
-1* in case of both basic and extended descriptors are used. */ -static void stmmac_clear_descriptors (struct stmmac_priv *priv) +static void stmmac_clear_rx_descriptors (struct stmmac_priv *priv) {int i;
This could be unsigned.
Quoted 11 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2
-1-/* Clear the Rx/Tx descriptors */ +/* Clear the RX descriptors */ for (i =0 ; i <DMA_RX_SIZE ; i++)if (priv->extend_desc) priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,@@ -943,6 +960,19 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) priv->hw->desc->init_rx_desc (&priv->dma_rx[i], priv->use_riwt, priv->mode, (i ==DMA_RX_SIZE -1 )); +}
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static void stmmac_clear_descriptors(struct stmmac_priv *priv) · line 973
Quoted 10 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +10
-0+ +/** +* stmmac_clear_tx_descriptors - clear tx descriptors +* @priv: driver private structure +* Description: this function is called to clear the tx descriptors +* in case of both basic and extended descriptors are used. +*/ +static void stmmac_clear_tx_descriptors (struct stmmac_priv *priv) +{ +int i;
Same here. There are a couple of other such occurrences throughout the file. This already exists in many places in the driver, so I don't think this needs to be changed. Or at least it could be a follow-up patch.
Quoted 28 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +17
-0+ +/* Clear the TX descriptors */ for (i =0 ; i <DMA_TX_SIZE ; i++)if (priv->extend_desc) priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,@@ -955,6 +985,21 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) }/** +* stmmac_clear_descriptors - clear descriptors +* @priv: driver private structure +* Description: this function is called to clear the tx and rx descriptors +* in case of both basic and extended descriptors are used. +*/ +static void stmmac_clear_descriptors (struct stmmac_priv *priv) +{ +/* Clear the RX descriptors */ +stmmac_clear_rx_descriptors (priv); + +/* Clear the TX descriptors */ +stmmac_clear_tx_descriptors (priv); +} + +/** * stmmac_init_rx_buffers - init the RX descriptor buffer. * @priv: driver private structure * @p: descriptor pointer
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, · line 1047
Quoted 7 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +4
-0@@ -996,6 +1041,11 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,return 0 ; } +/** +* stmmac_free_rx_buffers - free RX dma buffers +* @priv: private structure +* @i: buffer index.
If this operates on a single buffer, as specified by the buffer index, maybe this should be named singular stmmac_free_rx_buffer()?
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, · line 1049
Quoted 2 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1
-0+*/ static void stmmac_free_rx_buffers (struct stmmac_priv *priv,int i)
The index could be unsigned.
Quoted 120 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +72
-10{if (priv->rx_skbuff[i]) {@@ -1007,14 +1057,42 @@ static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i) }/** -* init_dma_desc_rings - init the RX/TX descriptor rings +* stmmac_free_tx_buffers - free RX dma buffers +* @priv: private structure +* @i: buffer index. +*/ +static void stmmac_free_tx_buffers (struct stmmac_priv *priv,int i) +{ +if (priv->tx_skbuff_dma[i].buf) { +if (priv->tx_skbuff_dma[i].map_as_page) +dma_unmap_page (priv->device, + priv->tx_skbuff_dma[i].buf, + priv->tx_skbuff_dma[i].len, +DMA_TO_DEVICE ); +else +dma_unmap_single (priv->device, + priv->tx_skbuff_dma[i].buf, + priv->tx_skbuff_dma[i].len, +DMA_TO_DEVICE ); + } + +if (priv->tx_skbuff[i]) { +dev_kfree_skb_any (priv->tx_skbuff[i]); + priv->tx_skbuff[i] =NULL ; + priv->tx_skbuff_dma[i].buf =0 ; + priv->tx_skbuff_dma[i].map_as_page = false; + } +} + +/** +* init_dma_rx_desc_rings - init the RX descriptor rings * @dev: net device structure * @flags: gfp flag. -* Description: this function initializes the DMA RX/TX descriptors +* Description: this function initializes the DMA RX descriptors * and allocates the socket buffers. It supports the chained and ring * modes. */ -static int init_dma_desc_rings (struct net_device *dev,gfp_t flags) +static int init_dma_rx_desc_rings (struct net_device *dev,gfp_t flags) {int i;struct stmmac_priv *priv =netdev_priv (dev);@@ -1030,8 +1108,7 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) priv->dma_buf_sz = bfsize;netif_dbg (priv, probe, priv->dev, -"(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n" , - __func__, (u32 )priv->dma_rx_phy, (u32 )priv->dma_tx_phy); +"(%s) dma_rx_phy=0x%08x\n" , __func__, (u32 )priv->dma_rx_phy);/* RX INITIALIZATION */ netif_dbg(priv, probe, priv->dev,@@ -1058,17 +1135,44 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)/* Setup the chained descriptor addresses */ if (priv->mode ==STMMAC_CHAIN_MODE ) { -if (priv->extend_desc) { +if (priv->extend_desc) priv->hw->mode->init (priv->dma_erx, priv->dma_rx_phy,DMA_RX_SIZE ,1 ); - priv->hw->mode->init (priv->dma_etx, priv->dma_tx_phy, -DMA_TX_SIZE ,1 ); - }else { +else priv->hw->mode->init (priv->dma_rx, priv->dma_rx_phy,DMA_RX_SIZE ,0 ); + } + +return 0 ; +err_init_rx_buffers: +while (--i >=0 ) +stmmac_free_rx_buffers (priv, i); +return ret; +} + +/** +* init_dma_tx_desc_rings - init the TX descriptor rings +* @dev: net device structure. +* Description: this function initializes the DMA TX descriptors +* and allocates the socket buffers. It supports the chained and ring +* modes. +*/ +static int init_dma_tx_desc_rings (struct net_device *dev) +{ +struct stmmac_priv *priv =netdev_priv (dev); +int i; + +netif_dbg (priv, probe, priv->dev, +"(%s) dma_tx_phy=0x%08x\n" , __func__, (u32 )priv->dma_rx_phy); + +/* Setup the chained descriptor addresses */ +if (priv->mode ==STMMAC_CHAIN_MODE ) { +if (priv->extend_desc) + priv->hw->mode->init (priv->dma_etx, priv->dma_tx_phy, +DMA_TX_SIZE ,1 ); +else priv->hw->mode->init (priv->dma_tx, priv->dma_tx_phy,DMA_TX_SIZE ,0 ); - } }/* TX INITIALIZATION */ @@ -1099,18 +1203,42 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) priv->cur_tx =0 ;netdev_reset_queue (priv->dev); +return 0 ; +} + +/** +* init_dma_desc_rings - init the RX/TX descriptor rings +* @dev: net device structure +* @flags: gfp flag. +* Description: this function initializes the DMA RX/TX descriptors
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) · line 1223
Quoted 10 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +10
-0+* and allocates the socket buffers. It supports the chained and ring +* modes. +*/ +static int init_dma_desc_rings (struct net_device *dev,gfp_t flags) +{ +struct stmmac_priv *priv =netdev_priv (dev); +int ret; + +/* RX INITIALIZATION */ + ret =init_dma_rx_desc_rings (dev, flags);
That comment already exists in init_dma_rx_desc_rings(). And even there it doesn't provide any useful information, so might as well drop it.
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) · line 1228
Quoted 5 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +5
-0+if (ret) +return ret; + +/* TX INITIALIZATION */ + ret =init_dma_tx_desc_rings (dev);
Same here.
[...]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int alloc_dma_desc_resources(struct stmmac_priv *priv) · line 1379
Quoted 13 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +12
-1-static void free_dma_desc_resources (struct stmmac_priv *priv) +/** +* alloc_dma_desc_resources - alloc TX/RX resources. +* @priv: private structure +* Description: according to which descriptor can be used (extend or basic) +* this function allocates the resources for TX and RX paths. In case of +* reception, for example, it pre-allocated the RX socket buffer in order to +* allow zero-copy mechanism. +*/ +static int alloc_dma_desc_resources (struct stmmac_priv *priv) +{ +/* RX Allocation */ +int ret =alloc_dma_rx_desc_resources (priv);
And here.
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int alloc_dma_desc_resources(struct stmmac_priv *priv) · line 1385
Quoted 6 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +6
-0+ +if (ret) +return ret; + +/* TX Allocation */ + ret =alloc_dma_tx_desc_resources (priv);
And here.
None of the above comments are critical and this could be cleaned up in follow-up patches, so:
It also doesn't break on Tegra186, so
Re: [PATCH 1/4] net: stmmac: break some functions into RX and TX scopes
Hi Thierry,
Às 7:57 PM de 4/4/2017, Thierry Reding escreveu:
Quoted 280 lines · Joao Pinto
Quoted 7 lines
This patch breaks several functions into RX and TX scopes, which will be useful when adding multiple buffers mechanism.
Signed-off-by Joao Pinto <[email protected]>--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 350 +++++++++++++++++----- 1 file changed, 268 insertions(+), 82 deletions(-)A couple of small nits below.
Quoted 1 line
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0
-0[...]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int stmmac_set_bfsize(int mtu, int bufsize) · line 946
Quoted 9 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2
-2@@ -924,16 +941,16 @@ static int stmmac_set_bfsize(int mtu, int bufsize) }/** -* stmmac_clear_descriptors - clear descriptors +* stmmac_clear_rx_descriptors - clear RX descriptors * @priv: driver private structure -* Description: this function is called to clear the tx and rx descriptors +* Description: this function is called to clear the rx descriptors You seem to be transitioning to "RX" and "TX" everywhere, maybe do the same in this comment for consistency?
Also, on a general note: there's no need for "Description:" here. The kerneldoc format mandates that you leave a blank line after the block of parameter descriptions, and the paragraph that follows becomes the description. I know that these are static functions and are therefore not parsed by kerneldoc, but since you already use the syntax anyway, you might as well get it right.
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int stmmac_set_bfsize(int mtu, int bufsize) · line 951
Quoted 6 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1
-1* in case of both basic and extended descriptors are used. */ -static void stmmac_clear_descriptors (struct stmmac_priv *priv) +static void stmmac_clear_rx_descriptors (struct stmmac_priv *priv) {int i;This could be unsigned.
Quoted 11 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2
-1-/* Clear the Rx/Tx descriptors */ +/* Clear the RX descriptors */ for (i =0 ; i <DMA_RX_SIZE ; i++)if (priv->extend_desc) priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,@@ -943,6 +960,19 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) priv->hw->desc->init_rx_desc (&priv->dma_rx[i], priv->use_riwt, priv->mode, (i ==DMA_RX_SIZE -1 )); +}drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static void stmmac_clear_descriptors(struct stmmac_priv *priv) · line 973
Quoted 10 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +10
-0+ +/** +* stmmac_clear_tx_descriptors - clear tx descriptors +* @priv: driver private structure +* Description: this function is called to clear the tx descriptors +* in case of both basic and extended descriptors are used. +*/ +static void stmmac_clear_tx_descriptors (struct stmmac_priv *priv) +{ +int i;Same here. There are a couple of other such occurrences throughout the file. This already exists in many places in the driver, so I don't think this needs to be changed. Or at least it could be a follow-up patch.
Quoted 28 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +17
-0+ +/* Clear the TX descriptors */ for (i =0 ; i <DMA_TX_SIZE ; i++)if (priv->extend_desc) priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,@@ -955,6 +985,21 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) }/** +* stmmac_clear_descriptors - clear descriptors +* @priv: driver private structure +* Description: this function is called to clear the tx and rx descriptors +* in case of both basic and extended descriptors are used. +*/ +static void stmmac_clear_descriptors (struct stmmac_priv *priv) +{ +/* Clear the RX descriptors */ +stmmac_clear_rx_descriptors (priv); + +/* Clear the TX descriptors */ +stmmac_clear_tx_descriptors (priv); +} + +/** * stmmac_init_rx_buffers - init the RX descriptor buffer. * @priv: driver private structure * @p: descriptor pointer drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, · line 1047
Quoted 7 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +4
-0@@ -996,6 +1041,11 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,return 0 ; } +/** +* stmmac_free_rx_buffers - free RX dma buffers +* @priv: private structure +* @i: buffer index. If this operates on a single buffer, as specified by the buffer index, maybe this should be named singular
stmmac_free_rx_buffer()?drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, · line 1049
Quoted 2 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1
-0+*/ static void stmmac_free_rx_buffers (struct stmmac_priv *priv,int i)The index could be unsigned.
Quoted 120 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +72
-10{if (priv->rx_skbuff[i]) {@@ -1007,14 +1057,42 @@ static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i) }/** -* init_dma_desc_rings - init the RX/TX descriptor rings +* stmmac_free_tx_buffers - free RX dma buffers +* @priv: private structure +* @i: buffer index. +*/ +static void stmmac_free_tx_buffers (struct stmmac_priv *priv,int i) +{ +if (priv->tx_skbuff_dma[i].buf) { +if (priv->tx_skbuff_dma[i].map_as_page) +dma_unmap_page (priv->device, + priv->tx_skbuff_dma[i].buf, + priv->tx_skbuff_dma[i].len, +DMA_TO_DEVICE ); +else +dma_unmap_single (priv->device, + priv->tx_skbuff_dma[i].buf, + priv->tx_skbuff_dma[i].len, +DMA_TO_DEVICE ); + } + +if (priv->tx_skbuff[i]) { +dev_kfree_skb_any (priv->tx_skbuff[i]); + priv->tx_skbuff[i] =NULL ; + priv->tx_skbuff_dma[i].buf =0 ; + priv->tx_skbuff_dma[i].map_as_page = false; + } +} + +/** +* init_dma_rx_desc_rings - init the RX descriptor rings * @dev: net device structure * @flags: gfp flag. -* Description: this function initializes the DMA RX/TX descriptors +* Description: this function initializes the DMA RX descriptors * and allocates the socket buffers. It supports the chained and ring * modes. */ -static int init_dma_desc_rings (struct net_device *dev,gfp_t flags) +static int init_dma_rx_desc_rings (struct net_device *dev,gfp_t flags) {int i;struct stmmac_priv *priv =netdev_priv (dev);@@ -1030,8 +1108,7 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) priv->dma_buf_sz = bfsize;netif_dbg (priv, probe, priv->dev, -"(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n" , - __func__, (u32 )priv->dma_rx_phy, (u32 )priv->dma_tx_phy); +"(%s) dma_rx_phy=0x%08x\n" , __func__, (u32 )priv->dma_rx_phy);/* RX INITIALIZATION */ netif_dbg(priv, probe, priv->dev,@@ -1058,17 +1135,44 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)/* Setup the chained descriptor addresses */ if (priv->mode ==STMMAC_CHAIN_MODE ) { -if (priv->extend_desc) { +if (priv->extend_desc) priv->hw->mode->init (priv->dma_erx, priv->dma_rx_phy,DMA_RX_SIZE ,1 ); - priv->hw->mode->init (priv->dma_etx, priv->dma_tx_phy, -DMA_TX_SIZE ,1 ); - }else { +else priv->hw->mode->init (priv->dma_rx, priv->dma_rx_phy,DMA_RX_SIZE ,0 ); + } + +return 0 ; +err_init_rx_buffers: +while (--i >=0 ) +stmmac_free_rx_buffers (priv, i); +return ret; +} + +/** +* init_dma_tx_desc_rings - init the TX descriptor rings +* @dev: net device structure. +* Description: this function initializes the DMA TX descriptors +* and allocates the socket buffers. It supports the chained and ring +* modes. +*/ +static int init_dma_tx_desc_rings (struct net_device *dev) +{ +struct stmmac_priv *priv =netdev_priv (dev); +int i; + +netif_dbg (priv, probe, priv->dev, +"(%s) dma_tx_phy=0x%08x\n" , __func__, (u32 )priv->dma_rx_phy); + +/* Setup the chained descriptor addresses */ +if (priv->mode ==STMMAC_CHAIN_MODE ) { +if (priv->extend_desc) + priv->hw->mode->init (priv->dma_etx, priv->dma_tx_phy, +DMA_TX_SIZE ,1 ); +else priv->hw->mode->init (priv->dma_tx, priv->dma_tx_phy,DMA_TX_SIZE ,0 ); - } }/* TX INITIALIZATION */ @@ -1099,18 +1203,42 @@ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) priv->cur_tx =0 ;netdev_reset_queue (priv->dev); +return 0 ; +} + +/** +* init_dma_desc_rings - init the RX/TX descriptor rings +* @dev: net device structure +* @flags: gfp flag. +* Description: this function initializes the DMA RX/TX descriptors drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) · line 1223
Quoted 10 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +10
-0+* and allocates the socket buffers. It supports the chained and ring +* modes. +*/ +static int init_dma_desc_rings (struct net_device *dev,gfp_t flags) +{ +struct stmmac_priv *priv =netdev_priv (dev); +int ret; + +/* RX INITIALIZATION */ + ret =init_dma_rx_desc_rings (dev, flags);That comment already exists in
init_dma_rx_desc_rings(). And even there it doesn't provide any useful information, so might as well drop it.drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) · line 1228
Quoted 5 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +5
-0+if (ret) +return ret; + +/* TX INITIALIZATION */ + ret =init_dma_tx_desc_rings (dev);Same here.
[...]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int alloc_dma_desc_resources(struct stmmac_priv *priv) · line 1379
Quoted 13 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +12
-1-static void free_dma_desc_resources (struct stmmac_priv *priv) +/** +* alloc_dma_desc_resources - alloc TX/RX resources. +* @priv: private structure +* Description: according to which descriptor can be used (extend or basic) +* this function allocates the resources for TX and RX paths. In case of +* reception, for example, it pre-allocated the RX socket buffer in order to +* allow zero-copy mechanism. +*/ +static int alloc_dma_desc_resources (struct stmmac_priv *priv) +{ +/* RX Allocation */ +int ret =alloc_dma_rx_desc_resources (priv);And here.
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int alloc_dma_desc_resources(struct stmmac_priv *priv) · line 1385
Quoted 6 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +6
-0+ +if (ret) +return ret; + +/* TX Allocation */ + ret =alloc_dma_tx_desc_resources (priv);And here.
Quoted 9 lines
None of the above comments are critical and this could be cleaned up in follow-up patches, so:
Reviewed-by Thierry Reding <[email protected]>It also doesn't break on Tegra186, so
Tested-by Thierry Reding <[email protected]>
Thanks for testing and for the feedback. Let's see if Corentin Labbe can test this in his setup.
Joao
PATCH 2/4 net: stmmac: adding multiple buffers for rx
In reply to Joao PintoThis patch adds the structure stmmac_rx_queue which contains rx queues specific data (previously in stmmac_priv).
--- drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 7 +- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 26 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 453 +++++++++++++--------- 3 files changed, 301 insertions(+), 185 deletions(-)
drivers/net/ethernet/stmicro/stmmac/chain_mode.c +4 -3
@@ -136,15 +136,16 @@ static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,static void stmmac_refill_desc3 (void *priv_ptr,struct dma_desc *p) { -struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr; +struct stmmac_rx_queue *rx_q = (struct stmmac_rx_queue *)priv_ptr; +struct stmmac_priv *priv = rx_q->priv_data;if (priv->hwts_rx_en && !priv->extend_desc)/* NOTE: Device will overwrite des3 with timestamp value if * 1588-2002 time stamping is enabled, hence reinitialize it * to keep explicit chaining in the descriptor. */ - p->des3 =cpu_to_le32 ((unsigned int )(priv->dma_rx_phy + - (((priv->dirty_rx) +1 ) % + p->des3 =cpu_to_le32 ((unsigned int )(rx_q->dma_rx_phy + + (((rx_q->dirty_rx) +1 ) %DMA_RX_SIZE ) *sizeof (struct dma_desc ))); }
drivers/net/ethernet/stmicro/stmmac/stmmac.h +17 -9
@@ -46,6 +46,20 @@ struct stmmac_tx_info {bool is_jumbo; }; +struct stmmac_rx_queue { +u32 queue_index; +struct stmmac_priv *priv_data; +struct dma_extended_desc *dma_erx; +struct dma_desc *dma_rx____cacheline_aligned_in_smp ; +struct sk_buff **rx_skbuff; +dma_addr_t *rx_skbuff_dma; +unsigned int cur_rx; +unsigned int dirty_rx; +u32 rx_zeroc_thresh; +dma_addr_t dma_rx_phy; +u32 rx_tail_addr; +}; +struct stmmac_priv {/* Frequently used values are kept adjacent for cache effect */ struct dma_extended_desc *dma_etx____cacheline_aligned_in_smp ;
@@ -64,18 +78,10 @@ struct stmmac_priv {struct timer_list txtimer;bool tso; -struct dma_desc *dma_rx____cacheline_aligned_in_smp ; -struct dma_extended_desc *dma_erx; -struct sk_buff **rx_skbuff; -unsigned int cur_rx; -unsigned int dirty_rx;unsigned int dma_buf_sz;unsigned int rx_copybreak; -unsigned int rx_zeroc_thresh;u32 rx_riwt;int hwts_rx_en; -dma_addr_t *rx_skbuff_dma; -dma_addr_t dma_rx_phy;struct napi_struct napi____cacheline_aligned_in_smp ;
@@ -85,6 +91,9 @@ struct stmmac_priv {struct mac_device_info *hw;spinlock_t lock; +/* RX Queue */ +struct stmmac_rx_queue rx_queue[MTL_MAX_RX_QUEUES ]; +int oldlink;int speed;int oldduplex;
@@ -119,7 +128,6 @@ struct stmmac_priv {spinlock_t ptp_lock;void __iomem *mmcaddr;void __iomem *ptpaddr; -u32 rx_tail_addr;u32 tx_tail_addr;u32 mss;
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +280 -173
831 lines not on this page · raw message
Signature · 1 line
2.9.3
Re: [PATCH 2/4] net: stmmac: adding multiple buffers for rx
On Tue, Apr 04, 2017 at 06:54:25PM +0100, Joao Pinto wrote:
[...]
Quoted 1 line
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0
-0
[...]
Quoted 7 lines
static void
stmmac_display_rx_rings(struct stmmac_priv *priv){drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2
-1+u32 rx_cnt = priv->plat->rx_queues_to_use;void *head_rx; +u32 queue; -if (priv->extend_desc)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int stmmac_init_phy(struct net_device *dev) · line 908
Quoted 10 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +4
-5- head_rx = (void *)priv->dma_erx; - else - head_rx = (void *)priv->dma_rx; +/* Display RX rings */ +for (queue =0 ; queue < rx_cnt; queue++) { +struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -/* Display RX ring */ - priv->hw->desc->display_ring (head_rx,DMA_RX_SIZE , true); +pr_info ("\tRX Queue %d rings\n" , queue);
Nit: %u is the right specifier for unsigned integers.
Quoted 1 line
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0
-0@@ -1107,46 +1135,65 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
[...]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags) · line 1190
Quoted 4 lines
err_init_rx_buffers:drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1
-2-while (--i >=0 ) -stmmac_free_rx_buffers (priv, i); +while (queue-- >=0 ) {
Why are you switching to postfix decrement here? Not only is it inconsistent with the prefix decrement below, I think this also gives you a wrong result. Consider what happens if queue == 0. The condition evaluates to true, but within the loop the queue variable will wrap to ~0 and probably crash stmmac_free_rx_buffers().
Other than that, this looks fine, so with the above fixed:
Also works on Tegra186, so:
Re: [PATCH 2/4] net: stmmac: adding multiple buffers for rx
In reply to Joao PintoOne more nit: subject should say "... for RX" for consistency with patch 3/4.
Thierry
Re: [PATCH 2/4] net: stmmac: adding multiple buffers for rx
In reply to Joao PintoOn Tue, Apr 04, 2017 at 06:54:25PM +0100, Joao Pinto wrote:
[...]
Quoted 1 line
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0
-0
[...]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static irqreturn_t stmmac_interrupt(int irq, void *dev_id) · line 3478
Quoted 6 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2
-0@@ -3402,6 +3474,9 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)if (priv->synopsys_id >=DWMAC_CORE_4_00 ) {for (queue =0 ; queue < queues_count; queue++) { +struct stmmac_rx_queue *rx_q = + &priv->rx_queue[queue];
Found one more: the indentation here looks wrong. I think it's more idiomatic to indent by at least a tab in such cases.
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static irqreturn_t stmmac_interrupt(int irq, void *dev_id) · line 3482
Quoted 4 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1
-0+ status |= priv->hw->mac->host_mtl_irq_status (priv->hw, queue);
This is becoming quite unwieldy because of the indentation levels. Maybe this could be split out into a separate function. Could be a separate patch, though.
Thierry
PATCH 3/4 net: stmmac: adding multiple buffers for TX
In reply to Joao PintoThis patch adds the structure stmmac_tx_queue which contains tx queues specific data (previously in stmmac_priv).
--- drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 38 +- drivers/net/ethernet/stmicro/stmmac/ring_mode.c | 46 +- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 26 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 521 +++++++++++++--------- 4 files changed, 375 insertions(+), 256 deletions(-)
drivers/net/ethernet/stmicro/stmmac/chain_mode.c +21 -17
@@ -26,12 +26,15 @@static int stmmac_jumbo_frm (void *p,struct sk_buff *skb,int csum) { -struct stmmac_priv *priv = (struct stmmac_priv *)p; -unsigned int entry = priv->cur_tx; -struct dma_desc *desc = priv->dma_tx + entry; +struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)p;unsigned int nopaged_len =skb_headlen (skb); +struct stmmac_priv *priv = tx_q->priv_data; +unsigned int entry = tx_q->cur_tx;unsigned int bmax, des2;unsigned int i =1 , len; +struct dma_desc *desc; + + desc = tx_q->dma_tx + entry;if (priv->plat->enh_desc) bmax = BUF_SIZE_8KiB;
@@ -45,16 +48,16 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) desc->des2 =cpu_to_le32 (des2);if (dma_mapping_error (priv->device, des2))return -1 ; - priv->tx_skbuff_dma[entry].buf = des2; - priv->tx_skbuff_dma[entry].len = bmax; + tx_q->tx_skbuff_dma[entry].buf = des2; + tx_q->tx_skbuff_dma[entry].len = bmax;/* do not close the descriptor and do not set own bit */ priv->hw->desc->prepare_tx_desc (desc,1 , bmax, csum,STMMAC_CHAIN_MODE ,0 , false);while (len !=0 ) { - priv->tx_skbuff[entry] =NULL ; + tx_q->tx_skbuff[entry] =NULL ; entry =STMMAC_GET_ENTRY (entry,DMA_TX_SIZE ); - desc = priv->dma_tx + entry; + desc = tx_q->dma_tx + entry;if (len > bmax) { des2 = dma_map_single(priv->device,
@@ -63,8 +66,8 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) desc->des2 =cpu_to_le32 (des2);if (dma_mapping_error (priv->device, des2))return -1 ; - priv->tx_skbuff_dma[entry].buf = des2; - priv->tx_skbuff_dma[entry].len = bmax; + tx_q->tx_skbuff_dma[entry].buf = des2; + tx_q->tx_skbuff_dma[entry].len = bmax; priv->hw->desc->prepare_tx_desc (desc,0 , bmax, csum,STMMAC_CHAIN_MODE ,1 , false);
@@ -77,8 +80,8 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) desc->des2 =cpu_to_le32 (des2);if (dma_mapping_error (priv->device, des2))return -1 ; - priv->tx_skbuff_dma[entry].buf = des2; - priv->tx_skbuff_dma[entry].len = len; + tx_q->tx_skbuff_dma[entry].buf = des2; + tx_q->tx_skbuff_dma[entry].len = len;/* last descriptor can be set now */ priv->hw->desc->prepare_tx_desc(desc, 0, len, csum, STMMAC_CHAIN_MODE, 1,
@@ -87,7 +90,7 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) } } - priv->cur_tx = entry; + tx_q->cur_tx = entry;return entry; }
@@ -152,17 +155,18 @@ static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)static void stmmac_clean_desc3 (void *priv_ptr,struct dma_desc *p) { -struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr; -unsigned int entry = priv->dirty_tx; +struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)priv_ptr; +struct stmmac_priv *priv = tx_q->priv_data; +unsigned int entry = tx_q->dirty_tx; -if (priv->tx_skbuff_dma[entry].last_segment && !priv->extend_desc && +if (tx_q->tx_skbuff_dma[entry].last_segment && !priv->extend_desc && priv->hwts_tx_en)/* NOTE: Device will overwrite des3 with timestamp value if * 1588-2002 time stamping is enabled, hence reinitialize it * to keep explicit chaining in the descriptor. */ - p->des3 =cpu_to_le32 ((unsigned int )((priv->dma_tx_phy + - ((priv->dirty_tx +1 ) %DMA_TX_SIZE )) + p->des3 =cpu_to_le32 ((unsigned int )((tx_q->dma_tx_phy + + ((tx_q->dirty_tx +1 ) %DMA_TX_SIZE )) *sizeof (struct dma_desc ))); }
drivers/net/ethernet/stmicro/stmmac/ring_mode.c +24 -22
96 lines not on this page · raw message
drivers/net/ethernet/stmicro/stmmac/stmmac.h +18 -8
@@ -46,6 +46,20 @@ struct stmmac_tx_info {bool is_jumbo; }; +/* Frequently used values are kept adjacent for cache effect */ +struct stmmac_tx_queue { +u32 queue_index; +struct stmmac_priv *priv_data; +struct dma_extended_desc *dma_etx____cacheline_aligned_in_smp ; +struct dma_desc *dma_tx; +struct sk_buff **tx_skbuff; +struct stmmac_tx_info *tx_skbuff_dma; +unsigned int cur_tx; +unsigned int dirty_tx; +dma_addr_t dma_tx_phy; +u32 tx_tail_addr; +}; +struct stmmac_rx_queue {u32 queue_index;struct stmmac_priv *priv_data;
@@ -62,16 +76,10 @@ struct stmmac_rx_queue {struct stmmac_priv {/* Frequently used values are kept adjacent for cache effect */ -struct dma_extended_desc *dma_etx____cacheline_aligned_in_smp ; -struct dma_desc *dma_tx; -struct sk_buff **tx_skbuff; -unsigned int cur_tx; -unsigned int dirty_tx;u32 tx_count_frames;u32 tx_coal_frames;u32 tx_coal_timer; -struct stmmac_tx_info *tx_skbuff_dma; -dma_addr_t dma_tx_phy; +int tx_coalesce;int hwts_tx_en;bool tx_path_in_lpi_mode;
@@ -94,6 +102,9 @@ struct stmmac_priv {/* RX Queue */ struct stmmac_rx_queue rx_queue[MTL_MAX_RX_QUEUES ]; +/* TX Queue */ +struct stmmac_tx_queue tx_queue[MTL_MAX_TX_QUEUES ]; +int oldlink;int speed;int oldduplex;
@@ -128,7 +139,6 @@ struct stmmac_priv {spinlock_t ptp_lock;void __iomem *mmcaddr;void __iomem *ptpaddr; -u32 tx_tail_addr;u32 mss;#ifdef CONFIG_DEBUG_FS
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +312 -209
975 lines not on this page · raw message
Signature · 1 line
2.9.3
Re: [PATCH 3/4] net: stmmac: adding multiple buffers for TX
Quoted 10 lines · Joao Pinto
This patch adds the structure
stmmac_tx_queuewhich contains tx queues specific data (previously instmmac_priv).Signed-off-by Joao Pinto <[email protected]>--- drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 38 +- drivers/net/ethernet/stmicro/stmmac/ring_mode.c | 46 +- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 26 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 521 +++++++++++++--------- 4 files changed, 375 insertions(+), 256 deletions(-)
Looks good to me:
And works fine on Tegra186, so:
PATCH 4/4 net: stmmac: adding multiple napi mechanism
In reply to Joao PintoThis patch adds the napi variable to the stmmac_rx_queue structure and forces that operations like netif_queue_stopped, netif_wake_queue, netif_stop_queue, netdev_reset_queue and netdev_sent_queue be made by queue.
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 193 ++++++++++++++++------ 2 files changed, 139 insertions(+), 57 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac.h +1 -2
@@ -72,6 +72,7 @@ struct stmmac_rx_queue {u32 rx_zeroc_thresh;dma_addr_t dma_rx_phy;u32 rx_tail_addr; +struct napi_struct napi____cacheline_aligned_in_smp ; };struct stmmac_priv {
@@ -91,8 +92,6 @@ struct stmmac_priv {u32 rx_riwt;int hwts_rx_en; -struct napi_struct napi____cacheline_aligned_in_smp ; -void __iomem *ioaddr;struct net_device *dev;struct device *device;
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +138 -55
370 lines not on this page · raw message
Signature · 1 line
2.9.3
Re: [PATCH 4/4] net: stmmac: adding multiple napi mechanism
On Tue, Apr 04, 2017 at 06:54:27PM +0100, Joao Pinto wrote:
[...]
Quoted 1 line
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0
-0
[...]
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c static int init_dma_tx_desc_rings(struct net_device *dev) · line 1322
Quoted 8 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0
-1@@ -1259,7 +1317,6 @@ static int init_dma_tx_desc_rings(struct net_device *dev)/* TX INITIALIZATION */ for (i =0 ; i <DMA_TX_SIZE ; i++) {struct dma_desc *p; -if (priv->extend_desc) p = &((tx_q->dma_etx + i)->basic);else
I think checkpatch would complain about this now because we're supposed to separate variable declarations from code by a single blank line.
Quoted 11 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +10
-1-netif_napi_add (ndev, &priv->napi, stmmac_poll,64 ); + ret =alloc_dma_desc_resources (priv); +if (ret <0 ) { +netdev_err (priv->dev,"%s: DMA descriptors allocation failed\n" , + __func__); + goto init_dma_error; + } + + ret =init_dma_desc_rings (priv->dev,GFP_KERNEL ); +if (ret <0 ) { + netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n",
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c int stmmac_dvr_probe(struct device *device, · line 4164
Quoted 10 lines
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +10
-0+ __func__); + goto init_dma_error; + } + +for (queue =0 ; queue < priv->plat->rx_queues_to_use; queue++) { +struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; + +netif_napi_add (ndev, &rx_q->napi, stmmac_poll, + (8 * priv->plat->rx_queues_to_use)); + }
Why is this moving to ->probe() now?
This works on Tegra186, so: