Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 369749
b: refs/heads/master
c: 4c09eed
h: refs/heads/master
i:
  369747: 4557b36
v: v3
  • Loading branch information
Jim Baxter authored and David S. Miller committed Apr 25, 2013
1 parent ccac1f9 commit dc99f82
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cf62cb72d63944f4dcc7376efd84959afc9366cb
refs/heads/master: 4c09eed9dc422e980fabdb25434ef68e599b704c
10 changes: 9 additions & 1 deletion trunk/drivers/net/ethernet/freescale/fec.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#define FEC_R_FIFO_RSEM 0x194 /* Receive FIFO section empty threshold */
#define FEC_R_FIFO_RAEM 0x198 /* Receive FIFO almost empty threshold */
#define FEC_R_FIFO_RAFL 0x19c /* Receive FIFO almost full threshold */
#define FEC_RACC 0x1C4 /* Receive Accelerator function */
#define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */
#define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */

Expand Down Expand Up @@ -164,9 +165,11 @@ struct bufdesc_ex {
#define BD_ENET_TX_CSL ((ushort)0x0001)
#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */

/*enhanced buffer desciptor control/status used by Ethernet transmit*/
/*enhanced buffer descriptor control/status used by Ethernet transmit*/
#define BD_ENET_TX_INT 0x40000000
#define BD_ENET_TX_TS 0x20000000
#define BD_ENET_TX_PINS 0x10000000
#define BD_ENET_TX_IINS 0x08000000


/* This device has up to three irqs on some platforms */
Expand All @@ -190,6 +193,10 @@ struct bufdesc_ex {

#define BD_ENET_RX_INT 0x00800000
#define BD_ENET_RX_PTP ((ushort)0x0400)
#define BD_ENET_RX_ICE 0x00000020
#define BD_ENET_RX_PCR 0x00000010
#define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
#define FLAG_RX_CSUM_ERROR (BD_ENET_RX_ICE | BD_ENET_RX_PCR)

/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
* tx_bd_base always point to the base of the buffer descriptors. The
Expand Down Expand Up @@ -247,6 +254,7 @@ struct fec_enet_private {
int pause_flag;

struct napi_struct napi;
int csum_flags;

struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_caps;
Expand Down
100 changes: 97 additions & 3 deletions trunk/drivers/net/ethernet/freescale/fec_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
Expand Down Expand Up @@ -176,6 +182,11 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
#define PKT_MINBUF_SIZE 64
#define PKT_MAXBLR_SIZE 1520

/* FEC receive acceleration */
#define FEC_RACC_IPDIS (1 << 1)
#define FEC_RACC_PRODIS (1 << 2)
#define FEC_RACC_OPTIONS (FEC_RACC_IPDIS | FEC_RACC_PRODIS)

/*
* The 5270/5271/5280/5282/532x RX control register also contains maximum frame
* size bits. Other FEC hardware does not, so we need to take that into
Expand Down Expand Up @@ -236,6 +247,21 @@ static void *swap_buffer(void *bufaddr, int len)
return bufaddr;
}

static int
fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)
{
/* Only run for packets requiring a checksum. */
if (skb->ip_summed != CHECKSUM_PARTIAL)
return 0;

if (unlikely(skb_cow_head(skb, 0)))
return -1;

*(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) = 0;

return 0;
}

static netdev_tx_t
fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
Expand All @@ -248,7 +274,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
unsigned int index;

if (!fep->link) {
/* Link is down or autonegotiation is in progress. */
/* Link is down or auto-negotiation is in progress. */
return NETDEV_TX_BUSY;
}

Expand All @@ -265,6 +291,12 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return NETDEV_TX_BUSY;
}

/* Protocol checksum off-load for TCP and UDP. */
if (fec_enet_clear_csum(skb, ndev)) {
kfree_skb(skb);
return NETDEV_TX_OK;
}

/* Clear all of the status flags */
status &= ~BD_ENET_TX_STATS;

Expand Down Expand Up @@ -321,8 +353,14 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
ebdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT);
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
} else {

ebdp->cbd_esc = BD_ENET_TX_INT;

/* Enable protocol checksum flags
* We do not bother with the IP Checksum bits as they
* are done by the kernel
*/
if (skb->ip_summed == CHECKSUM_PARTIAL)
ebdp->cbd_esc |= BD_ENET_TX_PINS;
}
}
/* If this was the last BD in the ring, start at the beginning again. */
Expand Down Expand Up @@ -402,6 +440,7 @@ fec_restart(struct net_device *ndev, int duplex)
const struct platform_device_id *id_entry =
platform_get_device_id(fep->pdev);
int i;
u32 val;
u32 temp_mac[2];
u32 rcntl = OPT_FRAME_SIZE | 0x04;
u32 ecntl = 0x2; /* ETHEREN */
Expand Down Expand Up @@ -468,6 +507,14 @@ fec_restart(struct net_device *ndev, int duplex)
/* Set MII speed */
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);

/* set RX checksum */
val = readl(fep->hwp + FEC_RACC);
if (fep->csum_flags & FLAG_RX_CSUM_ENABLED)
val |= FEC_RACC_OPTIONS;
else
val &= ~FEC_RACC_OPTIONS;
writel(val, fep->hwp + FEC_RACC);

/*
* The phy interface and speed need to get configured
* differently on enet-mac.
Expand Down Expand Up @@ -525,7 +572,7 @@ fec_restart(struct net_device *ndev, int duplex)
fep->phy_dev && fep->phy_dev->pause)) {
rcntl |= FEC_ENET_FCE;

/* set FIFO thresh hold parameter to reduce overrun */
/* set FIFO threshold parameter to reduce overrun */
writel(FEC_ENET_RSEM_V, fep->hwp + FEC_R_FIFO_RSEM);
writel(FEC_ENET_RSFL_V, fep->hwp + FEC_R_FIFO_RSFL);
writel(FEC_ENET_RAEM_V, fep->hwp + FEC_R_FIFO_RAEM);
Expand Down Expand Up @@ -813,6 +860,18 @@ fec_enet_rx(struct net_device *ndev, int budget)
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
}

if (fep->bufdesc_ex &&
(fep->csum_flags & FLAG_RX_CSUM_ENABLED)) {
struct bufdesc_ex *ebdp =
(struct bufdesc_ex *)bdp;
if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) {
/* don't check it */
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else {
skb_checksum_none_assert(skb);
}
}

if (!skb_defer_rx_timestamp(skb))
napi_gro_receive(&fep->napi, skb);
}
Expand Down Expand Up @@ -1614,6 +1673,33 @@ static void fec_poll_controller(struct net_device *dev)
}
#endif

static int fec_set_features(struct net_device *netdev,
netdev_features_t features)
{
struct fec_enet_private *fep = netdev_priv(netdev);
netdev_features_t changed = features ^ netdev->features;

netdev->features = features;

/* Receive checksum has been changed */
if (changed & NETIF_F_RXCSUM) {
if (features & NETIF_F_RXCSUM)
fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
else
fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED;

if (netif_running(netdev)) {
fec_stop(netdev);
fec_restart(netdev, fep->phy_dev->duplex);
netif_wake_queue(netdev);
} else {
fec_restart(netdev, fep->phy_dev->duplex);
}
}

return 0;
}

static const struct net_device_ops fec_netdev_ops = {
.ndo_open = fec_enet_open,
.ndo_stop = fec_enet_close,
Expand All @@ -1627,6 +1713,7 @@ static const struct net_device_ops fec_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = fec_poll_controller,
#endif
.ndo_set_features = fec_set_features,
};

/*
Expand Down Expand Up @@ -1668,6 +1755,13 @@ static int fec_enet_init(struct net_device *ndev)
writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT);

/* enable hw accelerator */
ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
| NETIF_F_RXCSUM);
ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
| NETIF_F_RXCSUM);
fep->csum_flags |= FLAG_RX_CSUM_ENABLED;

fec_restart(ndev, 0);

return 0;
Expand Down

0 comments on commit dc99f82

Please sign in to comment.