netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed
@ 2019-02-22 20:12 Parshuram Thombare
  2019-02-22 21:39 ` Andrew Lunn
  2019-02-25  2:31 ` Florian Fainelli
  0 siblings, 2 replies; 8+ messages in thread
From: Parshuram Thombare @ 2019-02-22 20:12 UTC (permalink / raw)
  To: nicolas.ferre, davem, netdev, andrew, f.fainelli, hkallweit1,
	linux-kernel, rafalc, piotrs, jank, pthombar

This patch add support for PCS (for SGMII interface) and 2.5Gbps MAC
in Cadence ethernet controller driver.

Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
 drivers/net/ethernet/cadence/macb.h      |   20 ++++
 drivers/net/ethernet/cadence/macb_main.c |  154 +++++++++++++++++++++++-------
 2 files changed, 140 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 9bbaad9..bed4ded 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -79,6 +79,7 @@
 #define MACB_RBQPH		0x04D4
 
 /* GEM register offsets. */
+#define GEM_NCR			0x0000 /* Network Control */
 #define GEM_NCFGR		0x0004 /* Network Config */
 #define GEM_USRIO		0x000c /* User IO */
 #define GEM_DMACFG		0x0010 /* DMA Configuration */
@@ -273,6 +274,10 @@
 #define MACB_IRXFCS_OFFSET	19
 #define MACB_IRXFCS_SIZE	1
 
+/* GEM specific NCR bitfields. */
+#define GEM_TWO_PT_FIVE_GIG_OFFSET	29
+#define GEM_TWO_PT_FIVE_GIG_SIZE	1
+
 /* GEM specific NCFGR bitfields. */
 #define GEM_GBE_OFFSET		10 /* Gigabit mode enable */
 #define GEM_GBE_SIZE		1
@@ -463,6 +468,8 @@
 #define GEM_IRQCOR_SIZE				1
 #define GEM_DBWDEF_OFFSET			25
 #define GEM_DBWDEF_SIZE				3
+#define GEM_NO_PCS_OFFSET			0
+#define GEM_NO_PCS_SIZE				1
 
 /* Bitfields in DCFG2. */
 #define GEM_RX_PKT_BUFF_OFFSET			20
@@ -648,6 +655,19 @@
 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE	0x20000000
 #define MACB_CAPS_SG_DISABLED			0x40000000
 #define MACB_CAPS_MACB_IS_GEM			0x80000000
+#define MACB_CAPS_PCS				0x01000000
+#define MACB_CAPS_TWO_PT_FIVE_GIG_SPEED		0x02000000
+
+#define MACB_GEM7010_IDNUM			0x009
+#define MACB_GEM7014_IDNUM			0x107
+#define MACB_GEM7014A_IDNUM			0x207
+#define MACB_GEM7016_IDNUM			0x10a
+#define MACB_GEM7017_IDNUM			0x00a
+#define MACB_GEM7017A_IDNUM			0x20a
+#define MACB_GEM7020_IDNUM			0x003
+#define MACB_GEM7021_IDNUM			0x00c
+#define MACB_GEM7021A_IDNUM			0x20c
+#define MACB_GEM7022_IDNUM			0x00b
 
 /* LSO settings */
 #define MACB_LSO_UFO_ENABLE			0x01
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index f2915f2..4f4f8e5 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -361,26 +361,50 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
  * macb_set_tx_clk() - Set a clock to a new frequency
  * @clk		Pointer to the clock to change
  * @rate	New frequency in Hz
+ * @interafce	Phy interface
  * @dev		Pointer to the struct net_device
  */
-static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
+static void macb_set_tx_clk(struct clk *clk, int speed,
+			    phy_interface_t interface, struct net_device *dev)
 {
 	long ferr, rate, rate_rounded;
 
 	if (!clk)
 		return;
 
-	switch (speed) {
-	case SPEED_10:
+	if (interface == PHY_INTERFACE_MODE_GMII ||
+	    interface == PHY_INTERFACE_MODE_MII) {
+		switch (speed) {
+		case SPEED_10:
 		rate = 2500000;
 		break;
-	case SPEED_100:
+		case SPEED_100:
 		rate = 25000000;
 		break;
-	case SPEED_1000:
+		case SPEED_1000:
 		rate = 125000000;
 		break;
-	default:
+		default:
+		return;
+		}
+	} else if (interface == PHY_INTERFACE_MODE_SGMII) {
+		switch (speed) {
+		case SPEED_10:
+		rate = 1250000;
+		break;
+		case SPEED_100:
+		rate = 12500000;
+		break;
+		case SPEED_1000:
+		rate = 125000000;
+		break;
+		case SPEED_2500:
+		rate = 312500000;
+		break;
+		default:
+		return;
+		}
+	} else {
 		return;
 	}
 
@@ -410,30 +434,49 @@ static void macb_handle_link_change(struct net_device *dev)
 
 	spin_lock_irqsave(&bp->lock, flags);
 
-	if (phydev->link) {
-		if ((bp->speed != phydev->speed) ||
-		    (bp->duplex != phydev->duplex)) {
-			u32 reg;
-
-			reg = macb_readl(bp, NCFGR);
-			reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
-			if (macb_is_gem(bp))
-				reg &= ~GEM_BIT(GBE);
+	if (phydev->link && (bp->speed != phydev->speed ||
+			     bp->duplex != phydev->duplex)) {
+		u32 reg;
 
-			if (phydev->duplex)
-				reg |= MACB_BIT(FD);
+		reg = macb_readl(bp, NCFGR);
+		reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+		if (macb_is_gem(bp))
+			reg &= ~GEM_BIT(GBE);
+		if (phydev->duplex)
+			reg |= MACB_BIT(FD);
+		macb_or_gem_writel(bp, NCFGR, reg);
+
+		if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII &&
+		    (phydev->speed == SPEED_1000 ||
+		     phydev->speed == SPEED_2500)) {
+			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED) {
+				reg = gem_readl(bp, NCR) &
+					~GEM_BIT(TWO_PT_FIVE_GIG);
+				gem_writel(bp, NCR, reg);
+			}
+			gem_writel(bp, NCFGR, GEM_BIT(GBE) |
+					gem_readl(bp, NCFGR));
+			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED &&
+			    phydev->speed == SPEED_2500)
+				gem_writel(bp, NCR, gem_readl(bp, NCR) |
+						GEM_BIT(TWO_PT_FIVE_GIG));
+		} else if (phydev->speed == SPEED_1000) {
+			gem_writel(bp, NCFGR, GEM_BIT(GBE) |
+					gem_readl(bp, NCFGR));
+		} else {
+			if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+				reg = gem_readl(bp, NCFGR);
+				reg &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
+				gem_writel(bp, NCFGR, reg);
+			}
 			if (phydev->speed == SPEED_100)
-				reg |= MACB_BIT(SPD);
-			if (phydev->speed == SPEED_1000 &&
-			    bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
-				reg |= GEM_BIT(GBE);
-
-			macb_or_gem_writel(bp, NCFGR, reg);
-
-			bp->speed = phydev->speed;
-			bp->duplex = phydev->duplex;
-			status_change = 1;
+				macb_writel(bp, NCFGR, MACB_BIT(SPD) |
+					macb_readl(bp, NCFGR));
 		}
+
+		bp->speed = phydev->speed;
+		bp->duplex = phydev->duplex;
+		status_change = 1;
 	}
 
 	if (phydev->link != bp->link) {
@@ -453,7 +496,8 @@ static void macb_handle_link_change(struct net_device *dev)
 			/* Update the TX clock rate if and only if the link is
 			 * up and there has been a link change.
 			 */
-			macb_set_tx_clk(bp->tx_clk, phydev->speed, dev);
+			macb_set_tx_clk(bp->tx_clk, phydev->speed,
+					bp->phy_interface, dev);
 
 			netif_carrier_on(dev);
 			netdev_info(dev, "link up (%d/%s)\n",
@@ -543,10 +587,16 @@ static int macb_mii_probe(struct net_device *dev)
 	}
 
 	/* mask with MAC supported features */
-	if (macb_is_gem(bp) && bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
-		phy_set_max_speed(phydev, SPEED_1000);
-	else
-		phy_set_max_speed(phydev, SPEED_100);
+	if (macb_is_gem(bp)) {
+		linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
+		if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
+			linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+					 phydev->supported);
+	} else {
+		linkmode_copy(phydev->supported, PHY_BASIC_FEATURES);
+	}
+
+	linkmode_copy(phydev->advertising, phydev->supported);
 
 	if (bp->caps & MACB_CAPS_NO_GIGABIT_HALF)
 		phy_remove_link_mode(phydev,
@@ -2217,8 +2267,6 @@ static void macb_init_hw(struct macb *bp)
 	macb_set_hwaddr(bp);
 
 	config = macb_mdc_clk_div(bp);
-	if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
-		config |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
 	config |= MACB_BF(RBOF, NET_IP_ALIGN);	/* Make eth data aligned */
 	config |= MACB_BIT(PAE);		/* PAuse Enable */
 	config |= MACB_BIT(DRFCS);		/* Discard Rx FCS */
@@ -3255,6 +3303,23 @@ static void macb_configure_caps(struct macb *bp,
 		dcfg = gem_readl(bp, DCFG1);
 		if (GEM_BFEXT(IRQCOR, dcfg) == 0)
 			bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
+		if (GEM_BFEXT(NO_PCS, dcfg) == 0)
+			bp->caps |= MACB_CAPS_PCS;
+		switch (MACB_BFEXT(IDNUM, macb_readl(bp, MID))) {
+		case MACB_GEM7016_IDNUM:
+		case MACB_GEM7017_IDNUM:
+		case MACB_GEM7017A_IDNUM:
+		case MACB_GEM7020_IDNUM:
+		case MACB_GEM7021_IDNUM:
+		case MACB_GEM7021A_IDNUM:
+		case MACB_GEM7022_IDNUM:
+		if (bp->caps & MACB_CAPS_PCS)
+			bp->caps |= MACB_CAPS_TWO_PT_FIVE_GIG_SPEED;
+		break;
+
+		default:
+		break;
+		}
 		dcfg = gem_readl(bp, DCFG2);
 		if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
 			bp->caps |= MACB_CAPS_FIFO_MODE;
@@ -4110,7 +4175,28 @@ static int macb_probe(struct platform_device *pdev)
 		else
 			bp->phy_interface = PHY_INTERFACE_MODE_MII;
 	} else {
+		switch (err) {
+		case PHY_INTERFACE_MODE_SGMII:
+		if (bp->caps & MACB_CAPS_PCS) {
+			bp->phy_interface = PHY_INTERFACE_MODE_SGMII;
+			break;
+		}
+		/* Fallthrough */
+
+		default:
+		if (macb_is_gem(bp))
+			err = PHY_INTERFACE_MODE_GMII;
+		else
+			err = PHY_INTERFACE_MODE_MII;
+		/* Fallthrough */
+
+		case PHY_INTERFACE_MODE_GMII:
+		case PHY_INTERFACE_MODE_RGMII:
+		case PHY_INTERFACE_MODE_MII:
+		case PHY_INTERFACE_MODE_RMII:
 		bp->phy_interface = err;
+		break;
+		}
 	}
 
 	/* IP specific init */
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed
  2019-02-22 20:12 [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed Parshuram Thombare
@ 2019-02-22 21:39 ` Andrew Lunn
  2019-02-23  6:24   ` Parshuram Raju Thombare
  2019-02-25  2:31 ` Florian Fainelli
  1 sibling, 1 reply; 8+ messages in thread
From: Andrew Lunn @ 2019-02-22 21:39 UTC (permalink / raw)
  To: Parshuram Thombare
  Cc: nicolas.ferre, davem, netdev, f.fainelli, hkallweit1,
	linux-kernel, rafalc, piotrs, jank

>  	/* mask with MAC supported features */
> -	if (macb_is_gem(bp) && bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
> -		phy_set_max_speed(phydev, SPEED_1000);
> -	else
> -		phy_set_max_speed(phydev, SPEED_100);
> +	if (macb_is_gem(bp)) {
> +		linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
> +		if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
> +			linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
> +					 phydev->supported);
> +	} else {
> +		linkmode_copy(phydev->supported, PHY_BASIC_FEATURES);
> +	}
> +
> +	linkmode_copy(phydev->advertising, phydev->supported);

This is not correct. Just because the MAC can do 2.5G does not mean
the PHY can. So you should not be adding links modes. Also, somebody
might be using a PHY that can do 2.5G with a MAC which can only do 1G.

The correct thing to do is call phy_set_max_speed() with the maximum
speed the MAC can do.

      Andrew

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed
  2019-02-22 21:39 ` Andrew Lunn
@ 2019-02-23  6:24   ` Parshuram Raju Thombare
  0 siblings, 0 replies; 8+ messages in thread
From: Parshuram Raju Thombare @ 2019-02-23  6:24 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: nicolas.ferre, davem, netdev, f.fainelli, hkallweit1,
	linux-kernel, Rafal Ciepiela, Piotr Sroka, Jan Kotas

>>  	/* mask with MAC supported features */
>> -	if (macb_is_gem(bp) && bp->caps &
>MACB_CAPS_GIGABIT_MODE_AVAILABLE)
>> -		phy_set_max_speed(phydev, SPEED_1000);
>> -	else
>> -		phy_set_max_speed(phydev, SPEED_100);
>> +	if (macb_is_gem(bp)) {
>> +		linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
>> +		if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
>> +
>	linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
>> +					 phydev->supported);
>> +	} else {
>> +		linkmode_copy(phydev->supported, PHY_BASIC_FEATURES);
>> +	}
>> +
>> +	linkmode_copy(phydev->advertising, phydev->supported);
>
>This is not correct. Just because the MAC can do 2.5G does not mean the PHY
>can. So you should not be adding links modes. Also, somebody might be using a
>PHY that can do 2.5G with a MAC which can only do 1G.
>
>The correct thing to do is call phy_set_max_speed() with the maximum speed the
>MAC can do.
Hi Andrew,

Ok, I think this should have been logical AND. I will modify to use phy_set_max_speed() 
instead of directly copying linkmodes.

Regards,
Parshuram Thombare

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed
  2019-02-22 20:12 [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed Parshuram Thombare
  2019-02-22 21:39 ` Andrew Lunn
@ 2019-02-25  2:31 ` Florian Fainelli
  2019-02-25  9:11   ` Parshuram Raju Thombare
  1 sibling, 1 reply; 8+ messages in thread
From: Florian Fainelli @ 2019-02-25  2:31 UTC (permalink / raw)
  To: Parshuram Thombare, nicolas.ferre, davem, netdev, andrew,
	hkallweit1, linux-kernel, rafalc, piotrs, jank

Le 2/22/19 à 12:12 PM, Parshuram Thombare a écrit :
> This patch add support for PCS (for SGMII interface) and 2.5Gbps MAC
> in Cadence ethernet controller driver.

At a high level you don't seem to be making use of PHYLINK so which
2.5Gbps interfaces do you actually support?

> 
> Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
> ---

[snip]

> @@ -361,26 +361,50 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
>   * macb_set_tx_clk() - Set a clock to a new frequency
>   * @clk		Pointer to the clock to change
>   * @rate	New frequency in Hz
> + * @interafce	Phy interface

Typo: @interface and this is an unrelated change.

>   * @dev		Pointer to the struct net_device
>   */
> -static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
> +static void macb_set_tx_clk(struct clk *clk, int speed,
> +			    phy_interface_t interface, struct net_device *dev)
>  {
>  	long ferr, rate, rate_rounded;
>  
>  	if (!clk)
>  		return;
>  
> -	switch (speed) {
> -	case SPEED_10:
> +	if (interface == PHY_INTERFACE_MODE_GMII ||
> +	    interface == PHY_INTERFACE_MODE_MII) {
> +		switch (speed) {
> +		case SPEED_10:>  		rate = 2500000;

You need to add one tab to align rate and break.

>  		break;
> -	case SPEED_100:
> +		case SPEED_100:
>  		rate = 25000000;
>  		break;
> -	case SPEED_1000:
> +		case SPEED_1000:
>  		rate = 125000000;
>  		break;
> -	default:
> +		default:
> +		return;
> +		}
> +	} else if (interface == PHY_INTERFACE_MODE_SGMII) {
> +		switch (speed) {
> +		case SPEED_10:
> +		rate = 1250000;
> +		break;
> +		case SPEED_100:
> +		rate = 12500000;
> +		break;
> +		case SPEED_1000:
> +		rate = 125000000;
> +		break;
> +		case SPEED_2500:
> +		rate = 312500000;
> +		break;
> +		default:
> +		return;

The indentation is broken here and you can greatly simplify this with a
simple function that returns speed * 1250 and does an initial check for
unsupported speeds.

> +		}
> +	} else {
>  		return;
>  	}
>  
> @@ -410,30 +434,49 @@ static void macb_handle_link_change(struct net_device *dev)
>  
>  	spin_lock_irqsave(&bp->lock, flags);
>  
> -	if (phydev->link) {
> -		if ((bp->speed != phydev->speed) ||
> -		    (bp->duplex != phydev->duplex)) {
> -			u32 reg;
> -
> -			reg = macb_readl(bp, NCFGR);
> -			reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
> -			if (macb_is_gem(bp))
> -				reg &= ~GEM_BIT(GBE);
> +	if (phydev->link && (bp->speed != phydev->speed ||
> +			     bp->duplex != phydev->duplex)) {
> +		u32 reg;
>  
> -			if (phydev->duplex)
> -				reg |= MACB_BIT(FD);
> +		reg = macb_readl(bp, NCFGR);
> +		reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
> +		if (macb_is_gem(bp))
> +			reg &= ~GEM_BIT(GBE);
> +		if (phydev->duplex)
> +			reg |= MACB_BIT(FD);
> +		macb_or_gem_writel(bp, NCFGR, reg);
> +
> +		if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII &&
> +		    (phydev->speed == SPEED_1000 ||
> +		     phydev->speed == SPEED_2500)) {
> +			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED) {
> +				reg = gem_readl(bp, NCR) &
> +					~GEM_BIT(TWO_PT_FIVE_GIG);
> +				gem_writel(bp, NCR, reg);
> +			}

If you are making correct use of the capabilities then there is no point
in re-checking them here. If you allowed the MAC to advertise 2.5Gbps
then it is de-facto SGMII capable.

> +			gem_writel(bp, NCFGR, GEM_BIT(GBE) |
> +					gem_readl(bp, NCFGR));
> +			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED &&
> +			    phydev->speed == SPEED_2500)
> +				gem_writel(bp, NCR, gem_readl(bp, NCR) |
> +						GEM_BIT(TWO_PT_FIVE_GIG));
> +		} else if (phydev->speed == SPEED_1000) {
> +			gem_writel(bp, NCFGR, GEM_BIT(GBE) |
> +					gem_readl(bp, NCFGR));
> +		} else {
> +			if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) {
> +				reg = gem_readl(bp, NCFGR);
> +				reg &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
> +				gem_writel(bp, NCFGR, reg);
> +			}
>  			if (phydev->speed == SPEED_100)
> -				reg |= MACB_BIT(SPD);
> -			if (phydev->speed == SPEED_1000 &&
> -			    bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
> -				reg |= GEM_BIT(GBE);
> -
> -			macb_or_gem_writel(bp, NCFGR, reg);
> -
> -			bp->speed = phydev->speed;
> -			bp->duplex = phydev->duplex;
> -			status_change = 1;
> +				macb_writel(bp, NCFGR, MACB_BIT(SPD) |
> +					macb_readl(bp, NCFGR));
>  		}

There is a lot of repetition while setting the GBE bit which always set
based on speed == 1000 irrespective of the mode, so take that part out
of the if () else if () else () clauses.

> +
> +		bp->speed = phydev->speed;
> +		bp->duplex = phydev->duplex;
> +		status_change = 1;
>  	}
>  
>  	if (phydev->link != bp->link) {
> @@ -453,7 +496,8 @@ static void macb_handle_link_change(struct net_device *dev)
>  			/* Update the TX clock rate if and only if the link is
>  			 * up and there has been a link change.
>  			 */
> -			macb_set_tx_clk(bp->tx_clk, phydev->speed, dev);
> +			macb_set_tx_clk(bp->tx_clk, phydev->speed,
> +					bp->phy_interface, dev);
>  
>  			netif_carrier_on(dev);
>  			netdev_info(dev, "link up (%d/%s)\n",
> @@ -543,10 +587,16 @@ static int macb_mii_probe(struct net_device *dev)
>  	}
>  
>  	/* mask with MAC supported features */
> -	if (macb_is_gem(bp) && bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
> -		phy_set_max_speed(phydev, SPEED_1000);
> -	else
> -		phy_set_max_speed(phydev, SPEED_100);
> +	if (macb_is_gem(bp)) {

You have changed the previous logic that also checked for
MACB_CAPS_GIGABIT_MODE_AVAILABLE, why?

> +		linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
> +		if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
> +			linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
> +					 phydev->supported);
> +	} else {
> +		linkmode_copy(phydev->supported, PHY_BASIC_FEATURES);
> +	}
> +
> +	linkmode_copy(phydev->advertising, phydev->supported);
>  
>  	if (bp->caps & MACB_CAPS_NO_GIGABIT_HALF)
>  		phy_remove_link_mode(phydev,
> @@ -2217,8 +2267,6 @@ static void macb_init_hw(struct macb *bp)
>  	macb_set_hwaddr(bp);
>  
>  	config = macb_mdc_clk_div(bp);
> -	if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
> -		config |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
>  	config |= MACB_BF(RBOF, NET_IP_ALIGN);	/* Make eth data aligned */
>  	config |= MACB_BIT(PAE);		/* PAuse Enable */
>  	config |= MACB_BIT(DRFCS);		/* Discard Rx FCS */
> @@ -3255,6 +3303,23 @@ static void macb_configure_caps(struct macb *bp,
>  		dcfg = gem_readl(bp, DCFG1);
>  		if (GEM_BFEXT(IRQCOR, dcfg) == 0)
>  			bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
> +		if (GEM_BFEXT(NO_PCS, dcfg) == 0)
> +			bp->caps |= MACB_CAPS_PCS;
> +		switch (MACB_BFEXT(IDNUM, macb_readl(bp, MID))) {
> +		case MACB_GEM7016_IDNUM:
> +		case MACB_GEM7017_IDNUM:
> +		case MACB_GEM7017A_IDNUM:
> +		case MACB_GEM7020_IDNUM:
> +		case MACB_GEM7021_IDNUM:
> +		case MACB_GEM7021A_IDNUM:
> +		case MACB_GEM7022_IDNUM:
> +		if (bp->caps & MACB_CAPS_PCS)
> +			bp->caps |= MACB_CAPS_TWO_PT_FIVE_GIG_SPEED;
> +		break;
> +
> +		default:
> +		break;
> +		}
>  		dcfg = gem_readl(bp, DCFG2);
>  		if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
>  			bp->caps |= MACB_CAPS_FIFO_MODE;
> @@ -4110,7 +4175,28 @@ static int macb_probe(struct platform_device *pdev)
>  		else
>  			bp->phy_interface = PHY_INTERFACE_MODE_MII;
>  	} else {
> +		switch (err) {
> +		case PHY_INTERFACE_MODE_SGMII:
> +		if (bp->caps & MACB_CAPS_PCS) {
> +			bp->phy_interface = PHY_INTERFACE_MODE_SGMII;
> +			break;
> +		}

If SGMII was selected on a version of the IP that does not support it,
then falling back to GMII or MII does not sound correct, this is a hard
error that must be handled as such.
-- 
Florian

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed
  2019-02-25  2:31 ` Florian Fainelli
@ 2019-02-25  9:11   ` Parshuram Raju Thombare
  2019-02-25 17:21     ` Florian Fainelli
  0 siblings, 1 reply; 8+ messages in thread
From: Parshuram Raju Thombare @ 2019-02-25  9:11 UTC (permalink / raw)
  To: Florian Fainelli, nicolas.ferre, davem, netdev, andrew,
	hkallweit1, linux-kernel, Rafal Ciepiela, Piotr Sroka, Jan Kotas

>Le 2/22/19 à 12:12 PM, Parshuram Thombare a écrit :
>> This patch add support for PCS (for SGMII interface) and 2.5Gbps MAC
>> in Cadence ethernet controller driver.
>
>At a high level you don't seem to be making use of PHYLINK so which 2.5Gbps
>interfaces do you actually support?
>

New ethernet controller have MAC which support 2.5G speed. 
Also there is addition of PCS and SGMII interface.

>>
>> Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
>> ---
>
>[snip]
>
>> @@ -361,26 +361,50 @@ static int macb_mdio_write(struct mii_bus *bus, int
>mii_id, int regnum,
>>   * macb_set_tx_clk() - Set a clock to a new frequency
>>   * @clk		Pointer to the clock to change
>>   * @rate	New frequency in Hz
>> + * @interafce	Phy interface
>
>Typo: @interface and this is an unrelated change.
>
>>   * @dev		Pointer to the struct net_device
>>   */
>> -static void macb_set_tx_clk(struct clk *clk, int speed, struct
>> net_device *dev)
>> +static void macb_set_tx_clk(struct clk *clk, int speed,
>> +			    phy_interface_t interface, struct net_device *dev)
>>  {
>>  	long ferr, rate, rate_rounded;
>>
>>  	if (!clk)
>>  		return;
>>
>> -	switch (speed) {
>> -	case SPEED_10:
>> +	if (interface == PHY_INTERFACE_MODE_GMII ||
>> +	    interface == PHY_INTERFACE_MODE_MII) {
>> +		switch (speed) {
>> +		case SPEED_10:>  		rate = 2500000;
>
>You need to add one tab to align rate and break.

Do you mean a tab each for rate and break lines ?
All switch statements are aligned at a tab.  I am not sure how does case and rate got on same line.

>
>>  		break;
>> -	case SPEED_100:
>> +		case SPEED_100:
>>  		rate = 25000000;
>>  		break;
>> -	case SPEED_1000:
>> +		case SPEED_1000:
>>  		rate = 125000000;
>>  		break;
>> -	default:
>> +		default:
>> +		return;
>> +		}
>> +	} else if (interface == PHY_INTERFACE_MODE_SGMII) {
>> +		switch (speed) {
>> +		case SPEED_10:
>> +		rate = 1250000;
>> +		break;
>> +		case SPEED_100:
>> +		rate = 12500000;
>> +		break;
>> +		case SPEED_1000:
>> +		rate = 125000000;
>> +		break;
>> +		case SPEED_2500:
>> +		rate = 312500000;
>> +		break;
>> +		default:
>> +		return;
>
>The indentation is broken here and you can greatly simplify this with a simple
>function that returns speed * 1250 and does an initial check for unsupported
>speeds.
>

I ran checkpatch.pl and all indentation issues were cleared. But I think having function
is better option, I will make that change.

>> +		}
>> +	} else {
>>  		return;
>>  	}
>>
>> @@ -410,30 +434,49 @@ static void macb_handle_link_change(struct
>> net_device *dev)
>>
>>  	spin_lock_irqsave(&bp->lock, flags);
>>
>> -	if (phydev->link) {
>> -		if ((bp->speed != phydev->speed) ||
>> -		    (bp->duplex != phydev->duplex)) {
>> -			u32 reg;
>> -
>> -			reg = macb_readl(bp, NCFGR);
>> -			reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
>> -			if (macb_is_gem(bp))
>> -				reg &= ~GEM_BIT(GBE);
>> +	if (phydev->link && (bp->speed != phydev->speed ||
>> +			     bp->duplex != phydev->duplex)) {
>> +		u32 reg;
>>
>> -			if (phydev->duplex)
>> -				reg |= MACB_BIT(FD);
>> +		reg = macb_readl(bp, NCFGR);
>> +		reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
>> +		if (macb_is_gem(bp))
>> +			reg &= ~GEM_BIT(GBE);
>> +		if (phydev->duplex)
>> +			reg |= MACB_BIT(FD);
>> +		macb_or_gem_writel(bp, NCFGR, reg);
>> +
>> +		if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII &&
>> +		    (phydev->speed == SPEED_1000 ||
>> +		     phydev->speed == SPEED_2500)) {
>> +			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED) {
>> +				reg = gem_readl(bp, NCR) &
>> +					~GEM_BIT(TWO_PT_FIVE_GIG);
>> +				gem_writel(bp, NCR, reg);
>> +			}
>
>If you are making correct use of the capabilities then there is no point in re-
>checking them here. If you allowed the MAC to advertise 2.5Gbps then it is de-
>facto SGMII capable.

PHY_INTERFACE_MODE_SGMII is selected only on the basis of presence of PCS.
This additional check is to make sure PHY also support 1G/2.5G.

>> +			gem_writel(bp, NCFGR, GEM_BIT(GBE) |
>> +					gem_readl(bp, NCFGR));
>> +			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED
>&&
>> +			    phydev->speed == SPEED_2500)
>> +				gem_writel(bp, NCR, gem_readl(bp, NCR) |
>> +						GEM_BIT(TWO_PT_FIVE_GIG));
>> +		} else if (phydev->speed == SPEED_1000) {
>> +			gem_writel(bp, NCFGR, GEM_BIT(GBE) |
>> +					gem_readl(bp, NCFGR));
>> +		} else {
>> +			if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
>{
>> +				reg = gem_readl(bp, NCFGR);
>> +				reg &= ~(GEM_BIT(SGMIIEN) |
>GEM_BIT(PCSSEL));
>> +				gem_writel(bp, NCFGR, reg);
>> +			}
>>  			if (phydev->speed == SPEED_100)
>> -				reg |= MACB_BIT(SPD);
>> -			if (phydev->speed == SPEED_1000 &&
>> -			    bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
>> -				reg |= GEM_BIT(GBE);
>> -
>> -			macb_or_gem_writel(bp, NCFGR, reg);
>> -
>> -			bp->speed = phydev->speed;
>> -			bp->duplex = phydev->duplex;
>> -			status_change = 1;
>> +				macb_writel(bp, NCFGR, MACB_BIT(SPD) |
>> +					macb_readl(bp, NCFGR));
>>  		}
>
>There is a lot of repetition while setting the GBE bit which always set based on
>speed == 1000 irrespective of the mode, so take that part out of the if () else if ()
>else () clauses.
>

Ok, I will change it.

>> +
>> +		bp->speed = phydev->speed;
>> +		bp->duplex = phydev->duplex;
>> +		status_change = 1;
>>  	}
>>
>>  	if (phydev->link != bp->link) {
>> @@ -453,7 +496,8 @@ static void macb_handle_link_change(struct net_device
>*dev)
>>  			/* Update the TX clock rate if and only if the link is
>>  			 * up and there has been a link change.
>>  			 */
>> -			macb_set_tx_clk(bp->tx_clk, phydev->speed, dev);
>> +			macb_set_tx_clk(bp->tx_clk, phydev->speed,
>> +					bp->phy_interface, dev);
>>
>>  			netif_carrier_on(dev);
>>  			netdev_info(dev, "link up (%d/%s)\n", @@ -543,10
>+587,16 @@ static
>> int macb_mii_probe(struct net_device *dev)
>>  	}
>>
>>  	/* mask with MAC supported features */
>> -	if (macb_is_gem(bp) && bp->caps &
>MACB_CAPS_GIGABIT_MODE_AVAILABLE)
>> -		phy_set_max_speed(phydev, SPEED_1000);
>> -	else
>> -		phy_set_max_speed(phydev, SPEED_100);
>> +	if (macb_is_gem(bp)) {
>
>You have changed the previous logic that also checked for
>MACB_CAPS_GIGABIT_MODE_AVAILABLE, why?

My understanding is all GEM (ID >= 0x2) support GIGABIT mode. 
Was there any other reason for this check ?

>> +		linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
>> +		if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
>> +
>	linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
>> +					 phydev->supported);
>> +	} else {
>> +		linkmode_copy(phydev->supported, PHY_BASIC_FEATURES);
>> +	}
>> +
>> +	linkmode_copy(phydev->advertising, phydev->supported);
>>
>>  	if (bp->caps & MACB_CAPS_NO_GIGABIT_HALF)
>>  		phy_remove_link_mode(phydev,
>> @@ -2217,8 +2267,6 @@ static void macb_init_hw(struct macb *bp)
>>  	macb_set_hwaddr(bp);
>>
>>  	config = macb_mdc_clk_div(bp);
>> -	if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
>> -		config |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
>>  	config |= MACB_BF(RBOF, NET_IP_ALIGN);	/* Make eth data
>aligned */
>>  	config |= MACB_BIT(PAE);		/* PAuse Enable */
>>  	config |= MACB_BIT(DRFCS);		/* Discard Rx FCS */
>> @@ -3255,6 +3303,23 @@ static void macb_configure_caps(struct macb *bp,
>>  		dcfg = gem_readl(bp, DCFG1);
>>  		if (GEM_BFEXT(IRQCOR, dcfg) == 0)
>>  			bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
>> +		if (GEM_BFEXT(NO_PCS, dcfg) == 0)
>> +			bp->caps |= MACB_CAPS_PCS;
>> +		switch (MACB_BFEXT(IDNUM, macb_readl(bp, MID))) {
>> +		case MACB_GEM7016_IDNUM:
>> +		case MACB_GEM7017_IDNUM:
>> +		case MACB_GEM7017A_IDNUM:
>> +		case MACB_GEM7020_IDNUM:
>> +		case MACB_GEM7021_IDNUM:
>> +		case MACB_GEM7021A_IDNUM:
>> +		case MACB_GEM7022_IDNUM:
>> +		if (bp->caps & MACB_CAPS_PCS)
>> +			bp->caps |= MACB_CAPS_TWO_PT_FIVE_GIG_SPEED;
>> +		break;
>> +
>> +		default:
>> +		break;
>> +		}
>>  		dcfg = gem_readl(bp, DCFG2);
>>  		if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF)))
>== 0)
>>  			bp->caps |= MACB_CAPS_FIFO_MODE;
>> @@ -4110,7 +4175,28 @@ static int macb_probe(struct platform_device
>*pdev)
>>  		else
>>  			bp->phy_interface = PHY_INTERFACE_MODE_MII;
>>  	} else {
>> +		switch (err) {
>> +		case PHY_INTERFACE_MODE_SGMII:
>> +		if (bp->caps & MACB_CAPS_PCS) {
>> +			bp->phy_interface = PHY_INTERFACE_MODE_SGMII;
>> +			break;
>> +		}
>
>If SGMII was selected on a version of the IP that does not support it, then falling
>back to GMII or MII does not sound correct, this is a hard error that must be
>handled as such.
>--
>Florian

My intention was to continue (instead of failing) with whatever functionality is available.
Can we have some error message and continue with what is available ?

Regards,
Parshuram Thombare

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed
  2019-02-25  9:11   ` Parshuram Raju Thombare
@ 2019-02-25 17:21     ` Florian Fainelli
  2019-02-26  9:23       ` Nicolas.Ferre
  0 siblings, 1 reply; 8+ messages in thread
From: Florian Fainelli @ 2019-02-25 17:21 UTC (permalink / raw)
  To: Parshuram Raju Thombare, nicolas.ferre, davem, netdev, andrew,
	hkallweit1, linux-kernel, Rafal Ciepiela, Piotr Sroka, Jan Kotas

On 2/25/19 1:11 AM, Parshuram Raju Thombare wrote:
>> Le 2/22/19 à 12:12 PM, Parshuram Thombare a écrit :
>>> This patch add support for PCS (for SGMII interface) and 2.5Gbps MAC
>>> in Cadence ethernet controller driver.
>>
>> At a high level you don't seem to be making use of PHYLINK so which 2.5Gbps
>> interfaces do you actually support?
>>
> 
> New ethernet controller have MAC which support 2.5G speed. 
> Also there is addition of PCS and SGMII interface.

I should have asked this more clearly: have you tested with SFP modules
for instance? If you want to be able to reliably support 2500baseT
and/or 2500baseX with hot plugging of such modules, you need to
implement PHYLINK for that network driver, there is no other way around.

> 
>>>
>>> Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
>>> ---
>>
>> [snip]
>>
>>> @@ -361,26 +361,50 @@ static int macb_mdio_write(struct mii_bus *bus, int
>> mii_id, int regnum,
>>>   * macb_set_tx_clk() - Set a clock to a new frequency
>>>   * @clk		Pointer to the clock to change
>>>   * @rate	New frequency in Hz
>>> + * @interafce	Phy interface
>>
>> Typo: @interface and this is an unrelated change.
>>
>>>   * @dev		Pointer to the struct net_device
>>>   */
>>> -static void macb_set_tx_clk(struct clk *clk, int speed, struct
>>> net_device *dev)
>>> +static void macb_set_tx_clk(struct clk *clk, int speed,
>>> +			    phy_interface_t interface, struct net_device *dev)
>>>  {
>>>  	long ferr, rate, rate_rounded;
>>>
>>>  	if (!clk)
>>>  		return;
>>>
>>> -	switch (speed) {
>>> -	case SPEED_10:
>>> +	if (interface == PHY_INTERFACE_MODE_GMII ||
>>> +	    interface == PHY_INTERFACE_MODE_MII) {
>>> +		switch (speed) {
>>> +		case SPEED_10:>  		rate = 2500000;
>>
>> You need to add one tab to align rate and break.
> 
> Do you mean a tab each for rate and break lines ?
> All switch statements are aligned at a tab.  I am not sure how does case and rate got on same line.

It should look like this:

switch (cond) {
case cond1:
	do_something();
	break;

etc.

> 
>>
>>>  		break;
>>> -	case SPEED_100:
>>> +		case SPEED_100:
>>>  		rate = 25000000;
>>>  		break;
>>> -	case SPEED_1000:
>>> +		case SPEED_1000:
>>>  		rate = 125000000;
>>>  		break;
>>> -	default:
>>> +		default:
>>> +		return;
>>> +		}
>>> +	} else if (interface == PHY_INTERFACE_MODE_SGMII) {
>>> +		switch (speed) {
>>> +		case SPEED_10:
>>> +		rate = 1250000;
>>> +		break;
>>> +		case SPEED_100:
>>> +		rate = 12500000;
>>> +		break;
>>> +		case SPEED_1000:
>>> +		rate = 125000000;
>>> +		break;
>>> +		case SPEED_2500:
>>> +		rate = 312500000;
>>> +		break;
>>> +		default:
>>> +		return;
>>
>> The indentation is broken here and you can greatly simplify this with a simple
>> function that returns speed * 1250 and does an initial check for unsupported
>> speeds.
>>
> 
> I ran checkpatch.pl and all indentation issues were cleared. But I think having function
> is better option, I will make that change.
> 
>>> +		}
>>> +	} else {
>>>  		return;
>>>  	}
>>>
>>> @@ -410,30 +434,49 @@ static void macb_handle_link_change(struct
>>> net_device *dev)
>>>
>>>  	spin_lock_irqsave(&bp->lock, flags);
>>>
>>> -	if (phydev->link) {
>>> -		if ((bp->speed != phydev->speed) ||
>>> -		    (bp->duplex != phydev->duplex)) {
>>> -			u32 reg;
>>> -
>>> -			reg = macb_readl(bp, NCFGR);
>>> -			reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
>>> -			if (macb_is_gem(bp))
>>> -				reg &= ~GEM_BIT(GBE);
>>> +	if (phydev->link && (bp->speed != phydev->speed ||
>>> +			     bp->duplex != phydev->duplex)) {
>>> +		u32 reg;
>>>
>>> -			if (phydev->duplex)
>>> -				reg |= MACB_BIT(FD);
>>> +		reg = macb_readl(bp, NCFGR);
>>> +		reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
>>> +		if (macb_is_gem(bp))
>>> +			reg &= ~GEM_BIT(GBE);
>>> +		if (phydev->duplex)
>>> +			reg |= MACB_BIT(FD);
>>> +		macb_or_gem_writel(bp, NCFGR, reg);
>>> +
>>> +		if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII &&
>>> +		    (phydev->speed == SPEED_1000 ||
>>> +		     phydev->speed == SPEED_2500)) {
>>> +			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED) {
>>> +				reg = gem_readl(bp, NCR) &
>>> +					~GEM_BIT(TWO_PT_FIVE_GIG);
>>> +				gem_writel(bp, NCR, reg);
>>> +			}
>>
>> If you are making correct use of the capabilities then there is no point in re-
>> checking them here. If you allowed the MAC to advertise 2.5Gbps then it is de-
>> facto SGMII capable.
> 
> PHY_INTERFACE_MODE_SGMII is selected only on the basis of presence of PCS.
> This additional check is to make sure PHY also support 1G/2.5G.

My point is that you should never get to that function with
bp->phy_interface == PHY_INTERFACE_MODE_SGMII if you have done necessary
verifications at the time you connect to the PHY. If you let
PHY_INTERFACE_MODE_SGMII go through on a Cadence IP version that does
not have the MACB_CAPS_TWO_PT_FIVE_GIG_SPEED capability bit set, then
this is broken.

> 
>>> +			gem_writel(bp, NCFGR, GEM_BIT(GBE) |
>>> +					gem_readl(bp, NCFGR));
>>> +			if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED
>> &&
>>> +			    phydev->speed == SPEED_2500)
>>> +				gem_writel(bp, NCR, gem_readl(bp, NCR) |
>>> +						GEM_BIT(TWO_PT_FIVE_GIG));
>>> +		} else if (phydev->speed == SPEED_1000) {
>>> +			gem_writel(bp, NCFGR, GEM_BIT(GBE) |
>>> +					gem_readl(bp, NCFGR));
>>> +		} else {
>>> +			if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
>> {
>>> +				reg = gem_readl(bp, NCFGR);
>>> +				reg &= ~(GEM_BIT(SGMIIEN) |
>> GEM_BIT(PCSSEL));
>>> +				gem_writel(bp, NCFGR, reg);
>>> +			}
>>>  			if (phydev->speed == SPEED_100)
>>> -				reg |= MACB_BIT(SPD);
>>> -			if (phydev->speed == SPEED_1000 &&
>>> -			    bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
>>> -				reg |= GEM_BIT(GBE);
>>> -
>>> -			macb_or_gem_writel(bp, NCFGR, reg);
>>> -
>>> -			bp->speed = phydev->speed;
>>> -			bp->duplex = phydev->duplex;
>>> -			status_change = 1;
>>> +				macb_writel(bp, NCFGR, MACB_BIT(SPD) |
>>> +					macb_readl(bp, NCFGR));
>>>  		}
>>
>> There is a lot of repetition while setting the GBE bit which always set based on
>> speed == 1000 irrespective of the mode, so take that part out of the if () else if ()
>> else () clauses.
>>
> 
> Ok, I will change it.
> 
>>> +
>>> +		bp->speed = phydev->speed;
>>> +		bp->duplex = phydev->duplex;
>>> +		status_change = 1;
>>>  	}
>>>
>>>  	if (phydev->link != bp->link) {
>>> @@ -453,7 +496,8 @@ static void macb_handle_link_change(struct net_device
>> *dev)
>>>  			/* Update the TX clock rate if and only if the link is
>>>  			 * up and there has been a link change.
>>>  			 */
>>> -			macb_set_tx_clk(bp->tx_clk, phydev->speed, dev);
>>> +			macb_set_tx_clk(bp->tx_clk, phydev->speed,
>>> +					bp->phy_interface, dev);
>>>
>>>  			netif_carrier_on(dev);
>>>  			netdev_info(dev, "link up (%d/%s)\n", @@ -543,10
>> +587,16 @@ static
>>> int macb_mii_probe(struct net_device *dev)
>>>  	}
>>>
>>>  	/* mask with MAC supported features */
>>> -	if (macb_is_gem(bp) && bp->caps &
>> MACB_CAPS_GIGABIT_MODE_AVAILABLE)
>>> -		phy_set_max_speed(phydev, SPEED_1000);
>>> -	else
>>> -		phy_set_max_speed(phydev, SPEED_100);
>>> +	if (macb_is_gem(bp)) {
>>
>> You have changed the previous logic that also checked for
>> MACB_CAPS_GIGABIT_MODE_AVAILABLE, why?
> 
> My understanding is all GEM (ID >= 0x2) support GIGABIT mode. 
> Was there any other reason for this check ?

Well, if anyone would know, it would be you, I don't work for Cadence
nor have access to the internal IP documentation.

> 
>>> +		linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
>>> +		if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
>>> +
>> 	linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
>>> +					 phydev->supported);
>>> +	} else {
>>> +		linkmode_copy(phydev->supported, PHY_BASIC_FEATURES);
>>> +	}
>>> +
>>> +	linkmode_copy(phydev->advertising, phydev->supported);
>>>
>>>  	if (bp->caps & MACB_CAPS_NO_GIGABIT_HALF)
>>>  		phy_remove_link_mode(phydev,
>>> @@ -2217,8 +2267,6 @@ static void macb_init_hw(struct macb *bp)
>>>  	macb_set_hwaddr(bp);
>>>
>>>  	config = macb_mdc_clk_div(bp);
>>> -	if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
>>> -		config |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
>>>  	config |= MACB_BF(RBOF, NET_IP_ALIGN);	/* Make eth data
>> aligned */
>>>  	config |= MACB_BIT(PAE);		/* PAuse Enable */
>>>  	config |= MACB_BIT(DRFCS);		/* Discard Rx FCS */
>>> @@ -3255,6 +3303,23 @@ static void macb_configure_caps(struct macb *bp,
>>>  		dcfg = gem_readl(bp, DCFG1);
>>>  		if (GEM_BFEXT(IRQCOR, dcfg) == 0)
>>>  			bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
>>> +		if (GEM_BFEXT(NO_PCS, dcfg) == 0)
>>> +			bp->caps |= MACB_CAPS_PCS;
>>> +		switch (MACB_BFEXT(IDNUM, macb_readl(bp, MID))) {
>>> +		case MACB_GEM7016_IDNUM:
>>> +		case MACB_GEM7017_IDNUM:
>>> +		case MACB_GEM7017A_IDNUM:
>>> +		case MACB_GEM7020_IDNUM:
>>> +		case MACB_GEM7021_IDNUM:
>>> +		case MACB_GEM7021A_IDNUM:
>>> +		case MACB_GEM7022_IDNUM:
>>> +		if (bp->caps & MACB_CAPS_PCS)
>>> +			bp->caps |= MACB_CAPS_TWO_PT_FIVE_GIG_SPEED;
>>> +		break;
>>> +
>>> +		default:
>>> +		break;
>>> +		}
>>>  		dcfg = gem_readl(bp, DCFG2);
>>>  		if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF)))
>> == 0)
>>>  			bp->caps |= MACB_CAPS_FIFO_MODE;
>>> @@ -4110,7 +4175,28 @@ static int macb_probe(struct platform_device
>> *pdev)
>>>  		else
>>>  			bp->phy_interface = PHY_INTERFACE_MODE_MII;
>>>  	} else {
>>> +		switch (err) {
>>> +		case PHY_INTERFACE_MODE_SGMII:
>>> +		if (bp->caps & MACB_CAPS_PCS) {
>>> +			bp->phy_interface = PHY_INTERFACE_MODE_SGMII;
>>> +			break;
>>> +		}
>>
>> If SGMII was selected on a version of the IP that does not support it, then falling
>> back to GMII or MII does not sound correct, this is a hard error that must be
>> handled as such.
>> --
>> Florian
> 
> My intention was to continue (instead of failing) with whatever functionality is available.
> Can we have some error message and continue with what is available ?

This is probably not going to help anyone, imagine you incorrectly
specified a 'phy-mode' property in the Device Tree and you have to dig
into the driver in the function that sets the clock rate to find out
what you just defaulted to 1Gbits/GMII for instance. This is not user
friendly at all and will increase the support burden on your end as
well, if SGMII is specified and the IP does not support it, detect it
and return an error, how that propagates, either as a probe failure or
the inability to open the network device, your call.
-- 
Florian

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed
  2019-02-25 17:21     ` Florian Fainelli
@ 2019-02-26  9:23       ` Nicolas.Ferre
  2019-02-26 17:09         ` David Miller
  0 siblings, 1 reply; 8+ messages in thread
From: Nicolas.Ferre @ 2019-02-26  9:23 UTC (permalink / raw)
  To: f.fainelli, pthombar, davem, netdev, andrew, hkallweit1,
	linux-kernel, rafalc, piotrs, jank, Claudiu.Beznea

$subject should begin with "net: macb: "

Parshuram,

Sorry but NACK on the series.

David,

This patch series seem pretty intrusive, so I would like that you wait 
for my explicit ACK before applying even next versions of it.

More comments below...


On 25/02/2019 at 18:21, Florian Fainelli wrote:
> On 2/25/19 1:11 AM, Parshuram Raju Thombare wrote:
>>> Le 2/22/19 à 12:12 PM, Parshuram Thombare a écrit :
>>>> This patch add support for PCS (for SGMII interface) and 2.5Gbps MAC
>>>> in Cadence ethernet controller driver.
>>>
>>> At a high level you don't seem to be making use of PHYLINK so which 2.5Gbps
>>> interfaces do you actually support?
>>>
>>
>> New ethernet controller have MAC which support 2.5G speed.
>> Also there is addition of PCS and SGMII interface.
> 
> I should have asked this more clearly: have you tested with SFP modules
> for instance? If you want to be able to reliably support 2500baseT
> and/or 2500baseX with hot plugging of such modules, you need to
> implement PHYLINK for that network driver, there is no other way around.
> 
>>
>>>>
>>>> Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
>>>> ---
>>>

[..]

>>>>
>>>> -	switch (speed) {
>>>> -	case SPEED_10:
>>>> +	if (interface == PHY_INTERFACE_MODE_GMII ||
>>>> +	    interface == PHY_INTERFACE_MODE_MII) {
>>>> +		switch (speed) {
>>>> +		case SPEED_10:>  		rate = 2500000;
>>>
>>> You need to add one tab to align rate and break.
>>
>> Do you mean a tab each for rate and break lines ?
>> All switch statements are aligned at a tab.  I am not sure how does case and rate got on same line.
> 
> It should look like this:
> 
> switch (cond) {
> case cond1:
> 	do_something();
> 	break;
> 
> etc.

Read the coding style documentation, everything is well explained there.


>>>>   		break;
>>>> -	case SPEED_100:
>>>> +		case SPEED_100:
>>>>   		rate = 25000000;
>>>>   		break;
>>>> -	case SPEED_1000:
>>>> +		case SPEED_1000:
>>>>   		rate = 125000000;
>>>>   		break;
>>>> -	default:
>>>> +		default:
>>>> +		return;
>>>> +		}
>>>> +	} else if (interface == PHY_INTERFACE_MODE_SGMII) {
>>>> +		switch (speed) {
>>>> +		case SPEED_10:
>>>> +		rate = 1250000;
>>>> +		break;
>>>> +		case SPEED_100:
>>>> +		rate = 12500000;
>>>> +		break;
>>>> +		case SPEED_1000:
>>>> +		rate = 125000000;
>>>> +		break;
>>>> +		case SPEED_2500:
>>>> +		rate = 312500000;
>>>> +		break;
>>>> +		default:
>>>> +		return;
>>>
>>> The indentation is broken here and you can greatly simplify this with a simple
>>> function that returns speed * 1250 and does an initial check for unsupported
>>> speeds.
>>>
>>
>> I ran checkpatch.pl and all indentation issues were cleared. But I think having function
>> is better option, I will make that change.
>>
>>>> +		}
>>>> +	} else {
>>>>   		return;
>>>>   	}

[..]

>>>> int macb_mii_probe(struct net_device *dev)
>>>>   	}
>>>>
>>>>   	/* mask with MAC supported features */
>>>> -	if (macb_is_gem(bp) && bp->caps &
>>> MACB_CAPS_GIGABIT_MODE_AVAILABLE)
>>>> -		phy_set_max_speed(phydev, SPEED_1000);
>>>> -	else
>>>> -		phy_set_max_speed(phydev, SPEED_100);
>>>> +	if (macb_is_gem(bp)) {
>>>
>>> You have changed the previous logic that also checked for
>>> MACB_CAPS_GIGABIT_MODE_AVAILABLE, why?
>>
>> My understanding is all GEM (ID >= 0x2) support GIGABIT mode.
>> Was there any other reason for this check ?

We use (ID >= 0x2) and only 10/100 mode on sama5d4/sama5d2 for more than 
5 years, as seen in their respective struct macb_config, weren't you aware?

> Well, if anyone would know, it would be you, I don't work for Cadence
> nor have access to the internal IP documentation.

I agree with Florian, and what you modify makes me feel that the rest of 
the patch might break my use of the Cadence IP in my products. That's 
not a good sign, to say the least.

I'm expecting that Cadence don't break software used by their customers 
on products already deployed on the field.
For next series, I would like that you report that you actually tested 
your changes on older IP revisions and that non-regression tests are 
passed successfully for some of the long time users of this IP (namely 
Microchip/Atmel and Xilinx products).



>>>> +		linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
>>>> +		if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
>>>> +
>>> 	linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
>>>> +					 phydev->supported);
>>>> +	} else {
>>>> +		linkmode_copy(phydev->supported, PHY_BASIC_FEATURES);
>>>> +	}
>>>> +
>>>> +	linkmode_copy(phydev->advertising, phydev->supported);
>>>>
>>>>   	if (bp->caps & MACB_CAPS_NO_GIGABIT_HALF)
>>>>   		phy_remove_link_mode(phydev,
>>>> @@ -2217,8 +2267,6 @@ static void macb_init_hw(struct macb *bp)
>>>>   	macb_set_hwaddr(bp);
>>>>
>>>>   	config = macb_mdc_clk_div(bp);
>>>> -	if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
>>>> -		config |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
>>>>   	config |= MACB_BF(RBOF, NET_IP_ALIGN);	/* Make eth data
>>> aligned */
>>>>   	config |= MACB_BIT(PAE);		/* PAuse Enable */
>>>>   	config |= MACB_BIT(DRFCS);		/* Discard Rx FCS */
>>>> @@ -3255,6 +3303,23 @@ static void macb_configure_caps(struct macb *bp,
>>>>   		dcfg = gem_readl(bp, DCFG1);
>>>>   		if (GEM_BFEXT(IRQCOR, dcfg) == 0)
>>>>   			bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
>>>> +		if (GEM_BFEXT(NO_PCS, dcfg) == 0)
>>>> +			bp->caps |= MACB_CAPS_PCS;
>>>> +		switch (MACB_BFEXT(IDNUM, macb_readl(bp, MID))) {
>>>> +		case MACB_GEM7016_IDNUM:
>>>> +		case MACB_GEM7017_IDNUM:
>>>> +		case MACB_GEM7017A_IDNUM:
>>>> +		case MACB_GEM7020_IDNUM:
>>>> +		case MACB_GEM7021_IDNUM:
>>>> +		case MACB_GEM7021A_IDNUM:
>>>> +		case MACB_GEM7022_IDNUM:
>>>> +		if (bp->caps & MACB_CAPS_PCS)
>>>> +			bp->caps |= MACB_CAPS_TWO_PT_FIVE_GIG_SPEED;
>>>> +		break;
>>>> +
>>>> +		default:
>>>> +		break;
>>>> +		}
>>>>   		dcfg = gem_readl(bp, DCFG2);
>>>>   		if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF)))
>>> == 0)
>>>>   			bp->caps |= MACB_CAPS_FIFO_MODE;
>>>> @@ -4110,7 +4175,28 @@ static int macb_probe(struct platform_device
>>> *pdev)
>>>>   		else
>>>>   			bp->phy_interface = PHY_INTERFACE_MODE_MII;
>>>>   	} else {
>>>> +		switch (err) {
>>>> +		case PHY_INTERFACE_MODE_SGMII:
>>>> +		if (bp->caps & MACB_CAPS_PCS) {
>>>> +			bp->phy_interface = PHY_INTERFACE_MODE_SGMII;
>>>> +			break;
>>>> +		}
>>>
>>> If SGMII was selected on a version of the IP that does not support it, then falling
>>> back to GMII or MII does not sound correct, this is a hard error that must be
>>> handled as such.
>>> --
>>> Florian
>>
>> My intention was to continue (instead of failing) with whatever functionality is available.
>> Can we have some error message and continue with what is available ?
> 
> This is probably not going to help anyone, imagine you incorrectly
> specified a 'phy-mode' property in the Device Tree and you have to dig
> into the driver in the function that sets the clock rate to find out
> what you just defaulted to 1Gbits/GMII for instance. This is not user
> friendly at all and will increase the support burden on your end as
> well, if SGMII is specified and the IP does not support it, detect it
> and return an error, how that propagates, either as a probe failure or
> the inability to open the network device, your call.
> 

Best regards,
-- 
Nicolas Ferre

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed
  2019-02-26  9:23       ` Nicolas.Ferre
@ 2019-02-26 17:09         ` David Miller
  0 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2019-02-26 17:09 UTC (permalink / raw)
  To: Nicolas.Ferre
  Cc: f.fainelli, pthombar, netdev, andrew, hkallweit1, linux-kernel,
	rafalc, piotrs, jank, Claudiu.Beznea

From: <Nicolas.Ferre@microchip.com>
Date: Tue, 26 Feb 2019 09:23:04 +0000

> This patch series seem pretty intrusive, so I would like that you wait 
> for my explicit ACK before applying even next versions of it.

Ok.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-02-26 17:09 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-22 20:12 [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed Parshuram Thombare
2019-02-22 21:39 ` Andrew Lunn
2019-02-23  6:24   ` Parshuram Raju Thombare
2019-02-25  2:31 ` Florian Fainelli
2019-02-25  9:11   ` Parshuram Raju Thombare
2019-02-25 17:21     ` Florian Fainelli
2019-02-26  9:23       ` Nicolas.Ferre
2019-02-26 17:09         ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).