Commit 25354001 authored by David S. Miller's avatar David S. Miller

Merge branch 'bcmgenet-irq-coalesce'

Florian Fainelli says:

====================
net: bcmgenet: Interrupt coalescing

This patch series adds support for interrupt coalescing for GENET
adapters.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9110fe4a 4a29645b
...@@ -205,6 +205,23 @@ enum dma_reg { ...@@ -205,6 +205,23 @@ enum dma_reg {
DMA_INDEX2RING_5, DMA_INDEX2RING_5,
DMA_INDEX2RING_6, DMA_INDEX2RING_6,
DMA_INDEX2RING_7, DMA_INDEX2RING_7,
DMA_RING0_TIMEOUT,
DMA_RING1_TIMEOUT,
DMA_RING2_TIMEOUT,
DMA_RING3_TIMEOUT,
DMA_RING4_TIMEOUT,
DMA_RING5_TIMEOUT,
DMA_RING6_TIMEOUT,
DMA_RING7_TIMEOUT,
DMA_RING8_TIMEOUT,
DMA_RING9_TIMEOUT,
DMA_RING10_TIMEOUT,
DMA_RING11_TIMEOUT,
DMA_RING12_TIMEOUT,
DMA_RING13_TIMEOUT,
DMA_RING14_TIMEOUT,
DMA_RING15_TIMEOUT,
DMA_RING16_TIMEOUT,
}; };
static const u8 bcmgenet_dma_regs_v3plus[] = { static const u8 bcmgenet_dma_regs_v3plus[] = {
...@@ -216,6 +233,23 @@ static const u8 bcmgenet_dma_regs_v3plus[] = { ...@@ -216,6 +233,23 @@ static const u8 bcmgenet_dma_regs_v3plus[] = {
[DMA_PRIORITY_0] = 0x30, [DMA_PRIORITY_0] = 0x30,
[DMA_PRIORITY_1] = 0x34, [DMA_PRIORITY_1] = 0x34,
[DMA_PRIORITY_2] = 0x38, [DMA_PRIORITY_2] = 0x38,
[DMA_RING0_TIMEOUT] = 0x2C,
[DMA_RING1_TIMEOUT] = 0x30,
[DMA_RING2_TIMEOUT] = 0x34,
[DMA_RING3_TIMEOUT] = 0x38,
[DMA_RING4_TIMEOUT] = 0x3c,
[DMA_RING5_TIMEOUT] = 0x40,
[DMA_RING6_TIMEOUT] = 0x44,
[DMA_RING7_TIMEOUT] = 0x48,
[DMA_RING8_TIMEOUT] = 0x4c,
[DMA_RING9_TIMEOUT] = 0x50,
[DMA_RING10_TIMEOUT] = 0x54,
[DMA_RING11_TIMEOUT] = 0x58,
[DMA_RING12_TIMEOUT] = 0x5c,
[DMA_RING13_TIMEOUT] = 0x60,
[DMA_RING14_TIMEOUT] = 0x64,
[DMA_RING15_TIMEOUT] = 0x68,
[DMA_RING16_TIMEOUT] = 0x6C,
[DMA_INDEX2RING_0] = 0x70, [DMA_INDEX2RING_0] = 0x70,
[DMA_INDEX2RING_1] = 0x74, [DMA_INDEX2RING_1] = 0x74,
[DMA_INDEX2RING_2] = 0x78, [DMA_INDEX2RING_2] = 0x78,
...@@ -235,6 +269,23 @@ static const u8 bcmgenet_dma_regs_v2[] = { ...@@ -235,6 +269,23 @@ static const u8 bcmgenet_dma_regs_v2[] = {
[DMA_PRIORITY_0] = 0x34, [DMA_PRIORITY_0] = 0x34,
[DMA_PRIORITY_1] = 0x38, [DMA_PRIORITY_1] = 0x38,
[DMA_PRIORITY_2] = 0x3C, [DMA_PRIORITY_2] = 0x3C,
[DMA_RING0_TIMEOUT] = 0x2C,
[DMA_RING1_TIMEOUT] = 0x30,
[DMA_RING2_TIMEOUT] = 0x34,
[DMA_RING3_TIMEOUT] = 0x38,
[DMA_RING4_TIMEOUT] = 0x3c,
[DMA_RING5_TIMEOUT] = 0x40,
[DMA_RING6_TIMEOUT] = 0x44,
[DMA_RING7_TIMEOUT] = 0x48,
[DMA_RING8_TIMEOUT] = 0x4c,
[DMA_RING9_TIMEOUT] = 0x50,
[DMA_RING10_TIMEOUT] = 0x54,
[DMA_RING11_TIMEOUT] = 0x58,
[DMA_RING12_TIMEOUT] = 0x5c,
[DMA_RING13_TIMEOUT] = 0x60,
[DMA_RING14_TIMEOUT] = 0x64,
[DMA_RING15_TIMEOUT] = 0x68,
[DMA_RING16_TIMEOUT] = 0x6C,
}; };
static const u8 bcmgenet_dma_regs_v1[] = { static const u8 bcmgenet_dma_regs_v1[] = {
...@@ -245,6 +296,23 @@ static const u8 bcmgenet_dma_regs_v1[] = { ...@@ -245,6 +296,23 @@ static const u8 bcmgenet_dma_regs_v1[] = {
[DMA_PRIORITY_0] = 0x34, [DMA_PRIORITY_0] = 0x34,
[DMA_PRIORITY_1] = 0x38, [DMA_PRIORITY_1] = 0x38,
[DMA_PRIORITY_2] = 0x3C, [DMA_PRIORITY_2] = 0x3C,
[DMA_RING0_TIMEOUT] = 0x2C,
[DMA_RING1_TIMEOUT] = 0x30,
[DMA_RING2_TIMEOUT] = 0x34,
[DMA_RING3_TIMEOUT] = 0x38,
[DMA_RING4_TIMEOUT] = 0x3c,
[DMA_RING5_TIMEOUT] = 0x40,
[DMA_RING6_TIMEOUT] = 0x44,
[DMA_RING7_TIMEOUT] = 0x48,
[DMA_RING8_TIMEOUT] = 0x4c,
[DMA_RING9_TIMEOUT] = 0x50,
[DMA_RING10_TIMEOUT] = 0x54,
[DMA_RING11_TIMEOUT] = 0x58,
[DMA_RING12_TIMEOUT] = 0x5c,
[DMA_RING13_TIMEOUT] = 0x60,
[DMA_RING14_TIMEOUT] = 0x64,
[DMA_RING15_TIMEOUT] = 0x68,
[DMA_RING16_TIMEOUT] = 0x6C,
}; };
/* Set at runtime once bcmgenet version is known */ /* Set at runtime once bcmgenet version is known */
...@@ -498,6 +566,86 @@ static void bcmgenet_set_msglevel(struct net_device *dev, u32 level) ...@@ -498,6 +566,86 @@ static void bcmgenet_set_msglevel(struct net_device *dev, u32 level)
priv->msg_enable = level; priv->msg_enable = level;
} }
static int bcmgenet_get_coalesce(struct net_device *dev,
struct ethtool_coalesce *ec)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
ec->tx_max_coalesced_frames =
bcmgenet_tdma_ring_readl(priv, DESC_INDEX,
DMA_MBUF_DONE_THRESH);
ec->rx_max_coalesced_frames =
bcmgenet_rdma_ring_readl(priv, DESC_INDEX,
DMA_MBUF_DONE_THRESH);
ec->rx_coalesce_usecs =
bcmgenet_rdma_readl(priv, DMA_RING16_TIMEOUT) * 8192 / 1000;
return 0;
}
static int bcmgenet_set_coalesce(struct net_device *dev,
struct ethtool_coalesce *ec)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
unsigned int i;
u32 reg;
/* Base system clock is 125Mhz, DMA timeout is this reference clock
* divided by 1024, which yields roughly 8.192us, our maximum value
* has to fit in the DMA_TIMEOUT_MASK (16 bits)
*/
if (ec->tx_max_coalesced_frames > DMA_INTR_THRESHOLD_MASK ||
ec->tx_max_coalesced_frames == 0 ||
ec->rx_max_coalesced_frames > DMA_INTR_THRESHOLD_MASK ||
ec->rx_coalesce_usecs > (DMA_TIMEOUT_MASK * 8) + 1)
return -EINVAL;
if (ec->rx_coalesce_usecs == 0 && ec->rx_max_coalesced_frames == 0)
return -EINVAL;
/* GENET TDMA hardware does not support a configurable timeout, but will
* always generate an interrupt either after MBDONE packets have been
* transmitted, or when the ring is emtpy.
*/
if (ec->tx_coalesce_usecs || ec->tx_coalesce_usecs_high ||
ec->tx_coalesce_usecs_irq || ec->tx_coalesce_usecs_high ||
ec->tx_coalesce_usecs_low)
return -EOPNOTSUPP;
/* Program all TX queues with the same values, as there is no
* ethtool knob to do coalescing on a per-queue basis
*/
for (i = 0; i < priv->hw_params->tx_queues; i++)
bcmgenet_tdma_ring_writel(priv, i,
ec->tx_max_coalesced_frames,
DMA_MBUF_DONE_THRESH);
bcmgenet_tdma_ring_writel(priv, DESC_INDEX,
ec->tx_max_coalesced_frames,
DMA_MBUF_DONE_THRESH);
for (i = 0; i < priv->hw_params->rx_queues; i++) {
bcmgenet_rdma_ring_writel(priv, i,
ec->rx_max_coalesced_frames,
DMA_MBUF_DONE_THRESH);
reg = bcmgenet_rdma_readl(priv, DMA_RING0_TIMEOUT + i);
reg &= ~DMA_TIMEOUT_MASK;
reg |= DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000, 8192);
bcmgenet_rdma_writel(priv, reg, DMA_RING0_TIMEOUT + i);
}
bcmgenet_rdma_ring_writel(priv, DESC_INDEX,
ec->rx_max_coalesced_frames,
DMA_MBUF_DONE_THRESH);
reg = bcmgenet_rdma_readl(priv, DMA_RING16_TIMEOUT);
reg &= ~DMA_TIMEOUT_MASK;
reg |= DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000, 8192);
bcmgenet_rdma_writel(priv, reg, DMA_RING16_TIMEOUT);
return 0;
}
/* standard ethtool support functions. */ /* standard ethtool support functions. */
enum bcmgenet_stat_type { enum bcmgenet_stat_type {
BCMGENET_STAT_NETDEV = -1, BCMGENET_STAT_NETDEV = -1,
...@@ -844,6 +992,8 @@ static struct ethtool_ops bcmgenet_ethtool_ops = { ...@@ -844,6 +992,8 @@ static struct ethtool_ops bcmgenet_ethtool_ops = {
.get_eee = bcmgenet_get_eee, .get_eee = bcmgenet_get_eee,
.set_eee = bcmgenet_set_eee, .set_eee = bcmgenet_set_eee,
.nway_reset = bcmgenet_nway_reset, .nway_reset = bcmgenet_nway_reset,
.get_coalesce = bcmgenet_get_coalesce,
.set_coalesce = bcmgenet_set_coalesce,
}; };
/* Power down the unimac, based on mode. */ /* Power down the unimac, based on mode. */
......
...@@ -304,13 +304,12 @@ struct bcmgenet_mib_counters { ...@@ -304,13 +304,12 @@ struct bcmgenet_mib_counters {
#define UMAC_IRQ_RXDMA_MBDONE (1 << 13) #define UMAC_IRQ_RXDMA_MBDONE (1 << 13)
#define UMAC_IRQ_RXDMA_PDONE (1 << 14) #define UMAC_IRQ_RXDMA_PDONE (1 << 14)
#define UMAC_IRQ_RXDMA_BDONE (1 << 15) #define UMAC_IRQ_RXDMA_BDONE (1 << 15)
#define UMAC_IRQ_RXDMA_DONE (UMAC_IRQ_RXDMA_PDONE | \ #define UMAC_IRQ_RXDMA_DONE UMAC_IRQ_RXDMA_MBDONE
UMAC_IRQ_RXDMA_BDONE)
#define UMAC_IRQ_TXDMA_MBDONE (1 << 16) #define UMAC_IRQ_TXDMA_MBDONE (1 << 16)
#define UMAC_IRQ_TXDMA_PDONE (1 << 17) #define UMAC_IRQ_TXDMA_PDONE (1 << 17)
#define UMAC_IRQ_TXDMA_BDONE (1 << 18) #define UMAC_IRQ_TXDMA_BDONE (1 << 18)
#define UMAC_IRQ_TXDMA_DONE (UMAC_IRQ_TXDMA_PDONE | \ #define UMAC_IRQ_TXDMA_DONE UMAC_IRQ_TXDMA_MBDONE
UMAC_IRQ_TXDMA_BDONE)
/* Only valid for GENETv3+ */ /* Only valid for GENETv3+ */
#define UMAC_IRQ_MDIO_DONE (1 << 23) #define UMAC_IRQ_MDIO_DONE (1 << 23)
#define UMAC_IRQ_MDIO_ERROR (1 << 24) #define UMAC_IRQ_MDIO_ERROR (1 << 24)
...@@ -386,7 +385,7 @@ struct bcmgenet_mib_counters { ...@@ -386,7 +385,7 @@ struct bcmgenet_mib_counters {
#define DMA_RING_BUFFER_SIZE_MASK 0xFFFF #define DMA_RING_BUFFER_SIZE_MASK 0xFFFF
/* DMA interrupt threshold register */ /* DMA interrupt threshold register */
#define DMA_INTR_THRESHOLD_MASK 0x00FF #define DMA_INTR_THRESHOLD_MASK 0x01FF
/* DMA XON/XOFF register */ /* DMA XON/XOFF register */
#define DMA_XON_THREHOLD_MASK 0xFFFF #define DMA_XON_THREHOLD_MASK 0xFFFF
......
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