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:
Родитель
0629bf17ea
Коммит
68888ce075
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче