aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2010-04-12 02:58:28 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-13 05:25:45 -0400
commit9dc7a1134919bda8951bf5909fb79c14defb8317 (patch)
tree29731e42632eff36276aa2726f1fcbd423532489 /drivers
parentd2757fc4076118e13180e91f02c3c52659be3d9d (diff)
tg3: Re-inline VLAN tags when appropriate
The tg3 driver is written so that VLAN tagged packets can be accepted, even if CONFIG_VLAN_8021Q or CONFIG_VLAN_8021Q_MODULE is not defined. (Think raw interfaces.) If the device has ASF support enabled, the firmware requires the driver to enable VLAN tag stripping. If VLAN tagging is not explicitly supported by the kernel and ASF is enabled, the driver will have to reinject the VLAN tag back into the packet stream. Signed-off-by: Matt Carlson <mcarlson@broadcom.com> Reviewed-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/tg3.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 57914050b098..3263f50bc52e 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -126,6 +126,9 @@
126 TG3_TX_RING_SIZE) 126 TG3_TX_RING_SIZE)
127#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) 127#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1))
128 128
129#define TG3_RX_DMA_ALIGN 16
130#define TG3_RX_HEADROOM ALIGN(VLAN_HLEN, TG3_RX_DMA_ALIGN)
131
129#define TG3_DMA_BYTE_ENAB 64 132#define TG3_DMA_BYTE_ENAB 64
130 133
131#define TG3_RX_STD_DMA_SZ 1536 134#define TG3_RX_STD_DMA_SZ 1536
@@ -4624,6 +4627,8 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
4624 struct sk_buff *skb; 4627 struct sk_buff *skb;
4625 dma_addr_t dma_addr; 4628 dma_addr_t dma_addr;
4626 u32 opaque_key, desc_idx, *post_ptr; 4629 u32 opaque_key, desc_idx, *post_ptr;
4630 bool hw_vlan __maybe_unused = false;
4631 u16 vtag __maybe_unused = 0;
4627 4632
4628 desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; 4633 desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
4629 opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; 4634 opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
@@ -4682,12 +4687,12 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
4682 tg3_recycle_rx(tnapi, tpr, opaque_key, 4687 tg3_recycle_rx(tnapi, tpr, opaque_key,
4683 desc_idx, *post_ptr); 4688 desc_idx, *post_ptr);
4684 4689
4685 copy_skb = netdev_alloc_skb(tp->dev, 4690 copy_skb = netdev_alloc_skb(tp->dev, len + VLAN_HLEN +
4686 len + TG3_RAW_IP_ALIGN); 4691 TG3_RAW_IP_ALIGN);
4687 if (copy_skb == NULL) 4692 if (copy_skb == NULL)
4688 goto drop_it_no_recycle; 4693 goto drop_it_no_recycle;
4689 4694
4690 skb_reserve(copy_skb, TG3_RAW_IP_ALIGN); 4695 skb_reserve(copy_skb, TG3_RAW_IP_ALIGN + VLAN_HLEN);
4691 skb_put(copy_skb, len); 4696 skb_put(copy_skb, len);
4692 pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); 4697 pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
4693 skb_copy_from_linear_data(skb, copy_skb->data, len); 4698 skb_copy_from_linear_data(skb, copy_skb->data, len);
@@ -4713,12 +4718,29 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
4713 goto next_pkt; 4718 goto next_pkt;
4714 } 4719 }
4715 4720
4721 if (desc->type_flags & RXD_FLAG_VLAN &&
4722 !(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG)) {
4723 vtag = desc->err_vlan & RXD_VLAN_MASK;
4716#if TG3_VLAN_TAG_USED 4724#if TG3_VLAN_TAG_USED
4717 if (tp->vlgrp != NULL && 4725 if (tp->vlgrp)
4718 desc->type_flags & RXD_FLAG_VLAN) { 4726 hw_vlan = true;
4719 vlan_gro_receive(&tnapi->napi, tp->vlgrp, 4727 else
4720 desc->err_vlan & RXD_VLAN_MASK, skb); 4728#endif
4721 } else 4729 {
4730 struct vlan_ethhdr *ve = (struct vlan_ethhdr *)
4731 __skb_push(skb, VLAN_HLEN);
4732
4733 memmove(ve, skb->data + VLAN_HLEN,
4734 ETH_ALEN * 2);
4735 ve->h_vlan_proto = htons(ETH_P_8021Q);
4736 ve->h_vlan_TCI = htons(vtag);
4737 }
4738 }
4739
4740#if TG3_VLAN_TAG_USED
4741 if (hw_vlan)
4742 vlan_gro_receive(&tnapi->napi, tp->vlgrp, vtag, skb);
4743 else
4722#endif 4744#endif
4723 napi_gro_receive(&tnapi->napi, skb); 4745 napi_gro_receive(&tnapi->napi, skb);
4724 4746
@@ -13481,13 +13503,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
13481 else 13503 else
13482 tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; 13504 tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
13483 13505
13484 tp->rx_offset = NET_IP_ALIGN; 13506 tp->rx_offset = NET_IP_ALIGN + TG3_RX_HEADROOM;
13485 tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD; 13507 tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD;
13486 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && 13508 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
13487 (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) { 13509 (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
13488 tp->rx_offset = 0; 13510 tp->rx_offset -= NET_IP_ALIGN;
13489#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 13511#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
13490 tp->rx_copy_thresh = ~0; 13512 tp->rx_copy_thresh = ~(u16)0;
13491#endif 13513#endif
13492 } 13514 }
13493 13515