aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe
diff options
context:
space:
mode:
authorMallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>2008-06-18 18:32:19 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-06-24 23:06:19 -0400
commit177db6ffd0599430a2ab63045e88fc4031f42420 (patch)
tree1c1e0b71a9589628e8b2abd82c213e1e7d1cc34b /drivers/net/ixgbe
parent8f85cd7fefa3d01c4e05aac1cb198733336cf44b (diff)
ixgbe: add LRO support
Support for in-kernel LRO with the ability to enable/disable via ethtool based on comments from Ben Hutchings. Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/ixgbe')
-rw-r--r--drivers/net/ixgbe/ixgbe.h9
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c11
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c111
3 files changed, 110 insertions, 21 deletions
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index d98113472a89..956914a5028d 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -32,6 +32,7 @@
32#include <linux/types.h> 32#include <linux/types.h>
33#include <linux/pci.h> 33#include <linux/pci.h>
34#include <linux/netdevice.h> 34#include <linux/netdevice.h>
35#include <linux/inet_lro.h>
35 36
36#include "ixgbe_type.h" 37#include "ixgbe_type.h"
37#include "ixgbe_common.h" 38#include "ixgbe_common.h"
@@ -100,6 +101,9 @@
100#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000 101#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000
101#define IXGBE_TX_FLAGS_VLAN_SHIFT 16 102#define IXGBE_TX_FLAGS_VLAN_SHIFT 16
102 103
104#define IXGBE_MAX_LRO_DESCRIPTORS 8
105#define IXGBE_MAX_LRO_AGGREGATE 32
106
103/* wrapper around a pointer to a socket buffer, 107/* wrapper around a pointer to a socket buffer,
104 * so a DMA handle can be stored along with the buffer */ 108 * so a DMA handle can be stored along with the buffer */
105struct ixgbe_tx_buffer { 109struct ixgbe_tx_buffer {
@@ -150,6 +154,8 @@ struct ixgbe_ring {
150 /* cpu for tx queue */ 154 /* cpu for tx queue */
151 int cpu; 155 int cpu;
152#endif 156#endif
157 struct net_lro_mgr lro_mgr;
158 bool lro_used;
153 struct ixgbe_queue_stats stats; 159 struct ixgbe_queue_stats stats;
154 u8 v_idx; /* maps directly to the index for this ring in the hardware 160 u8 v_idx; /* maps directly to the index for this ring in the hardware
155 * vector array, can also be used for finding the bit in EICR 161 * vector array, can also be used for finding the bit in EICR
@@ -287,6 +293,9 @@ struct ixgbe_adapter {
287 293
288 unsigned long state; 294 unsigned long state;
289 u64 tx_busy; 295 u64 tx_busy;
296 u64 lro_aggregated;
297 u64 lro_flushed;
298 u64 lro_no_desc;
290}; 299};
291 300
292enum ixbge_state_t { 301enum ixbge_state_t {
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 4e463778bcfd..12990b1fe7e4 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -90,6 +90,8 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
90 {"rx_header_split", IXGBE_STAT(rx_hdr_split)}, 90 {"rx_header_split", IXGBE_STAT(rx_hdr_split)},
91 {"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)}, 91 {"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)},
92 {"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)}, 92 {"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)},
93 {"lro_aggregated", IXGBE_STAT(lro_aggregated)},
94 {"lro_flushed", IXGBE_STAT(lro_flushed)},
93}; 95};
94 96
95#define IXGBE_QUEUE_STATS_LEN \ 97#define IXGBE_QUEUE_STATS_LEN \
@@ -787,6 +789,7 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
787 int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64); 789 int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64);
788 int j, k; 790 int j, k;
789 int i; 791 int i;
792 u64 aggregated = 0, flushed = 0, no_desc = 0;
790 793
791 ixgbe_update_stats(adapter); 794 ixgbe_update_stats(adapter);
792 for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { 795 for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
@@ -801,11 +804,17 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
801 i += k; 804 i += k;
802 } 805 }
803 for (j = 0; j < adapter->num_rx_queues; j++) { 806 for (j = 0; j < adapter->num_rx_queues; j++) {
807 aggregated += adapter->rx_ring[j].lro_mgr.stats.aggregated;
808 flushed += adapter->rx_ring[j].lro_mgr.stats.flushed;
809 no_desc += adapter->rx_ring[j].lro_mgr.stats.no_desc;
804 queue_stat = (u64 *)&adapter->rx_ring[j].stats; 810 queue_stat = (u64 *)&adapter->rx_ring[j].stats;
805 for (k = 0; k < stat_count; k++) 811 for (k = 0; k < stat_count; k++)
806 data[i + k] = queue_stat[k]; 812 data[i + k] = queue_stat[k];
807 i += k; 813 i += k;
808 } 814 }
815 adapter->lro_aggregated = aggregated;
816 adapter->lro_flushed = flushed;
817 adapter->lro_no_desc = no_desc;
809} 818}
810 819
811static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, 820static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
@@ -973,6 +982,8 @@ static struct ethtool_ops ixgbe_ethtool_ops = {
973 .get_ethtool_stats = ixgbe_get_ethtool_stats, 982 .get_ethtool_stats = ixgbe_get_ethtool_stats,
974 .get_coalesce = ixgbe_get_coalesce, 983 .get_coalesce = ixgbe_get_coalesce,
975 .set_coalesce = ixgbe_set_coalesce, 984 .set_coalesce = ixgbe_set_coalesce,
985 .get_flags = ethtool_op_get_flags,
986 .set_flags = ethtool_op_set_flags,
976}; 987};
977 988
978void ixgbe_set_ethtool_ops(struct net_device *netdev) 989void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 0d37c9025be4..f429c9a4754f 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -389,24 +389,39 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
389 * ixgbe_receive_skb - Send a completed packet up the stack 389 * ixgbe_receive_skb - Send a completed packet up the stack
390 * @adapter: board private structure 390 * @adapter: board private structure
391 * @skb: packet to send up 391 * @skb: packet to send up
392 * @is_vlan: packet has a VLAN tag 392 * @status: hardware indication of status of receive
393 * @tag: VLAN tag from descriptor 393 * @rx_ring: rx descriptor ring (for a specific queue) to setup
394 * @rx_desc: rx descriptor
394 **/ 395 **/
395static void ixgbe_receive_skb(struct ixgbe_adapter *adapter, 396static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
396 struct sk_buff *skb, bool is_vlan, 397 struct sk_buff *skb, u8 status,
397 u16 tag) 398 struct ixgbe_ring *ring,
399 union ixgbe_adv_rx_desc *rx_desc)
398{ 400{
399 if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { 401 bool is_vlan = (status & IXGBE_RXD_STAT_VP);
400 if (adapter->vlgrp && is_vlan) 402 u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
401 vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag);
402 else
403 netif_receive_skb(skb);
404 } else {
405 403
404 if (adapter->netdev->features & NETIF_F_LRO &&
405 skb->ip_summed == CHECKSUM_UNNECESSARY) {
406 if (adapter->vlgrp && is_vlan) 406 if (adapter->vlgrp && is_vlan)
407 vlan_hwaccel_rx(skb, adapter->vlgrp, tag); 407 lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb,
408 adapter->vlgrp, tag,
409 rx_desc);
408 else 410 else
409 netif_rx(skb); 411 lro_receive_skb(&ring->lro_mgr, skb, rx_desc);
412 ring->lro_used = true;
413 } else {
414 if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
415 if (adapter->vlgrp && is_vlan)
416 vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag);
417 else
418 netif_receive_skb(skb);
419 } else {
420 if (adapter->vlgrp && is_vlan)
421 vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
422 else
423 netif_rx(skb);
424 }
410 } 425 }
411} 426}
412 427
@@ -546,8 +561,8 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
546 struct sk_buff *skb; 561 struct sk_buff *skb;
547 unsigned int i; 562 unsigned int i;
548 u32 upper_len, len, staterr; 563 u32 upper_len, len, staterr;
549 u16 hdr_info, vlan_tag; 564 u16 hdr_info;
550 bool is_vlan, cleaned = false; 565 bool cleaned = false;
551 int cleaned_count = 0; 566 int cleaned_count = 0;
552 unsigned int total_rx_bytes = 0, total_rx_packets = 0; 567 unsigned int total_rx_bytes = 0, total_rx_packets = 0;
553 568
@@ -556,8 +571,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
556 rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i); 571 rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
557 staterr = le32_to_cpu(rx_desc->wb.upper.status_error); 572 staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
558 rx_buffer_info = &rx_ring->rx_buffer_info[i]; 573 rx_buffer_info = &rx_ring->rx_buffer_info[i];
559 is_vlan = (staterr & IXGBE_RXD_STAT_VP);
560 vlan_tag = le16_to_cpu(rx_desc->wb.upper.vlan);
561 574
562 while (staterr & IXGBE_RXD_STAT_DD) { 575 while (staterr & IXGBE_RXD_STAT_DD) {
563 if (*work_done >= work_to_do) 576 if (*work_done >= work_to_do)
@@ -635,7 +648,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
635 total_rx_packets++; 648 total_rx_packets++;
636 649
637 skb->protocol = eth_type_trans(skb, netdev); 650 skb->protocol = eth_type_trans(skb, netdev);
638 ixgbe_receive_skb(adapter, skb, is_vlan, vlan_tag); 651 ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc);
639 netdev->last_rx = jiffies; 652 netdev->last_rx = jiffies;
640 653
641next_desc: 654next_desc:
@@ -652,8 +665,11 @@ next_desc:
652 rx_buffer_info = next_buffer; 665 rx_buffer_info = next_buffer;
653 666
654 staterr = le32_to_cpu(rx_desc->wb.upper.status_error); 667 staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
655 is_vlan = (staterr & IXGBE_RXD_STAT_VP); 668 }
656 vlan_tag = le16_to_cpu(rx_desc->wb.upper.vlan); 669
670 if (rx_ring->lro_used) {
671 lro_flush_all(&rx_ring->lro_mgr);
672 rx_ring->lro_used = false;
657 } 673 }
658 674
659 rx_ring->next_to_clean = i; 675 rx_ring->next_to_clean = i;
@@ -1382,6 +1398,33 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
1382 1398
1383#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 1399#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
1384/** 1400/**
1401 * ixgbe_get_skb_hdr - helper function for LRO header processing
1402 * @skb: pointer to sk_buff to be added to LRO packet
1403 * @iphdr: pointer to tcp header structure
1404 * @tcph: pointer to tcp header structure
1405 * @hdr_flags: pointer to header flags
1406 * @priv: private data
1407 **/
1408static int ixgbe_get_skb_hdr(struct sk_buff *skb, void **iphdr, void **tcph,
1409 u64 *hdr_flags, void *priv)
1410{
1411 union ixgbe_adv_rx_desc *rx_desc = priv;
1412
1413 /* Verify that this is a valid IPv4 TCP packet */
1414 if (!(rx_desc->wb.lower.lo_dword.pkt_info &
1415 (IXGBE_RXDADV_PKTTYPE_IPV4 | IXGBE_RXDADV_PKTTYPE_TCP)))
1416 return -1;
1417
1418 /* Set network headers */
1419 skb_reset_network_header(skb);
1420 skb_set_transport_header(skb, ip_hdrlen(skb));
1421 *iphdr = ip_hdr(skb);
1422 *tcph = tcp_hdr(skb);
1423 *hdr_flags = LRO_IPV4 | LRO_TCP;
1424 return 0;
1425}
1426
1427/**
1385 * ixgbe_configure_rx - Configure 8254x Receive Unit after Reset 1428 * ixgbe_configure_rx - Configure 8254x Receive Unit after Reset
1386 * @adapter: board private structure 1429 * @adapter: board private structure
1387 * 1430 *
@@ -1470,6 +1513,17 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
1470 adapter->rx_ring[i].tail = IXGBE_RDT(i); 1513 adapter->rx_ring[i].tail = IXGBE_RDT(i);
1471 } 1514 }
1472 1515
1516 /* Intitial LRO Settings */
1517 adapter->rx_ring[i].lro_mgr.max_aggr = IXGBE_MAX_LRO_AGGREGATE;
1518 adapter->rx_ring[i].lro_mgr.max_desc = IXGBE_MAX_LRO_DESCRIPTORS;
1519 adapter->rx_ring[i].lro_mgr.get_skb_header = ixgbe_get_skb_hdr;
1520 adapter->rx_ring[i].lro_mgr.features = LRO_F_EXTRACT_VLAN_ID;
1521 if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
1522 adapter->rx_ring[i].lro_mgr.features |= LRO_F_NAPI;
1523 adapter->rx_ring[i].lro_mgr.dev = adapter->netdev;
1524 adapter->rx_ring[i].lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
1525 adapter->rx_ring[i].lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
1526
1473 if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { 1527 if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
1474 /* Fill out redirection table */ 1528 /* Fill out redirection table */
1475 for (i = 0, j = 0; i < 128; i++, j++) { 1529 for (i = 0, j = 0; i < 128; i++, j++) {
@@ -2489,12 +2543,18 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
2489 struct pci_dev *pdev = adapter->pdev; 2543 struct pci_dev *pdev = adapter->pdev;
2490 int size; 2544 int size;
2491 2545
2546 size = sizeof(struct net_lro_desc) * IXGBE_MAX_LRO_DESCRIPTORS;
2547 rxdr->lro_mgr.lro_arr = vmalloc(size);
2548 if (!rxdr->lro_mgr.lro_arr)
2549 return -ENOMEM;
2550 memset(rxdr->lro_mgr.lro_arr, 0, size);
2551
2492 size = sizeof(struct ixgbe_rx_buffer) * rxdr->count; 2552 size = sizeof(struct ixgbe_rx_buffer) * rxdr->count;
2493 rxdr->rx_buffer_info = vmalloc(size); 2553 rxdr->rx_buffer_info = vmalloc(size);
2494 if (!rxdr->rx_buffer_info) { 2554 if (!rxdr->rx_buffer_info) {
2495 DPRINTK(PROBE, ERR, 2555 DPRINTK(PROBE, ERR,
2496 "vmalloc allocation failed for the rx desc ring\n"); 2556 "vmalloc allocation failed for the rx desc ring\n");
2497 return -ENOMEM; 2557 goto alloc_failed;
2498 } 2558 }
2499 memset(rxdr->rx_buffer_info, 0, size); 2559 memset(rxdr->rx_buffer_info, 0, size);
2500 2560
@@ -2508,13 +2568,18 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
2508 DPRINTK(PROBE, ERR, 2568 DPRINTK(PROBE, ERR,
2509 "Memory allocation failed for the rx desc ring\n"); 2569 "Memory allocation failed for the rx desc ring\n");
2510 vfree(rxdr->rx_buffer_info); 2570 vfree(rxdr->rx_buffer_info);
2511 return -ENOMEM; 2571 goto alloc_failed;
2512 } 2572 }
2513 2573
2514 rxdr->next_to_clean = 0; 2574 rxdr->next_to_clean = 0;
2515 rxdr->next_to_use = 0; 2575 rxdr->next_to_use = 0;
2516 2576
2517 return 0; 2577 return 0;
2578
2579alloc_failed:
2580 vfree(rxdr->lro_mgr.lro_arr);
2581 rxdr->lro_mgr.lro_arr = NULL;
2582 return -ENOMEM;
2518} 2583}
2519 2584
2520/** 2585/**
@@ -2565,6 +2630,9 @@ static void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter,
2565{ 2630{
2566 struct pci_dev *pdev = adapter->pdev; 2631 struct pci_dev *pdev = adapter->pdev;
2567 2632
2633 vfree(rx_ring->lro_mgr.lro_arr);
2634 rx_ring->lro_mgr.lro_arr = NULL;
2635
2568 ixgbe_clean_rx_ring(adapter, rx_ring); 2636 ixgbe_clean_rx_ring(adapter, rx_ring);
2569 2637
2570 vfree(rx_ring->rx_buffer_info); 2638 vfree(rx_ring->rx_buffer_info);
@@ -3517,6 +3585,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
3517 NETIF_F_HW_VLAN_RX | 3585 NETIF_F_HW_VLAN_RX |
3518 NETIF_F_HW_VLAN_FILTER; 3586 NETIF_F_HW_VLAN_FILTER;
3519 3587
3588 netdev->features |= NETIF_F_LRO;
3520 netdev->features |= NETIF_F_TSO; 3589 netdev->features |= NETIF_F_TSO;
3521 netdev->features |= NETIF_F_TSO6; 3590 netdev->features |= NETIF_F_TSO6;
3522 3591