summaryrefslogtreecommitdiffstats
path: root/target/linux/mvebu/patches-4.4/122-phy-separate-swphy-state-validation-from-register-ge.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mvebu/patches-4.4/122-phy-separate-swphy-state-validation-from-register-ge.patch')
-rw-r--r--target/linux/mvebu/patches-4.4/122-phy-separate-swphy-state-validation-from-register-ge.patch138
1 files changed, 138 insertions, 0 deletions
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
index 0000000000..4b332cc8b7
--- /dev/null
+++ b/target/linux/mvebu/patches-4.4/122-phy-separate-swphy-state-validation-from-register-ge.patch
@@ -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