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@
This commit is contained in:
parent
6639db6cc2
commit
5abfef80e1
|
@ -527,6 +527,9 @@ alc_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
|
|||
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 self, void *aux)
|
|||
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 alc_rxdesc *rxd, bool init)
|
|||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue