From 6bdb87ef9f95d9986199367acd15103c6918a756 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:03 +0100 Subject: [PATCH 01/15] net: mvpp2: fix a typo in the header This cosmetic patch fixes a typo made in a comment in the Marvell PPv2 Ethernet driver header. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 96e3f0669032..83fb2b03e789 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -549,7 +549,7 @@ #define MVPP2_MAX_TSO_SEGS 300 #define MVPP2_MAX_SKB_DESCS (MVPP2_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS) -/* Dfault number of RXQs in use */ +/* Default number of RXQs in use */ #define MVPP2_DEFAULT_RXQ 1 /* Max number of Rx descriptors */ From 31383c03c03193220132dfedbe9052183fbfd86c Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:04 +0100 Subject: [PATCH 02/15] net: mvpp2: update the port documentation regarding the GoP The Marvell PPv2 port structure stores the GoP id of a given port. This information is specific to PPv2.2, but cannot be used by PPv2.1. Update its comment to denote this specificity. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 83fb2b03e789..9b05fcbc6953 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -803,7 +803,7 @@ struct mvpp2_port { u8 id; /* Index of the port from the "group of ports" complex point - * of view + * of view. This is specific to PPv2.2. */ int gop_id; From 0caa756b7745ff5d2b839ea69be9a1d94f3b779f Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:05 +0100 Subject: [PATCH 03/15] net: mvpp2: fix alignment of MVPP2_GMAC_CONFIG_MII_SPEED definition Cosmetic patch fix the alignment of the MVPP2_GMAC_CONFIG_MII_SPEED macro definition. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 9b05fcbc6953..17ff330cce5f 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -389,7 +389,7 @@ #define MVPP2_GMAC_IN_BAND_AUTONEG BIT(2) #define MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS BIT(3) #define MVPP2_GMAC_IN_BAND_RESTART_AN BIT(4) -#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5) +#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5) #define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6) #define MVPP2_GMAC_AN_SPEED_EN BIT(7) #define MVPP2_GMAC_FC_ADV_EN BIT(9) From 052f7c8bac4440bc5e3b2086e4134055b862453a Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:06 +0100 Subject: [PATCH 04/15] net: mvpp2: a port can be disabled even if we use the link IRQ We had a check in the mvpp2_mac_link_down() function (called by phylink) to avoid disabling the port when link interrupts are used. It turned out the interrupt can still be used with the port disabled. We can thus remove this check. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 6638a3339efc..5a2638b7443a 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4738,13 +4738,6 @@ static void mvpp2_mac_link_down(struct net_device *dev, unsigned int mode, mvpp2_egress_disable(port); mvpp2_ingress_disable(port); - /* When using link interrupts to notify phylink of a MAC state change, - * we do not want the port to be disabled (we want to receive further - * interrupts, to be notified when the port will have a link later). - */ - if (!port->has_phy) - return; - mvpp2_port_disable(port); } From d78a18091f42122d4094e8ddcaeee083198a9c17 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:07 +0100 Subject: [PATCH 05/15] net: mvpp2: reconfiguring the port interface is PPv2.2 specific This patch adds a check on the PPv2 version in-use not to reconfigure the port mode when an interface is updated when using PPv2.1 as the functions called are PPv2.2 specific. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 5a2638b7443a..9467a2258ee0 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4672,16 +4672,14 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, /* Make sure the port is disabled when reconfiguring the mode */ mvpp2_port_disable(port); - if (change_interface) { + if (port->priv->hw_version == MVPP22 && change_interface) { mvpp22_gop_mask_irq(port); - if (port->priv->hw_version == MVPP22) { - port->phy_interface = state->interface; + port->phy_interface = state->interface; - /* Reconfigure the serdes lanes */ - phy_power_off(port->comphy); - mvpp22_mode_reconfigure(port); - } + /* Reconfigure the serdes lanes */ + phy_power_off(port->comphy); + mvpp22_mode_reconfigure(port); } /* mac (re)configuration */ @@ -4695,7 +4693,7 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, if (port->priv->hw_version == MVPP21 && port->flags & MVPP2_F_LOOPBACK) mvpp2_port_loopback_set(port, state); - if (change_interface) + if (port->priv->hw_version == MVPP22 && change_interface) mvpp22_gop_unmask_irq(port); mvpp2_port_enable(port); From 8b318f30ab4ef9bbc1241e6f8c1db366dbd347f2 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:08 +0100 Subject: [PATCH 06/15] net: mvpp2: fix validate for PPv2.1 The Phylink validate function is the Marvell PPv2 driver makes a check on the GoP id. This is valid an has to be done when using PPv2.2 engines but makes no sense when using PPv2.1. The check done when using an RGMII interface makes sure the GoP id is not 0, but this breaks PPv2.1. Fixes it. Fixes: 0fb628f0f250 ("net: mvpp2: fix phylink handling of invalid PHY modes") Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 9467a2258ee0..e7d768381f4f 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4363,7 +4363,7 @@ static void mvpp2_phylink_validate(struct net_device *dev, case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: - if (port->gop_id == 0) + if (port->priv->hw_version == MVPP22 && port->gop_id == 0) goto empty_set; break; default: From 3f13684948aed6214842d6f864d94c9a36080041 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:09 +0100 Subject: [PATCH 07/15] net: mvpp2: fix the computation of the RXQs The patch fixes the computation of RXQs being used by the PPv2 driver, which is set depending on the PPv2 engine version and the queue mode used. There are three cases: - PPv2.1: 1 RXQ per CPU. - PPV2.2 with MVPP2_QDIST_MULTI_MODE: 1 RXQ per CPU. - PPv2.2 with MVPP2_QDIST_SINGLE_MODE: 1 RXQ is shared between the CPUs. The PPv2 engine supports a maximum of 32 queues per port. This patch adds a check so that we do not overstep this maximum. It appeared the calculation was broken for PPv2.1 engines since f8c6ba8424b0, as PPv2.1 ports ended up with a single RXQ while they needed 4. This patch fixes it. Fixes: f8c6ba8424b0 ("net: mvpp2: use only one rx queue per port per CPU") Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 4 ++-- .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 23 ++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 17ff330cce5f..687e011de5ef 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -549,8 +549,8 @@ #define MVPP2_MAX_TSO_SEGS 300 #define MVPP2_MAX_SKB_DESCS (MVPP2_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS) -/* Default number of RXQs in use */ -#define MVPP2_DEFAULT_RXQ 1 +/* Max number of RXQs per port */ +#define MVPP2_PORT_MAX_RXQ 32 /* Max number of Rx descriptors */ #define MVPP2_MAX_RXD_MAX 1024 diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index e7d768381f4f..2a6faddeb95f 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4061,8 +4061,8 @@ static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port, snprintf(irqname, sizeof(irqname), "hif%d", i); if (queue_mode == MVPP2_QDIST_MULTI_MODE) { - v->first_rxq = i * MVPP2_DEFAULT_RXQ; - v->nrxqs = MVPP2_DEFAULT_RXQ; + v->first_rxq = i; + v->nrxqs = 1; } else if (queue_mode == MVPP2_QDIST_SINGLE_MODE && i == (port->nqvecs - 1)) { v->first_rxq = 0; @@ -4155,8 +4155,7 @@ static int mvpp2_port_init(struct mvpp2_port *port) MVPP2_MAX_PORTS * priv->max_port_rxqs) return -EINVAL; - if (port->nrxqs % MVPP2_DEFAULT_RXQ || - port->nrxqs > priv->max_port_rxqs || port->ntxqs > MVPP2_MAX_TXQ) + if (port->nrxqs > priv->max_port_rxqs || port->ntxqs > MVPP2_MAX_TXQ) return -EINVAL; /* Disable port */ @@ -4777,10 +4776,18 @@ static int mvpp2_port_probe(struct platform_device *pdev, } ntxqs = MVPP2_MAX_TXQ; - if (priv->hw_version == MVPP22 && queue_mode == MVPP2_QDIST_MULTI_MODE) - nrxqs = MVPP2_DEFAULT_RXQ * num_possible_cpus(); - else - nrxqs = MVPP2_DEFAULT_RXQ; + if (priv->hw_version == MVPP22 && queue_mode == MVPP2_QDIST_SINGLE_MODE) { + nrxqs = 1; + } else { + /* According to the PPv2.2 datasheet and our experiments on + * PPv2.1, RX queues have an allocation granularity of 4 (when + * more than a single one on PPv2.2). + * Round up to nearest multiple of 4. + */ + nrxqs = (num_possible_cpus() + 3) & ~0x3; + if (nrxqs > MVPP2_PORT_MAX_RXQ) + nrxqs = MVPP2_PORT_MAX_RXQ; + } dev = alloc_etherdev_mqs(sizeof(*port), ntxqs, nrxqs); if (!dev) From 9a490e34069dff988d38327360862a622a149bd0 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:10 +0100 Subject: [PATCH 08/15] net: mvpp2: some AN fields require the link to be down when updated The GMAC configuration helper modifies values in the auto-negotiation register. Some of its values require the port to be forced down when modifying their values. This patches fixes the check made on the bit to be updated in this register, so that the port is forced down when needed. This fix cases where some of those parameters were updated, but not taken into account, such as when using RGMII interfaces. Fixes: d14e078f23cc ("net: marvell: mvpp2: only reprogram what is necessary on mac_config") Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 2a6faddeb95f..908dfe86db92 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4626,9 +4626,19 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, } } +/* Some fields of the auto-negotiation register require the port to be down when + * their value is updated. + */ +#define MVPP2_GMAC_AN_PORT_DOWN_MASK \ + (MVPP2_GMAC_IN_BAND_AUTONEG | \ + MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS | \ + MVPP2_GMAC_CONFIG_MII_SPEED | MVPP2_GMAC_CONFIG_GMII_SPEED | \ + MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_CONFIG_FULL_DUPLEX | \ + MVPP2_GMAC_AN_DUPLEX_EN) + if ((old_ctrl0 ^ ctrl0) & MVPP2_GMAC_PORT_TYPE_MASK || (old_ctrl2 ^ ctrl2) & MVPP2_GMAC_INBAND_AN_MASK || - (old_an ^ an) & MVPP2_GMAC_IN_BAND_AUTONEG) { + (old_an ^ an) & MVPP2_GMAC_AN_PORT_DOWN_MASK) { /* Force link down */ old_an &= ~MVPP2_GMAC_FORCE_LINK_PASS; old_an |= MVPP2_GMAC_FORCE_LINK_DOWN; From 6b10bfc51c494e0a2b2c0871797a1d825da9997c Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:11 +0100 Subject: [PATCH 09/15] net: mvpp2: always disable both MACs when disabling a port This patch modifies the port_disable() helper to always disable both the GMAC and the XLG MAC when called. At boot time we do not know of a port was enabled in the firmware/bootloader, and if so what mode was used (hence which of the two MACs was used). This also help in implementing a logic where all blocks are disabled when not used, and only enabled regarding the current mode used on a given port. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 908dfe86db92..e9cbbe871a1a 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1213,11 +1213,11 @@ static void mvpp2_port_disable(struct mvpp2_port *port) /* Disable & reset should be done separately */ val &= ~MVPP22_XLG_CTRL0_MAC_RESET_DIS; writel(val, port->base + MVPP22_XLG_CTRL0_REG); - } else { - val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); - val &= ~(MVPP2_GMAC_PORT_EN_MASK); - writel(val, port->base + MVPP2_GMAC_CTRL_0_REG); } + + val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); + val &= ~(MVPP2_GMAC_PORT_EN_MASK); + writel(val, port->base + MVPP2_GMAC_CTRL_0_REG); } /* Set IEEE 802.3x Flow Control Xon Packet Transmission Mode */ From f17e70d2586a81d69d7b011e81af0456fe65d658 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:12 +0100 Subject: [PATCH 10/15] net: mvpp2: only update the XLG configuration when needed This patch improves the XLG configuration function, to only update the XLG configuration register when a change is needed. This helps not writing over and over the same XLG configuration each time phylink request the MAC to be configured. This mimics the GMAC configuration function. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index e9cbbe871a1a..b1add5c6b75c 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4505,10 +4505,11 @@ static void mvpp2_mac_an_restart(struct net_device *dev) static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, const struct phylink_link_state *state) { - u32 ctrl0, ctrl4; + u32 old_ctrl0, ctrl0; + u32 old_ctrl4, ctrl4; - ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG); - ctrl4 = readl(port->base + MVPP22_XLG_CTRL4_REG); + old_ctrl0 = ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG); + old_ctrl4 = ctrl4 = readl(port->base + MVPP22_XLG_CTRL4_REG); if (state->pause & MLO_PAUSE_TX) ctrl0 |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN; @@ -4524,8 +4525,10 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC | MVPP22_XLG_CTRL4_EN_IDLE_CHECK; - writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG); - writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG); + if (old_ctrl0 != ctrl0) + writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG); + if (old_ctrl4 != ctrl4) + writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG); } static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, From 1970ee9614d89df88a263f56c3a55d34633fe181 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:13 +0100 Subject: [PATCH 11/15] net: mvpp2: force the XLG MAC link up or down when not using in-band This patch force the XLG MAC link state in the phylink link_up() and link_down() helpers when not using in-band auto-negotiation. This mimics what's already done for the GMAC and follows what's advised in the phylink documentation. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 ++ .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 35 +++++++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 687e011de5ef..c9edeac9ec01 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -430,6 +430,8 @@ #define MVPP22_XLG_CTRL0_REG 0x100 #define MVPP22_XLG_CTRL0_PORT_EN BIT(0) #define MVPP22_XLG_CTRL0_MAC_RESET_DIS BIT(1) +#define MVPP22_XLG_CTRL0_FORCE_LINK_DOWN BIT(2) +#define MVPP22_XLG_CTRL0_FORCE_LINK_PASS BIT(3) #define MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN BIT(7) #define MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN BIT(8) #define MVPP22_XLG_CTRL0_MIB_CNT_DIS BIT(14) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index b1add5c6b75c..ba40b06d3ca3 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4684,6 +4684,7 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, /* Make sure the port is disabled when reconfiguring the mode */ mvpp2_port_disable(port); + if (port->priv->hw_version == MVPP22 && change_interface) { mvpp22_gop_mask_irq(port); @@ -4717,11 +4718,18 @@ static void mvpp2_mac_link_up(struct net_device *dev, unsigned int mode, struct mvpp2_port *port = netdev_priv(dev); u32 val; - if (!phylink_autoneg_inband(mode) && !mvpp2_is_xlg(interface)) { - val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); - val &= ~MVPP2_GMAC_FORCE_LINK_DOWN; - val |= MVPP2_GMAC_FORCE_LINK_PASS; - writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + if (!phylink_autoneg_inband(mode)) { + if (mvpp2_is_xlg(interface)) { + val = readl(port->base + MVPP22_XLG_CTRL0_REG); + val &= ~MVPP22_XLG_CTRL0_FORCE_LINK_DOWN; + val |= MVPP22_XLG_CTRL0_FORCE_LINK_PASS; + writel(val, port->base + MVPP22_XLG_CTRL0_REG); + } else { + val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); + val &= ~MVPP2_GMAC_FORCE_LINK_DOWN; + val |= MVPP2_GMAC_FORCE_LINK_PASS; + writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + } } mvpp2_port_enable(port); @@ -4737,11 +4745,18 @@ static void mvpp2_mac_link_down(struct net_device *dev, unsigned int mode, struct mvpp2_port *port = netdev_priv(dev); u32 val; - if (!phylink_autoneg_inband(mode) && !mvpp2_is_xlg(interface)) { - val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); - val &= ~MVPP2_GMAC_FORCE_LINK_PASS; - val |= MVPP2_GMAC_FORCE_LINK_DOWN; - writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + if (!phylink_autoneg_inband(mode)) { + if (mvpp2_is_xlg(interface)) { + val = readl(port->base + MVPP22_XLG_CTRL0_REG); + val &= ~MVPP22_XLG_CTRL0_FORCE_LINK_PASS; + val |= MVPP22_XLG_CTRL0_FORCE_LINK_DOWN; + writel(val, port->base + MVPP22_XLG_CTRL0_REG); + } else { + val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); + val &= ~MVPP2_GMAC_FORCE_LINK_PASS; + val |= MVPP2_GMAC_FORCE_LINK_DOWN; + writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + } } netif_tx_stop_all_queues(dev); From 649e51d5607b502242c387302523741030354ea5 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:14 +0100 Subject: [PATCH 12/15] net: mvpp2: rework the XLG MAC reset handling This patch reworks the way the XLG MAC is set in reset: the XLG MAC is set in reset at probe time and taken out of this state only when used. The idea is to move forward a situation where only the blocks used are taken out of reset. This also has the effect to handle the GMAC and the XLG MAC in a similar way (the GMAC already is set in reset at boot time). Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index ba40b06d3ca3..c64ddad6b2b3 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1188,8 +1188,7 @@ static void mvpp2_port_enable(struct mvpp2_port *port) /* Only GOP port 0 has an XLG MAC */ if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) { val = readl(port->base + MVPP22_XLG_CTRL0_REG); - val |= MVPP22_XLG_CTRL0_PORT_EN | - MVPP22_XLG_CTRL0_MAC_RESET_DIS; + val |= MVPP22_XLG_CTRL0_PORT_EN; val &= ~MVPP22_XLG_CTRL0_MIB_CNT_DIS; writel(val, port->base + MVPP22_XLG_CTRL0_REG); } else { @@ -1209,10 +1208,6 @@ static void mvpp2_port_disable(struct mvpp2_port *port) val = readl(port->base + MVPP22_XLG_CTRL0_REG); val &= ~MVPP22_XLG_CTRL0_PORT_EN; writel(val, port->base + MVPP22_XLG_CTRL0_REG); - - /* Disable & reset should be done separately */ - val &= ~MVPP22_XLG_CTRL0_MAC_RESET_DIS; - writel(val, port->base + MVPP22_XLG_CTRL0_REG); } val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); @@ -1369,10 +1364,10 @@ static int mvpp2_ethtool_get_sset_count(struct net_device *dev, int sset) return -EOPNOTSUPP; } -static void mvpp2_port_reset(struct mvpp2_port *port) +static void mvpp2_mac_reset_assert(struct mvpp2_port *port) { - u32 val; unsigned int i; + u32 val; /* Read the GOP statistics to reset the hardware counters */ for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++) @@ -1381,6 +1376,12 @@ static void mvpp2_port_reset(struct mvpp2_port *port) val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) | MVPP2_GMAC_PORT_RESET_MASK; writel(val, port->base + MVPP2_GMAC_CTRL_2_REG); + + if (port->priv->hw_version == MVPP22 && port->gop_id == 0) { + val = readl(port->base + MVPP22_XLG_CTRL0_REG) & + ~MVPP22_XLG_CTRL0_MAC_RESET_DIS; + writel(val, port->base + MVPP22_XLG_CTRL0_REG); + } } /* Change maximum receive size of the port */ @@ -4511,6 +4512,8 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, old_ctrl0 = ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG); old_ctrl4 = ctrl4 = readl(port->base + MVPP22_XLG_CTRL4_REG); + ctrl0 |= MVPP22_XLG_CTRL0_MAC_RESET_DIS; + if (state->pause & MLO_PAUSE_TX) ctrl0 |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN; else @@ -4529,6 +4532,12 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG); if (old_ctrl4 != ctrl4) writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG); + + if (!(old_ctrl0 & MVPP22_XLG_CTRL0_MAC_RESET_DIS)) { + while (!(readl(port->base + MVPP22_XLG_CTRL0_REG) & + MVPP22_XLG_CTRL0_MAC_RESET_DIS)) + continue; + } } static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, @@ -4946,7 +4955,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, mvpp2_port_periodic_xon_disable(port); - mvpp2_port_reset(port); + mvpp2_mac_reset_assert(port); port->pcpu = alloc_percpu(struct mvpp2_port_pcpu); if (!port->pcpu) { From 5434e8faf05a3a9514b0a3698245764780be41e0 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:15 +0100 Subject: [PATCH 13/15] net: mvpp2: reset the MACs when reconfiguring a port This patch makes sure both PPv2 MACs (GMAC + XLG MAC) are set in reset while a port is reconfigured. This is done so that we make sure a MAC is in a reset state when not used, as only one of the two will be set out of reset after the port is configured properly. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index c64ddad6b2b3..57a23c96ad4d 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -3136,6 +3136,9 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port) { u32 ctrl3; + /* Set the GMAC & XLG MAC in reset */ + mvpp2_mac_reset_assert(port); + /* comphy reconfiguration */ mvpp22_comphy_init(port); From 7409e66e9eee89f75d6eec6142279146f0999977 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:16 +0100 Subject: [PATCH 14/15] net: mvpp2: set the XPCS and MPCS in reset when not used This patch sets both the XPCS and MPCS blocks in reset when they aren't used. This is done both at boot time and when reconfiguring a port mode. The advantage now is that only the PCS used is set out of reset when the port is configured (10GKR uses the MCPS while RXAUI uses the XPCS). Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 1 + .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 66 ++++++++++++++++--- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index c9edeac9ec01..ff0f4c503f53 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -483,6 +483,7 @@ /* XPCS registers. PPv2.2 only */ #define MVPP22_XPCS_BASE(port) (0x7400 + (port) * 0x1000) #define MVPP22_XPCS_CFG0 0x0 +#define MVPP22_XPCS_CFG0_RESET_DIS BIT(0) #define MVPP22_XPCS_CFG0_PCS_MODE(n) ((n) << 3) #define MVPP22_XPCS_CFG0_ACTIVE_LANE(n) ((n) << 5) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 57a23c96ad4d..18ca3257a3ad 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1015,27 +1015,20 @@ static void mvpp22_gop_init_10gkr(struct mvpp2_port *port) void __iomem *xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id); u32 val; - /* XPCS */ val = readl(xpcs + MVPP22_XPCS_CFG0); val &= ~(MVPP22_XPCS_CFG0_PCS_MODE(0x3) | MVPP22_XPCS_CFG0_ACTIVE_LANE(0x3)); val |= MVPP22_XPCS_CFG0_ACTIVE_LANE(2); writel(val, xpcs + MVPP22_XPCS_CFG0); - /* MPCS */ val = readl(mpcs + MVPP22_MPCS_CTRL); val &= ~MVPP22_MPCS_CTRL_FWD_ERR_CONN; writel(val, mpcs + MVPP22_MPCS_CTRL); val = readl(mpcs + MVPP22_MPCS_CLK_RESET); - val &= ~(MVPP22_MPCS_CLK_RESET_DIV_RATIO(0x7) | MAC_CLK_RESET_MAC | - MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX); + val &= ~MVPP22_MPCS_CLK_RESET_DIV_RATIO(0x7); val |= MVPP22_MPCS_CLK_RESET_DIV_RATIO(1); writel(val, mpcs + MVPP22_MPCS_CLK_RESET); - - val &= ~MVPP22_MPCS_CLK_RESET_DIV_SET; - val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX; - writel(val, mpcs + MVPP22_MPCS_CLK_RESET); } static int mvpp22_gop_init(struct mvpp2_port *port) @@ -1384,6 +1377,57 @@ static void mvpp2_mac_reset_assert(struct mvpp2_port *port) } } +static void mvpp22_pcs_reset_assert(struct mvpp2_port *port) +{ + struct mvpp2 *priv = port->priv; + void __iomem *mpcs, *xpcs; + u32 val; + + if (port->priv->hw_version != MVPP22 || port->gop_id != 0) + return; + + mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id); + xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id); + + val = readl(mpcs + MVPP22_MPCS_CLK_RESET); + val &= ~(MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX); + val |= MVPP22_MPCS_CLK_RESET_DIV_SET; + writel(val, mpcs + MVPP22_MPCS_CLK_RESET); + + val = readl(xpcs + MVPP22_XPCS_CFG0); + writel(val & ~MVPP22_XPCS_CFG0_RESET_DIS, xpcs + MVPP22_XPCS_CFG0); +} + +static void mvpp22_pcs_reset_deassert(struct mvpp2_port *port) +{ + struct mvpp2 *priv = port->priv; + void __iomem *mpcs, *xpcs; + u32 val; + + if (port->priv->hw_version != MVPP22 || port->gop_id != 0) + return; + + mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id); + xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id); + + switch (port->phy_interface) { + case PHY_INTERFACE_MODE_10GKR: + val = readl(mpcs + MVPP22_MPCS_CLK_RESET); + val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | + MAC_CLK_RESET_SD_TX; + val &= ~MVPP22_MPCS_CLK_RESET_DIV_SET; + writel(val, mpcs + MVPP22_MPCS_CLK_RESET); + break; + case PHY_INTERFACE_MODE_XAUI: + case PHY_INTERFACE_MODE_RXAUI: + val = readl(xpcs + MVPP22_XPCS_CFG0); + writel(val | MVPP22_XPCS_CFG0_RESET_DIS, xpcs + MVPP22_XPCS_CFG0); + break; + default: + break; + } +} + /* Change maximum receive size of the port */ static inline void mvpp2_gmac_max_rx_size_set(struct mvpp2_port *port) { @@ -3139,12 +3183,17 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port) /* Set the GMAC & XLG MAC in reset */ mvpp2_mac_reset_assert(port); + /* Set the MPCS and XPCS in reset */ + mvpp22_pcs_reset_assert(port); + /* comphy reconfiguration */ mvpp22_comphy_init(port); /* gop reconfiguration */ mvpp22_gop_init(port); + mvpp22_pcs_reset_deassert(port); + /* Only GOP port 0 has an XLG MAC */ if (port->gop_id == 0) { ctrl3 = readl(port->base + MVPP22_XLG_CTRL3_REG); @@ -4959,6 +5008,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, mvpp2_port_periodic_xon_disable(port); mvpp2_mac_reset_assert(port); + mvpp22_pcs_reset_assert(port); port->pcpu = alloc_percpu(struct mvpp2_port_pcpu); if (!port->pcpu) { From 1f69afce382f2858c825f027ed5afa97ec532f3e Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:17 +0100 Subject: [PATCH 15/15] net: mvpp2: set the GMAC, XLG MAC, XPCS and MPCS in reset when a port is down This patch adds calls in the stop() helper to ensure both MACs and both PCS blocks are set in reset when the user manually sets a port down. This is done so that we have the exact same block reset states at boot time and when a port is set down. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 18ca3257a3ad..25fbed2b8d94 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -3525,6 +3525,9 @@ static int mvpp2_stop(struct net_device *dev) cancel_delayed_work_sync(&port->stats_work); + mvpp2_mac_reset_assert(port); + mvpp22_pcs_reset_assert(port); + return 0; }