Changeset 33503


Ignore:
Timestamp:
2012-09-22T02:34:49+02:00 (4 years ago)
Author:
nbd
Message:

cns3xxx: implement ethernet fraglist tx support for improved bridging performance with jumbo frames

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/cns3xxx/patches-3.3/410-ethernet_fix_jumbo_frame.patch

    r33499 r33503  
    121121+               dma_unmap_single(NULL, rx_ring->phys_tab[i], 
    122122+                                RX_SEGMENT_MRU, DMA_FROM_DEVICE); 
    123   
    124 -               dev = switch_port_tab[desc->sp]->netdev; 
     123+ 
    125124+               skb = build_skb(rx_ring->buff_tab[i]); 
    126125+               if (!skb) 
    127126+                       break; 
    128 + 
     127  
     128-               dev = switch_port_tab[desc->sp]->netdev; 
    129129+               skb->dev = switch_port_tab[desc->sp]->netdev; 
    130130  
     
    159159+               } 
    160160+               sw->frag_last = skb; 
    161 + 
     161  
     162-               dev->stats.rx_packets++; 
     163-               dev->stats.rx_bytes += length; 
    162164+               if (desc->lsd) { 
    163165+                       struct net_device *dev; 
    164   
    165 -               dev->stats.rx_packets++; 
    166 -               dev->stats.rx_bytes += length; 
     166+ 
    167167+                       skb = sw->frag_first; 
    168168+                       dev = skb->dev; 
     
    218218                        i = 0; 
    219219                        desc = &(rx_ring)->desc[i]; 
    220 @@ -671,12 +709,6 @@ static int eth_xmit(struct sk_buff *skb, 
     220@@ -653,42 +691,60 @@ static int eth_poll(struct napi_struct * 
     221        return received; 
     222 } 
     223  
     224+static void eth_set_desc(struct _tx_ring *tx_ring, int index, int index_last, 
     225+                        void *data, int len, u32 config0, u32 pmap) 
     226+{ 
     227+       struct tx_desc *tx_desc = &(tx_ring)->desc[index]; 
     228+       unsigned int phys; 
     229+ 
     230+       phys = dma_map_single(NULL, data, len, DMA_TO_DEVICE); 
     231+       tx_desc->sdp = phys; 
     232+       tx_desc->pmap = pmap; 
     233+       tx_ring->phys_tab[index] = phys; 
     234+ 
     235+       config0 |= len; 
     236+       if (index == TX_DESCS - 1) 
     237+               config0 |= END_OF_RING; 
     238+       if (index == index_last) 
     239+               config0 |= LAST_SEGMENT; 
     240+ 
     241+       mb(); 
     242+       tx_desc->config0 = config0; 
     243+} 
     244+ 
     245 static int eth_xmit(struct sk_buff *skb, struct net_device *dev) 
     246 { 
     247        struct port *port = netdev_priv(dev); 
     248        struct sw *sw = port->sw; 
     249        struct _tx_ring *tx_ring = sw->tx_ring; 
     250-       struct tx_desc *tx_desc; 
     251-       int index; 
     252-       int len; 
     253+       struct sk_buff *skb1; 
     254        char pmap = (1 << port->id); 
     255-       unsigned int phys; 
     256        int nr_frags = skb_shinfo(skb)->nr_frags; 
     257-       struct skb_frag_struct *frag; 
     258+       int nr_desc = nr_frags; 
     259+       int index0, index, index_last; 
     260+       int len0; 
     261        unsigned int i; 
     262-       u32 config0 = 0; 
     263+       u32 config0; 
     264  
    221265        if (pmap == 8) 
    222266                pmap = (1 << 4); 
     
    227271-               return NETDEV_TX_OK; 
    228272-       } 
    229 - 
     273+       skb_walk_frags(skb, skb1) 
     274+               nr_desc++; 
     275  
    230276        spin_lock(&tx_lock); 
    231277  
    232         if ((tx_ring->num_used + nr_frags) >= TX_DESCS) { 
    233 @@ -701,8 +733,7 @@ static int eth_xmit(struct sk_buff *skb, 
    234   
    235                 len = skb->len; 
     278-       if ((tx_ring->num_used + nr_frags) >= TX_DESCS) { 
     279+       if ((tx_ring->num_used + nr_desc + 1) >= TX_DESCS) { 
     280                clear_tx_desc(sw); 
     281-               if ((tx_ring->num_used + nr_frags) >= TX_DESCS) { 
     282+               if ((tx_ring->num_used + nr_desc + 1) >= TX_DESCS) { 
     283                        spin_unlock(&tx_lock); 
     284                        return NETDEV_TX_BUSY; 
     285                } 
     286        } 
     287  
     288-       index = tx_ring->cur_index; 
     289-       tx_ring->cur_index = ((tx_ring->cur_index + nr_frags + 1) % TX_DESCS); 
     290+       index = index0 = tx_ring->cur_index; 
     291+       index_last = (index0 + nr_desc) % TX_DESCS; 
     292+       tx_ring->cur_index = (index_last + 1) % TX_DESCS; 
     293  
     294        spin_unlock(&tx_lock); 
     295  
     296@@ -696,79 +752,41 @@ static int eth_xmit(struct sk_buff *skb, 
     297        if (skb->ip_summed == CHECKSUM_PARTIAL) 
     298                config0 |= UDP_CHECKSUM | TCP_CHECKSUM; 
     299  
     300-       if (!nr_frags) { 
     301-               tx_desc = &(tx_ring)->desc[index]; 
     302- 
     303-               len = skb->len; 
     304+       len0 = skb->len; 
    236305  
    237306-               phys = dma_map_single(NULL, skb->data, len, 
    238307-                                       DMA_TO_DEVICE); 
    239 +               phys = dma_map_single(NULL, skb->data, len, DMA_TO_DEVICE); 
    240   
    241                 tx_desc->sdp = phys; 
    242                 tx_desc->pmap = pmap; 
    243 @@ -849,24 +880,24 @@ static int init_rings(struct sw *sw) 
     308+       /* fragments */ 
     309+       for (i = 0; i < nr_frags; i++) { 
     310+               struct skb_frag_struct *frag; 
     311+               void *addr; 
     312  
     313-               tx_desc->sdp = phys; 
     314-               tx_desc->pmap = pmap; 
     315-               tx_ring->phys_tab[index] = phys; 
     316+               index = (index + 1) % TX_DESCS; 
     317  
     318-               tx_ring->buff_tab[index] = skb; 
     319-               config0 |= FIRST_SEGMENT | LAST_SEGMENT; 
     320-       } else { 
     321-               index = ((index + nr_frags) % TX_DESCS); 
     322-               tx_desc = &(tx_ring)->desc[index]; 
     323+               frag = &skb_shinfo(skb)->frags[i]; 
     324+               addr = page_address(skb_frag_page(frag)) + frag->page_offset; 
     325  
     326-               /* fragments */ 
     327-               for (i = nr_frags; i > 0; i--) { 
     328-                       u32 config; 
     329-                       void *addr; 
     330- 
     331-                       frag = &skb_shinfo(skb)->frags[i-1]; 
     332-                       len = frag->size; 
     333- 
     334-                       addr = page_address(skb_frag_page(frag)) + 
     335-                              frag->page_offset; 
     336-                       phys = dma_map_single(NULL, addr, len, DMA_TO_DEVICE); 
     337- 
     338-                       tx_desc->sdp = phys; 
     339- 
     340-                       tx_desc->pmap = pmap; 
     341-                       tx_ring->phys_tab[index] = phys; 
     342- 
     343-                       config = config0 | len; 
     344-                       if (i == nr_frags) { 
     345-                               config |= LAST_SEGMENT; 
     346-                               tx_ring->buff_tab[index] = skb; 
     347-                       } 
     348-                       if (index == TX_DESCS - 1) 
     349-                               config |= END_OF_RING; 
     350-                       tx_desc->config0 = config; 
     351- 
     352-                       if (index == 0) { 
     353-                               index = TX_DESCS - 1; 
     354-                               tx_desc = &(tx_ring)->desc[index]; 
     355-                       } else { 
     356-                               index--; 
     357-                               tx_desc--; 
     358-                       } 
     359-               } 
     360+               eth_set_desc(tx_ring, index, index_last, addr, frag->size, 
     361+                            config0, pmap); 
     362+       } 
     363  
     364-               /* header */ 
     365-               len = skb->len - skb->data_len; 
     366+       if (nr_frags) 
     367+               len0 = skb->len - skb->data_len; 
     368  
     369-               phys = dma_map_single(NULL, skb->data, len, DMA_TO_DEVICE); 
     370+       skb_walk_frags(skb, skb1) { 
     371+               index = (index + 1) % TX_DESCS; 
     372+               len0 -= skb1->len; 
     373  
     374-               tx_desc->sdp = phys; 
     375-               tx_desc->pmap = pmap; 
     376-               tx_ring->phys_tab[index] = phys; 
     377-               config0 |= FIRST_SEGMENT; 
     378+               eth_set_desc(tx_ring, index, index_last, skb1->data, skb1->len, 
     379+                            config0, pmap); 
     380        } 
     381  
     382-       if (index == TX_DESCS - 1) 
     383-               config0 |= END_OF_RING; 
     384- 
     385-       tx_desc->config0 = config0 | len; 
     386+       tx_ring->buff_tab[index0] = skb; 
     387+       eth_set_desc(tx_ring, index0, index_last, skb->data, len0, 
     388+                    config0 | FIRST_SEGMENT, pmap); 
     389  
     390        mb(); 
     391  
     392        spin_lock(&tx_lock); 
     393-       tx_ring->num_used += nr_frags + 1; 
     394+       tx_ring->num_used += nr_desc + 1; 
     395        spin_unlock(&tx_lock); 
     396  
     397        dev->stats.tx_packets++; 
     398@@ -849,24 +867,24 @@ static int init_rings(struct sw *sw) 
    244399        /* Setup RX buffers */ 
    245400        for (i = 0; i < RX_DESCS; i++) { 
     
    277432                desc->cown = 0; 
    278433        } 
    279 @@ -905,12 +936,13 @@ static void destroy_rings(struct sw *sw) 
     434@@ -905,12 +923,13 @@ static void destroy_rings(struct sw *sw) 
    280435                        struct _rx_ring *rx_ring = sw->rx_ring; 
    281436                        struct rx_desc *desc = &(rx_ring)->desc[i]; 
     
    297452                dma_pool_free(rx_dma_pool, sw->rx_ring->desc, sw->rx_ring->phys_addr); 
    298453                dma_pool_destroy(rx_dma_pool); 
    299 @@ -1085,13 +1117,22 @@ static int eth_set_mac(struct net_device 
     454@@ -1085,13 +1104,22 @@ static int eth_set_mac(struct net_device 
    300455        return 0; 
    301456 } 
     
    321476        .ndo_validate_addr = eth_validate_addr, 
    322477 }; 
    323 @@ -1124,6 +1165,10 @@ static int __devinit eth_init_one(struct 
     478@@ -1111,7 +1139,7 @@ static int __devinit eth_init_one(struct 
     479        if (!(napi_dev = alloc_etherdev(sizeof(struct sw)))) 
     480                return -ENOMEM; 
     481        strcpy(napi_dev->name, "switch%d"); 
     482-       napi_dev->features = NETIF_F_IP_CSUM | NETIF_F_SG; 
     483+       napi_dev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_FRAGLIST; 
     484  
     485        SET_NETDEV_DEV(napi_dev, &pdev->dev); 
     486        sw = netdev_priv(napi_dev); 
     487@@ -1124,6 +1152,10 @@ static int __devinit eth_init_one(struct 
    324488                goto err_free; 
    325489        } 
     
    332496                temp = __raw_readl(&sw->regs->mac_cfg[i]); 
    333497                temp |= (PORT_DISABLE); 
     498@@ -1185,7 +1217,7 @@ static int __devinit eth_init_one(struct 
     499                dev->netdev_ops = &cns3xxx_netdev_ops; 
     500                dev->ethtool_ops = &cns3xxx_ethtool_ops; 
     501                dev->tx_queue_len = 1000; 
     502-               dev->features = NETIF_F_IP_CSUM | NETIF_F_SG; 
     503+               dev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_FRAGLIST; 
     504  
     505                switch_port_tab[port->id] = port; 
     506                memcpy(dev->dev_addr, &plat->hwaddr[i], ETH_ALEN); 
Note: See TracChangeset for help on using the changeset viewer.