aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;