2019-02-22 20:14:37

by Parshuram Raju Thombare

[permalink] [raw]
Subject: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed

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

Signed-off-by: Parshuram Thombare <[email protected]>
---
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



2019-02-22 21:41:49

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed

> /* 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

2019-02-23 06:26:09

by Parshuram Raju Thombare

[permalink] [raw]
Subject: RE: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed

>> /* 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

2019-02-25 02:31:45

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed

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 <[email protected]>
> ---

[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

2019-02-25 09:15:46

by Parshuram Raju Thombare

[permalink] [raw]
Subject: RE: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed

>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 <[email protected]>
>> ---
>
>[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

2019-02-25 17:22:10

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed

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 <[email protected]>
>>> ---
>>
>> [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

2019-02-26 09:24:03

by Nicolas Ferre

[permalink] [raw]
Subject: Re: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed

$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 <[email protected]>
>>>> ---
>>>

[..]

>>>>
>>>> - 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

2019-02-26 17:10:39

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 1/3] net: ethernet: add support for PCS and 2.5G speed

From: <[email protected]>
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.