e1000: correctly handle phy_ctrl reserved & self-clearing bits
Make phyreg_writeops responsible for actually writing their respective phy registers, rather than rely on set_mdic() to do it on their behalf. The only current instance of phyreg_writeops is set_phy_ctrl(); modify it to write the register on its own, while also correctly handling reserved and self-clearing bits. have_autoneg() does not need to check for MII_CR_RESTART_AUTO_NEG, since the only time the flag comes into play is during set_phy_ctrl(), and, following this patch, never actually gets written to the phy control register. Signed-off-by: Gabriel Somlo <somlo@cmu.edu> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
7f9efb6b80
commit
1195fed9e6
@ -186,21 +186,31 @@ e1000_link_up(E1000State *s)
|
||||
s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
|
||||
}
|
||||
|
||||
static bool
|
||||
have_autoneg(E1000State *s)
|
||||
{
|
||||
return (s->compat_flags & E1000_FLAG_AUTONEG) &&
|
||||
(s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN);
|
||||
}
|
||||
|
||||
static void
|
||||
set_phy_ctrl(E1000State *s, int index, uint16_t val)
|
||||
{
|
||||
/* bits 0-5 reserved; MII_CR_[RESTART_AUTO_NEG,RESET] are self clearing */
|
||||
s->phy_reg[PHY_CTRL] = val & ~(0x3f |
|
||||
MII_CR_RESET |
|
||||
MII_CR_RESTART_AUTO_NEG);
|
||||
|
||||
/*
|
||||
* QEMU 1.3 does not support link auto-negotiation emulation, so if we
|
||||
* migrate during auto negotiation, after migration the link will be
|
||||
* down.
|
||||
*/
|
||||
if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
|
||||
return;
|
||||
}
|
||||
if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) {
|
||||
if (have_autoneg(s) && (val & MII_CR_RESTART_AUTO_NEG)) {
|
||||
e1000_link_down(s);
|
||||
DBGOUT(PHY, "Start link auto negotiation\n");
|
||||
timer_mod(s->autoneg_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
|
||||
timer_mod(s->autoneg_timer,
|
||||
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
|
||||
}
|
||||
}
|
||||
|
||||
@ -446,8 +456,9 @@ set_mdic(E1000State *s, int index, uint32_t val)
|
||||
} else {
|
||||
if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) {
|
||||
phyreg_writeops[addr](s, index, data);
|
||||
} else {
|
||||
s->phy_reg[addr] = data;
|
||||
}
|
||||
s->phy_reg[addr] = data;
|
||||
}
|
||||
}
|
||||
s->mac_reg[MDIC] = val | E1000_MDIC_READY;
|
||||
@ -848,14 +859,6 @@ receive_filter(E1000State *s, const uint8_t *buf, int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
have_autoneg(E1000State *s)
|
||||
{
|
||||
return (s->compat_flags & E1000_FLAG_AUTONEG) &&
|
||||
(s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN) &&
|
||||
(s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG);
|
||||
}
|
||||
|
||||
static void
|
||||
e1000_set_link_status(NetClientState *nc)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user