aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy
diff options
context:
space:
mode:
authorStas Sergeev <stsp@list.ru>2015-04-01 13:30:31 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-03 15:08:20 -0400
commita3bebdce4135a44d09e96ba66c40797c8f9fa902 (patch)
tree8627743774e7dbf217f0d46c770a7baa6002b067 /drivers/net/phy
parentbcad57182425426dd4aa14deb27f97acb329f3cd (diff)
add fixed_phy_update_state() - update state of fixed_phy
Currently fixed_phy uses a callback to periodically poll the link state. This patch adds the fixed_phy_update_state() API. It solves the following problems: - On link state interrupt, MAC driver can't update status. Instead it needs to provide the callback to periodically query the HW about the link state. It is more efficient to update status after interrupt. - The callback needs to be unregistered before phy_disconnect(), or otherwise it will be called with net_dev==NULL. phy_disconnect() does not have enough info to unregister the callback automatically. - The callback needs to be registered before of_phy_connect() to avoid running with outdated state, but of_phy_connect() returns the phy_device pointer, which is needed to register the callback. Registering it before of_phy_connect() will therefore require a hack to get the pointer earlier. Overall, this addition makes the subsequent patch that implements SGMII link status for mvneta, much cleaner. CC: Florian Fainelli <f.fainelli@gmail.com> CC: netdev@vger.kernel.org CC: linux-kernel@vger.kernel.org Signed-off-by: Stas Sergeev <stsp@users.sourceforge.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/fixed_phy.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index a08a3c78ba97..1960b46add65 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -183,6 +183,35 @@ int fixed_phy_set_link_update(struct phy_device *phydev,
183} 183}
184EXPORT_SYMBOL_GPL(fixed_phy_set_link_update); 184EXPORT_SYMBOL_GPL(fixed_phy_set_link_update);
185 185
186int fixed_phy_update_state(struct phy_device *phydev,
187 const struct fixed_phy_status *status,
188 const struct fixed_phy_status *changed)
189{
190 struct fixed_mdio_bus *fmb = &platform_fmb;
191 struct fixed_phy *fp;
192
193 if (!phydev || !phydev->bus)
194 return -EINVAL;
195
196 list_for_each_entry(fp, &fmb->phys, node) {
197 if (fp->addr == phydev->addr) {
198#define _UPD(x) if (changed->x) \
199 fp->status.x = status->x
200 _UPD(link);
201 _UPD(speed);
202 _UPD(duplex);
203 _UPD(pause);
204 _UPD(asym_pause);
205#undef _UPD
206 fixed_phy_update_regs(fp);
207 return 0;
208 }
209 }
210
211 return -ENOENT;
212}
213EXPORT_SYMBOL(fixed_phy_update_state);
214
186int fixed_phy_add(unsigned int irq, int phy_addr, 215int fixed_phy_add(unsigned int irq, int phy_addr,
187 struct fixed_phy_status *status) 216 struct fixed_phy_status *status)
188{ 217{