Commit dc975382 authored by Frank Li's avatar Frank Li Committed by David S. Miller

net: fec: add napi support to improve proformance

Add napi support

Before this patch

 iperf -s -i 1
 ------------------------------------------------------------
 Server listening on TCP port 5001
 TCP window size: 85.3 KByte (default)
 ------------------------------------------------------------
 [  4] local 10.192.242.153 port 5001 connected with 10.192.242.138 port 50004
 [ ID] Interval       Transfer     Bandwidth
 [  4]  0.0- 1.0 sec  41.2 MBytes   345 Mbits/sec
 [  4]  1.0- 2.0 sec  43.7 MBytes   367 Mbits/sec
 [  4]  2.0- 3.0 sec  42.8 MBytes   359 Mbits/sec
 [  4]  3.0- 4.0 sec  43.7 MBytes   367 Mbits/sec
 [  4]  4.0- 5.0 sec  42.7 MBytes   359 Mbits/sec
 [  4]  5.0- 6.0 sec  43.8 MBytes   367 Mbits/sec
 [  4]  6.0- 7.0 sec  43.0 MBytes   361 Mbits/sec

After this patch
 [  4]  2.0- 3.0 sec  51.6 MBytes   433 Mbits/sec
 [  4]  3.0- 4.0 sec  51.8 MBytes   435 Mbits/sec
 [  4]  4.0- 5.0 sec  52.2 MBytes   438 Mbits/sec
 [  4]  5.0- 6.0 sec  52.1 MBytes   437 Mbits/sec
 [  4]  6.0- 7.0 sec  52.1 MBytes   437 Mbits/sec
 [  4]  7.0- 8.0 sec  52.3 MBytes   439 Mbits/sec
Signed-off-by: default avatarFrank Li <Frank.Li@freescale.com>
Signed-off-by: default avatarFugang Duan <B38611@freescale.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 72aa8e1b
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
#endif #endif
#define DRIVER_NAME "fec" #define DRIVER_NAME "fec"
#define FEC_NAPI_WEIGHT 64
/* Pause frame feild and FIFO threshold */ /* Pause frame feild and FIFO threshold */
#define FEC_ENET_FCE (1 << 5) #define FEC_ENET_FCE (1 << 5)
...@@ -168,6 +169,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); ...@@ -168,6 +169,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ #define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII) #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
/* The FEC stores dest/src/type, data, and checksum for receive packets. /* The FEC stores dest/src/type, data, and checksum for receive packets.
*/ */
...@@ -656,8 +658,8 @@ fec_enet_tx(struct net_device *ndev) ...@@ -656,8 +658,8 @@ fec_enet_tx(struct net_device *ndev)
* not been given to the system, we just set the empty indicator, * not been given to the system, we just set the empty indicator,
* effectively tossing the packet. * effectively tossing the packet.
*/ */
static void static int
fec_enet_rx(struct net_device *ndev) fec_enet_rx(struct net_device *ndev, int budget)
{ {
struct fec_enet_private *fep = netdev_priv(ndev); struct fec_enet_private *fep = netdev_priv(ndev);
const struct platform_device_id *id_entry = const struct platform_device_id *id_entry =
...@@ -667,13 +669,12 @@ fec_enet_rx(struct net_device *ndev) ...@@ -667,13 +669,12 @@ fec_enet_rx(struct net_device *ndev)
struct sk_buff *skb; struct sk_buff *skb;
ushort pkt_len; ushort pkt_len;
__u8 *data; __u8 *data;
int pkt_received = 0;
#ifdef CONFIG_M532x #ifdef CONFIG_M532x
flush_cache_all(); flush_cache_all();
#endif #endif
spin_lock(&fep->hw_lock);
/* First, grab all of the stats for the incoming packet. /* First, grab all of the stats for the incoming packet.
* These get messed up if we get called due to a busy condition. * These get messed up if we get called due to a busy condition.
*/ */
...@@ -681,6 +682,10 @@ fec_enet_rx(struct net_device *ndev) ...@@ -681,6 +682,10 @@ fec_enet_rx(struct net_device *ndev)
while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
if (pkt_received >= budget)
break;
pkt_received++;
/* Since we have allocated space to hold a complete frame, /* Since we have allocated space to hold a complete frame,
* the last indicator should be set. * the last indicator should be set.
*/ */
...@@ -762,7 +767,7 @@ fec_enet_rx(struct net_device *ndev) ...@@ -762,7 +767,7 @@ fec_enet_rx(struct net_device *ndev)
} }
if (!skb_defer_rx_timestamp(skb)) if (!skb_defer_rx_timestamp(skb))
netif_rx(skb); napi_gro_receive(&fep->napi, skb);
} }
bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data, bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
...@@ -796,7 +801,7 @@ fec_enet_rx(struct net_device *ndev) ...@@ -796,7 +801,7 @@ fec_enet_rx(struct net_device *ndev)
} }
fep->cur_rx = bdp; fep->cur_rx = bdp;
spin_unlock(&fep->hw_lock); return pkt_received;
} }
static irqreturn_t static irqreturn_t
...@@ -813,7 +818,13 @@ fec_enet_interrupt(int irq, void *dev_id) ...@@ -813,7 +818,13 @@ fec_enet_interrupt(int irq, void *dev_id)
if (int_events & FEC_ENET_RXF) { if (int_events & FEC_ENET_RXF) {
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
fec_enet_rx(ndev);
/* Disable the RX interrupt */
if (napi_schedule_prep(&fep->napi)) {
writel(FEC_RX_DISABLED_IMASK,
fep->hwp + FEC_IMASK);
__napi_schedule(&fep->napi);
}
} }
/* Transmit OK, or non-fatal error. Update the buffer /* Transmit OK, or non-fatal error. Update the buffer
...@@ -834,7 +845,18 @@ fec_enet_interrupt(int irq, void *dev_id) ...@@ -834,7 +845,18 @@ fec_enet_interrupt(int irq, void *dev_id)
return ret; return ret;
} }
static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
{
struct net_device *ndev = napi->dev;
int pkts = fec_enet_rx(ndev, budget);
struct fec_enet_private *fep = netdev_priv(ndev);
if (pkts < budget) {
napi_complete(napi);
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
}
return pkts;
}
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static void fec_get_mac(struct net_device *ndev) static void fec_get_mac(struct net_device *ndev)
...@@ -1392,6 +1414,8 @@ fec_enet_open(struct net_device *ndev) ...@@ -1392,6 +1414,8 @@ fec_enet_open(struct net_device *ndev)
struct fec_enet_private *fep = netdev_priv(ndev); struct fec_enet_private *fep = netdev_priv(ndev);
int ret; int ret;
napi_enable(&fep->napi);
/* I should reset the ring buffers here, but I don't yet know /* I should reset the ring buffers here, but I don't yet know
* a simple way to do that. * a simple way to do that.
*/ */
...@@ -1604,6 +1628,9 @@ static int fec_enet_init(struct net_device *ndev) ...@@ -1604,6 +1628,9 @@ static int fec_enet_init(struct net_device *ndev)
ndev->netdev_ops = &fec_netdev_ops; ndev->netdev_ops = &fec_netdev_ops;
ndev->ethtool_ops = &fec_enet_ethtool_ops; ndev->ethtool_ops = &fec_enet_ethtool_ops;
writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT);
/* Initialize the receive buffer descriptors. */ /* Initialize the receive buffer descriptors. */
bdp = fep->rx_bd_base; bdp = fep->rx_bd_base;
for (i = 0; i < RX_RING_SIZE; i++) { for (i = 0; i < RX_RING_SIZE; i++) {
......
...@@ -249,6 +249,8 @@ struct fec_enet_private { ...@@ -249,6 +249,8 @@ struct fec_enet_private {
int bufdesc_ex; int bufdesc_ex;
int pause_flag; int pause_flag;
struct napi_struct napi;
struct ptp_clock *ptp_clock; struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_caps; struct ptp_clock_info ptp_caps;
unsigned long last_overflow_check; unsigned long last_overflow_check;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment