| From foo@baz Wed Sep 30 05:25:07 CEST 2015 |
| From: Stas Sergeev <stsp@list.ru> |
| Date: Mon, 20 Jul 2015 17:49:56 -0700 |
| Subject: net: phy: fixed_phy: handle link-down case |
| |
| From: Stas Sergeev <stsp@list.ru> |
| |
| [ Upstream 868a4215be9a6d80548ccb74763b883dc99d32a2 in net-next tree, |
| will be pushed to Linus very soon. ] |
| |
| fixed_phy_register() currently hardcodes the fixed PHY link to 1, and |
| expects to find a "speed" parameter to provide correct information |
| towards the fixed PHY consumer. |
| |
| In a subsequent change, where we allow "managed" (e.g: (RS)GMII in-band |
| status auto-negotiation) fixed PHYs, none of these parameters can be |
| provided since they will be auto-negotiated, hence, we just provide a |
| zero-initialized fixed_phy_status to fixed_phy_register() which makes it |
| fail when we call fixed_phy_update_regs() since status.speed = 0 which |
| makes us hit the "default" label and error out. |
| |
| Without this change, we would also see potentially inconsistent |
| speed/duplex parameters for fixed PHYs when the link is DOWN. |
| |
| CC: netdev@vger.kernel.org |
| CC: linux-kernel@vger.kernel.org |
| Signed-off-by: Stas Sergeev <stsp@users.sourceforge.net> |
| [florian: add more background to why this is correct and desirable] |
| Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/phy/fixed_phy.c | 8 +++++--- |
| 1 file changed, 5 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/net/phy/fixed_phy.c |
| +++ b/drivers/net/phy/fixed_phy.c |
| @@ -52,6 +52,10 @@ static int fixed_phy_update_regs(struct |
| 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 |
| } |
| } |
| |
| - 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; |
| |