diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-29 00:28:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-29 00:28:46 -0400 |
commit | 332e4af80d1214fbf0e263e1408fc7c5b64ecdd6 (patch) | |
tree | 7c8f8ada7ab8fc9cb2497d95e52dce4d2c4493a3 /drivers/net/ixgbe/ixgbe_main.c | |
parent | 1b63ba8a86c85524a8d7e5953b314ce71ebcb9c9 (diff) | |
parent | be0976be9148f31ee0d1997354c3e30ff8d07587 (diff) |
Merge branch 'davem-next' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_main.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 111 |
1 files changed, 90 insertions, 21 deletions
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 1674b6a5b903..b37d618d8e2a 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 | **/ |
395 | static void ixgbe_receive_skb(struct ixgbe_adapter *adapter, | 396 | static 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 | ||
641 | next_desc: | 654 | next_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 | **/ | ||
1408 | static 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++) { |
@@ -2490,12 +2544,18 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, | |||
2490 | struct pci_dev *pdev = adapter->pdev; | 2544 | struct pci_dev *pdev = adapter->pdev; |
2491 | int size; | 2545 | int size; |
2492 | 2546 | ||
2547 | size = sizeof(struct net_lro_desc) * IXGBE_MAX_LRO_DESCRIPTORS; | ||
2548 | rxdr->lro_mgr.lro_arr = vmalloc(size); | ||
2549 | if (!rxdr->lro_mgr.lro_arr) | ||
2550 | return -ENOMEM; | ||
2551 | memset(rxdr->lro_mgr.lro_arr, 0, size); | ||
2552 | |||
2493 | size = sizeof(struct ixgbe_rx_buffer) * rxdr->count; | 2553 | size = sizeof(struct ixgbe_rx_buffer) * rxdr->count; |
2494 | rxdr->rx_buffer_info = vmalloc(size); | 2554 | rxdr->rx_buffer_info = vmalloc(size); |
2495 | if (!rxdr->rx_buffer_info) { | 2555 | if (!rxdr->rx_buffer_info) { |
2496 | DPRINTK(PROBE, ERR, | 2556 | DPRINTK(PROBE, ERR, |
2497 | "vmalloc allocation failed for the rx desc ring\n"); | 2557 | "vmalloc allocation failed for the rx desc ring\n"); |
2498 | return -ENOMEM; | 2558 | goto alloc_failed; |
2499 | } | 2559 | } |
2500 | memset(rxdr->rx_buffer_info, 0, size); | 2560 | memset(rxdr->rx_buffer_info, 0, size); |
2501 | 2561 | ||
@@ -2509,13 +2569,18 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, | |||
2509 | DPRINTK(PROBE, ERR, | 2569 | DPRINTK(PROBE, ERR, |
2510 | "Memory allocation failed for the rx desc ring\n"); | 2570 | "Memory allocation failed for the rx desc ring\n"); |
2511 | vfree(rxdr->rx_buffer_info); | 2571 | vfree(rxdr->rx_buffer_info); |
2512 | return -ENOMEM; | 2572 | goto alloc_failed; |
2513 | } | 2573 | } |
2514 | 2574 | ||
2515 | rxdr->next_to_clean = 0; | 2575 | rxdr->next_to_clean = 0; |
2516 | rxdr->next_to_use = 0; | 2576 | rxdr->next_to_use = 0; |
2517 | 2577 | ||
2518 | return 0; | 2578 | return 0; |
2579 | |||
2580 | alloc_failed: | ||
2581 | vfree(rxdr->lro_mgr.lro_arr); | ||
2582 | rxdr->lro_mgr.lro_arr = NULL; | ||
2583 | return -ENOMEM; | ||
2519 | } | 2584 | } |
2520 | 2585 | ||
2521 | /** | 2586 | /** |
@@ -2566,6 +2631,9 @@ static void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter, | |||
2566 | { | 2631 | { |
2567 | struct pci_dev *pdev = adapter->pdev; | 2632 | struct pci_dev *pdev = adapter->pdev; |
2568 | 2633 | ||
2634 | vfree(rx_ring->lro_mgr.lro_arr); | ||
2635 | rx_ring->lro_mgr.lro_arr = NULL; | ||
2636 | |||
2569 | ixgbe_clean_rx_ring(adapter, rx_ring); | 2637 | ixgbe_clean_rx_ring(adapter, rx_ring); |
2570 | 2638 | ||
2571 | vfree(rx_ring->rx_buffer_info); | 2639 | vfree(rx_ring->rx_buffer_info); |
@@ -3518,6 +3586,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
3518 | NETIF_F_HW_VLAN_RX | | 3586 | NETIF_F_HW_VLAN_RX | |
3519 | NETIF_F_HW_VLAN_FILTER; | 3587 | NETIF_F_HW_VLAN_FILTER; |
3520 | 3588 | ||
3589 | netdev->features |= NETIF_F_LRO; | ||
3521 | netdev->features |= NETIF_F_TSO; | 3590 | netdev->features |= NETIF_F_TSO; |
3522 | netdev->features |= NETIF_F_TSO6; | 3591 | netdev->features |= NETIF_F_TSO6; |
3523 | 3592 | ||