|
@@ -2495,9 +2495,11 @@ static struct sk_buff *receive_copy(struct sky2_port *sky2,
|
|
skb->ip_summed = re->skb->ip_summed;
|
|
skb->ip_summed = re->skb->ip_summed;
|
|
skb->csum = re->skb->csum;
|
|
skb->csum = re->skb->csum;
|
|
skb->rxhash = re->skb->rxhash;
|
|
skb->rxhash = re->skb->rxhash;
|
|
|
|
+ skb->vlan_tci = re->skb->vlan_tci;
|
|
|
|
|
|
pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
|
|
pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
|
|
length, PCI_DMA_FROMDEVICE);
|
|
length, PCI_DMA_FROMDEVICE);
|
|
|
|
+ re->skb->vlan_tci = 0;
|
|
re->skb->rxhash = 0;
|
|
re->skb->rxhash = 0;
|
|
re->skb->ip_summed = CHECKSUM_NONE;
|
|
re->skb->ip_summed = CHECKSUM_NONE;
|
|
skb_put(skb, length);
|
|
skb_put(skb, length);
|
|
@@ -2583,9 +2585,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
|
|
struct sk_buff *skb = NULL;
|
|
struct sk_buff *skb = NULL;
|
|
u16 count = (status & GMR_FS_LEN) >> 16;
|
|
u16 count = (status & GMR_FS_LEN) >> 16;
|
|
|
|
|
|
- if (status & GMR_FS_VLAN)
|
|
|
|
- count -= VLAN_HLEN; /* Account for vlan tag */
|
|
|
|
-
|
|
|
|
netif_printk(sky2, rx_status, KERN_DEBUG, dev,
|
|
netif_printk(sky2, rx_status, KERN_DEBUG, dev,
|
|
"rx slot %u status 0x%x len %d\n",
|
|
"rx slot %u status 0x%x len %d\n",
|
|
sky2->rx_next, status, length);
|
|
sky2->rx_next, status, length);
|
|
@@ -2593,6 +2592,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
|
|
sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
|
|
sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
|
|
prefetch(sky2->rx_ring + sky2->rx_next);
|
|
prefetch(sky2->rx_ring + sky2->rx_next);
|
|
|
|
|
|
|
|
+ if (vlan_tx_tag_present(re->skb))
|
|
|
|
+ count -= VLAN_HLEN; /* Account for vlan tag */
|
|
|
|
+
|
|
/* This chip has hardware problems that generates bogus status.
|
|
/* This chip has hardware problems that generates bogus status.
|
|
* So do only marginal checking and expect higher level protocols
|
|
* So do only marginal checking and expect higher level protocols
|
|
* to handle crap frames.
|
|
* to handle crap frames.
|
|
@@ -2650,11 +2652,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
|
|
}
|
|
}
|
|
|
|
|
|
static inline void sky2_skb_rx(const struct sky2_port *sky2,
|
|
static inline void sky2_skb_rx(const struct sky2_port *sky2,
|
|
- u32 status, struct sk_buff *skb)
|
|
|
|
|
|
+ struct sk_buff *skb)
|
|
{
|
|
{
|
|
- if (status & GMR_FS_VLAN)
|
|
|
|
- __vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
|
|
|
|
-
|
|
|
|
if (skb->ip_summed == CHECKSUM_NONE)
|
|
if (skb->ip_summed == CHECKSUM_NONE)
|
|
netif_receive_skb(skb);
|
|
netif_receive_skb(skb);
|
|
else
|
|
else
|
|
@@ -2708,6 +2707,14 @@ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void sky2_rx_tag(struct sky2_port *sky2, u16 length)
|
|
|
|
+{
|
|
|
|
+ struct sk_buff *skb;
|
|
|
|
+
|
|
|
|
+ skb = sky2->rx_ring[sky2->rx_next].skb;
|
|
|
|
+ __vlan_hwaccel_put_tag(skb, be16_to_cpu(length));
|
|
|
|
+}
|
|
|
|
+
|
|
static void sky2_rx_hash(struct sky2_port *sky2, u32 status)
|
|
static void sky2_rx_hash(struct sky2_port *sky2, u32 status)
|
|
{
|
|
{
|
|
struct sk_buff *skb;
|
|
struct sk_buff *skb;
|
|
@@ -2766,8 +2773,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
|
|
}
|
|
}
|
|
|
|
|
|
skb->protocol = eth_type_trans(skb, dev);
|
|
skb->protocol = eth_type_trans(skb, dev);
|
|
-
|
|
|
|
- sky2_skb_rx(sky2, status, skb);
|
|
|
|
|
|
+ sky2_skb_rx(sky2, skb);
|
|
|
|
|
|
/* Stop after net poll weight */
|
|
/* Stop after net poll weight */
|
|
if (++work_done >= to_do)
|
|
if (++work_done >= to_do)
|
|
@@ -2775,11 +2781,11 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
|
|
break;
|
|
break;
|
|
|
|
|
|
case OP_RXVLAN:
|
|
case OP_RXVLAN:
|
|
- sky2->rx_tag = length;
|
|
|
|
|
|
+ sky2_rx_tag(sky2, length);
|
|
break;
|
|
break;
|
|
|
|
|
|
case OP_RXCHKSVLAN:
|
|
case OP_RXCHKSVLAN:
|
|
- sky2->rx_tag = length;
|
|
|
|
|
|
+ sky2_rx_tag(sky2, length);
|
|
/* fall through */
|
|
/* fall through */
|
|
case OP_RXCHKS:
|
|
case OP_RXCHKS:
|
|
if (likely(dev->features & NETIF_F_RXCSUM))
|
|
if (likely(dev->features & NETIF_F_RXCSUM))
|