aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
authorJim Baxter <jim_baxter@mentor.com>2013-04-19 04:10:49 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-25 03:58:26 -0400
commit4c09eed9dc422e980fabdb25434ef68e599b704c (patch)
treea00da8b76aed9cc916649eafdaf9504e27038b03 /drivers/net/ethernet/freescale
parentcf62cb72d63944f4dcc7376efd84959afc9366cb (diff)
net: fec: Enable imx6 enet checksum acceleration.
Enables hardware generation of IP header and protocol specific checksums for transmitted packets. Enabled hardware discarding of received packets with invalid IP header or protocol specific checksums. The feature is enabled by default but can be enabled/disabled by ethtool. Signed-off-by: Fugang Duan <B38611@freescale.com> Signed-off-by: Jim Baxter <jim_baxter@mentor.com> Reviewed-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r--drivers/net/ethernet/freescale/fec.h10
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c100
2 files changed, 106 insertions, 4 deletions
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index eb4372962839..d44f65bac1d4 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -52,6 +52,7 @@
52#define FEC_R_FIFO_RSEM 0x194 /* Receive FIFO section empty threshold */ 52#define FEC_R_FIFO_RSEM 0x194 /* Receive FIFO section empty threshold */
53#define FEC_R_FIFO_RAEM 0x198 /* Receive FIFO almost empty threshold */ 53#define FEC_R_FIFO_RAEM 0x198 /* Receive FIFO almost empty threshold */
54#define FEC_R_FIFO_RAFL 0x19c /* Receive FIFO almost full threshold */ 54#define FEC_R_FIFO_RAFL 0x19c /* Receive FIFO almost full threshold */
55#define FEC_RACC 0x1C4 /* Receive Accelerator function */
55#define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */ 56#define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */
56#define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */ 57#define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */
57 58
@@ -164,9 +165,11 @@ struct bufdesc_ex {
164#define BD_ENET_TX_CSL ((ushort)0x0001) 165#define BD_ENET_TX_CSL ((ushort)0x0001)
165#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */ 166#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */
166 167
167/*enhanced buffer desciptor control/status used by Ethernet transmit*/ 168/*enhanced buffer descriptor control/status used by Ethernet transmit*/
168#define BD_ENET_TX_INT 0x40000000 169#define BD_ENET_TX_INT 0x40000000
169#define BD_ENET_TX_TS 0x20000000 170#define BD_ENET_TX_TS 0x20000000
171#define BD_ENET_TX_PINS 0x10000000
172#define BD_ENET_TX_IINS 0x08000000
170 173
171 174
172/* This device has up to three irqs on some platforms */ 175/* This device has up to three irqs on some platforms */
@@ -190,6 +193,10 @@ struct bufdesc_ex {
190 193
191#define BD_ENET_RX_INT 0x00800000 194#define BD_ENET_RX_INT 0x00800000
192#define BD_ENET_RX_PTP ((ushort)0x0400) 195#define BD_ENET_RX_PTP ((ushort)0x0400)
196#define BD_ENET_RX_ICE 0x00000020
197#define BD_ENET_RX_PCR 0x00000010
198#define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
199#define FLAG_RX_CSUM_ERROR (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
193 200
194/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and 201/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
195 * tx_bd_base always point to the base of the buffer descriptors. The 202 * tx_bd_base always point to the base of the buffer descriptors. The
@@ -247,6 +254,7 @@ struct fec_enet_private {
247 int pause_flag; 254 int pause_flag;
248 255
249 struct napi_struct napi; 256 struct napi_struct napi;
257 int csum_flags;
250 258
251 struct ptp_clock *ptp_clock; 259 struct ptp_clock *ptp_clock;
252 struct ptp_clock_info ptp_caps; 260 struct ptp_clock_info ptp_caps;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 2451ab1b5a83..b9748f14ea78 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -34,6 +34,12 @@
34#include <linux/netdevice.h> 34#include <linux/netdevice.h>
35#include <linux/etherdevice.h> 35#include <linux/etherdevice.h>
36#include <linux/skbuff.h> 36#include <linux/skbuff.h>
37#include <linux/in.h>
38#include <linux/ip.h>
39#include <net/ip.h>
40#include <linux/tcp.h>
41#include <linux/udp.h>
42#include <linux/icmp.h>
37#include <linux/spinlock.h> 43#include <linux/spinlock.h>
38#include <linux/workqueue.h> 44#include <linux/workqueue.h>
39#include <linux/bitops.h> 45#include <linux/bitops.h>
@@ -176,6 +182,11 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
176#define PKT_MINBUF_SIZE 64 182#define PKT_MINBUF_SIZE 64
177#define PKT_MAXBLR_SIZE 1520 183#define PKT_MAXBLR_SIZE 1520
178 184
185/* FEC receive acceleration */
186#define FEC_RACC_IPDIS (1 << 1)
187#define FEC_RACC_PRODIS (1 << 2)
188#define FEC_RACC_OPTIONS (FEC_RACC_IPDIS | FEC_RACC_PRODIS)
189
179/* 190/*
180 * The 5270/5271/5280/5282/532x RX control register also contains maximum frame 191 * The 5270/5271/5280/5282/532x RX control register also contains maximum frame
181 * size bits. Other FEC hardware does not, so we need to take that into 192 * size bits. Other FEC hardware does not, so we need to take that into
@@ -236,6 +247,21 @@ static void *swap_buffer(void *bufaddr, int len)
236 return bufaddr; 247 return bufaddr;
237} 248}
238 249
250static int
251fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)
252{
253 /* Only run for packets requiring a checksum. */
254 if (skb->ip_summed != CHECKSUM_PARTIAL)
255 return 0;
256
257 if (unlikely(skb_cow_head(skb, 0)))
258 return -1;
259
260 *(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) = 0;
261
262 return 0;
263}
264
239static netdev_tx_t 265static netdev_tx_t
240fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) 266fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
241{ 267{
@@ -248,7 +274,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
248 unsigned int index; 274 unsigned int index;
249 275
250 if (!fep->link) { 276 if (!fep->link) {
251 /* Link is down or autonegotiation is in progress. */ 277 /* Link is down or auto-negotiation is in progress. */
252 return NETDEV_TX_BUSY; 278 return NETDEV_TX_BUSY;
253 } 279 }
254 280
@@ -265,6 +291,12 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
265 return NETDEV_TX_BUSY; 291 return NETDEV_TX_BUSY;
266 } 292 }
267 293
294 /* Protocol checksum off-load for TCP and UDP. */
295 if (fec_enet_clear_csum(skb, ndev)) {
296 kfree_skb(skb);
297 return NETDEV_TX_OK;
298 }
299
268 /* Clear all of the status flags */ 300 /* Clear all of the status flags */
269 status &= ~BD_ENET_TX_STATS; 301 status &= ~BD_ENET_TX_STATS;
270 302
@@ -321,8 +353,14 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
321 ebdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT); 353 ebdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT);
322 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 354 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
323 } else { 355 } else {
324
325 ebdp->cbd_esc = BD_ENET_TX_INT; 356 ebdp->cbd_esc = BD_ENET_TX_INT;
357
358 /* Enable protocol checksum flags
359 * We do not bother with the IP Checksum bits as they
360 * are done by the kernel
361 */
362 if (skb->ip_summed == CHECKSUM_PARTIAL)
363 ebdp->cbd_esc |= BD_ENET_TX_PINS;
326 } 364 }
327 } 365 }
328 /* If this was the last BD in the ring, start at the beginning again. */ 366 /* If this was the last BD in the ring, start at the beginning again. */
@@ -402,6 +440,7 @@ fec_restart(struct net_device *ndev, int duplex)
402 const struct platform_device_id *id_entry = 440 const struct platform_device_id *id_entry =
403 platform_get_device_id(fep->pdev); 441 platform_get_device_id(fep->pdev);
404 int i; 442 int i;
443 u32 val;
405 u32 temp_mac[2]; 444 u32 temp_mac[2];
406 u32 rcntl = OPT_FRAME_SIZE | 0x04; 445 u32 rcntl = OPT_FRAME_SIZE | 0x04;
407 u32 ecntl = 0x2; /* ETHEREN */ 446 u32 ecntl = 0x2; /* ETHEREN */
@@ -468,6 +507,14 @@ fec_restart(struct net_device *ndev, int duplex)
468 /* Set MII speed */ 507 /* Set MII speed */
469 writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); 508 writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
470 509
510 /* set RX checksum */
511 val = readl(fep->hwp + FEC_RACC);
512 if (fep->csum_flags & FLAG_RX_CSUM_ENABLED)
513 val |= FEC_RACC_OPTIONS;
514 else
515 val &= ~FEC_RACC_OPTIONS;
516 writel(val, fep->hwp + FEC_RACC);
517
471 /* 518 /*
472 * The phy interface and speed need to get configured 519 * The phy interface and speed need to get configured
473 * differently on enet-mac. 520 * differently on enet-mac.
@@ -525,7 +572,7 @@ fec_restart(struct net_device *ndev, int duplex)
525 fep->phy_dev && fep->phy_dev->pause)) { 572 fep->phy_dev && fep->phy_dev->pause)) {
526 rcntl |= FEC_ENET_FCE; 573 rcntl |= FEC_ENET_FCE;
527 574
528 /* set FIFO thresh hold parameter to reduce overrun */ 575 /* set FIFO threshold parameter to reduce overrun */
529 writel(FEC_ENET_RSEM_V, fep->hwp + FEC_R_FIFO_RSEM); 576 writel(FEC_ENET_RSEM_V, fep->hwp + FEC_R_FIFO_RSEM);
530 writel(FEC_ENET_RSFL_V, fep->hwp + FEC_R_FIFO_RSFL); 577 writel(FEC_ENET_RSFL_V, fep->hwp + FEC_R_FIFO_RSFL);
531 writel(FEC_ENET_RAEM_V, fep->hwp + FEC_R_FIFO_RAEM); 578 writel(FEC_ENET_RAEM_V, fep->hwp + FEC_R_FIFO_RAEM);
@@ -813,6 +860,18 @@ fec_enet_rx(struct net_device *ndev, int budget)
813 spin_unlock_irqrestore(&fep->tmreg_lock, flags); 860 spin_unlock_irqrestore(&fep->tmreg_lock, flags);
814 } 861 }
815 862
863 if (fep->bufdesc_ex &&
864 (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) {
865 struct bufdesc_ex *ebdp =
866 (struct bufdesc_ex *)bdp;
867 if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) {
868 /* don't check it */
869 skb->ip_summed = CHECKSUM_UNNECESSARY;
870 } else {
871 skb_checksum_none_assert(skb);
872 }
873 }
874
816 if (!skb_defer_rx_timestamp(skb)) 875 if (!skb_defer_rx_timestamp(skb))
817 napi_gro_receive(&fep->napi, skb); 876 napi_gro_receive(&fep->napi, skb);
818 } 877 }
@@ -1614,6 +1673,33 @@ static void fec_poll_controller(struct net_device *dev)
1614} 1673}
1615#endif 1674#endif
1616 1675
1676static int fec_set_features(struct net_device *netdev,
1677 netdev_features_t features)
1678{
1679 struct fec_enet_private *fep = netdev_priv(netdev);
1680 netdev_features_t changed = features ^ netdev->features;
1681
1682 netdev->features = features;
1683
1684 /* Receive checksum has been changed */
1685 if (changed & NETIF_F_RXCSUM) {
1686 if (features & NETIF_F_RXCSUM)
1687 fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
1688 else
1689 fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED;
1690
1691 if (netif_running(netdev)) {
1692 fec_stop(netdev);
1693 fec_restart(netdev, fep->phy_dev->duplex);
1694 netif_wake_queue(netdev);
1695 } else {
1696 fec_restart(netdev, fep->phy_dev->duplex);
1697 }
1698 }
1699
1700 return 0;
1701}
1702
1617static const struct net_device_ops fec_netdev_ops = { 1703static const struct net_device_ops fec_netdev_ops = {
1618 .ndo_open = fec_enet_open, 1704 .ndo_open = fec_enet_open,
1619 .ndo_stop = fec_enet_close, 1705 .ndo_stop = fec_enet_close,
@@ -1627,6 +1713,7 @@ static const struct net_device_ops fec_netdev_ops = {
1627#ifdef CONFIG_NET_POLL_CONTROLLER 1713#ifdef CONFIG_NET_POLL_CONTROLLER
1628 .ndo_poll_controller = fec_poll_controller, 1714 .ndo_poll_controller = fec_poll_controller,
1629#endif 1715#endif
1716 .ndo_set_features = fec_set_features,
1630}; 1717};
1631 1718
1632 /* 1719 /*
@@ -1668,6 +1755,13 @@ static int fec_enet_init(struct net_device *ndev)
1668 writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK); 1755 writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
1669 netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT); 1756 netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT);
1670 1757
1758 /* enable hw accelerator */
1759 ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
1760 | NETIF_F_RXCSUM);
1761 ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
1762 | NETIF_F_RXCSUM);
1763 fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
1764
1671 fec_restart(ndev, 0); 1765 fec_restart(ndev, 0);
1672 1766
1673 return 0; 1767 return 0;