summaryrefslogtreecommitdiff
path: root/drivers/net/phy/phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r--drivers/net/phy/phy.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 3376e58e2b88..ae1916861986 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -993,6 +993,27 @@ static int phy_check_link_status(struct phy_device *phydev)
}
/**
+ * phy_query_inband - query which in-band signalling modes are supported
+ * @phydev: a pointer to a &struct phy_device
+ * @interface: the interface mode for the PHY
+ *
+ * Returns zero if it is unknown what in-band signalling is supported by the
+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
+ * returns a bit mask of the LINK_INBAND_* values from
+ * &enum link_inband_signalling to describe which inband modes are supported
+ * for this interface mode.
+ */
+unsigned int phy_query_inband(struct phy_device *phydev,
+ phy_interface_t interface)
+{
+ if (phydev->drv && phydev->drv->query_inband)
+ return phydev->drv->query_inband(phydev, interface);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(phy_query_inband);
+
+/**
* _phy_start_aneg - start auto-negotiation for this PHY device
* @phydev: the phy_device struct
*
@@ -1239,6 +1260,8 @@ void phy_stop_machine(struct phy_device *phydev)
static void phy_process_error(struct phy_device *phydev)
{
+ phydev_err(phydev, "Error detected, halting PHY\n");
+
/* phydev->lock must be held for the state change to be safe */
if (!mutex_is_locked(&phydev->lock))
phydev_err(phydev, "PHY-device data unsafe context\n");
@@ -1265,7 +1288,6 @@ static void phy_error_precise(struct phy_device *phydev,
*/
void phy_error(struct phy_device *phydev)
{
- WARN_ON(1);
phy_process_error(phydev);
}
EXPORT_SYMBOL(phy_error);
@@ -1290,7 +1312,6 @@ int phy_disable_interrupts(struct phy_device *phydev)
static irqreturn_t phy_interrupt(int irq, void *phy_dat)
{
struct phy_device *phydev = phy_dat;
- struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
/* Wakeup interrupts may occur during a system sleep transition.
@@ -1316,7 +1337,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
}
mutex_lock(&phydev->lock);
- ret = drv->handle_interrupt(phydev);
+ ret = phydev->drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
return ret;
@@ -1513,6 +1534,10 @@ void phy_stop(struct phy_device *phydev)
phy_process_state_change(phydev, old_state);
state_work = _phy_state_machine(phydev);
+
+ if (phydev->drv->stop)
+ phydev->drv->stop(phydev);
+
mutex_unlock(&phydev->lock);
_phy_state_machine_post_work(phydev, state_work);
@@ -1545,6 +1570,9 @@ void phy_start(struct phy_device *phydev)
goto out;
}
+ if (phydev->drv->start && phydev->drv->start(phydev))
+ goto out;
+
if (phydev->sfp_bus)
sfp_upstream_start(phydev->sfp_bus);