Re: [PATCH net-next 2/2] net: phy: Add PHY Auto/Mdi/Mdix set driver for Microsemi PHYs.
Hi Florian/Andrew, Thank you for review comments. On Thu, Oct 06, 2016 at 04:09:56AM -0700, Florian Fainelli wrote: > EXTERNAL EMAIL > > > On 10/05/2016 12:18 AM, Andrew Lunn wrote: > + phydev->mdix = ETH_TP_MDI_AUTO; > >>> > >>> Humm, interesting. The only other driver supporting mdix is the > >>> Marvell one. It does not do this, it leaves it to its default value of > >>> ETH_TP_MDI_INVALID. It does however interpret ETH_TP_MDI_INVALID as > >>> meaning as ETH_TP_MDI_AUTO. > >>> > >>> There needs to be consistency here. You either need to do the same as > >>> the Marvell driver, or you need to modify the Marvell driver to also > >>> set phydev->mdix to ETH_TP_MDI_AUTO. > >>> > >> In Ethtool two variable i.e. eth_tp_mdix_ctrl, eth_tp_mdix use to update > >> the status. But, driver header is having one variable i.e. mdix. > >> Driver header should also have another variabl like mdix_ctrl. > >> Then, Ethtool can get/set the Auto MDIX/MDI. > >> In case, mdix is not configure with ETH_TP_MDI_AUTO, Ethtool shows error as > >> "setting MDI not supported" > > Agreed, we currently report eth_tp_mdi and eth_tp_mdi_ctrl using > phydev->mdix, but this is too limiting. > > >> > >> Please suggest me if you have any better method to fix this issue. > > > > Maybe we should add a new flag for the .flags member of the > > phy_driver. If PHY_HAS_MDIX is set, the phy core will set phydev->mdix > > to ETH_TP_MDI_AUTO? > > I agree with Raju here, like most other Ethernet drivers, we should > allow PHY drivers to have an eth_tp_mdix_ctrl to indicate what is the > configured MDI setting, and read eth_tp_mdi to indicate what is the > current status, then ethtool can properly differentiate what is going on. > Andrew, Do you want me to add new flag (mdix_ctrl) or keep it as it is? These changes are more relevant for mdix get status function. Do you want to me implement along with mdix get status function? > Raju, Andrew, does that work for you? > -- > Florian --- Thanks, Raju.
Re: [PATCH net-next 2/2] net: phy: Add PHY Auto/Mdi/Mdix set driver for Microsemi PHYs.
Hi Andrew, Thank you for code review and valuable comments. On Wed, Sep 28, 2016 at 10:24:51PM +0200, Andrew Lunn wrote: > EXTERNAL EMAIL > > > > + reg_val = phy_read(phydev, MSCC_PHY_BYPASS_CONTROL); > > + if ((mdix == ETH_TP_MDI) || (mdix == ETH_TP_MDI_X)) { > > + reg_val |= (DISABLE_PAIR_SWAP_CORR_MASK | > > + DISABLE_POLARITY_CORR_MASK | > > + DISABLE_HP_AUTO_MDIX_MASK); > > + } else { > > + reg_val &= ~(DISABLE_PAIR_SWAP_CORR_MASK | > > + DISABLE_POLARITY_CORR_MASK | > > + DISABLE_HP_AUTO_MDIX_MASK); > > + } > > + rc = phy_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg_val); > > + if (rc != 0) > > + goto out_unlock; > > + > > + rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED); > > + if (rc != 0) > > + goto out_unlock; > > + > > + reg_val = phy_read(phydev, MSCC_PHY_EXT_MODE_CNTL); > > + reg_val &= ~(FORCE_MDI_CROSSOVER_MASK); > > + if (mdix == ETH_TP_MDI) > > + reg_val |= FORCE_MDI_CROSSOVER_MDI; > > + else if (mdix == ETH_TP_MDI_X) > > + reg_val |= FORCE_MDI_CROSSOVER_MDIX; > > + rc = phy_write(phydev, MSCC_PHY_EXT_MODE_CNTL, reg_val); > > + if (rc != 0) > > + goto out_unlock; > > + > > + rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD); > > + > > +out_unlock: > > out_unlock seems a bit of an odd name, since you are not unlocking > anything. > Accepted. I will change. > I also wonder if you should try to reset to MSCC_PHY_PAGE_STANDARD in > the error condition? > In case of PHY write error, then PHY page set will also return error. I would like to return error condition, so return after write failure. > > + > > + return rc; > > +} > > + > > static int vsc85xx_wol_set(struct phy_device *phydev, > > struct ethtool_wolinfo *wol) > > { > > @@ -227,6 +281,7 @@ static int vsc85xx_default_config(struct phy_device > > *phydev) > > int rc; > > u16 reg_val; > > > > + phydev->mdix = ETH_TP_MDI_AUTO; > > Humm, interesting. The only other driver supporting mdix is the > Marvell one. It does not do this, it leaves it to its default value of > ETH_TP_MDI_INVALID. It does however interpret ETH_TP_MDI_INVALID as > meaning as ETH_TP_MDI_AUTO. > > There needs to be consistency here. You either need to do the same as > the Marvell driver, or you need to modify the Marvell driver to also > set phydev->mdix to ETH_TP_MDI_AUTO. > > I don't yet know which of these two is the right thing to do. > > Florian? > > Andrew For this comment, I responded in another thread. --- Thanks, Raju.
Re: [PATCH net-next 2/2] net: phy: Add PHY Auto/Mdi/Mdix set driver for Microsemi PHYs.
Hi Florian/Andrew, Thank you for review comments. On Thu, Oct 06, 2016 at 03:57:32AM -0700, Florian Fainelli wrote: > EXTERNAL EMAIL > > > On 09/28/2016 01:24 PM, Andrew Lunn wrote: > >> static int vsc85xx_wol_set(struct phy_device *phydev, > >> struct ethtool_wolinfo *wol) > >> { > >> @@ -227,6 +281,7 @@ static int vsc85xx_default_config(struct phy_device > >> *phydev) > >> int rc; > >> u16 reg_val; > >> > >> +phydev->mdix = ETH_TP_MDI_AUTO; > > > > Humm, interesting. The only other driver supporting mdix is the > > Marvell one. It does not do this, it leaves it to its default value of > > ETH_TP_MDI_INVALID. It does however interpret ETH_TP_MDI_INVALID as > > meaning as ETH_TP_MDI_AUTO. > > > > There needs to be consistency here. You either need to do the same as > > the Marvell driver, or you need to modify the Marvell driver to also > > set phydev->mdix to ETH_TP_MDI_AUTO. > > > > I don't yet know which of these two is the right thing to do. > > > > Florian? > > It's really hard to tell because the other drivers I looked at do not > necessarily seem to be consistent either. Here, if the MDI status is > really auto, then this is the correct value to return, if it is unknown, > it should be ETH_TP_MDI_INVALID. > In mdix get status function, This value will be update as per PHY mdix current status. Shall i configure "phydev->mdix = ETH_TP_MDI_AUTO" as default ? Andrew, do you have any comments? > For the Marvell PHY, it sounds like we should be able to determine what > was configured and return the correct MDI status value > -- > Florian --- Thanks, Raju.
Re: [PATCH net-next 2/2] net: phy: Add PHY Auto/Mdi/Mdix set driver for Microsemi PHYs.
On 10/05/2016 12:18 AM, Andrew Lunn wrote: + phydev->mdix = ETH_TP_MDI_AUTO; >>> >>> Humm, interesting. The only other driver supporting mdix is the >>> Marvell one. It does not do this, it leaves it to its default value of >>> ETH_TP_MDI_INVALID. It does however interpret ETH_TP_MDI_INVALID as >>> meaning as ETH_TP_MDI_AUTO. >>> >>> There needs to be consistency here. You either need to do the same as >>> the Marvell driver, or you need to modify the Marvell driver to also >>> set phydev->mdix to ETH_TP_MDI_AUTO. >>> >> In Ethtool two variable i.e. eth_tp_mdix_ctrl, eth_tp_mdix use to update >> the status. But, driver header is having one variable i.e. mdix. >> Driver header should also have another variabl like mdix_ctrl. >> Then, Ethtool can get/set the Auto MDIX/MDI. >> In case, mdix is not configure with ETH_TP_MDI_AUTO, Ethtool shows error as >> "setting MDI not supported" Agreed, we currently report eth_tp_mdi and eth_tp_mdi_ctrl using phydev->mdix, but this is too limiting. >> >> Please suggest me if you have any better method to fix this issue. > > Maybe we should add a new flag for the .flags member of the > phy_driver. If PHY_HAS_MDIX is set, the phy core will set phydev->mdix > to ETH_TP_MDI_AUTO? I agree with Raju here, like most other Ethernet drivers, we should allow PHY drivers to have an eth_tp_mdix_ctrl to indicate what is the configured MDI setting, and read eth_tp_mdi to indicate what is the current status, then ethtool can properly differentiate what is going on. Raju, Andrew, does that work for you? -- Florian
Re: [PATCH net-next 2/2] net: phy: Add PHY Auto/Mdi/Mdix set driver for Microsemi PHYs.
On 09/28/2016 01:24 PM, Andrew Lunn wrote: >> static int vsc85xx_wol_set(struct phy_device *phydev, >> struct ethtool_wolinfo *wol) >> { >> @@ -227,6 +281,7 @@ static int vsc85xx_default_config(struct phy_device >> *phydev) >> int rc; >> u16 reg_val; >> >> +phydev->mdix = ETH_TP_MDI_AUTO; > > Humm, interesting. The only other driver supporting mdix is the > Marvell one. It does not do this, it leaves it to its default value of > ETH_TP_MDI_INVALID. It does however interpret ETH_TP_MDI_INVALID as > meaning as ETH_TP_MDI_AUTO. > > There needs to be consistency here. You either need to do the same as > the Marvell driver, or you need to modify the Marvell driver to also > set phydev->mdix to ETH_TP_MDI_AUTO. > > I don't yet know which of these two is the right thing to do. > > Florian? It's really hard to tell because the other drivers I looked at do not necessarily seem to be consistent either. Here, if the MDI status is really auto, then this is the correct value to return, if it is unknown, it should be ETH_TP_MDI_INVALID. For the Marvell PHY, it sounds like we should be able to determine what was configured and return the correct MDI status value -- Florian
Re: [PATCH net-next 2/2] net: phy: Add PHY Auto/Mdi/Mdix set driver for Microsemi PHYs.
> > > + phydev->mdix = ETH_TP_MDI_AUTO; > > > > Humm, interesting. The only other driver supporting mdix is the > > Marvell one. It does not do this, it leaves it to its default value of > > ETH_TP_MDI_INVALID. It does however interpret ETH_TP_MDI_INVALID as > > meaning as ETH_TP_MDI_AUTO. > > > > There needs to be consistency here. You either need to do the same as > > the Marvell driver, or you need to modify the Marvell driver to also > > set phydev->mdix to ETH_TP_MDI_AUTO. > > > In Ethtool two variable i.e. eth_tp_mdix_ctrl, eth_tp_mdix use to update > the status. But, driver header is having one variable i.e. mdix. > Driver header should also have another variabl like mdix_ctrl. > Then, Ethtool can get/set the Auto MDIX/MDI. > In case, mdix is not configure with ETH_TP_MDI_AUTO, Ethtool shows error as > "setting MDI not supported" > > Please suggest me if you have any better method to fix this issue. Maybe we should add a new flag for the .flags member of the phy_driver. If PHY_HAS_MDIX is set, the phy core will set phydev->mdix to ETH_TP_MDI_AUTO? Florian, what do you think? Andrew
Re: [PATCH net-next 2/2] net: phy: Add PHY Auto/Mdi/Mdix set driver for Microsemi PHYs.
Hi Andrew, Thank you for code review and valuable comments. On Wed, Sep 28, 2016 at 10:24:51PM +0200, Andrew Lunn wrote: > EXTERNAL EMAIL > > > > + reg_val = phy_read(phydev, MSCC_PHY_BYPASS_CONTROL); > > + if ((mdix == ETH_TP_MDI) || (mdix == ETH_TP_MDI_X)) { > > + reg_val |= (DISABLE_PAIR_SWAP_CORR_MASK | > > + DISABLE_POLARITY_CORR_MASK | > > + DISABLE_HP_AUTO_MDIX_MASK); > > + } else { > > + reg_val &= ~(DISABLE_PAIR_SWAP_CORR_MASK | > > + DISABLE_POLARITY_CORR_MASK | > > + DISABLE_HP_AUTO_MDIX_MASK); > > + } > > + rc = phy_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg_val); > > + if (rc != 0) > > + goto out_unlock; > > + > > + rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED); > > + if (rc != 0) > > + goto out_unlock; > > + > > + reg_val = phy_read(phydev, MSCC_PHY_EXT_MODE_CNTL); > > + reg_val &= ~(FORCE_MDI_CROSSOVER_MASK); > > + if (mdix == ETH_TP_MDI) > > + reg_val |= FORCE_MDI_CROSSOVER_MDI; > > + else if (mdix == ETH_TP_MDI_X) > > + reg_val |= FORCE_MDI_CROSSOVER_MDIX; > > + rc = phy_write(phydev, MSCC_PHY_EXT_MODE_CNTL, reg_val); > > + if (rc != 0) > > + goto out_unlock; > > + > > + rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD); > > + > > +out_unlock: > > out_unlock seems a bit of an odd name, since you are not unlocking > anything. > It's my mistake. Mutex should be there. I will add mutex. > I also wonder if you should try to reset to MSCC_PHY_PAGE_STANDARD in > the error condition? > > > + > > + return rc; > > +} > > + > > static int vsc85xx_wol_set(struct phy_device *phydev, > > struct ethtool_wolinfo *wol) > > { > > @@ -227,6 +281,7 @@ static int vsc85xx_default_config(struct phy_device > > *phydev) > > int rc; > > u16 reg_val; > > > > + phydev->mdix = ETH_TP_MDI_AUTO; > > Humm, interesting. The only other driver supporting mdix is the > Marvell one. It does not do this, it leaves it to its default value of > ETH_TP_MDI_INVALID. It does however interpret ETH_TP_MDI_INVALID as > meaning as ETH_TP_MDI_AUTO. > > There needs to be consistency here. You either need to do the same as > the Marvell driver, or you need to modify the Marvell driver to also > set phydev->mdix to ETH_TP_MDI_AUTO. > In Ethtool two variable i.e. eth_tp_mdix_ctrl, eth_tp_mdix use to update the status. But, driver header is having one variable i.e. mdix. Driver header should also have another variabl like mdix_ctrl. Then, Ethtool can get/set the Auto MDIX/MDI. In case, mdix is not configure with ETH_TP_MDI_AUTO, Ethtool shows error as "setting MDI not supported" Please suggest me if you have any better method to fix this issue. > I don't yet know which of these two is the right thing to do. > > Florian? > > Andrew --- Thanks, Raju.
Re: [PATCH net-next 2/2] net: phy: Add PHY Auto/Mdi/Mdix set driver for Microsemi PHYs.
> + reg_val = phy_read(phydev, MSCC_PHY_BYPASS_CONTROL); > + if ((mdix == ETH_TP_MDI) || (mdix == ETH_TP_MDI_X)) { > + reg_val |= (DISABLE_PAIR_SWAP_CORR_MASK | > + DISABLE_POLARITY_CORR_MASK | > + DISABLE_HP_AUTO_MDIX_MASK); > + } else { > + reg_val &= ~(DISABLE_PAIR_SWAP_CORR_MASK | > + DISABLE_POLARITY_CORR_MASK | > + DISABLE_HP_AUTO_MDIX_MASK); > + } > + rc = phy_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg_val); > + if (rc != 0) > + goto out_unlock; > + > + rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED); > + if (rc != 0) > + goto out_unlock; > + > + reg_val = phy_read(phydev, MSCC_PHY_EXT_MODE_CNTL); > + reg_val &= ~(FORCE_MDI_CROSSOVER_MASK); > + if (mdix == ETH_TP_MDI) > + reg_val |= FORCE_MDI_CROSSOVER_MDI; > + else if (mdix == ETH_TP_MDI_X) > + reg_val |= FORCE_MDI_CROSSOVER_MDIX; > + rc = phy_write(phydev, MSCC_PHY_EXT_MODE_CNTL, reg_val); > + if (rc != 0) > + goto out_unlock; > + > + rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD); > + > +out_unlock: out_unlock seems a bit of an odd name, since you are not unlocking anything. I also wonder if you should try to reset to MSCC_PHY_PAGE_STANDARD in the error condition? > + > + return rc; > +} > + > static int vsc85xx_wol_set(struct phy_device *phydev, > struct ethtool_wolinfo *wol) > { > @@ -227,6 +281,7 @@ static int vsc85xx_default_config(struct phy_device > *phydev) > int rc; > u16 reg_val; > > + phydev->mdix = ETH_TP_MDI_AUTO; Humm, interesting. The only other driver supporting mdix is the Marvell one. It does not do this, it leaves it to its default value of ETH_TP_MDI_INVALID. It does however interpret ETH_TP_MDI_INVALID as meaning as ETH_TP_MDI_AUTO. There needs to be consistency here. You either need to do the same as the Marvell driver, or you need to modify the Marvell driver to also set phydev->mdix to ETH_TP_MDI_AUTO. I don't yet know which of these two is the right thing to do. Florian? Andrew
[PATCH net-next 2/2] net: phy: Add PHY Auto/Mdi/Mdix set driver for Microsemi PHYs.
From: Raju Lakkaraju To connect two ports of the same configuration (MDI to MDI or MDI-X to MDI-X) with a 10/100/1000 Mbit/s connection, an Ethernet crossover cable is needed to cross over the transmit and receive signals in the cable, so that they are matched at the connector level. When connecting an MDI port to an MDI-X port a straight through cable is used while to connect two MDI ports or two MDI-X ports a crossover cable must be used. Conventionally MDI is used on end devices while MDI-X is used on hubs and switches Auto MDI-X automatically detects the required cable connection type and configures the connection appropriately, removing the need for crossover cables to interconnect switches or connecting PCs peer-to-peer. VSC8531 PHY supports Auto MDI-x, MDI and MDI-X configuraion by driver set mdix function. Tested on Beaglebone Black with VSC 8531 PHY. Signed-off-by: Raju Lakkaraju --- drivers/net/phy/mscc.c | 72 -- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index ca6ea23..dbf8434 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -26,6 +26,11 @@ enum rgmii_rx_clock_delay { /* Microsemi VSC85xx PHY registers */ /* IEEE 802. Std Registers */ +#define MSCC_PHY_BYPASS_CONTROL 18 +#define DISABLE_HP_AUTO_MDIX_MASK0x0080 +#define DISABLE_PAIR_SWAP_CORR_MASK 0x0020 +#define DISABLE_POLARITY_CORR_MASK 0x0010 + #define MSCC_PHY_EXT_PHY_CNTL_1 23 #define MAC_IF_SELECTION_MASK 0x1800 #define MAC_IF_SELECTION_GMII 0 @@ -41,8 +46,16 @@ enum rgmii_rx_clock_delay { #define MSCC_EXT_PAGE_ACCESS 31 #define MSCC_PHY_PAGE_STANDARD 0x /* Standard registers */ +#define MSCC_PHY_PAGE_EXTENDED 0x0001 /* Extended registers */ #define MSCC_PHY_PAGE_EXTENDED_2 0x0002 /* Extended reg - page 2 */ +/* Extended Page 1 Registers */ +#define MSCC_PHY_EXT_MODE_CNTL 19 +#define FORCE_MDI_CROSSOVER_MASK 0x000C +#define FORCE_MDI_CROSSOVER_MDIX 0x000C +#define FORCE_MDI_CROSSOVER_MDI 0x0008 +#define FORCE_MDI_CROSSOVER_NORMAL 0x + /* Extended Page 2 Registers */ #define MSCC_PHY_RGMII_CNTL 20 #define RGMII_RX_CLK_DELAY_MASK 0x0070 @@ -73,6 +86,47 @@ static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page) return rc; } +static int vsc85xx_mdix_set(struct phy_device *phydev, + u8 mdix) +{ + int rc; + u16 reg_val; + + reg_val = phy_read(phydev, MSCC_PHY_BYPASS_CONTROL); + if ((mdix == ETH_TP_MDI) || (mdix == ETH_TP_MDI_X)) { + reg_val |= (DISABLE_PAIR_SWAP_CORR_MASK | + DISABLE_POLARITY_CORR_MASK | + DISABLE_HP_AUTO_MDIX_MASK); + } else { + reg_val &= ~(DISABLE_PAIR_SWAP_CORR_MASK | +DISABLE_POLARITY_CORR_MASK | +DISABLE_HP_AUTO_MDIX_MASK); + } + rc = phy_write(phydev, MSCC_PHY_BYPASS_CONTROL, reg_val); + if (rc != 0) + goto out_unlock; + + rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED); + if (rc != 0) + goto out_unlock; + + reg_val = phy_read(phydev, MSCC_PHY_EXT_MODE_CNTL); + reg_val &= ~(FORCE_MDI_CROSSOVER_MASK); + if (mdix == ETH_TP_MDI) + reg_val |= FORCE_MDI_CROSSOVER_MDI; + else if (mdix == ETH_TP_MDI_X) + reg_val |= FORCE_MDI_CROSSOVER_MDIX; + rc = phy_write(phydev, MSCC_PHY_EXT_MODE_CNTL, reg_val); + if (rc != 0) + goto out_unlock; + + rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD); + +out_unlock: + + return rc; +} + static int vsc85xx_wol_set(struct phy_device *phydev, struct ethtool_wolinfo *wol) { @@ -227,6 +281,7 @@ static int vsc85xx_default_config(struct phy_device *phydev) int rc; u16 reg_val; + phydev->mdix = ETH_TP_MDI_AUTO; mutex_lock(&phydev->lock); rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2); if (rc != 0) @@ -288,6 +343,19 @@ static int vsc85xx_config_intr(struct phy_device *phydev) return rc; } +static int vsc85xx_config_aneg(struct phy_device *phydev) +{ + int rc; + + rc = vsc85xx_mdix_set(phydev, phydev->mdix); + if (rc < 0) + return rc; + + rc = genphy_config_aneg(phydev); + + return rc; +} + /* Microsemi VSC85xx PHYs */ static struct phy_driver vsc85xx_driver[] = { { @@ -298,7 +366,7 @@ static struct phy_driver vsc85xx_driver[] = { .flags = PHY_HAS_INTERRUPT, .soft_reset = &genphy_soft_reset, .config_init= &vsc85xx_config_init, - .config_aneg= &genphy_config_aneg, + .config_ane