Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-9]: src/sys/dev/pci Pull up following revision(s) (requested by m...
details: https://anonhg.NetBSD.org/src/rev/8ace2963d869
branches: netbsd-9
changeset: 963338:8ace2963d869
user: martin <martin%NetBSD.org@localhost>
date: Wed Nov 27 11:08:24 2019 +0000
description:
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.
diffstat:
sys/dev/pci/if_bge.c | 127 ++++++++++++++++++++++++++++++++++++++------------
1 files changed, 95 insertions(+), 32 deletions(-)
diffs (296 lines):
diff -r f0caa5718f36 -r 8ace2963d869 sys/dev/pci/if_bge.c
--- a/sys/dev/pci/if_bge.c Tue Nov 26 18:31:55 2019 +0000
+++ b/sys/dev/pci/if_bge.c Wed Nov 27 11:08:24 2019 +0000
@@ -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 @@
* 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 @@
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 @@
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 @@
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 @@
return ETIMEDOUT;
}
- return 0;
+ return rv;
}
static void
@@ -1827,7 +1839,7 @@
/* 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 @@
#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 @@
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_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 @@
* 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 @@
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 @@
* 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 @@
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,22 @@
/* 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
+ * probe if ASF is running. Retry a couple of times
+ * if we get a conflict with the ASF firmware accessing
+ * the PHY.
+ */
+ 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
@@ -3891,18 +3932,39 @@
* if we get a conflict with the ASF firmware accessing
* the PHY.
*/
+ trys = 0;
BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
- bge_asf_driver_up(sc);
-
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 @@
/* 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 @@
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_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);
}
Home |
Main Index |
Thread Index |
Old Index