Commit 67b2914b authored by David S. Miller's avatar David S. Miller

Merge branch 'explicit-inbound-link-state'

Florian Fainelli says:

====================
net: enable inband link state negotiation only when explicitly requested

Changes in v5:

- removed an invalid use of the link_update callback in the SF2 driver
  was appeared after merging "net: phy: fixed_phy: handle link-down case"

- reworded the commit message for patch 2 to make it clear what it fixes and
  why this is required

Initial cover letter from Stas:

Hello.

Currently the link status auto-negotiation is enabled
for any SGMII link with fixed-link DT binding.
The regression was reported:
https://lkml.org/lkml/2015/7/8/865
Apparently not all HW that implements SGMII protocol, generates the
inband status for the auto-negotiation to work.
More details here:
https://lkml.org/lkml/2015/7/10/206

The following patches reverts to the old behavior by default,
which is to not enable the auto-negotiation for fixed-link.
The new DT property is added that allows to explicitly request
the auto-negotiation.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e181a543 f8af8e6e
......@@ -25,7 +25,11 @@ The following properties are common to the Ethernet controllers:
flow control thresholds.
- tx-fifo-depth: the size of the controller's transmit fifo in bytes. This
is used for components that can have configurable fifo sizes.
- managed: string, specifies the PHY management type. Supported values are:
"auto", "in-band-status". "auto" is the default, it usess MDIO for
management if fixed-link is not specified.
Child nodes of the Ethernet controller are typically the individual PHY devices
connected via the MDIO bus (sometimes the MDIO bus controller is separate).
They are described in the phy.txt file in this same directory.
For non-MDIO PHY management see fixed-link.txt.
......@@ -890,15 +890,11 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
struct fixed_phy_status *status)
{
struct bcm_sf2_priv *priv = ds_to_priv(ds);
u32 duplex, pause, speed;
u32 duplex, pause;
u32 reg;
duplex = core_readl(priv, CORE_DUPSTS);
pause = core_readl(priv, CORE_PAUSESTS);
speed = core_readl(priv, CORE_SPDSTS);
speed >>= (port * SPDSTS_SHIFT);
speed &= SPDSTS_MASK;
status->link = 0;
......@@ -933,18 +929,6 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
reg &= ~LINK_STS;
core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port));
switch (speed) {
case SPDSTS_10:
status->speed = SPEED_10;
break;
case SPDSTS_100:
status->speed = SPEED_100;
break;
case SPDSTS_1000:
status->speed = SPEED_1000;
break;
}
if ((pause & (1 << port)) &&
(pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT)))) {
status->asym_pause = 1;
......
......@@ -3029,8 +3029,8 @@ static int mvneta_probe(struct platform_device *pdev)
const char *dt_mac_addr;
char hw_mac_addr[ETH_ALEN];
const char *mac_from;
const char *managed;
int phy_mode;
int fixed_phy = 0;
int err;
/* Our multiqueue support is not complete, so for now, only
......@@ -3064,7 +3064,6 @@ static int mvneta_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "cannot register fixed PHY\n");
goto err_free_irq;
}
fixed_phy = 1;
/* In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
......@@ -3088,8 +3087,10 @@ static int mvneta_probe(struct platform_device *pdev)
pp = netdev_priv(dev);
pp->phy_node = phy_node;
pp->phy_interface = phy_mode;
pp->use_inband_status = (phy_mode == PHY_INTERFACE_MODE_SGMII) &&
fixed_phy;
err = of_property_read_string(dn, "managed", &managed);
pp->use_inband_status = (err == 0 &&
strcmp(managed, "in-band-status") == 0);
pp->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pp->clk)) {
......
......@@ -52,6 +52,10 @@ static int fixed_phy_update_regs(struct fixed_phy *fp)
u16 lpagb = 0;
u16 lpa = 0;
if (!fp->status.link)
goto done;
bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;
if (fp->status.duplex) {
bmcr |= BMCR_FULLDPLX;
......@@ -96,15 +100,13 @@ static int fixed_phy_update_regs(struct fixed_phy *fp)
}
}
if (fp->status.link)
bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;
if (fp->status.pause)
lpa |= LPA_PAUSE_CAP;
if (fp->status.asym_pause)
lpa |= LPA_PAUSE_ASYM;
done:
fp->regs[MII_PHYSID1] = 0;
fp->regs[MII_PHYSID2] = 0;
......
......@@ -266,7 +266,8 @@ EXPORT_SYMBOL(of_phy_attach);
bool of_phy_is_fixed_link(struct device_node *np)
{
struct device_node *dn;
int len;
int len, err;
const char *managed;
/* New binding */
dn = of_get_child_by_name(np, "fixed-link");
......@@ -275,6 +276,10 @@ bool of_phy_is_fixed_link(struct device_node *np)
return true;
}
err = of_property_read_string(np, "managed", &managed);
if (err == 0 && strcmp(managed, "auto") != 0)
return true;
/* Old binding */
if (of_get_property(np, "fixed-link", &len) &&
len == (5 * sizeof(__be32)))
......@@ -289,8 +294,18 @@ int of_phy_register_fixed_link(struct device_node *np)
struct fixed_phy_status status = {};
struct device_node *fixed_link_node;
const __be32 *fixed_link_prop;
int len;
int len, err;
struct phy_device *phy;
const char *managed;
err = of_property_read_string(np, "managed", &managed);
if (err == 0) {
if (strcmp(managed, "in-band-status") == 0) {
/* status is zeroed, namely its .link member */
phy = fixed_phy_register(PHY_POLL, &status, np);
return IS_ERR(phy) ? PTR_ERR(phy) : 0;
}
}
/* New binding */
fixed_link_node = of_get_child_by_name(np, "fixed-link");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment