From: Raju Lakkaraju <redacted>
This series adds support to the Wake-on-LAN and Auto/Mdi-x set drivers
for Microsemi PHYs.
Patch 1/2:
Wake-on-LAN (WoL) is an Ethernet networking standard that allows
a computer/device to be turned on or awakened by a network message.
VSC8531 PHY can support this feature configure by driver set function.
WoL status get by driver get function.
Patch 2/2:
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 loopback function.
Tested on Beaglebone Black with VSC 8531 PHY.
Raju Lakkaraju (2):
net: phy: Add Wake-on-LAN driver for Microsemi PHYs.
net: phy: Add PHY Auto/Mdi/Mdix set driver for Microsemi PHYs.
drivers/net/phy/mscc.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 202 insertions(+), 2 deletions(-)
--
2.7.4
From: Raju Lakkaraju <redacted>
Wake-on-LAN (WoL) is an Ethernet networking standard that allows
a computer/device to be turned on or awakened by a network message.
VSC8531 PHY can support this feature configure by driver set function.
WoL status get by driver get function.
Tested on Beaglebone Black with VSC 8531 PHY.
Signed-off-by: Raju Lakkaraju <redacted>
---
drivers/net/phy/mscc.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
@@ -58,6 +73,119 @@ static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page)returnrc;}+staticintvsc85xx_wol_set(structphy_device*phydev,+structethtool_wolinfo*wol)+{+intrc;+u16reg_val;+structethtool_wolinfo*wol_conf=wol;++mutex_lock(&phydev->lock);+rc=vsc85xx_phy_page_set(phydev,MSCC_PHY_PAGE_EXTENDED_2);+if(rc!=0)+gotoout_unlock;++if(wol->wolopts&WAKE_MAGIC){+/* Store the device address for the magic packet */+reg_val=phydev->attached_dev->dev_addr[4]<<8;+reg_val|=phydev->attached_dev->dev_addr[5];+phy_write(phydev,MSCC_PHY_WOL_LOWER_MAC_ADDR,reg_val);+reg_val=phydev->attached_dev->dev_addr[2]<<8;+reg_val|=phydev->attached_dev->dev_addr[3];+phy_write(phydev,MSCC_PHY_WOL_MID_MAC_ADDR,reg_val);+reg_val=phydev->attached_dev->dev_addr[0]<<8;+reg_val|=phydev->attached_dev->dev_addr[1];+phy_write(phydev,MSCC_PHY_WOL_UPPER_MAC_ADDR,reg_val);+}else{+phy_write(phydev,MSCC_PHY_WOL_LOWER_MAC_ADDR,0);+phy_write(phydev,MSCC_PHY_WOL_MID_MAC_ADDR,0);+phy_write(phydev,MSCC_PHY_WOL_UPPER_MAC_ADDR,0);+}++reg_val=phy_read(phydev,MSCC_PHY_WOL_MAC_CONTROL);+if(wol_conf->wolopts&WAKE_MAGICSECURE)+reg_val|=SECURE_ON_ENABLE;+else+reg_val&=~SECURE_ON_ENABLE;+phy_write(phydev,MSCC_PHY_WOL_MAC_CONTROL,reg_val);++if(wol_conf->wolopts&WAKE_MAGICSECURE){+reg_val=wol_conf->sopass[4]<<8;+reg_val|=wol_conf->sopass[5];+phy_write(phydev,MSCC_PHY_WOL_LOWER_PASSWD,reg_val);+reg_val=wol_conf->sopass[2]<<8;+reg_val|=wol_conf->sopass[3];+phy_write(phydev,MSCC_PHY_WOL_MID_PASSWD,reg_val);+reg_val=wol_conf->sopass[0]<<8;+reg_val|=wol_conf->sopass[1];+phy_write(phydev,MSCC_PHY_WOL_UPPER_PASSWD,reg_val);+}else{+phy_write(phydev,MSCC_PHY_WOL_LOWER_PASSWD,0);+phy_write(phydev,MSCC_PHY_WOL_MID_PASSWD,0);+phy_write(phydev,MSCC_PHY_WOL_UPPER_PASSWD,0);+}++rc=vsc85xx_phy_page_set(phydev,MSCC_PHY_PAGE_STANDARD);+if(rc!=0)+gotoout_unlock;++if(wol->wolopts&WAKE_MAGIC){+/* Enable the WOL interrupt */+reg_val=phy_read(phydev,MII_VSC85XX_INT_MASK);+reg_val|=MII_VSC85XX_INT_MASK_WOL;+rc=phy_write(phydev,MII_VSC85XX_INT_MASK,reg_val);+if(rc!=0)+gotoout_unlock;+}else{+/* Disable the WOL interrupt */+reg_val=phy_read(phydev,MII_VSC85XX_INT_MASK);+reg_val&=(~MII_VSC85XX_INT_MASK_WOL);+rc=phy_write(phydev,MII_VSC85XX_INT_MASK,reg_val);+if(rc!=0)+gotoout_unlock;+}+/* Clear WOL iterrupt status */+reg_val=phy_read(phydev,MII_VSC85XX_INT_STATUS);++out_unlock:+mutex_unlock(&phydev->lock);++returnrc;+}++staticvoidvsc85xx_wol_get(structphy_device*phydev,+structethtool_wolinfo*wol)+{+intrc;+u16reg_val;+structethtool_wolinfo*wol_conf=wol;++mutex_lock(&phydev->lock);+rc=vsc85xx_phy_page_set(phydev,MSCC_PHY_PAGE_EXTENDED_2);+if(rc!=0)+gotoout_unlock;++reg_val=phy_read(phydev,MSCC_PHY_WOL_MAC_CONTROL);+if(reg_val&SECURE_ON_ENABLE)+wol_conf->wolopts|=WAKE_MAGICSECURE;+if(wol_conf->wolopts&WAKE_MAGICSECURE){+reg_val=phy_read(phydev,MSCC_PHY_WOL_LOWER_PASSWD);+wol_conf->sopass[5]=reg_val&0x00ff;+wol_conf->sopass[4]=(reg_val&0xff00)>>8;+reg_val=phy_read(phydev,MSCC_PHY_WOL_MID_PASSWD);+wol_conf->sopass[3]=reg_val&0x00ff;+wol_conf->sopass[2]=(reg_val&0xff00)>>8;+reg_val=phy_read(phydev,MSCC_PHY_WOL_UPPER_PASSWD);+wol_conf->sopass[1]=reg_val&0x00ff;+wol_conf->sopass[0]=(reg_val&0xff00)>>8;+}++rc=vsc85xx_phy_page_set(phydev,MSCC_PHY_PAGE_STANDARD);++out_unlock:+mutex_unlock(&phydev->lock);+}+staticintvsc85xx_mac_if_set(structphy_device*phydev,phy_interface_tinterface){
From: Raju Lakkaraju <redacted>
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 <redacted>
---
drivers/net/phy/mscc.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 70 insertions(+), 2 deletions(-)
This patch does not require these two #defines.
Please indicate in the cover note if the patches depends on other
patches in order to cleanly apply. Or if these patches are going to
conflict with some other patches.
Wouldn't it be better to set the password, and then enable the
password feature?
I don't know much about WOL. Hopefully Florian will add further
comments.
Andrew
From: Raju Lakkaraju <redacted>
Wake-on-LAN (WoL) is an Ethernet networking standard that allows
a computer/device to be turned on or awakened by a network message.
VSC8531 PHY can support this feature configure by driver set function.
WoL status get by driver get function.
Tested on Beaglebone Black with VSC 8531 PHY.
Signed-off-by: Raju Lakkaraju <redacted>
---
drivers/net/phy/mscc.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
This mutex is used here because you are using an indirect page access,
right? This is not to protect against multiple calls of wol_set from
different executing threads?
How about making the code a little simpler in both cases with something
like this the following:
u16 pwd = { };
unsigned int i;
if (wol_conf->wolopts & WAKE_MAGICECURE)
for (i = 0; i < ARRAY_SIZE(pwd); i++)
pwd[i] = wol_conf->so_pass[5 - (i * 2 + 1)] << 8|
wol_conf->so_pass[5 - i * 2 ]
phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, pwd[0]);
phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, pwd[1]);
phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, pwd[2]);
quoted hunk
++ rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);+ if (rc != 0)+ goto out_unlock;++ if (wol->wolopts & WAKE_MAGIC) {
Don't you also need to check WAKE_MAGICSECURE here as well? Or is the
interrupt going to be generated only if there is no password defined?
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?
@@ -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
This patch does not require these two #defines.
Please indicate in the cover note if the patches depends on other
patches in order to cleanly apply. Or if these patches are going to
conflict with some other patches.
Hi Florian,
Thank you for code review and valuable comments.
On Wed, Sep 28, 2016 at 10:37:07AM -0700, Florian Fainelli wrote:
EXTERNAL EMAIL
On 09/28/2016 05:01 AM, Raju Lakkaraju wrote:
quoted
From: Raju Lakkaraju <redacted>
Wake-on-LAN (WoL) is an Ethernet networking standard that allows
a computer/device to be turned on or awakened by a network message.
VSC8531 PHY can support this feature configure by driver set function.
WoL status get by driver get function.
Tested on Beaglebone Black with VSC 8531 PHY.
Signed-off-by: Raju Lakkaraju <redacted>
---
drivers/net/phy/mscc.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
This mutex is used here because you are using an indirect page access,
right? This is not to protect against multiple calls of wol_set from
different executing threads?
Correct. mutex is used for indirect page access.
I did find any protect against multiple calls of wol_set in other vendors.
Do you have any suggestions?
How about making the code a little simpler in both cases with something
like this the following:
u16 pwd = { };
unsigned int i;
if (wol_conf->wolopts & WAKE_MAGICECURE)
for (i = 0; i < ARRAY_SIZE(pwd); i++)
pwd[i] = wol_conf->so_pass[5 - (i * 2 + 1)] << 8|
wol_conf->so_pass[5 - i * 2 ]
phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, pwd[0]);
phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, pwd[1]);
phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, pwd[2]);
Accepted. I will change.
quoted
++ rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);+ if (rc != 0)+ goto out_unlock;++ if (wol->wolopts & WAKE_MAGIC) {
Don't you also need to check WAKE_MAGICSECURE here as well? Or is the
interrupt going to be generated only if there is no password defined?
Interrupt is going to be generated when WAKE_MAGIC.
WAKE_MAGICSECURE is extra protection.
@@ -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
From: Andrew Lunn <andrew@lunn.ch> Date: 2016-10-05 07:18:37
quoted
quoted
+ 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
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
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.
quoted
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
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:
quoted
quoted
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
@@ -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.
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:
quoted
quoted
quoted
quoted
+ 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.
quoted
quoted
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?