Module Name: src
Committed By: leot
Date: Tue Sep 8 08:24:42 UTC 2015
Modified Files:
src/sys/dev/pci: if_alc.c if_alcreg.h
Log Message:
Add some missing fixes to alc(4) to sync with the latest FreeBSD and OpenBSD
alc(4)s.
Fix a long standing bug in MAC statistics register access. One
additional register was erroneously added in the MAC register set
such that 7 TX statistics counters were wrong. (from OpenBSD, if_alc.c 1.29)
Remove setting an initial assumed baudrate upon driver attach which is not
necessarily correct, there might not even be a link when attaching.
(from OpenBSD, if_alc.c 1.22)
Add some missing bus_dmamap_sync()'s and sync the others with
the FreeBSD code. (from OpenBSD, if_alc.c 1.21)
Help with the watchdog timeouts seen when unplugging the cable from
the alc(4) NIC while running or the NIC not working if the cable is
not plugged in upon boot up. (from OpenBSD, if_alc.c 1.16)
ok mrg@
To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/pci/if_alc.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/pci/if_alcreg.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/if_alc.c
diff -u src/sys/dev/pci/if_alc.c:1.14 src/sys/dev/pci/if_alc.c:1.15
--- src/sys/dev/pci/if_alc.c:1.14 Mon Apr 13 16:33:25 2015
+++ src/sys/dev/pci/if_alc.c Tue Sep 8 08:24:42 2015
@@ -527,6 +527,9 @@ alc_mediastatus(struct ifnet *ifp, struc
struct alc_softc *sc = ifp->if_softc;
struct mii_data *mii = &sc->sc_miibus;
+ if ((ifp->if_flags & IFF_UP) == 0)
+ return;
+
mii_pollstat(mii);
ifmr->ifm_status = mii->mii_media_status;
ifmr->ifm_active = mii->mii_media_active;
@@ -1405,7 +1408,6 @@ alc_attach(device_t parent, device_t sel
ifp->if_start = alc_start;
ifp->if_stop = alc_stop;
ifp->if_watchdog = alc_watchdog;
- ifp->if_baudrate = IF_Gbps(1);
IFQ_SET_MAXLEN(&ifp->if_snd, ALC_TX_RING_CNT - 1);
IFQ_SET_READY(&ifp->if_snd);
strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
@@ -1959,6 +1961,10 @@ alc_start(struct ifnet *ifp)
if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
return;
+ if ((sc->alc_flags & ALC_FLAG_LINK) == 0)
+ return;
+ if (IFQ_IS_EMPTY(&ifp->if_snd))
+ return;
/* Reclaim transmitted frames. */
if (sc->alc_cdata.alc_tx_cnt >= ALC_TX_DESC_HIWAT)
@@ -2021,9 +2027,7 @@ alc_watchdog(struct ifnet *ifp)
printf("%s: watchdog timeout\n", device_xname(sc->sc_dev));
ifp->if_oerrors++;
alc_init_backend(ifp, false);
-
- if (!IFQ_IS_EMPTY(&ifp->if_snd))
- alc_start(ifp);
+ alc_start(ifp);
}
static int
@@ -2089,13 +2093,13 @@ alc_stats_clear(struct alc_softc *sc)
if ((sc->alc_flags & ALC_FLAG_SMB_BUG) == 0) {
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_smb_map, 0,
sc->alc_cdata.alc_smb_map->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
smb = sc->alc_rdata.alc_smb;
/* Update done, clear. */
smb->updated = 0;
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_smb_map, 0,
sc->alc_cdata.alc_smb_map->dm_mapsize,
- BUS_DMASYNC_PREWRITE);
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
} else {
for (reg = &sb.rx_frames, i = 0; reg <= &sb.rx_pkts_filtered;
reg++) {
@@ -2124,7 +2128,7 @@ alc_stats_update(struct alc_softc *sc)
if ((sc->alc_flags & ALC_FLAG_SMB_BUG) == 0) {
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_smb_map, 0,
sc->alc_cdata.alc_smb_map->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
smb = sc->alc_rdata.alc_smb;
if (smb->updated == 0)
return;
@@ -2190,7 +2194,6 @@ alc_stats_update(struct alc_softc *sc)
stat->tx_multi_colls += smb->tx_multi_colls;
stat->tx_late_colls += smb->tx_late_colls;
stat->tx_excess_colls += smb->tx_excess_colls;
- stat->tx_abort += smb->tx_abort;
stat->tx_underrun += smb->tx_underrun;
stat->tx_desc_underrun += smb->tx_desc_underrun;
stat->tx_lenerrs += smb->tx_lenerrs;
@@ -2203,17 +2206,10 @@ alc_stats_update(struct alc_softc *sc)
ifp->if_collisions += smb->tx_single_colls +
smb->tx_multi_colls * 2 + smb->tx_late_colls +
- smb->tx_abort * HDPX_CFG_RETRY_DEFAULT;
+ smb->tx_excess_colls * HDPX_CFG_RETRY_DEFAULT;
- /*
- * XXX
- * tx_pkts_truncated counter looks suspicious. It constantly
- * increments with no sign of Tx errors. This may indicate
- * the counter name is not correct one so I've removed the
- * counter in output errors.
- */
- ifp->if_oerrors += smb->tx_abort + smb->tx_late_colls +
- smb->tx_underrun;
+ ifp->if_oerrors += smb->tx_late_colls + smb->tx_excess_colls +
+ smb->tx_underrun + smb->tx_pkts_truncated;
ifp->if_ipackets += smb->rx_frames;
@@ -2226,7 +2222,8 @@ alc_stats_update(struct alc_softc *sc)
/* Update done, clear. */
smb->updated = 0;
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_smb_map, 0,
- sc->alc_cdata.alc_smb_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
+ sc->alc_cdata.alc_smb_map->dm_mapsize,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
}
@@ -2318,6 +2315,8 @@ alc_txeof(struct alc_softc *sc)
txd = &sc->alc_cdata.alc_txdesc[cons];
if (txd->tx_m != NULL) {
/* Reclaim transmitted mbufs. */
+ bus_dmamap_sync(sc->sc_dmat, txd->tx_dmamap, 0,
+ txd->tx_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, txd->tx_dmamap);
m_freem(txd->tx_m);
txd->tx_m = NULL;
@@ -2326,7 +2325,7 @@ alc_txeof(struct alc_softc *sc)
if ((sc->alc_flags & ALC_FLAG_CMB_BUG) == 0)
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_cmb_map, 0,
- sc->alc_cdata.alc_cmb_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
+ sc->alc_cdata.alc_cmb_map->dm_mapsize, BUS_DMASYNC_PREREAD);
sc->alc_cdata.alc_tx_cons = cons;
/*
* Unarm watchdog timer only when there is no pending
@@ -2381,6 +2380,8 @@ alc_newbuf(struct alc_softc *sc, struct
map = rxd->rx_dmamap;
rxd->rx_dmamap = sc->alc_cdata.alc_rx_sparemap;
sc->alc_cdata.alc_rx_sparemap = map;
+ bus_dmamap_sync(sc->sc_dmat, rxd->rx_dmamap, 0, rxd->rx_dmamap->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
rxd->rx_m = m;
rxd->rx_desc->addr = htole64(rxd->rx_dmamap->dm_segs[0].ds_addr);
return (0);
@@ -2395,9 +2396,11 @@ alc_rxintr(struct alc_softc *sc)
int rr_cons, prog;
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_rr_ring_map, 0,
- sc->alc_cdata.alc_rr_ring_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
+ sc->alc_cdata.alc_rr_ring_map->dm_mapsize,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_rx_ring_map, 0,
- sc->alc_cdata.alc_rx_ring_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
+ sc->alc_cdata.alc_rx_ring_map->dm_mapsize,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
rr_cons = sc->alc_cdata.alc_rr_cons;
for (prog = 0; (ifp->if_flags & IFF_RUNNING) != 0;) {
rrd = &sc->alc_rdata.alc_rr_ring[rr_cons];
@@ -2427,7 +2430,7 @@ alc_rxintr(struct alc_softc *sc)
/* Sync Rx return descriptors. */
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_rr_ring_map, 0,
sc->alc_cdata.alc_rr_ring_map->dm_mapsize,
- BUS_DMASYNC_PREWRITE);
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
/*
* Sync updated Rx descriptors such that controller see
* modified buffer addresses.
@@ -3153,6 +3156,8 @@ alc_stop(struct ifnet *ifp, int disable)
for (i = 0; i < ALC_RX_RING_CNT; i++) {
rxd = &sc->alc_cdata.alc_rxdesc[i];
if (rxd->rx_m != NULL) {
+ bus_dmamap_sync(sc->sc_dmat, rxd->rx_dmamap, 0,
+ rxd->rx_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->sc_dmat, rxd->rx_dmamap);
m_freem(rxd->rx_m);
rxd->rx_m = NULL;
@@ -3161,6 +3166,8 @@ alc_stop(struct ifnet *ifp, int disable)
for (i = 0; i < ALC_TX_RING_CNT; i++) {
txd = &sc->alc_cdata.alc_txdesc[i];
if (txd->tx_m != NULL) {
+ bus_dmamap_sync(sc->sc_dmat, txd->tx_dmamap, 0,
+ txd->tx_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, txd->tx_dmamap);
m_freem(txd->tx_m);
txd->tx_m = NULL;
@@ -3319,7 +3326,8 @@ alc_init_rr_ring(struct alc_softc *sc)
rd = &sc->alc_rdata;
memset(rd->alc_rr_ring, 0, ALC_RR_RING_SZ);
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_rr_ring_map, 0,
- sc->alc_cdata.alc_rr_ring_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
+ sc->alc_cdata.alc_rr_ring_map->dm_mapsize,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
static void
@@ -3330,7 +3338,8 @@ alc_init_cmb(struct alc_softc *sc)
rd = &sc->alc_rdata;
memset(rd->alc_cmb, 0, ALC_CMB_SZ);
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_cmb_map, 0,
- sc->alc_cdata.alc_cmb_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
+ sc->alc_cdata.alc_cmb_map->dm_mapsize,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
static void
@@ -3341,7 +3350,8 @@ alc_init_smb(struct alc_softc *sc)
rd = &sc->alc_rdata;
memset(rd->alc_smb, 0, ALC_SMB_SZ);
bus_dmamap_sync(sc->sc_dmat, sc->alc_cdata.alc_smb_map, 0,
- sc->alc_cdata.alc_smb_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
+ sc->alc_cdata.alc_smb_map->dm_mapsize,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
static void
Index: src/sys/dev/pci/if_alcreg.h
diff -u src/sys/dev/pci/if_alcreg.h:1.3 src/sys/dev/pci/if_alcreg.h:1.4
--- src/sys/dev/pci/if_alcreg.h:1.3 Sun Jan 18 15:30:03 2015
+++ src/sys/dev/pci/if_alcreg.h Tue Sep 8 08:24:42 2015
@@ -200,7 +200,7 @@
* alc(4) does not rely on Tx completion interrupts, so set it
* somewhat large value to reduce Tx completion interrupts.
*/
-#define ALC_IM_TX_TIMER_DEFAULT 50000 /* 50ms */
+#define ALC_IM_TX_TIMER_DEFAULT 1000 /* 1ms */
#define ALC_GPHY_CFG 0x140C /* 16 bits, 32 bits on AR816x */
#define GPHY_CFG_EXT_RESET 0x0001
@@ -1147,7 +1147,6 @@ struct smb {
uint32_t tx_multi_colls;
uint32_t tx_late_colls;
uint32_t tx_excess_colls;
- uint32_t tx_abort;
uint32_t tx_underrun;
uint32_t tx_desc_underrun;
uint32_t tx_lenerrs;
@@ -1421,7 +1420,6 @@ struct alc_hw_stats {
uint32_t tx_multi_colls;
uint32_t tx_late_colls;
uint32_t tx_excess_colls;
- uint32_t tx_abort;
uint32_t tx_underrun;
uint32_t tx_desc_underrun;
uint32_t tx_lenerrs;