From 548879cdc1da0a74d4ca998e8eaf89f37ec7b31b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 9 Dec 2014 12:28:46 +0000 Subject: [PATCH] ar71xx: improve ethernet driver cache footprint by removing an unnecessary pointer Signed-off-by: Felix Fietkau git-svn-id: svn://svn.openwrt.org/openwrt/trunk@43588 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../net/ethernet/atheros/ag71xx/ag71xx.h | 7 ++- .../ethernet/atheros/ag71xx/ag71xx_debugfs.c | 9 ++-- .../net/ethernet/atheros/ag71xx/ag71xx_main.c | 47 ++++++++++--------- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h index 2d7c963a44..b18c20b6dd 100644 --- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h @@ -90,7 +90,6 @@ struct ag71xx_buf { struct sk_buff *skb; void *rx_buf; }; - struct ag71xx_desc *desc; union { dma_addr_t dma_addr; unsigned long timestamp; @@ -203,6 +202,12 @@ static inline int ag71xx_desc_empty(struct ag71xx_desc *desc) return (desc->ctrl & DESC_EMPTY) != 0; } +static inline struct ag71xx_desc * +ag71xx_ring_desc(struct ag71xx_ring *ring, int idx) +{ + return (struct ag71xx_desc *) &ring->descs_cpu[idx * ring->desc_size]; +} + /* Register offsets */ #define AG71XX_REG_MAC_CFG1 0x0000 #define AG71XX_REG_MAC_CFG2 0x0004 diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c index 757a572b00..c480121040 100644 --- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c +++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c @@ -183,6 +183,7 @@ static ssize_t read_file_ring(struct file *file, char __user *user_buf, desc_hw = ag71xx_rr(ag, desc_reg); for (i = 0; i < ring->size; i++) { struct ag71xx_buf *ab = &ring->buf[i]; + struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); u32 desc_dma = ((u32) ring->descs_dma) + i * ring->desc_size; len += snprintf(buf + len, buflen - len, @@ -192,10 +193,10 @@ static ssize_t read_file_ring(struct file *file, char __user *user_buf, (i == dirty) ? 'D' : ' ', (desc_hw == desc_dma) ? 'H' : ' ', desc_dma, - ab->desc->next, - ab->desc->data, - ab->desc->ctrl, - (ab->desc->ctrl & DESC_EMPTY) ? 'E' : '*', + desc->next, + desc->data, + desc->ctrl, + (desc->ctrl & DESC_EMPTY) ? 'E' : '*', ab->timestamp); } diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c index 259cc205cb..5ef324e853 100644 --- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c @@ -100,7 +100,6 @@ static void ag71xx_ring_free(struct ag71xx_ring *ring) static int ag71xx_ring_alloc(struct ag71xx_ring *ring) { int err; - int i; ring->desc_size = sizeof(struct ag71xx_desc); if (ring->desc_size % cache_line_size()) { @@ -124,13 +123,6 @@ static int ag71xx_ring_alloc(struct ag71xx_ring *ring) goto err; } - for (i = 0; i < ring->size; i++) { - int idx = i * ring->desc_size; - ring->buf[i].desc = (struct ag71xx_desc *)&ring->descs_cpu[idx]; - DBG("ag71xx: ring %p, desc %d at %p\n", - ring, i, ring->buf[i].desc); - } - return 0; err: @@ -144,10 +136,12 @@ static void ag71xx_ring_tx_clean(struct ag71xx *ag) u32 bytes_compl = 0, pkts_compl = 0; while (ring->curr != ring->dirty) { + struct ag71xx_desc *desc; u32 i = ring->dirty % ring->size; - if (!ag71xx_desc_empty(ring->buf[i].desc)) { - ring->buf[i].desc->ctrl = 0; + desc = ag71xx_ring_desc(ring, i); + if (!ag71xx_desc_empty(desc)) { + desc->ctrl = 0; dev->stats.tx_errors++; } @@ -172,10 +166,12 @@ static void ag71xx_ring_tx_init(struct ag71xx *ag) int i; for (i = 0; i < ring->size; i++) { - ring->buf[i].desc->next = (u32) (ring->descs_dma + + struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); + + desc->next = (u32) (ring->descs_dma + ring->desc_size * ((i + 1) % ring->size)); - ring->buf[i].desc->ctrl = DESC_EMPTY; + desc->ctrl = DESC_EMPTY; ring->buf[i].skb = NULL; } @@ -222,6 +218,8 @@ static int ag71xx_buffer_offset(struct ag71xx *ag) static bool ag71xx_fill_rx_buf(struct ag71xx *ag, struct ag71xx_buf *buf, int offset) { + struct ag71xx_ring *ring = &ag->rx_ring; + struct ag71xx_desc *desc = ag71xx_ring_desc(ring, buf - &ring->buf[0]); void *data; data = kmalloc(ag->rx_buf_size + @@ -233,7 +231,7 @@ static bool ag71xx_fill_rx_buf(struct ag71xx *ag, struct ag71xx_buf *buf, buf->rx_buf = data; buf->dma_addr = dma_map_single(&ag->dev->dev, data, ag->rx_buf_size, DMA_FROM_DEVICE); - buf->desc->data = (u32) buf->dma_addr + offset; + desc->data = (u32) buf->dma_addr + offset; return true; } @@ -246,21 +244,24 @@ static int ag71xx_ring_rx_init(struct ag71xx *ag) ret = 0; for (i = 0; i < ring->size; i++) { - ring->buf[i].desc->next = (u32) (ring->descs_dma + + struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); + + desc->next = (u32) (ring->descs_dma + ring->desc_size * ((i + 1) % ring->size)); DBG("ag71xx: RX desc at %p, next is %08x\n", - ring->buf[i].desc, - ring->buf[i].desc->next); + desc, desc->next); } for (i = 0; i < ring->size; i++) { + struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); + if (!ag71xx_fill_rx_buf(ag, &ring->buf[i], offset)) { ret = -ENOMEM; break; } - ring->buf[i].desc->ctrl = DESC_EMPTY; + desc->ctrl = DESC_EMPTY; } /* flush descriptors */ @@ -280,15 +281,17 @@ static int ag71xx_ring_rx_refill(struct ag71xx *ag) count = 0; for (; ring->curr - ring->dirty > 0; ring->dirty++) { + struct ag71xx_desc *desc; unsigned int i; i = ring->dirty % ring->size; + desc = ag71xx_ring_desc(ring, i); if (!ring->buf[i].rx_buf && !ag71xx_fill_rx_buf(ag, &ring->buf[i], offset)) break; - ring->buf[i].desc->ctrl = DESC_EMPTY; + desc->ctrl = DESC_EMPTY; count++; } @@ -697,7 +700,7 @@ static int ag71xx_fill_dma_desc(struct ag71xx_ring *ring, u32 addr, int len) unsigned int cur_len = len; i = (ring->curr + ndesc) % ring->size; - desc = ring->buf[i].desc; + desc = ag71xx_ring_desc(ring, i); if (!ag71xx_desc_empty(desc)) return -1; @@ -752,7 +755,7 @@ static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb, DMA_TO_DEVICE); i = ring->curr % ring->size; - desc = ring->buf[i].desc; + desc = ag71xx_ring_desc(ring, i); /* setup descriptor fields */ n = ag71xx_fill_dma_desc(ring, (u32) dma_addr, skb->len & ag->desc_pktlen_mask); @@ -907,7 +910,7 @@ static int ag71xx_tx_packets(struct ag71xx *ag) while (ring->dirty + n != ring->curr) { unsigned int i = (ring->dirty + n) % ring->size; - struct ag71xx_desc *desc = ring->buf[i].desc; + struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); struct sk_buff *skb = ring->buf[i].skb; if (!ag71xx_desc_empty(desc)) { @@ -963,7 +966,7 @@ static int ag71xx_rx_packets(struct ag71xx *ag, int limit) while (done < limit) { unsigned int i = ring->curr % ring->size; - struct ag71xx_desc *desc = ring->buf[i].desc; + struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); struct sk_buff *skb; int pktlen; int err = 0;