diff options
Diffstat (limited to 'drivers/net/enic/enic_main.c')
-rw-r--r-- | drivers/net/enic/enic_main.c | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 413e362e3275..eda5530004dc 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -594,7 +594,7 @@ static irqreturn_t enic_isr_msix_notify(int irq, void *data) | |||
594 | 594 | ||
595 | static inline void enic_queue_wq_skb_cont(struct enic *enic, | 595 | static inline void enic_queue_wq_skb_cont(struct enic *enic, |
596 | struct vnic_wq *wq, struct sk_buff *skb, | 596 | struct vnic_wq *wq, struct sk_buff *skb, |
597 | unsigned int len_left) | 597 | unsigned int len_left, int loopback) |
598 | { | 598 | { |
599 | skb_frag_t *frag; | 599 | skb_frag_t *frag; |
600 | 600 | ||
@@ -606,13 +606,14 @@ static inline void enic_queue_wq_skb_cont(struct enic *enic, | |||
606 | frag->page_offset, frag->size, | 606 | frag->page_offset, frag->size, |
607 | PCI_DMA_TODEVICE), | 607 | PCI_DMA_TODEVICE), |
608 | frag->size, | 608 | frag->size, |
609 | (len_left == 0)); /* EOP? */ | 609 | (len_left == 0), /* EOP? */ |
610 | loopback); | ||
610 | } | 611 | } |
611 | } | 612 | } |
612 | 613 | ||
613 | static inline void enic_queue_wq_skb_vlan(struct enic *enic, | 614 | static inline void enic_queue_wq_skb_vlan(struct enic *enic, |
614 | struct vnic_wq *wq, struct sk_buff *skb, | 615 | struct vnic_wq *wq, struct sk_buff *skb, |
615 | int vlan_tag_insert, unsigned int vlan_tag) | 616 | int vlan_tag_insert, unsigned int vlan_tag, int loopback) |
616 | { | 617 | { |
617 | unsigned int head_len = skb_headlen(skb); | 618 | unsigned int head_len = skb_headlen(skb); |
618 | unsigned int len_left = skb->len - head_len; | 619 | unsigned int len_left = skb->len - head_len; |
@@ -628,15 +629,15 @@ static inline void enic_queue_wq_skb_vlan(struct enic *enic, | |||
628 | head_len, PCI_DMA_TODEVICE), | 629 | head_len, PCI_DMA_TODEVICE), |
629 | head_len, | 630 | head_len, |
630 | vlan_tag_insert, vlan_tag, | 631 | vlan_tag_insert, vlan_tag, |
631 | eop); | 632 | eop, loopback); |
632 | 633 | ||
633 | if (!eop) | 634 | if (!eop) |
634 | enic_queue_wq_skb_cont(enic, wq, skb, len_left); | 635 | enic_queue_wq_skb_cont(enic, wq, skb, len_left, loopback); |
635 | } | 636 | } |
636 | 637 | ||
637 | static inline void enic_queue_wq_skb_csum_l4(struct enic *enic, | 638 | static inline void enic_queue_wq_skb_csum_l4(struct enic *enic, |
638 | struct vnic_wq *wq, struct sk_buff *skb, | 639 | struct vnic_wq *wq, struct sk_buff *skb, |
639 | int vlan_tag_insert, unsigned int vlan_tag) | 640 | int vlan_tag_insert, unsigned int vlan_tag, int loopback) |
640 | { | 641 | { |
641 | unsigned int head_len = skb_headlen(skb); | 642 | unsigned int head_len = skb_headlen(skb); |
642 | unsigned int len_left = skb->len - head_len; | 643 | unsigned int len_left = skb->len - head_len; |
@@ -656,15 +657,15 @@ static inline void enic_queue_wq_skb_csum_l4(struct enic *enic, | |||
656 | csum_offset, | 657 | csum_offset, |
657 | hdr_len, | 658 | hdr_len, |
658 | vlan_tag_insert, vlan_tag, | 659 | vlan_tag_insert, vlan_tag, |
659 | eop); | 660 | eop, loopback); |
660 | 661 | ||
661 | if (!eop) | 662 | if (!eop) |
662 | enic_queue_wq_skb_cont(enic, wq, skb, len_left); | 663 | enic_queue_wq_skb_cont(enic, wq, skb, len_left, loopback); |
663 | } | 664 | } |
664 | 665 | ||
665 | static inline void enic_queue_wq_skb_tso(struct enic *enic, | 666 | static inline void enic_queue_wq_skb_tso(struct enic *enic, |
666 | struct vnic_wq *wq, struct sk_buff *skb, unsigned int mss, | 667 | struct vnic_wq *wq, struct sk_buff *skb, unsigned int mss, |
667 | int vlan_tag_insert, unsigned int vlan_tag) | 668 | int vlan_tag_insert, unsigned int vlan_tag, int loopback) |
668 | { | 669 | { |
669 | unsigned int frag_len_left = skb_headlen(skb); | 670 | unsigned int frag_len_left = skb_headlen(skb); |
670 | unsigned int len_left = skb->len - frag_len_left; | 671 | unsigned int len_left = skb->len - frag_len_left; |
@@ -701,7 +702,7 @@ static inline void enic_queue_wq_skb_tso(struct enic *enic, | |||
701 | len, | 702 | len, |
702 | mss, hdr_len, | 703 | mss, hdr_len, |
703 | vlan_tag_insert, vlan_tag, | 704 | vlan_tag_insert, vlan_tag, |
704 | eop && (len == frag_len_left)); | 705 | eop && (len == frag_len_left), loopback); |
705 | frag_len_left -= len; | 706 | frag_len_left -= len; |
706 | offset += len; | 707 | offset += len; |
707 | } | 708 | } |
@@ -727,7 +728,8 @@ static inline void enic_queue_wq_skb_tso(struct enic *enic, | |||
727 | dma_addr, | 728 | dma_addr, |
728 | len, | 729 | len, |
729 | (len_left == 0) && | 730 | (len_left == 0) && |
730 | (len == frag_len_left)); /* EOP? */ | 731 | (len == frag_len_left), /* EOP? */ |
732 | loopback); | ||
731 | frag_len_left -= len; | 733 | frag_len_left -= len; |
732 | offset += len; | 734 | offset += len; |
733 | } | 735 | } |
@@ -740,22 +742,26 @@ static inline void enic_queue_wq_skb(struct enic *enic, | |||
740 | unsigned int mss = skb_shinfo(skb)->gso_size; | 742 | unsigned int mss = skb_shinfo(skb)->gso_size; |
741 | unsigned int vlan_tag = 0; | 743 | unsigned int vlan_tag = 0; |
742 | int vlan_tag_insert = 0; | 744 | int vlan_tag_insert = 0; |
745 | int loopback = 0; | ||
743 | 746 | ||
744 | if (enic->vlan_group && vlan_tx_tag_present(skb)) { | 747 | if (enic->vlan_group && vlan_tx_tag_present(skb)) { |
745 | /* VLAN tag from trunking driver */ | 748 | /* VLAN tag from trunking driver */ |
746 | vlan_tag_insert = 1; | 749 | vlan_tag_insert = 1; |
747 | vlan_tag = vlan_tx_tag_get(skb); | 750 | vlan_tag = vlan_tx_tag_get(skb); |
751 | } else if (enic->loop_enable) { | ||
752 | vlan_tag = enic->loop_tag; | ||
753 | loopback = 1; | ||
748 | } | 754 | } |
749 | 755 | ||
750 | if (mss) | 756 | if (mss) |
751 | enic_queue_wq_skb_tso(enic, wq, skb, mss, | 757 | enic_queue_wq_skb_tso(enic, wq, skb, mss, |
752 | vlan_tag_insert, vlan_tag); | 758 | vlan_tag_insert, vlan_tag, loopback); |
753 | else if (skb->ip_summed == CHECKSUM_PARTIAL) | 759 | else if (skb->ip_summed == CHECKSUM_PARTIAL) |
754 | enic_queue_wq_skb_csum_l4(enic, wq, skb, | 760 | enic_queue_wq_skb_csum_l4(enic, wq, skb, |
755 | vlan_tag_insert, vlan_tag); | 761 | vlan_tag_insert, vlan_tag, loopback); |
756 | else | 762 | else |
757 | enic_queue_wq_skb_vlan(enic, wq, skb, | 763 | enic_queue_wq_skb_vlan(enic, wq, skb, |
758 | vlan_tag_insert, vlan_tag); | 764 | vlan_tag_insert, vlan_tag, loopback); |
759 | } | 765 | } |
760 | 766 | ||
761 | /* netif_tx_lock held, process context with BHs disabled, or BH */ | 767 | /* netif_tx_lock held, process context with BHs disabled, or BH */ |
@@ -1275,7 +1281,7 @@ static int enic_rq_alloc_buf(struct vnic_rq *rq) | |||
1275 | struct enic *enic = vnic_dev_priv(rq->vdev); | 1281 | struct enic *enic = vnic_dev_priv(rq->vdev); |
1276 | struct net_device *netdev = enic->netdev; | 1282 | struct net_device *netdev = enic->netdev; |
1277 | struct sk_buff *skb; | 1283 | struct sk_buff *skb; |
1278 | unsigned int len = netdev->mtu + ETH_HLEN; | 1284 | unsigned int len = netdev->mtu + VLAN_ETH_HLEN; |
1279 | unsigned int os_buf_index = 0; | 1285 | unsigned int os_buf_index = 0; |
1280 | dma_addr_t dma_addr; | 1286 | dma_addr_t dma_addr; |
1281 | 1287 | ||
@@ -2441,6 +2447,12 @@ static int __devinit enic_probe(struct pci_dev *pdev, | |||
2441 | netdev->ethtool_ops = &enic_ethtool_ops; | 2447 | netdev->ethtool_ops = &enic_ethtool_ops; |
2442 | 2448 | ||
2443 | netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | 2449 | netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; |
2450 | if (ENIC_SETTING(enic, LOOP)) { | ||
2451 | netdev->features &= ~NETIF_F_HW_VLAN_TX; | ||
2452 | enic->loop_enable = 1; | ||
2453 | enic->loop_tag = enic->config.loop_tag; | ||
2454 | dev_info(dev, "loopback tag=0x%04x\n", enic->loop_tag); | ||
2455 | } | ||
2444 | if (ENIC_SETTING(enic, TXCSUM)) | 2456 | if (ENIC_SETTING(enic, TXCSUM)) |
2445 | netdev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; | 2457 | netdev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; |
2446 | if (ENIC_SETTING(enic, TSO)) | 2458 | if (ENIC_SETTING(enic, TSO)) |