summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2014-03-12 17:41:12 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-10-17 14:35:46 +0100
commit932e908a07bb584119b7aee4280b95adf415f246 (patch)
tree01a3996805459b8ce1284c08df224342fe79e899
parent7528c9d58454de2aa661ab97a62a92c57a49c32a (diff)
net:fec: move skb allocation earlier
Move the skb allocation before we sync the buffer for CPU access. In order to do this, we need to detect whether the packet contains a VLAN header so we can adjust the packet size appropriately. This allows us to tidy the code a little in the following patches. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-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);