summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/fec_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_main.c')
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index c0f166538738..791d6f519256 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -977,7 +977,6 @@ fec_enet_rx(struct net_device *ndev, int budget)
ushort pkt_len;
__u8 *data;
int pkt_received = 0;
- bool vlan_packet_rcvd = false;
u16 vlan_tag;
unsigned int index = fep->rx_next;
@@ -1053,13 +1052,6 @@ fec_enet_rx(struct net_device *ndev, int budget)
pkt_len = bdp->bd.cbd_datlen - 4;
ndev->stats.rx_bytes += pkt_len;
- data = fep->rx_skbuff[index]->data;
- dma_sync_single_for_cpu(&fep->pdev->dev, bdp->bd.cbd_bufaddr,
- FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
-
- if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
- swap_buffer(data, pkt_len);
-
if (fep->flags & FEC_FLAG_BUFDESC_EX) {
cbd_esc = bdp->ebd.cbd_esc;
if (!(fep->flags & FEC_FLAG_RX_VLAN))
@@ -1068,32 +1060,43 @@ fec_enet_rx(struct net_device *ndev, int budget)
cbd_esc = 0;
}
+ /*
+ * Detect the presence of the VLANG tag, and just
+ * the packet length appropriately.
+ */
+ if (cbd_esc & BD_ENET_RX_VLAN)
+ pkt_len -= VLAN_HLEN;
+
+ /* This does 16 byte alignment, exactly what we need. */
+ skb = netdev_alloc_skb(ndev, pkt_len + NET_IP_ALIGN);
+ if (unlikely(!skb)) {
+ ndev->stats.rx_dropped++;
+ goto rx_processing_done;
+ }
+
+ data = fep->rx_skbuff[index]->data;
+ dma_sync_single_for_cpu(&fep->pdev->dev, bdp->bd.cbd_bufaddr,
+ FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+
+ if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
+ swap_buffer(data, pkt_len);
+
/* If this is a VLAN packet remove the VLAN Tag */
- vlan_packet_rcvd = false;
if (cbd_esc & BD_ENET_RX_VLAN) {
/* Push and remove the vlan tag */
struct vlan_hdr *vlan_header =
(struct vlan_hdr *) (data + ETH_HLEN);
vlan_tag = ntohs(vlan_header->h_vlan_TCI);
- pkt_len -= VLAN_HLEN;
-
- vlan_packet_rcvd = true;
}
- /* This does 16 byte alignment, exactly what we need.
- */
- skb = netdev_alloc_skb(ndev, pkt_len + NET_IP_ALIGN);
-
- if (unlikely(!skb)) {
- ndev->stats.rx_dropped++;
- } else {
+ {
int payload_offset = (2 * ETH_ALEN);
skb_reserve(skb, NET_IP_ALIGN);
skb_put(skb, pkt_len); /* Make room */
/* Extract the frame data without the VLAN header. */
skb_copy_to_linear_data(skb, data, (2 * ETH_ALEN));
- if (vlan_packet_rcvd)
+ if (cbd_esc & BD_ENET_RX_VLAN)
payload_offset = (2 * ETH_ALEN) + VLAN_HLEN;
skb_copy_to_linear_data_offset(skb, (2 * ETH_ALEN),
data + payload_offset,
@@ -1116,7 +1119,7 @@ fec_enet_rx(struct net_device *ndev, int budget)
}
/* Handle received VLAN packets */
- if (vlan_packet_rcvd)
+ if (cbd_esc & BD_ENET_RX_VLAN)
__vlan_hwaccel_put_tag(skb,
htons(ETH_P_8021Q),
vlan_tag);