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>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Russell King 2016-06-23 14:50:15 +01:00 коммит произвёл David S. Miller
Родитель 0629bf17ea
Коммит 68888ce075
3 изменённых файлов: 35 добавлений и 16 удалений

Просмотреть файл

@ -48,12 +48,12 @@ static struct fixed_mdio_bus platform_fmb = {
.phys = LIST_HEAD_INIT(platform_fmb.phys), .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)) if (gpio_is_valid(fp->link_gpio))
fp->status.link = !!gpio_get_value_cansleep(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) static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)
@ -160,6 +160,10 @@ int fixed_phy_add(unsigned int irq, int phy_addr,
struct fixed_mdio_bus *fmb = &platform_fmb; struct fixed_mdio_bus *fmb = &platform_fmb;
struct fixed_phy *fp; struct fixed_phy *fp;
ret = swphy_validate_state(status);
if (ret < 0)
return ret;
fp = kzalloc(sizeof(*fp), GFP_KERNEL); fp = kzalloc(sizeof(*fp), GFP_KERNEL);
if (!fp) if (!fp)
return -ENOMEM; return -ENOMEM;
@ -180,17 +184,12 @@ int fixed_phy_add(unsigned int irq, int phy_addr,
goto err_regs; goto err_regs;
} }
ret = fixed_phy_update_regs(fp); fixed_phy_update_regs(fp);
if (ret)
goto err_gpio;
list_add_tail(&fp->node, &fmb->phys); list_add_tail(&fp->node, &fmb->phys);
return 0; return 0;
err_gpio:
if (gpio_is_valid(fp->link_gpio))
gpio_free(fp->link_gpio);
err_regs: err_regs:
kfree(fp); kfree(fp);
return ret; return ret;

Просмотреть файл

@ -86,6 +86,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 * swphy_update_regs - update MII register array with fixed phy state
* @regs: array of 32 registers to update * @regs: array of 32 registers to update
@ -94,7 +117,7 @@ static int swphy_decode_speed(int speed)
* Update the array of MII registers with the fixed phy link, speed, * Update the array of MII registers with the fixed phy link, speed,
* duplex and pause mode settings. * 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; int speed_index, duplex_index;
u16 bmsr = BMSR_ANEGCAPABLE; u16 bmsr = BMSR_ANEGCAPABLE;
@ -103,10 +126,8 @@ int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state)
u16 lpa = 0; u16 lpa = 0;
speed_index = swphy_decode_speed(state->speed); speed_index = swphy_decode_speed(state->speed);
if (speed_index < 0) { if (WARN_ON(speed_index < 0))
pr_warn("swphy: unknown speed\n"); return;
return -EINVAL;
}
duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF; duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF;
@ -133,7 +154,5 @@ int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state)
regs[MII_BMCR] = bmcr; regs[MII_BMCR] = bmcr;
regs[MII_LPA] = lpa; regs[MII_LPA] = lpa;
regs[MII_STAT1000] = lpagb; regs[MII_STAT1000] = lpagb;
return 0;
} }
EXPORT_SYMBOL_GPL(swphy_update_regs); EXPORT_SYMBOL_GPL(swphy_update_regs);

Просмотреть файл

@ -3,6 +3,7 @@
struct fixed_phy_status; 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 #endif