From e07630ad84c7dc145863f079f108154fb7c975e7 Mon Sep 17 00:00:00 2001 From: Russell King 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 Signed-off-by: Russell King --- 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