aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/octeon/ethernet-mdio.c
diff options
context:
space:
mode:
authorDavid Daney <david.daney@cavium.com>2014-05-29 11:10:02 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-06-19 15:24:52 -0700
commitec3a2207c322e518f7f42c80e54b8ecaf8a6f03e (patch)
tree5a0783b7013cab2d9c8327d54884b798c8d41e9d /drivers/staging/octeon/ethernet-mdio.c
parentstaging: dgap: unwind on error in dgap_init_one() (diff)
downloadlinux-dev-ec3a2207c322e518f7f42c80e54b8ecaf8a6f03e.tar.xz
linux-dev-ec3a2207c322e518f7f42c80e54b8ecaf8a6f03e.zip
staging: octeon-ethernet: Move PHY activation to .ndo_open().
This prevents PHY not found types of errors for PHY drivers that are probed after the Ethernet driver is probed, because the ifconfig UP is done from userspace after all drivers have been probed. Also avoid the cvmx-helper-board.c PHY code if a real PHY driver is present, this allows a bootloader supplied device tree to specify the PHY information rather than having to modify the code for each different board. Tested-by: Alex Smith <alex.smith@imgtec.com> Signed-off-by: David Daney <david.daney@cavium.com> Signed-off-by: Alex Smith <alex.smith@imgtec.com> Cc: devel@driverdev.osuosl.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/octeon/ethernet-mdio.c')
-rw-r--r--drivers/staging/octeon/ethernet-mdio.c79
1 files changed, 58 insertions, 21 deletions
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index 3f067f189b3d..ebfa9c9e71b1 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -116,7 +116,34 @@ int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return phy_mii_ioctl(priv->phydev, rq, cmd);
}
-static void cvm_oct_adjust_link(struct net_device *dev)
+static void cvm_oct_note_carrier(struct octeon_ethernet *priv,
+ cvmx_helper_link_info_t li)
+{
+ if (li.s.link_up) {
+ pr_notice_ratelimited("%s: %u Mbps %s duplex, port %d\n",
+ netdev_name(priv->netdev), li.s.speed,
+ (li.s.full_duplex) ? "Full" : "Half",
+ priv->port);
+ } else {
+ pr_notice_ratelimited("%s: Link down\n",
+ netdev_name(priv->netdev));
+ }
+}
+
+void cvm_oct_set_carrier(struct octeon_ethernet *priv,
+ cvmx_helper_link_info_t link_info)
+{
+ cvm_oct_note_carrier(priv, link_info);
+ if (link_info.s.link_up) {
+ if (!netif_carrier_ok(priv->netdev))
+ netif_carrier_on(priv->netdev);
+ } else {
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
+ }
+}
+
+void cvm_oct_adjust_link(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
cvmx_helper_link_info_t link_info;
@@ -127,28 +154,32 @@ static void cvm_oct_adjust_link(struct net_device *dev)
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);
- if (priv->last_link) {
- netif_carrier_on(dev);
- if (priv->queue != -1)
- printk_ratelimited("%s: %u Mbps %s duplex, "
- "port %2d, queue %2d\n", dev->name,
- priv->phydev->speed,
- priv->phydev->duplex ? "Full" : "Half",
- priv->port, priv->queue);
- else
- printk_ratelimited("%s: %u Mbps %s duplex, "
- "port %2d, POW\n", dev->name,
- priv->phydev->speed,
- priv->phydev->duplex ? "Full" : "Half",
- priv->port);
- } else {
- netif_carrier_off(dev);
- printk_ratelimited("%s: Link down\n", dev->name);
- }
+ cvm_oct_note_carrier(priv, link_info);
}
}
+int cvm_oct_common_stop(struct net_device *dev)
+{
+ struct octeon_ethernet *priv = netdev_priv(dev);
+ cvmx_helper_link_info_t link_info;
+
+ priv->poll = NULL;
+
+ if (priv->phydev)
+ phy_disconnect(priv->phydev);
+ priv->phydev = NULL;
+
+ if (priv->last_link) {
+ link_info.u64 = 0;
+ priv->last_link = 0;
+
+ cvmx_helper_link_set(priv->port, link_info);
+ cvm_oct_note_carrier(priv, link_info);
+ }
+ return 0;
+}
/**
* cvm_oct_phy_setup_device - setup the PHY
@@ -163,11 +194,11 @@ int cvm_oct_phy_setup_device(struct net_device *dev)
struct device_node *phy_node;
if (!priv->of_node)
- return 0;
+ goto no_phy;
phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0);
if (!phy_node)
- return 0;
+ goto no_phy;
priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0,
PHY_INTERFACE_MODE_GMII);
@@ -179,4 +210,10 @@ int cvm_oct_phy_setup_device(struct net_device *dev)
phy_start_aneg(priv->phydev);
return 0;
+no_phy:
+ /* If there is no phy, assume a direct MAC connection and that
+ * the link is up.
+ */
+ netif_carrier_on(dev);
+ return 0;
}