From 99b261307939e1cb6a96e436ce5dc058cbfacfb1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 21 Mar 2014 20:31:56 +0000 Subject: net:fec: move copying receive function out of line Signed-off-by: Russell King --- drivers/net/ethernet/freescale/fec_main.c | 149 +++++++++++++++--------------- 1 file 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 @@ -1006,6 +1006,76 @@ fec_enet_receive(struct sk_buff *skb, union bufdesc_u *bdp, struct net_device *n napi_gro_receive(&fep->napi, skb); } +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: -- cgit