diff options
author | Claudiu Manoil <claudiu.manoil@freescale.com> | 2014-03-07 12:42:46 (GMT) |
---|---|---|
committer | Madalin-Cristian Bucur <madalin.bucur@freescale.com> | 2014-03-12 15:35:15 (GMT) |
commit | f98117a17f0104ab5a12eb3c2a41bfd345b6284e (patch) | |
tree | 9e79da6331562b76c3f2226c0df5a42ddee8ca4d /drivers/net/ethernet/freescale/gianfar.h | |
parent | 29c90ee9cb48734299d3ad4e08af70e8501f1bd5 (diff) | |
download | linux-fsl-qoriq-f98117a17f0104ab5a12eb3c2a41bfd345b6284e.tar.xz |
gianfar: Use Single-Queue polling for "fsl,etsec2"
For the "fsl,etsec2" compatible models the driver currently
supports 8 Tx and Rx DMA rings (aka HW queues). However, there
are only 2 pairs of Rx/Tx interrupt lines, as these controllers
are integrated in low power SoCs with 2 CPUs at most. As a result,
there are at most 2 NAPI instances that have to service multiple
Tx and Rx queues for these devices. This complicates the NAPI
polling routine having to iterate over the mutiple Rx/Tx queues
hooked to the same interrupt lines. And there's also an overhead
at HW level, as the controller needs to service all the 8 Tx rings
in a round robin manner. The combined overhead shows up for multi
parallel Tx flows transmitted by the kernel stack, when the driver
usually starts returning NETDEV_TX_BUSY leading to NETDEV WATCHDOG
Tx timeout triggering if the Tx path is congested for too long.
As an alternative, this patch makes the driver support only one
Tx/Rx DMA ring per NAPI instance (per interrupt group or pair
of Tx/Rx interrupt lines) by default. The simplified single queue
polling routine (gfar_poll_sq) will be the default napi poll routine
for the etsec2 devices too. Some adjustments needed to be made to
link the Tx/Rx HW queues with each NAPI instance (2 in this case).
The gfar_poll_sq() is already successfully used by older SQ_SG_MODE
(single interrupt group) controllers.
This patch fixes Tx timeout triggering under heavy Tx traffic load
(i.e. iperf -c -P 8) for the "fsl,etsec2" (currently the only
MQ_MG_MODE devices). There's also a significant memory footprint
reduction by supporting 2 Rx/Tx DMA rings (at most), instead of 8,
for these devices.
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Change-Id: Id9a2f2737ea0d1d0413e68c6401d86d43a7dc237
Reviewed-on: http://git.am.freescale.net:8181/9705
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Madalin-Cristian Bucur <madalin.bucur@freescale.com>
Diffstat (limited to 'drivers/net/ethernet/freescale/gianfar.h')
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.h | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 84e6db8..34b8e38 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -435,7 +435,9 @@ static inline int devfp_register_tx_hook(devfp_hook_t hook) /* This default RIR value directly corresponds * to the 3-bit hash value generated */ -#define DEFAULT_RIR0 0x05397700 +#define DEFAULT_8RXQ_RIR0 0x05397700 +/* Map even hash values to Q0, and odd ones to Q1 */ +#define DEFAULT_2RXQ_RIR0 0x04104100 /* RQFCR register bits */ #define RQFCR_GPI 0x80000000 @@ -930,6 +932,22 @@ enum { MQ_MG_MODE }; +/* GFAR_SQ_POLLING: Single Queue NAPI polling mode + * The driver supports a single pair of RX/Tx queues + * per interrupt group (Rx/Tx int line). MQ_MG mode + * devices have 2 interrupt groups, so the device will + * have a total of 2 Tx and 2 Rx queues in this case. + * GFAR_MQ_POLLING: Multi Queue NAPI polling mode + * The driver supports all the 8 Rx and Tx HW queues + * each queue mapped by the Device Tree to one of + * the 2 interrupt groups. This mode implies significant + * processing overhead (CPU and controller level). + */ +enum gfar_poll_mode { + GFAR_SQ_POLLING = 0, + GFAR_MQ_POLLING +}; + /* * Per TX queue stats */ @@ -1039,17 +1057,20 @@ struct gfar_irqinfo { */ struct gfar_priv_grp { - spinlock_t grplock __attribute__ ((aligned (SMP_CACHE_BYTES))); + spinlock_t grplock __aligned(SMP_CACHE_BYTES); struct napi_struct napi_rx; struct napi_struct napi_tx; - struct gfar_private *priv; struct gfar __iomem *regs; - unsigned int rstat; - unsigned long num_rx_queues; - unsigned long rx_bit_map; + struct gfar_priv_tx_q *tx_queue; + struct gfar_priv_rx_q *rx_queue; unsigned int tstat; + unsigned int rstat; + + struct gfar_private *priv; unsigned long num_tx_queues; unsigned long tx_bit_map; + unsigned long num_rx_queues; + unsigned long rx_bit_map; struct gfar_irqinfo *irqinfo[GFAR_NUM_IRQS]; }; @@ -1079,8 +1100,6 @@ enum gfar_dev_state { * the buffer descriptor determines the actual condition. */ struct gfar_private { - unsigned int num_rx_queues; - struct device *dev; struct net_device *ndev; enum gfar_errata errata; @@ -1088,6 +1107,7 @@ struct gfar_private { u16 uses_rxfcb; u16 padding; + u32 device_flags; /* HW time stamping enabled flag */ int hwts_rx_en; @@ -1098,10 +1118,11 @@ struct gfar_private { struct gfar_priv_grp gfargrp[MAXGROUPS]; unsigned long state; - u32 device_flags; - unsigned int mode; + unsigned short mode; + unsigned short poll_mode; unsigned int num_tx_queues; + unsigned int num_rx_queues; unsigned int num_grps; /* Network Statistics */ |