ar71xx: use page fragment API in the ethernet driver
Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 48578
This commit is contained in:
parent
8fe8360981
commit
2067f7f1de
1 changed files with 24 additions and 10 deletions
|
@ -13,6 +13,13 @@
|
|||
|
||||
#include "ag71xx.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
|
||||
static inline void skb_free_frag(void *data)
|
||||
{
|
||||
put_page(virt_to_head_page(data));
|
||||
}
|
||||
#endif
|
||||
|
||||
#define AG71XX_DEFAULT_MSG_ENABLE \
|
||||
(NETIF_MSG_DRV \
|
||||
| NETIF_MSG_PROBE \
|
||||
|
@ -197,7 +204,7 @@ static void ag71xx_ring_rx_clean(struct ag71xx *ag)
|
|||
if (ring->buf[i].rx_buf) {
|
||||
dma_unmap_single(&ag->dev->dev, ring->buf[i].dma_addr,
|
||||
ag->rx_buf_size, DMA_FROM_DEVICE);
|
||||
kfree(ring->buf[i].rx_buf);
|
||||
skb_free_frag(ring->buf[i].rx_buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,16 +224,21 @@ static int ag71xx_buffer_offset(struct ag71xx *ag)
|
|||
return offset + NET_IP_ALIGN;
|
||||
}
|
||||
|
||||
static int ag71xx_buffer_size(struct ag71xx *ag)
|
||||
{
|
||||
return ag->rx_buf_size +
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
||||
}
|
||||
|
||||
static bool ag71xx_fill_rx_buf(struct ag71xx *ag, struct ag71xx_buf *buf,
|
||||
int offset)
|
||||
int offset,
|
||||
void *(*alloc)(unsigned int size))
|
||||
{
|
||||
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 +
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
|
||||
GFP_ATOMIC);
|
||||
data = alloc(ag71xx_buffer_size(ag));
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
|
@ -258,7 +270,8 @@ static int ag71xx_ring_rx_init(struct ag71xx *ag)
|
|||
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)) {
|
||||
if (!ag71xx_fill_rx_buf(ag, &ring->buf[i], offset,
|
||||
netdev_alloc_frag)) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
@ -290,7 +303,8 @@ static int ag71xx_ring_rx_refill(struct ag71xx *ag)
|
|||
desc = ag71xx_ring_desc(ring, i);
|
||||
|
||||
if (!ring->buf[i].rx_buf &&
|
||||
!ag71xx_fill_rx_buf(ag, &ring->buf[i], offset))
|
||||
!ag71xx_fill_rx_buf(ag, &ring->buf[i], offset,
|
||||
napi_alloc_frag))
|
||||
break;
|
||||
|
||||
desc->ctrl = DESC_EMPTY;
|
||||
|
@ -680,7 +694,7 @@ static int ag71xx_open(struct net_device *dev)
|
|||
|
||||
netif_carrier_off(dev);
|
||||
max_frame_len = ag71xx_max_frame_len(dev->mtu);
|
||||
ag->rx_buf_size = max_frame_len + NET_SKB_PAD + NET_IP_ALIGN;
|
||||
ag->rx_buf_size = SKB_DATA_ALIGN(max_frame_len + NET_SKB_PAD + NET_IP_ALIGN);
|
||||
|
||||
/* setup max frame length */
|
||||
ag71xx_wr(ag, AG71XX_REG_MAC_MFL, max_frame_len);
|
||||
|
@ -1012,9 +1026,9 @@ static int ag71xx_rx_packets(struct ag71xx *ag, int limit)
|
|||
dev->stats.rx_packets++;
|
||||
dev->stats.rx_bytes += pktlen;
|
||||
|
||||
skb = build_skb(ring->buf[i].rx_buf, 0);
|
||||
skb = build_skb(ring->buf[i].rx_buf, ag71xx_buffer_size(ag));
|
||||
if (!skb) {
|
||||
kfree(ring->buf[i].rx_buf);
|
||||
skb_free_frag(ring->buf[i].rx_buf);
|
||||
goto next;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue