mvebu: add support for SFP
[openwrt/openwrt.git] / target / linux / mvebu / patches-4.4 / 122-phy-separate-swphy-state-validation-from-register-ge.patch
diff --git a/target/linux/mvebu/patches-4.4/122-phy-separate-swphy-state-validation-from-register-ge.patch b/target/linux/mvebu/patches-4.4/122-phy-separate-swphy-state-validation-from-register-ge.patch
new file mode 100644 (file)
index 0000000..4b332cc
--- /dev/null
@@ -0,0 +1,138 @@
+From e07630ad84c7dc145863f079f108154fb7c975e7 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Sun, 20 Sep 2015 11:12:15 +0100
+Subject: [PATCH 711/744] phy: separate swphy state validation from register
+ generation
+
+Separate out the generation of MII registers from the state validation.
+This allows us to simplify the error handing in fixed_phy() by allowing
+earlier error detection.
+
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ drivers/net/phy/fixed_phy.c | 15 +++++++--------
+ drivers/net/phy/swphy.c     | 33 ++++++++++++++++++++++++++-------
+ drivers/net/phy/swphy.h     |  3 ++-
+ 3 files changed, 35 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/phy/fixed_phy.c
++++ b/drivers/net/phy/fixed_phy.c
+@@ -49,12 +49,12 @@ static struct fixed_mdio_bus platform_fm
+       .phys = LIST_HEAD_INIT(platform_fmb.phys),
+ };
+-static int fixed_phy_update_regs(struct fixed_phy *fp)
++static void fixed_phy_update_regs(struct fixed_phy *fp)
+ {
+       if (gpio_is_valid(fp->link_gpio))
+               fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio);
+-      return swphy_update_regs(fp->regs, &fp->status);
++      swphy_update_regs(fp->regs, &fp->status);
+ }
+ static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)
+@@ -161,6 +161,10 @@ int fixed_phy_add(unsigned int irq, int
+       struct fixed_mdio_bus *fmb = &platform_fmb;
+       struct fixed_phy *fp;
++      ret = swphy_validate_state(status);
++      if (ret < 0)
++              return ret;
++
+       fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+       if (!fp)
+               return -ENOMEM;
+@@ -180,17 +184,12 @@ int fixed_phy_add(unsigned int irq, int
+                       goto err_regs;
+       }
+-      ret = fixed_phy_update_regs(fp);
+-      if (ret)
+-              goto err_gpio;
++      fixed_phy_update_regs(fp);
+       list_add_tail(&fp->node, &fmb->phys);
+       return 0;
+-err_gpio:
+-      if (gpio_is_valid(fp->link_gpio))
+-              gpio_free(fp->link_gpio);
+ err_regs:
+       kfree(fp);
+       return ret;
+--- a/drivers/net/phy/swphy.c
++++ b/drivers/net/phy/swphy.c
+@@ -87,6 +87,29 @@ static int swphy_decode_speed(int speed)
+ }
+ /**
++ * swphy_validate_state - validate the software phy status
++ * @state: software phy status
++ *
++ * This checks that we can represent the state stored in @state can be
++ * represented in the emulated MII registers.  Returns 0 if it can,
++ * otherwise returns -EINVAL.
++ */
++int swphy_validate_state(const struct fixed_phy_status *state)
++{
++      int err;
++
++      if (state->link) {
++              err = swphy_decode_speed(state->speed);
++              if (err < 0) {
++                      pr_warn("swphy: unknown speed\n");
++                      return -EINVAL;
++              }
++      }
++      return 0;
++}
++EXPORT_SYMBOL_GPL(swphy_validate_state);
++
++/**
+  * swphy_update_regs - update MII register array with fixed phy state
+  * @regs: array of 32 registers to update
+  * @state: fixed phy status
+@@ -94,7 +117,7 @@ static int swphy_decode_speed(int speed)
+  * Update the array of MII registers with the fixed phy link, speed,
+  * duplex and pause mode settings.
+  */
+-int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state)
++void swphy_update_regs(u16 *regs, const struct fixed_phy_status *state)
+ {
+       int speed_index, duplex_index;
+       u16 bmsr = BMSR_ANEGCAPABLE;
+@@ -103,10 +126,8 @@ int swphy_update_regs(u16 *regs, const s
+       u16 lpa = 0;
+       speed_index = swphy_decode_speed(state->speed);
+-      if (speed_index < 0) {
+-              pr_warn("swphy: unknown speed\n");
+-              return -EINVAL;
+-      }
++      if (WARN_ON(speed_index < 0))
++              return;
+       duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF;
+@@ -133,7 +154,5 @@ int swphy_update_regs(u16 *regs, const s
+       regs[MII_BMCR] = bmcr;
+       regs[MII_LPA] = lpa;
+       regs[MII_STAT1000] = lpagb;
+-
+-      return 0;
+ }
+ EXPORT_SYMBOL_GPL(swphy_update_regs);
+--- a/drivers/net/phy/swphy.h
++++ b/drivers/net/phy/swphy.h
+@@ -3,6 +3,7 @@
+ struct fixed_phy_status;
+-int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state);
++int swphy_validate_state(const struct fixed_phy_status *state);
++void swphy_update_regs(u16 *regs, const struct fixed_phy_status *state);
+ #endif