summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2014-03-21 20:31:56 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-10-17 14:35:56 +0100
commit99b261307939e1cb6a96e436ce5dc058cbfacfb1 (patch)
tree573ed16e5313c938e0b568daa6f687550da396d8
parent70d8a8a74a1627de5cd472b8bb0ce5755e5a6eee (diff)
net:fec: move copying receive function out of line
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c149
1 files changed, 72 insertions, 77 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 45ceac59ae61..578f0bdac309 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1007,6 +1007,76 @@ fec_enet_receive(struct sk_buff *skb, union bufdesc_u *bdp, struct net_device *n
}
static void
+fec_enet_receive_copy(unsigned pkt_len, unsigned index, union bufdesc_u *bdp, struct net_device *ndev)
+{
+ struct fec_enet_private *fep = netdev_priv(ndev);
+ struct sk_buff *skb;
+ unsigned char *data;
+ bool vlan_packet_rcvd = false;
+
+ /*
+ * Detect the presence of the VLAN tag, and adjust
+ * the packet length appropriately.
+ */
+ if (fep->flags & FEC_FLAG_RX_VLAN &&
+ bdp->ebd.cbd_esc & BD_ENET_RX_VLAN) {
+ 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++;
+ return;
+ }
+
+ dma_sync_single_for_cpu(&fep->pdev->dev, bdp->bd.cbd_bufaddr,
+ FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+
+ data = fep->rx_skbuff[index]->data;
+
+#ifndef CONFIG_M5272
+ /*
+ * If we have enabled this feature, we need to discard
+ * the two bytes at the beginning of the packet before
+ * copying it.
+ */
+ if (fep->quirks & FEC_QUIRK_RX_SHIFT16) {
+ pkt_len -= 2;
+ data += 2;
+ }
+#endif
+
+ if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
+ swap_buffer(data, pkt_len);
+
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb_put(skb, pkt_len); /* Make room */
+
+ /* If this is a VLAN packet remove the VLAN Tag */
+ if (vlan_packet_rcvd) {
+ struct vlan_hdr *vlan = (struct vlan_hdr *)(data + ETH_HLEN);
+
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+ ntohs(vlan->h_vlan_TCI));
+
+ /* Extract the frame data without the VLAN header. */
+ skb_copy_to_linear_data(skb, data, 2 * ETH_ALEN);
+ skb_copy_to_linear_data_offset(skb, 2 * ETH_ALEN,
+ data + 2 * ETH_ALEN + VLAN_HLEN,
+ pkt_len - 2 * ETH_ALEN);
+ } else {
+ skb_copy_to_linear_data(skb, data, pkt_len);
+ }
+
+ dma_sync_single_for_device(&fep->pdev->dev, bdp->bd.cbd_bufaddr,
+ FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+
+ fec_enet_receive(skb, bdp, ndev);
+}
+
+static void
fec_enet_receive_nocopy(unsigned pkt_len, unsigned index, union bufdesc_u *bdp,
struct net_device *ndev)
{
@@ -1078,7 +1148,6 @@ fec_enet_rx(struct net_device *ndev, int budget)
{
struct fec_enet_private *fep = netdev_priv(ndev);
ushort pkt_len;
- __u8 *data;
int pkt_received = 0;
unsigned int index = fep->rx_next;
@@ -1091,8 +1160,7 @@ fec_enet_rx(struct net_device *ndev, int budget)
*/
do {
union bufdesc_u *bdp = fec_enet_rx_get(index, fep);
- unsigned status, cbd_esc;
- struct sk_buff *skb;
+ unsigned status;
status = bdp->bd.cbd_sc;
if (status & BD_ENET_RX_EMPTY)
@@ -1158,80 +1226,7 @@ fec_enet_rx(struct net_device *ndev, int budget)
if (fec_enet_rx_zerocopy(fep, pkt_len)) {
fec_enet_receive_nocopy(pkt_len, index, bdp, ndev);
} else {
- if (fep->flags & FEC_FLAG_BUFDESC_EX) {
- cbd_esc = bdp->ebd.cbd_esc;
- if (!(fep->flags & FEC_FLAG_RX_VLAN))
- cbd_esc &= ~BD_ENET_RX_VLAN;
- } else {
- 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;
- }
-
- dma_sync_single_for_cpu(&fep->pdev->dev,
- bdp->bd.cbd_bufaddr,
- FEC_ENET_RX_FRSIZE,
- DMA_FROM_DEVICE);
-
- data = fep->rx_skbuff[index]->data;
-
-#ifndef CONFIG_M5272
- /*
- * If we have enabled this feature, we need to discard
- * the two bytes at the beginning of the packet before
- * copying it.
- */
- if (fep->quirks & FEC_QUIRK_RX_SHIFT16) {
- pkt_len -= 2;
- data += 2;
- }
-#endif
-
- if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
- swap_buffer(data, pkt_len);
-
- skb_reserve(skb, NET_IP_ALIGN);
- skb_put(skb, pkt_len); /* Make room */
-
- /* If this is a VLAN packet remove the VLAN Tag */
- if (cbd_esc & BD_ENET_RX_VLAN) {
- /* Push and remove the vlan tag */
- struct vlan_hdr *vlan =
- (struct vlan_hdr *) (data + ETH_HLEN);
-
- __vlan_hwaccel_put_tag(skb,
- htons(ETH_P_8021Q),
- ntohs(vlan->h_vlan_TCI));
-
- /* Extract the frame data without the VLAN header. */
- skb_copy_to_linear_data(skb, data, 2 * ETH_ALEN);
- skb_copy_to_linear_data_offset(skb, 2 * ETH_ALEN,
- data + 2 * ETH_ALEN + VLAN_HLEN,
- pkt_len - 2 * ETH_ALEN);
- } else {
- skb_copy_to_linear_data(skb, data, pkt_len);
- }
-
- dma_sync_single_for_device(&fep->pdev->dev,
- bdp->bd.cbd_bufaddr,
- FEC_ENET_RX_FRSIZE,
- DMA_FROM_DEVICE);
-
- fec_enet_receive(skb, bdp, ndev);
+ fec_enet_receive_copy(pkt_len, index, bdp, ndev);
}
rx_processing_done: