diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2017-10-11 10:57:51 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-10-12 12:10:02 -0700 |
commit | 32e47ff0cd236d5fcab8ffcce85d1dcded663f61 (patch) | |
tree | 95b7a54b57c0185cb579dbe10502be78dadd015d /drivers/net/dsa/bcm_sf2.c | |
parent | d156576362c07e954dc36e07b0d7b0733a010f7d (diff) | |
download | linux-stable-32e47ff0cd236d5fcab8ffcce85d1dcded663f61.tar.gz linux-stable-32e47ff0cd236d5fcab8ffcce85d1dcded663f61.tar.bz2 linux-stable-32e47ff0cd236d5fcab8ffcce85d1dcded663f61.zip |
net: dsa: bcm_sf2: Turn on ACB at the switch level
Turn on the out of band Advanced Congestion Buffering (ACB) mechanism at
the switch level now that we have properly established the queue mapping
between the switch egress queues and the SYSTEMPORT egress queues. This
allows the switch to correctly backpressure the host system when one of
its queue drops below the configured thresholds.
This is also helping achieve so called "lossless" behavior by adapting
the TX interrupt pacing to the actual speed and capacity of the switch
port.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/bcm_sf2.c')
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 7aecc98d0a18..32025b990437 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -205,6 +205,19 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, if (port == priv->moca_port) bcm_sf2_port_intr_enable(priv, port); + /* Set per-queue pause threshold to 32 */ + core_writel(priv, 32, CORE_TXQ_THD_PAUSE_QN_PORT(port)); + + /* Set ACB threshold to 24 */ + for (i = 0; i < SF2_NUM_EGRESS_QUEUES; i++) { + reg = acb_readl(priv, ACB_QUEUE_CFG(port * + SF2_NUM_EGRESS_QUEUES + i)); + reg &= ~XOFF_THRESHOLD_MASK; + reg |= 24; + acb_writel(priv, reg, ACB_QUEUE_CFG(port * + SF2_NUM_EGRESS_QUEUES + i)); + } + return b53_enable_port(ds, port, phy); } @@ -613,6 +626,20 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, status->pause = 1; } +static void bcm_sf2_enable_acb(struct dsa_switch *ds) +{ + struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); + u32 reg; + + /* Enable ACB globally */ + reg = acb_readl(priv, ACB_CONTROL); + reg |= (ACB_FLUSH_MASK << ACB_FLUSH_SHIFT); + acb_writel(priv, reg, ACB_CONTROL); + reg &= ~(ACB_FLUSH_MASK << ACB_FLUSH_SHIFT); + reg |= ACB_EN | ACB_ALGORITHM; + acb_writel(priv, reg, ACB_CONTROL); +} + static int bcm_sf2_sw_suspend(struct dsa_switch *ds) { struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); @@ -655,6 +682,8 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) bcm_sf2_imp_setup(ds, port); } + bcm_sf2_enable_acb(ds); + return 0; } @@ -766,6 +795,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) } bcm_sf2_sw_configure_vlan(ds); + bcm_sf2_enable_acb(ds); return 0; } |