Pull up following revision(s) (requested by msaitoh in ticket #487):
sys/dev/pci/if_bge.c: revision 1.340 sys/dev/pci/if_bge.c: revision 1.341 sys/dev/pci/if_bge.c: revision 1.342 sys/dev/pci/if_bge.c: revision 1.336 - Avoid undefined behavior in bge_setmulti(). found by kUBSan. - Avoid undefined behavior when setting the MAC address in bge_init(). found by kUBSan. Fix a bug that SK-9D41 can't detect fiber media. Check the subsystem ID correctly. This bug was added in if_bge.c rev. 1.161. - Use *_FLUSH() more. The main purpose is to wait following delay() correctly. - Add missing DELAY(80) after writing BGE_MI_MODE register. Modify PHY initialization code. This change fix a bug that SK-9D21 doesn't detect MII PHY. - Add error check to bge_miibus_writereg(). - Change return value of bge_miibus_readreg() when a read error occurred. It also add error message using with aprint_debug_dev(). This error occurs on some devices while detecting MII devices. - Move the location of BGE_MI_MODE register's initialization to next to bge_chipinit(). - Set BGE_MAC_MODE before calling ifmedia_init() and/or mii_attach(). - Add retry code for mii_attach() failed. Same as FreeBSD.
This commit is contained in:
parent
52075ce9b8
commit
c2ea55bc07
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_bge.c,v 1.335 2019/07/09 08:46:58 msaitoh Exp $ */
|
||||
/* $NetBSD: if_bge.c,v 1.335.2.1 2019/11/27 11:08:24 martin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wind River Systems
|
||||
|
@ -79,7 +79,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.335 2019/07/09 08:46:58 msaitoh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.335.2.1 2019/11/27 11:08:24 martin Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -1027,10 +1027,10 @@ bge_eeprom_getbyte(struct bge_softc *sc, int addr, uint8_t *dest)
|
|||
* Enable use of auto EEPROM access so we can avoid
|
||||
* having to use the bitbang method.
|
||||
*/
|
||||
BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_AUTO_EEPROM);
|
||||
BGE_SETBIT_FLUSH(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_AUTO_EEPROM);
|
||||
|
||||
/* Reset the EEPROM, load the clock period. */
|
||||
CSR_WRITE_4(sc, BGE_EE_ADDR,
|
||||
CSR_WRITE_4_FLUSH(sc, BGE_EE_ADDR,
|
||||
BGE_EEADDR_RESET | BGE_EEHALFCLK(BGE_HALFCLK_384SCL));
|
||||
DELAY(20);
|
||||
|
||||
|
@ -1113,9 +1113,11 @@ bge_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val)
|
|||
if (i == BGE_TIMEOUT) {
|
||||
aprint_error_dev(sc->bge_dev, "PHY read timed out\n");
|
||||
rv = ETIMEDOUT;
|
||||
} else if ((data & BGE_MICOMM_READFAIL) != 0)
|
||||
rv = -1;
|
||||
else
|
||||
} else if ((data & BGE_MICOMM_READFAIL) != 0) {
|
||||
/* XXX This error occurs on some devices while attaching. */
|
||||
aprint_debug_dev(sc->bge_dev, "PHY read I/O error\n");
|
||||
rv = EIO;
|
||||
} else
|
||||
*val = data & BGE_MICOMM_DATA;
|
||||
|
||||
if (autopoll & BGE_MIMODE_AUTOPOLL) {
|
||||
|
@ -1133,7 +1135,8 @@ static int
|
|||
bge_miibus_writereg(device_t dev, int phy, int reg, uint16_t val)
|
||||
{
|
||||
struct bge_softc *sc = device_private(dev);
|
||||
uint32_t autopoll;
|
||||
uint32_t data, autopoll;
|
||||
int rv = 0;
|
||||
int i;
|
||||
|
||||
if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906 &&
|
||||
|
@ -1156,13 +1159,22 @@ bge_miibus_writereg(device_t dev, int phy, int reg, uint16_t val)
|
|||
|
||||
for (i = 0; i < BGE_TIMEOUT; i++) {
|
||||
delay(10);
|
||||
if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) {
|
||||
data = CSR_READ_4(sc, BGE_MI_COMM);
|
||||
if (!(data & BGE_MICOMM_BUSY)) {
|
||||
delay(5);
|
||||
CSR_READ_4(sc, BGE_MI_COMM);
|
||||
data = CSR_READ_4(sc, BGE_MI_COMM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == BGE_TIMEOUT) {
|
||||
aprint_error_dev(sc->bge_dev, "PHY write timed out\n");
|
||||
rv = ETIMEDOUT;
|
||||
} else if ((data & BGE_MICOMM_READFAIL) != 0) {
|
||||
aprint_error_dev(sc->bge_dev, "PHY write I/O error\n");
|
||||
rv = EIO;
|
||||
}
|
||||
|
||||
if (autopoll & BGE_MIMODE_AUTOPOLL) {
|
||||
BGE_STS_SETBIT(sc, BGE_STS_AUTOPOLL);
|
||||
BGE_SETBIT_FLUSH(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
|
||||
|
@ -1176,7 +1188,7 @@ bge_miibus_writereg(device_t dev, int phy, int reg, uint16_t val)
|
|||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1827,7 +1839,7 @@ bge_setmulti(struct bge_softc *sc)
|
|||
/* Just want the 7 least-significant bits. */
|
||||
h &= 0x7f;
|
||||
|
||||
hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F);
|
||||
hashes[(h & 0x60) >> 5] |= 1U << (h & 0x1F);
|
||||
ETHER_NEXT_MULTI(step, enm);
|
||||
}
|
||||
ETHER_UNLOCK(ec);
|
||||
|
@ -2286,7 +2298,7 @@ bge_chipinit(struct bge_softc *sc)
|
|||
#endif
|
||||
|
||||
/* Set the timer prescaler (always 66MHz) */
|
||||
CSR_WRITE_4(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ);
|
||||
CSR_WRITE_4_FLUSH(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ);
|
||||
|
||||
if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
|
||||
DELAY(40); /* XXX */
|
||||
|
@ -3182,14 +3194,14 @@ bge_attach(device_t parent, device_t self, void *aux)
|
|||
uint32_t command;
|
||||
struct ifnet *ifp;
|
||||
struct mii_data * const mii = &sc->bge_mii;
|
||||
uint32_t misccfg, mimode;
|
||||
uint32_t misccfg, mimode, macmode;
|
||||
void * kva;
|
||||
u_char eaddr[ETHER_ADDR_LEN];
|
||||
pcireg_t memtype, subid, reg;
|
||||
bus_addr_t memaddr;
|
||||
uint32_t pm_ctl;
|
||||
bool no_seeprom;
|
||||
int capmask;
|
||||
int capmask, trys;
|
||||
int mii_flags;
|
||||
int map_flags;
|
||||
char intrbuf[PCI_INTRSTR_LEN];
|
||||
|
@ -3433,14 +3445,6 @@ bge_attach(device_t parent, device_t self, void *aux)
|
|||
BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM57780)
|
||||
sc->bge_flags |= BGEF_CPMU_PRESENT;
|
||||
|
||||
/* Set MI_MODE */
|
||||
mimode = BGE_MIMODE_PHYADDR(sc->bge_phy_addr);
|
||||
if ((sc->bge_flags & BGEF_CPMU_PRESENT) != 0)
|
||||
mimode |= BGE_MIMODE_500KHZ_CONST;
|
||||
else
|
||||
mimode |= BGE_MIMODE_BASE;
|
||||
CSR_WRITE_4(sc, BGE_MI_MODE, mimode);
|
||||
|
||||
/*
|
||||
* When using the BCM5701 in PCI-X mode, data corruption has
|
||||
* been observed in the first few bytes of some received packets.
|
||||
|
@ -3636,10 +3640,10 @@ bge_attach(device_t parent, device_t self, void *aux)
|
|||
* Reset NVRAM before bge_reset(). It's required to acquire NVRAM
|
||||
* lock in bge_reset().
|
||||
*/
|
||||
CSR_WRITE_4(sc, BGE_EE_ADDR,
|
||||
CSR_WRITE_4_FLUSH(sc, BGE_EE_ADDR,
|
||||
BGE_EEADDR_RESET | BGE_EEHALFCLK(BGE_HALFCLK_384SCL));
|
||||
delay(1000);
|
||||
BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_AUTO_EEPROM);
|
||||
BGE_SETBIT_FLUSH(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_AUTO_EEPROM);
|
||||
|
||||
bge_stop_fw(sc);
|
||||
bge_sig_pre_reset(sc, BGE_RESET_START);
|
||||
|
@ -3685,6 +3689,21 @@ bge_attach(device_t parent, device_t self, void *aux)
|
|||
return;
|
||||
}
|
||||
|
||||
if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5700) {
|
||||
BGE_SETBIT_FLUSH(sc, BGE_MISC_LOCAL_CTL,
|
||||
BGE_MLC_MISCIO_OUT1 | BGE_MLC_MISCIO_OUTEN1);
|
||||
DELAY(100);
|
||||
}
|
||||
|
||||
/* Set MI_MODE */
|
||||
mimode = BGE_MIMODE_PHYADDR(sc->bge_phy_addr);
|
||||
if ((sc->bge_flags & BGEF_CPMU_PRESENT) != 0)
|
||||
mimode |= BGE_MIMODE_500KHZ_CONST;
|
||||
else
|
||||
mimode |= BGE_MIMODE_BASE;
|
||||
CSR_WRITE_4_FLUSH(sc, BGE_MI_MODE, mimode);
|
||||
DELAY(80);
|
||||
|
||||
/*
|
||||
* Get station address from the EEPROM.
|
||||
*/
|
||||
|
@ -3853,7 +3872,7 @@ bge_attach(device_t parent, device_t self, void *aux)
|
|||
* by its PCI subsystem ID, as we do below for the SysKonnect SK-9D41.
|
||||
* The SysKonnect SK-9D41 is a 1000baseSX card.
|
||||
*/
|
||||
if (PCI_PRODUCT(pa->pa_id) == SK_SUBSYSID_9D41 ||
|
||||
if (PCI_PRODUCT(subid) == SK_SUBSYSID_9D41 ||
|
||||
(hwcfg & BGE_HWCFG_MEDIA) == BGE_MEDIA_FIBER) {
|
||||
if (BGE_IS_5705_PLUS(sc)) {
|
||||
sc->bge_flags |= BGEF_FIBER_MII;
|
||||
|
@ -3871,8 +3890,14 @@ bge_attach(device_t parent, device_t self, void *aux)
|
|||
prop_dictionary_set_uint32(dict, "phyflags", sc->bge_phy_flags);
|
||||
prop_dictionary_set_uint32(dict, "chipid", sc->bge_chipid);
|
||||
|
||||
macmode = CSR_READ_4(sc, BGE_MAC_MODE);
|
||||
macmode &= ~BGE_MACMODE_PORTMODE;
|
||||
/* Initialize ifmedia structures. */
|
||||
if (sc->bge_flags & BGEF_FIBER_TBI) {
|
||||
CSR_WRITE_4_FLUSH(sc, BGE_MAC_MODE,
|
||||
macmode | BGE_PORTMODE_TBI);
|
||||
DELAY(40);
|
||||
|
||||
sc->ethercom.ec_ifmedia = &sc->bge_ifmedia;
|
||||
ifmedia_init(&sc->bge_ifmedia, IFM_IMASK, bge_ifmedia_upd,
|
||||
bge_ifmedia_sts);
|
||||
|
@ -3884,6 +3909,8 @@ bge_attach(device_t parent, device_t self, void *aux)
|
|||
/* Pretend the user requested this setting */
|
||||
sc->bge_ifmedia.ifm_media = sc->bge_ifmedia.ifm_cur->ifm_media;
|
||||
} else {
|
||||
uint16_t phyreg;
|
||||
int rv;
|
||||
/*
|
||||
* Do transceiver setup and tell the firmware the
|
||||
* driver is down so we can try to get access the
|
||||
|
@ -3891,18 +3918,53 @@ bge_attach(device_t parent, device_t self, void *aux)
|
|||
* if we get a conflict with the ASF firmware accessing
|
||||
* the PHY.
|
||||
*/
|
||||
BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
|
||||
bge_asf_driver_up(sc);
|
||||
if (sc->bge_flags & BGEF_FIBER_MII)
|
||||
macmode |= BGE_PORTMODE_GMII;
|
||||
else
|
||||
macmode |= BGE_PORTMODE_MII;
|
||||
CSR_WRITE_4_FLUSH(sc, BGE_MAC_MODE, macmode);
|
||||
DELAY(40);
|
||||
|
||||
/*
|
||||
* Do transceiver setup and tell the firmware the
|
||||
* driver is down so we can try to get access the
|
||||
* probe if ASF is running. Retry a couple of times
|
||||
* if we get a conflict with the ASF firmware accessing
|
||||
* the PHY.
|
||||
*/
|
||||
trys = 0;
|
||||
BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
|
||||
sc->ethercom.ec_mii = mii;
|
||||
ifmedia_init(&mii->mii_media, 0, bge_ifmedia_upd,
|
||||
bge_ifmedia_sts);
|
||||
mii_flags = MIIF_DOPAUSE;
|
||||
if (sc->bge_flags & BGEF_FIBER_MII)
|
||||
mii_flags |= MIIF_HAVEFIBER;
|
||||
again:
|
||||
bge_asf_driver_up(sc);
|
||||
rv = bge_miibus_readreg(sc->bge_dev, sc->bge_phy_addr,
|
||||
MII_BMCR, &phyreg);
|
||||
if ((rv != 0) || ((phyreg & BMCR_PDOWN) != 0)) {
|
||||
int i;
|
||||
|
||||
bge_miibus_writereg(sc->bge_dev, sc->bge_phy_addr,
|
||||
MII_BMCR, BMCR_RESET);
|
||||
/* Wait up to 500ms for it to complete. */
|
||||
for (i = 0; i < 500; i++) {
|
||||
bge_miibus_readreg(sc->bge_dev,
|
||||
sc->bge_phy_addr, MII_BMCR, &phyreg);
|
||||
if ((phyreg & BMCR_RESET) == 0)
|
||||
break;
|
||||
DELAY(1000);
|
||||
}
|
||||
}
|
||||
|
||||
mii_attach(sc->bge_dev, mii, capmask, sc->bge_phy_addr,
|
||||
MII_OFFSET_ANY, mii_flags);
|
||||
|
||||
if (LIST_EMPTY(&mii->mii_phys) && (trys++ < 4))
|
||||
goto again;
|
||||
|
||||
if (LIST_EMPTY(&mii->mii_phys)) {
|
||||
aprint_error_dev(sc->bge_dev, "no PHY found!\n");
|
||||
ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_MANUAL,
|
||||
|
@ -5530,7 +5592,8 @@ bge_init(struct ifnet *ifp)
|
|||
/* Load our MAC address. */
|
||||
m = (const uint16_t *)&(CLLADDR(ifp->if_sadl)[0]);
|
||||
CSR_WRITE_4(sc, BGE_MAC_ADDR1_LO, htons(m[0]));
|
||||
CSR_WRITE_4(sc, BGE_MAC_ADDR1_HI, (htons(m[1]) << 16) | htons(m[2]));
|
||||
CSR_WRITE_4(sc, BGE_MAC_ADDR1_HI,
|
||||
((uint32_t)htons(m[1]) << 16) | htons(m[2]));
|
||||
|
||||
/* Enable or disable promiscuous mode as needed. */
|
||||
if (ifp->if_flags & IFF_PROMISC)
|
||||
|
@ -5676,10 +5739,10 @@ bge_ifmedia_upd(struct ifnet *ifp)
|
|||
break;
|
||||
case IFM_1000_SX:
|
||||
if ((ifm->ifm_media & IFM_FDX) != 0) {
|
||||
BGE_CLRBIT(sc, BGE_MAC_MODE,
|
||||
BGE_CLRBIT_FLUSH(sc, BGE_MAC_MODE,
|
||||
BGE_MACMODE_HALF_DUPLEX);
|
||||
} else {
|
||||
BGE_SETBIT(sc, BGE_MAC_MODE,
|
||||
BGE_SETBIT_FLUSH(sc, BGE_MAC_MODE,
|
||||
BGE_MACMODE_HALF_DUPLEX);
|
||||
}
|
||||
DELAY(40);
|
||||
|
@ -6077,7 +6140,7 @@ bge_link_upd(struct bge_softc *sc)
|
|||
BGE_STS_SETBIT(sc, BGE_STS_LINK);
|
||||
if (BGE_ASICREV(sc->bge_chipid)
|
||||
== BGE_ASICREV_BCM5704) {
|
||||
BGE_CLRBIT(sc, BGE_MAC_MODE,
|
||||
BGE_CLRBIT_FLUSH(sc, BGE_MAC_MODE,
|
||||
BGE_MACMODE_TBI_SEND_CFGS);
|
||||
DELAY(40);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue