Commit 710086db authored by Aaro Koskinen's avatar Aaro Koskinen Committed by Greg Kroah-Hartman

staging: octeon: refactor rgmii 10 mbps preamble error checking

Refactor RGMII 10 Mbps preamble error checking. The current implementation
does not work correctly in phydev mode since only the link status changes
trigger the callback, and if we stay on 10 Mbps operation the periodic
checks for error counters are never done.

Provide a periodic worker also during the phydev operation, and notify
the link status changes through the phydev instead of the inband
status change interrupt. This also has the benefit that we don't need
to use legacy CVMX MDIO calls to check the PHY state, and we can avoid
races that trigger bogus "Using 10Mbps with software preamble removal"
logs when interfaces are being bringed up. It also avoids some corner-case
crashes when the in-band interrupt triggers while the interface is
being taken down.

Tested on EdgeRouter Lite & D-Link DSR-1000N.
Signed-off-by: default avatarAaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1d5047c9
......@@ -118,13 +118,20 @@ void cvm_oct_adjust_link(struct net_device *dev)
struct octeon_ethernet *priv = netdev_priv(dev);
cvmx_helper_link_info_t link_info;
link_info.u64 = 0;
link_info.s.link_up = priv->phydev->link ? 1 : 0;
link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0;
link_info.s.speed = priv->phydev->speed;
priv->link_info = link_info.u64;
/*
* The polling task need to know about link status changes.
*/
if (priv->poll)
priv->poll(dev);
if (priv->last_link != priv->phydev->link) {
priv->last_link = priv->phydev->link;
link_info.u64 = 0;
link_info.s.link_up = priv->last_link ? 1 : 0;
link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0;
link_info.s.speed = priv->phydev->speed;
cvmx_helper_link_set(priv->port, link_info);
cvm_oct_note_carrier(priv, link_info);
}
......
This diff is collapsed.
......@@ -601,8 +601,8 @@ static const struct net_device_ops cvm_oct_spi_netdev_ops = {
#endif
};
static const struct net_device_ops cvm_oct_rgmii_netdev_ops = {
.ndo_init = cvm_oct_rgmii_init,
.ndo_uninit = cvm_oct_rgmii_uninit,
.ndo_init = cvm_oct_common_init,
.ndo_uninit = cvm_oct_common_uninit,
.ndo_open = cvm_oct_rgmii_open,
.ndo_stop = cvm_oct_common_stop,
.ndo_start_xmit = cvm_oct_xmit,
......
......@@ -41,20 +41,18 @@ struct octeon_ethernet {
/* Device statistics */
struct net_device_stats stats;
struct phy_device *phydev;
unsigned int last_speed;
unsigned int last_link;
/* Last negotiated link state */
u64 link_info;
/* Called periodically to check link status */
void (*poll)(struct net_device *dev);
struct delayed_work port_periodic_work;
struct work_struct port_work; /* may be unused. */
struct device_node *of_node;
};
int cvm_oct_free_work(void *work_queue_entry);
int cvm_oct_rgmii_init(struct net_device *dev);
void cvm_oct_rgmii_uninit(struct net_device *dev);
int cvm_oct_rgmii_open(struct net_device *dev);
int cvm_oct_sgmii_init(struct net_device *dev);
......
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