Changeset 31934


Ignore:
Timestamp:
2012-05-28T04:55:59+02:00 (6 years ago)
Author:
nbd
Message:

ar71xx: improve rx performance of the ethernet driver by using build_skb to deliver a cache-hot skb to the network stack

Location:
trunk/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h

    r31925 r31934  
    5454#define AG71XX_RX_PKT_SIZE      \ 
    5555        (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN) 
     56#define AG71XX_RX_BUF_SIZE (AG71XX_RX_PKT_SIZE + NET_SKB_PAD + NET_IP_ALIGN) 
    5657 
    5758#define AG71XX_TX_RING_SIZE_DEFAULT     64 
     
    8687 
    8788struct ag71xx_buf { 
    88         struct sk_buff          *skb; 
     89        union { 
     90                struct sk_buff  *skb; 
     91                void            *rx_buf; 
     92        }; 
    8993        struct ag71xx_desc      *desc; 
    9094        dma_addr_t              dma_addr; 
  • trunk/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c

    r31637 r31934  
    190190 
    191191        for (i = 0; i < ring->size; i++) 
    192                 if (ring->buf[i].skb) { 
     192                if (ring->buf[i].rx_buf) { 
    193193                        dma_unmap_single(&ag->dev->dev, ring->buf[i].dma_addr, 
    194                                          AG71XX_RX_PKT_SIZE, DMA_FROM_DEVICE); 
    195                         kfree_skb(ring->buf[i].skb); 
     194                                         AG71XX_RX_BUF_SIZE, DMA_FROM_DEVICE); 
     195                        kfree(ring->buf[i].rx_buf); 
    196196                } 
    197197} 
    198198 
    199 struct sk_buff *ag71xx_rx_alloc(struct ag71xx *ag) 
    200 { 
     199static int ag71xx_buffer_offset(struct ag71xx *ag) 
     200{ 
     201        int offset = NET_SKB_PAD; 
     202 
    201203        /* 
    202204         * On AR71xx/AR91xx packets must be 4-byte aligned. 
     
    206208         */ 
    207209        if (!ag71xx_get_pdata(ag)->is_ar724x || ag71xx_has_ar8216(ag)) 
    208                 return netdev_alloc_skb(ag->dev, AG71XX_RX_PKT_SIZE); 
    209  
    210         return netdev_alloc_skb_ip_align(ag->dev, AG71XX_RX_PKT_SIZE); 
    211 } 
    212  
     210                return offset; 
     211 
     212        return offset + NET_IP_ALIGN; 
     213} 
     214 
     215static bool ag71xx_fill_rx_buf(struct ag71xx *ag, struct ag71xx_buf *buf, 
     216                               int offset) 
     217{ 
     218        void *data; 
     219 
     220        data = kmalloc(AG71XX_RX_BUF_SIZE + 
     221                       SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), 
     222                       GFP_ATOMIC); 
     223        if (!data) 
     224                return false; 
     225 
     226        buf->rx_buf = data; 
     227        buf->dma_addr = dma_map_single(&ag->dev->dev, data, 
     228                                       AG71XX_RX_BUF_SIZE, DMA_FROM_DEVICE); 
     229        buf->desc->data = (u32) buf->dma_addr + offset; 
     230        return true; 
     231} 
    213232 
    214233static int ag71xx_ring_rx_init(struct ag71xx *ag) 
     
    217236        unsigned int i; 
    218237        int ret; 
     238        int offset = ag71xx_buffer_offset(ag); 
    219239 
    220240        ret = 0; 
     
    229249 
    230250        for (i = 0; i < ring->size; i++) { 
    231                 struct sk_buff *skb; 
    232                 dma_addr_t dma_addr; 
    233  
    234                 skb = ag71xx_rx_alloc(ag); 
    235                 if (!skb) { 
     251                if (!ag71xx_fill_rx_buf(ag, &ring->buf[i], offset)) { 
    236252                        ret = -ENOMEM; 
    237253                        break; 
    238254                } 
    239255 
    240                 skb->dev = ag->dev; 
    241                 dma_addr = dma_map_single(&ag->dev->dev, skb->data, 
    242                                           AG71XX_RX_PKT_SIZE, 
    243                                           DMA_FROM_DEVICE); 
    244                 ring->buf[i].skb = skb; 
    245                 ring->buf[i].dma_addr = dma_addr; 
    246                 ring->buf[i].desc->data = (u32) dma_addr; 
    247256                ring->buf[i].desc->ctrl = DESC_EMPTY; 
    248257        } 
     
    261270        struct ag71xx_ring *ring = &ag->rx_ring; 
    262271        unsigned int count; 
     272        int offset = ag71xx_buffer_offset(ag); 
    263273 
    264274        count = 0; 
     
    268278                i = ring->dirty % ring->size; 
    269279 
    270                 if (ring->buf[i].skb == NULL) { 
    271                         dma_addr_t dma_addr; 
    272                         struct sk_buff *skb; 
    273  
    274                         skb = ag71xx_rx_alloc(ag); 
    275                         if (skb == NULL) 
    276                                 break; 
    277  
    278                         skb->dev = ag->dev; 
    279  
    280                         dma_addr = dma_map_single(&ag->dev->dev, skb->data, 
    281                                                   AG71XX_RX_PKT_SIZE, 
    282                                                   DMA_FROM_DEVICE); 
    283  
    284                         ring->buf[i].skb = skb; 
    285                         ring->buf[i].dma_addr = dma_addr; 
    286                         ring->buf[i].desc->data = (u32) dma_addr; 
    287                 } 
     280                if (!ring->buf[i].rx_buf && 
     281                    !ag71xx_fill_rx_buf(ag, &ring->buf[i], offset)) 
     282                        break; 
    288283 
    289284                ring->buf[i].desc->ctrl = DESC_EMPTY; 
     
    864859        struct net_device *dev = ag->dev; 
    865860        struct ag71xx_ring *ring = &ag->rx_ring; 
     861        int offset = ag71xx_buffer_offset(ag); 
    866862        int done = 0; 
    867863 
     
    886882                ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_PR); 
    887883 
    888                 skb = ring->buf[i].skb; 
    889884                pktlen = ag71xx_desc_pktlen(desc); 
    890885                pktlen -= ETH_FCS_LEN; 
    891886 
    892887                dma_unmap_single(&dev->dev, ring->buf[i].dma_addr, 
    893                                  AG71XX_RX_PKT_SIZE, DMA_FROM_DEVICE); 
     888                                 AG71XX_RX_BUF_SIZE, DMA_FROM_DEVICE); 
    894889 
    895890                dev->last_rx = jiffies; 
     
    897892                dev->stats.rx_bytes += pktlen; 
    898893 
     894                skb = build_skb(ring->buf[i].rx_buf); 
     895                if (!skb) { 
     896                        kfree(ring->buf[i].rx_buf); 
     897                        goto next; 
     898                } 
     899 
     900                skb_reserve(skb, offset); 
    899901                skb_put(skb, pktlen); 
     902 
    900903                if (ag71xx_has_ar8216(ag)) 
    901904                        err = ag71xx_remove_ar8216_header(ag, skb, pktlen); 
     
    911914                } 
    912915 
    913                 ring->buf[i].skb = NULL; 
     916next: 
     917                ring->buf[i].rx_buf = NULL; 
    914918                done++; 
    915919 
     
    945949 
    946950        rx_ring = &ag->rx_ring; 
    947         if (rx_ring->buf[rx_ring->dirty % rx_ring->size].skb == NULL) 
     951        if (rx_ring->buf[rx_ring->dirty % rx_ring->size].rx_buf == NULL) 
    948952                goto oom; 
    949953 
Note: See TracChangeset for help on using the changeset viewer.