Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1583282 > unrolled thread
| Started by | Jisheng Zhang <jszhang@marvell.com> |
|---|---|
| First post | 2017-02-17 11:10 +0100 |
| Last post | 2017-02-17 11:10 +0100 |
| Articles | 3 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH net-next 0/2] net: mvneta: improve rx performance Jisheng Zhang <jszhang@marvell.com> - 2017-02-17 11:10 +0100
[PATCH net-next 2/2] net: mvneta: Use cacheable memory to store the rx buffer DMA address Jisheng Zhang <jszhang@marvell.com> - 2017-02-17 11:10 +0100
[PATCH net-next 1/2] net: mvneta: avoid getting status from rx_desc as much as possible Jisheng Zhang <jszhang@marvell.com> - 2017-02-17 11:10 +0100
| From | Jisheng Zhang <jszhang@marvell.com> |
|---|---|
| Date | 2017-02-17 11:10 +0100 |
| Subject | [PATCH net-next 0/2] net: mvneta: improve rx performance |
| Message-ID | <tbNEd-2WR-1@gated-at.bofh.it> |
In hot code path such as mvneta_rx_hwbm() and mvneta_rx_swbm(), we may access fields of rx_desc. The rx_desc is allocated by dma_alloc_coherent, it's uncacheable if the device isn't cache coherent, reading from uncached memory is fairly slow. patch1 reuses the read out status to getting status field of rx_desc again. patch2 uses cacheable memory to store the rx buffer DMA address. We get the following performance data on Marvell BG4CT Platforms (tested with iperf): before the patch: recving 1GB in mvneta_rx_swbm() costs 149265960 ns after the patch: recving 1GB in mvneta_rx_swbm() costs 1421565640 ns We saved 4.76% time. RFC: can we do similar modification for tx? If yes, I can prepare a v2. Basically, these two patches do what Arnd mentioned in [1]. Hi Arnd, I added "Suggested-by you" tag, I hope you don't mind ;) Thanks [1] https://www.spinics.net/lists/netdev/msg405889.html Jisheng Zhang (2): net: mvneta: avoid getting status from rx_desc as much as possible net: mvneta: Use cacheable memory to store the rx buffer DMA address drivers/net/ethernet/marvell/mvneta.c | 36 ++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) -- 2.11.0
[toc] | [next] | [standalone]
| From | Jisheng Zhang <jszhang@marvell.com> |
|---|---|
| Date | 2017-02-17 11:10 +0100 |
| Subject | [PATCH net-next 2/2] net: mvneta: Use cacheable memory to store the rx buffer DMA address |
| Message-ID | <tbNEd-2WR-9@gated-at.bofh.it> |
| In reply to | #1583282 |
In hot code path such as mvneta_rx_hwbm() and mvneta_rx_swbm, the
buf_phys_addr field of rx_dec is accessed. The rx_desc is allocated by
dma_alloc_coherent, it's uncacheable if the device isn't cache
coherent, reading from uncached memory is fairly slow. This patch uses
cacheable memory to store the rx buffer DMA address. We get the
following performance data on Marvell BG4CT Platforms (tested with
iperf):
before the patch:
recving 1GB in mvneta_rx_swbm() costs 149265960 ns
after the patch:
recving 1GB in mvneta_rx_swbm() costs 1421565640 ns
We saved 4.76% time.
Signed-off-by: Jisheng Zhang <jszhang@marvell.com>
Suggested-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/ethernet/marvell/mvneta.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 06df72b8da85..e24c3028fe1d 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -580,6 +580,9 @@ struct mvneta_rx_queue {
/* Virtual address of the RX buffer */
void **buf_virt_addr;
+ /* DMA address of the RX buffer */
+ dma_addr_t *buf_dma_addr;
+
/* Virtual address of the RX DMA descriptors array */
struct mvneta_rx_desc *descs;
@@ -1617,6 +1620,7 @@ static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
rx_desc->buf_phys_addr = phys_addr;
i = rx_desc - rxq->descs;
+ rxq->buf_dma_addr[i] = phys_addr;
rxq->buf_virt_addr[i] = virt_addr;
}
@@ -1900,22 +1904,22 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
for (i = 0; i < rx_done; i++) {
struct mvneta_rx_desc *rx_desc =
mvneta_rxq_next_desc_get(rxq);
+ int index = rx_desc - rxq->descs;
u8 pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc->status);
struct mvneta_bm_pool *bm_pool;
bm_pool = &pp->bm_priv->bm_pools[pool_id];
/* Return dropped buffer to the pool */
mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool,
- rx_desc->buf_phys_addr);
+ rxq->buf_dma_addr[index]);
}
return;
}
for (i = 0; i < rxq->size; i++) {
- struct mvneta_rx_desc *rx_desc = rxq->descs + i;
void *data = rxq->buf_virt_addr[i];
- dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
+ dma_unmap_single(pp->dev->dev.parent, rxq->buf_dma_addr[i],
MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
mvneta_frag_free(pp->frag_size, data);
}
@@ -1953,7 +1957,7 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
index = rx_desc - rxq->descs;
data = rxq->buf_virt_addr[index];
- phys_addr = rx_desc->buf_phys_addr;
+ phys_addr = rxq->buf_dma_addr[index];
if (!mvneta_rxq_desc_is_first_last(rx_status) ||
(rx_status & MVNETA_RXD_ERR_SUMMARY)) {
@@ -2062,6 +2066,7 @@ static int mvneta_rx_hwbm(struct mvneta_port *pp, int rx_todo,
/* Fairness NAPI loop */
while (rx_done < rx_todo) {
struct mvneta_rx_desc *rx_desc = mvneta_rxq_next_desc_get(rxq);
+ int index = rx_desc - rxq->descs;
struct mvneta_bm_pool *bm_pool = NULL;
struct sk_buff *skb;
unsigned char *data;
@@ -2074,7 +2079,7 @@ static int mvneta_rx_hwbm(struct mvneta_port *pp, int rx_todo,
rx_status = rx_desc->status;
rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
data = (u8 *)(uintptr_t)rx_desc->buf_cookie;
- phys_addr = rx_desc->buf_phys_addr;
+ phys_addr = rxq->buf_dma_addr[index];
pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_status);
bm_pool = &pp->bm_priv->bm_pools[pool_id];
@@ -2082,8 +2087,7 @@ static int mvneta_rx_hwbm(struct mvneta_port *pp, int rx_todo,
(rx_status & MVNETA_RXD_ERR_SUMMARY)) {
err_drop_frame_ret_pool:
/* Return the buffer to the pool */
- mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool,
- rx_desc->buf_phys_addr);
+ mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool, phys_addr);
err_drop_frame:
dev->stats.rx_errors++;
mvneta_rx_error(pp, rx_desc);
@@ -2098,7 +2102,7 @@ static int mvneta_rx_hwbm(struct mvneta_port *pp, int rx_todo,
goto err_drop_frame_ret_pool;
dma_sync_single_range_for_cpu(dev->dev.parent,
- rx_desc->buf_phys_addr,
+ phys_addr,
MVNETA_MH_SIZE + NET_SKB_PAD,
rx_bytes,
DMA_FROM_DEVICE);
@@ -2114,8 +2118,7 @@ static int mvneta_rx_hwbm(struct mvneta_port *pp, int rx_todo,
rcvd_bytes += rx_bytes;
/* Return the buffer to the pool */
- mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool,
- rx_desc->buf_phys_addr);
+ mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool, phys_addr);
/* leave the descriptor and buffer untouched */
continue;
@@ -4019,7 +4022,10 @@ static int mvneta_init(struct device *dev, struct mvneta_port *pp)
rxq->buf_virt_addr = devm_kmalloc(pp->dev->dev.parent,
rxq->size * sizeof(void *),
GFP_KERNEL);
- if (!rxq->buf_virt_addr)
+ rxq->buf_dma_addr = devm_kmalloc(pp->dev->dev.parent,
+ rxq->size * sizeof(dma_addr_t),
+ GFP_KERNEL);
+ if (!rxq->buf_virt_addr || !rxq->buf_dma_addr)
return -ENOMEM;
}
--
2.11.0
[toc] | [prev] | [next] | [standalone]
| From | Jisheng Zhang <jszhang@marvell.com> |
|---|---|
| Date | 2017-02-17 11:10 +0100 |
| Subject | [PATCH net-next 1/2] net: mvneta: avoid getting status from rx_desc as much as possible |
| Message-ID | <tbNEd-2WR-5@gated-at.bofh.it> |
| In reply to | #1583282 |
In hot code path mvneta_rx_hwbm(), the rx_desc->status is read twice.
The rx_desc is allocated by dma_alloc_coherent, it's uncacheable if
the device isn't cache-coherent, reading from uncached memory is
fairly slow. So reuse the read out rx_status to avoid the second
reading from uncached memory.
Signed-off-by: Jisheng Zhang <jszhang@marvell.com>
Suggested-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/ethernet/marvell/mvneta.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 61dd4462411c..06df72b8da85 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -313,8 +313,8 @@
((addr >= txq->tso_hdrs_phys) && \
(addr < txq->tso_hdrs_phys + txq->size * TSO_HEADER_SIZE))
-#define MVNETA_RX_GET_BM_POOL_ID(rxd) \
- (((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT)
+#define MVNETA_RX_GET_BM_POOL_ID(status) \
+ (((status) & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT)
struct mvneta_statistic {
unsigned short offset;
@@ -1900,7 +1900,7 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
for (i = 0; i < rx_done; i++) {
struct mvneta_rx_desc *rx_desc =
mvneta_rxq_next_desc_get(rxq);
- u8 pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc);
+ u8 pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc->status);
struct mvneta_bm_pool *bm_pool;
bm_pool = &pp->bm_priv->bm_pools[pool_id];
@@ -2075,7 +2075,7 @@ static int mvneta_rx_hwbm(struct mvneta_port *pp, int rx_todo,
rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
data = (u8 *)(uintptr_t)rx_desc->buf_cookie;
phys_addr = rx_desc->buf_phys_addr;
- pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc);
+ pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_status);
bm_pool = &pp->bm_priv->bm_pools[pool_id];
if (!mvneta_rxq_desc_is_first_last(rx_status) ||
--
2.11.0
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web