Changeset 42328


Ignore:
Timestamp:
2014-08-29T21:42:08+02:00 (3 years ago)
Author:
nbd
Message:

ar71xx: split packets into multiple descriptors on ar716x

This improves performance when doing concurrent rx/tx on a single
ethernet MAC, e.g. when routing between VLANs.

Fixes #13072

Signed-off-by: Felix Fietkau <nbd@…>

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

Legend:

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

    r39144 r42328  
    5353#define AG71XX_TX_MTU_LEN       1540 
    5454 
    55 #define AG71XX_TX_RING_SIZE_DEFAULT     32 
     55#define AG71XX_TX_RING_SPLIT            256 
     56#define AG71XX_TX_RING_DS_PER_PKT       DIV_ROUND_UP(AG71XX_TX_MTU_LEN, \ 
     57                                                     AG71XX_TX_RING_SPLIT) 
     58#define AG71XX_TX_RING_SIZE_DEFAULT     48 
    5659#define AG71XX_RX_RING_SIZE_DEFAULT     128 
    5760 
    58 #define AG71XX_TX_RING_SIZE_MAX         32 
     61#define AG71XX_TX_RING_SIZE_MAX         48 
    5962#define AG71XX_RX_RING_SIZE_MAX         128 
    6063 
     
    100103        u8                      *descs_cpu; 
    101104        dma_addr_t              descs_dma; 
    102         unsigned int            desc_size; 
     105        u16                     desc_split; 
     106        u16                     desc_size; 
    103107        unsigned int            curr; 
    104108        unsigned int            dirty; 
  • trunk/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c

    r30405 r42328  
    7676        er->rx_mini_pending = 0; 
    7777        er->rx_jumbo_pending = 0; 
     78 
     79        if (ag->tx_ring.desc_split) 
     80                er->tx_pending /= AG71XX_TX_RING_DS_PER_PKT; 
    7881} 
    7982 
     
    104107        } 
    105108 
     109        if (ag->tx_ring.desc_split) 
     110                tx_size *= AG71XX_TX_RING_DS_PER_PKT; 
     111 
    106112        ag->tx_ring.size = tx_size; 
    107113        ag->rx_ring.size = rx_size; 
  • trunk/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c

    r39219 r42328  
    537537        u32 ifctl; 
    538538        u32 fifo5; 
     539        u32 fifo3; 
    539540 
    540541        if (!ag->link) { 
     
    577578 
    578579        if (pdata->is_ar91xx) 
    579                 ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x00780fff); 
     580                fifo3 = 0x00780fff; 
    580581        else if (pdata->is_ar724x) 
    581                 ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, pdata->fifo_cfg3); 
     582                fifo3 = pdata->fifo_cfg3; 
    582583        else 
    583                 ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff); 
     584                fifo3 = 0x008001ff; 
     585 
     586        if (ag->tx_ring.desc_split) { 
     587                fifo3 &= 0xffff; 
     588                fifo3 |= ((2048 - ag->tx_ring.desc_split) / 4) << 16; 
     589        } 
     590 
     591        ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, fifo3); 
    584592 
    585593        if (pdata->set_speed) 
     
    676684} 
    677685 
     686static int ag71xx_fill_dma_desc(struct ag71xx_ring *ring, u32 addr, int len) 
     687{ 
     688        int i; 
     689        struct ag71xx_desc *desc; 
     690        int ndesc = 0; 
     691        int split = ring->desc_split; 
     692 
     693        if (!split) 
     694                split = len; 
     695 
     696        while (len > 0) { 
     697                unsigned int cur_len = len; 
     698 
     699                i = (ring->curr + ndesc) % ring->size; 
     700                desc = ring->buf[i].desc; 
     701 
     702                if (!ag71xx_desc_empty(desc)) 
     703                        return -1; 
     704 
     705                if (cur_len > split) { 
     706                        cur_len = split; 
     707                        if (len < split + 4) 
     708                                cur_len -= 4; 
     709                } 
     710 
     711                desc->data = addr; 
     712                addr += cur_len; 
     713                len -= cur_len; 
     714 
     715                if (len > 0) 
     716                        cur_len |= DESC_MORE; 
     717 
     718                /* prevent early tx attempt of this descriptor */ 
     719                if (!ndesc) 
     720                        cur_len |= DESC_EMPTY; 
     721 
     722                desc->ctrl = cur_len; 
     723                ndesc++; 
     724        } 
     725 
     726        return ndesc; 
     727} 
     728 
    678729static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb, 
    679730                                          struct net_device *dev) 
     
    683734        struct ag71xx_desc *desc; 
    684735        dma_addr_t dma_addr; 
    685         int i; 
     736        int i, n, ring_min; 
     737 
     738        if (ag71xx_has_ar8216(ag)) 
     739                ag71xx_add_ar8216_header(ag, skb); 
     740 
     741        if (skb->len <= 4) { 
     742                DBG("%s: packet len is too small\n", ag->dev->name); 
     743                goto err_drop; 
     744        } 
     745 
     746        dma_addr = dma_map_single(&dev->dev, skb->data, skb->len, 
     747                                  DMA_TO_DEVICE); 
    686748 
    687749        i = ring->curr % ring->size; 
    688750        desc = ring->buf[i].desc; 
    689751 
    690         if (!ag71xx_desc_empty(desc)) 
    691                 goto err_drop; 
    692  
    693         if (ag71xx_has_ar8216(ag)) 
    694                 ag71xx_add_ar8216_header(ag, skb); 
    695  
    696         if (skb->len <= 0) { 
    697                 DBG("%s: packet len is too small\n", ag->dev->name); 
    698                 goto err_drop; 
    699         } 
    700  
    701         dma_addr = dma_map_single(&dev->dev, skb->data, skb->len, 
    702                                   DMA_TO_DEVICE); 
    703  
    704         netdev_sent_queue(dev, skb->len); 
     752        /* setup descriptor fields */ 
     753        n = ag71xx_fill_dma_desc(ring, (u32) dma_addr, skb->len & ag->desc_pktlen_mask); 
     754        if (n < 0) 
     755                goto err_drop_unmap; 
     756 
     757        i = (ring->curr + n - 1) % ring->size; 
    705758        ring->buf[i].len = skb->len; 
    706759        ring->buf[i].skb = skb; 
    707760        ring->buf[i].timestamp = jiffies; 
    708761 
    709         /* setup descriptor fields */ 
    710         desc->data = (u32) dma_addr; 
    711         desc->ctrl = skb->len & ag->desc_pktlen_mask; 
     762        netdev_sent_queue(dev, skb->len); 
     763 
     764        desc->ctrl &= ~DESC_EMPTY; 
     765        ring->curr += n; 
    712766 
    713767        /* flush descriptor */ 
    714768        wmb(); 
    715769 
    716         ring->curr++; 
    717         if (ring->curr == (ring->dirty + ring->size)) { 
    718                 DBG("%s: tx queue full\n", ag->dev->name); 
     770        ring_min = 2; 
     771        if (ring->desc_split) 
     772            ring_min *= AG71XX_TX_RING_DS_PER_PKT; 
     773 
     774        if (ring->curr - ring->dirty >= ring->size - ring_min) { 
     775                DBG("%s: tx queue full\n", dev->name); 
    719776                netif_stop_queue(dev); 
    720777        } 
     
    726783 
    727784        return NETDEV_TX_OK; 
     785 
     786err_drop_unmap: 
     787        dma_unmap_single(&dev->dev, dma_addr, skb->len, DMA_TO_DEVICE); 
    728788 
    729789err_drop: 
     
    844904                struct ag71xx_desc *desc = ring->buf[i].desc; 
    845905                struct sk_buff *skb = ring->buf[i].skb; 
    846                 int len = ring->buf[i].len; 
    847906 
    848907                if (!ag71xx_desc_empty(desc)) { 
     
    855914                ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS); 
    856915 
    857                 bytes_compl += len; 
    858                 ag->dev->stats.tx_bytes += len; 
    859                 ag->dev->stats.tx_packets++; 
    860  
    861                 dev_kfree_skb_any(skb); 
    862                 ring->buf[i].skb = NULL; 
     916                if (skb) { 
     917                        dev_kfree_skb_any(skb); 
     918                        ring->buf[i].skb = NULL; 
     919 
     920                        bytes_compl += ring->buf[i].len; 
     921                        sent++; 
     922                } 
    863923 
    864924                ring->dirty++; 
    865                 sent++; 
    866925        } 
    867926 
    868927        DBG("%s: %d packets sent out\n", ag->dev->name, sent); 
     928 
     929        ag->dev->stats.tx_bytes += bytes_compl; 
     930        ag->dev->stats.tx_packets += sent; 
    869931 
    870932        if (!sent) 
     
    11951257        ag->max_frame_len = pdata->max_frame_len; 
    11961258        ag->desc_pktlen_mask = pdata->desc_pktlen_mask; 
     1259 
     1260        if (!pdata->is_ar724x && !pdata->is_ar91xx) { 
     1261                ag->tx_ring.desc_split = AG71XX_TX_RING_SPLIT; 
     1262                ag->tx_ring.size *= AG71XX_TX_RING_DS_PER_PKT; 
     1263        } 
    11971264 
    11981265        ag->stop_desc = dma_alloc_coherent(NULL, 
Note: See TracChangeset for help on using the changeset viewer.