Please could you split out the PNIC parts of the diff? They would
definitely be a separate commit whatever happens with MCLGETI, and
I think they make sense.
quoted text > Index: src/sys/dev/ic/dc.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/dc.c,v
> retrieving revision 1.121
> diff -u -p -r1.121 dc.c
> --- src/sys/dev/ic/dc.c 7 Sep 2010 16:21:42 -0000 1.121
> +++ src/sys/dev/ic/dc.c 13 Dec 2010 18:43:42 -0000
> @@ -131,12 +131,11 @@
>
> int dc_intr(void *);
> struct dc_type *dc_devtype(void *);
> -int dc_newbuf(struct dc_softc *, int, struct mbuf *);
> +int dc_newbuf(struct dc_softc *);
> int dc_encap(struct dc_softc *, struct mbuf *, u_int32_t *);
> int dc_coal(struct dc_softc *, struct mbuf **);
>
> void dc_pnic_rx_bug_war(struct dc_softc *, int);
> -int dc_rx_resync(struct dc_softc *);
> void dc_rxeof(struct dc_softc *);
> void dc_txeof(struct dc_softc *);
> void dc_tick(void *);
> @@ -178,6 +177,7 @@ void dc_setfilt(struct dc_softc *);
>
> void dc_reset(struct dc_softc *);
> int dc_list_rx_init(struct dc_softc *);
> +void dc_fill_rx_ring(struct dc_softc *);
> int dc_list_tx_init(struct dc_softc *);
>
> void dc_read_srom(struct dc_softc *, int);
> @@ -1224,7 +1224,7 @@ dc_setcfg(struct dc_softc *sc, int media
> }
>
> if (i == DC_TIMEOUT) {
> - if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc))
> + if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc) && !DC_IS_PNIC(sc))
> printf("%s: failed to force tx to idle state\n",
> sc->sc_dev.dv_xname);
> if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
> @@ -1737,7 +1737,7 @@ hasmac:
> bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
>
> ifp->if_capabilities = IFCAP_VLAN_MTU;
> -
> + m_clsetwms(ifp, MCLBYTES, 2, DC_RX_LIST_CNT - 1);
> /* Do MII setup. If this is a 21143, check for a PHY on the
> * MII bus after applying any necessary fixups to twiddle the
> * GPIO bits. If we don't end up finding a PHY, restore the
> @@ -1792,9 +1792,11 @@ hasmac:
> ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
> ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
> printf("%s: MII without any PHY!\n", sc->sc_dev.dv_xname);
> - } else if (sc->dc_type == DC_TYPE_21145) {
> + } else if (sc->dc_type == DC_TYPE_21145)
> ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_10_T);
> - } else
> + else if (sc->dc_type == DC_TYPE_PNIC)
> + ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_10_T);
> + else
> ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
>
> if (DC_IS_DAVICOM(sc) && sc->dc_revision >= DC_REVISION_DM9102A)
> @@ -1867,8 +1869,6 @@ dc_list_rx_init(struct dc_softc *sc)
> ld = sc->dc_ldata;
>
> for (i = 0; i < DC_RX_LIST_CNT; i++) {
> - if (dc_newbuf(sc, i, NULL) == ENOBUFS)
> - return (ENOBUFS);
> next = sc->sc_listmap->dm_segs[0].ds_addr;
> if (i == (DC_RX_LIST_CNT - 1))
> next +=
> @@ -1879,52 +1879,52 @@ dc_list_rx_init(struct dc_softc *sc)
> ld->dc_rx_list[i].dc_next = htole32(next);
> }
>
> - cd->dc_rx_prod = 0;
> -
> + cd->dc_rx_prod = cd->dc_rx_cons = cd->dc_rx_cnt = 0;
> + dc_fill_rx_ring(sc);
> return (0);
> }
>
> +void dc_fill_rx_ring(struct dc_softc *sc) {
> + struct dc_chain_data *cd;
> + struct dc_list_data *ld;
> +
> + cd = &sc->dc_cdata;
> + ld = sc->dc_ldata;
> +
> + while (cd->dc_rx_cnt < DC_RX_LIST_CNT) {
> + if(dc_newbuf(sc) == ENOBUFS)
> + break;
> + DC_INC(cd->dc_rx_prod, DC_RX_LIST_CNT);
> + cd->dc_rx_cnt++;
> + }
> +}
> +
> /*
> * Initialize an RX descriptor and attach an MBUF cluster.
> */
> int
> -dc_newbuf(struct dc_softc *sc, int i, struct mbuf *m)
> +dc_newbuf(struct dc_softc *sc)
> {
> struct mbuf *m_new = NULL;
> struct dc_desc *c;
> bus_dmamap_t map;
> -
> + int i;
> + i = sc->dc_cdata.dc_rx_prod;
> c = &sc->dc_ldata->dc_rx_list[i];
>
> - if (m == NULL) {
> - MGETHDR(m_new, M_DONTWAIT, MT_DATA);
> - if (m_new == NULL)
> - return (ENOBUFS);
> -
> - MCLGET(m_new, M_DONTWAIT);
> - if (!(m_new->m_flags & M_EXT)) {
> - m_freem(m_new);
> - return (ENOBUFS);
> - }
> - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
> - if (bus_dmamap_load_mbuf(sc->sc_dmat, sc->sc_rx_sparemap,
> - m_new, BUS_DMA_NOWAIT) != 0) {
> - m_freem(m_new);
> - return (ENOBUFS);
> - }
> - map = sc->dc_cdata.dc_rx_chain[i].sd_map;
> - sc->dc_cdata.dc_rx_chain[i].sd_map = sc->sc_rx_sparemap;
> - sc->sc_rx_sparemap = map;
> - } else {
> - /*
> - * We're re-using a previously allocated mbuf;
> - * be sure to re-init pointers and lengths to
> - * default values.
> - */
> - m_new = m;
> - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
> - m_new->m_data = m_new->m_ext.ext_buf;
> - }
> + m_new = MCLGETI(NULL, M_DONTWAIT, &sc->sc_arpcom.ac_if, MCLBYTES);
> + if (!m_new)
> + return (ENOBUFS);
> +
> + m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
> + if (bus_dmamap_load_mbuf(sc->sc_dmat, sc->sc_rx_sparemap,
> + m_new, BUS_DMA_NOWAIT) != 0) {
> + m_freem(m_new);
> + return (ENOBUFS);
> + }
> + map = sc->dc_cdata.dc_rx_chain[i].sd_map;
> + sc->dc_cdata.dc_rx_chain[i].sd_map = sc->sc_rx_sparemap;
> + sc->sc_rx_sparemap = map;
>
> m_adj(m_new, sizeof(u_int64_t));
>
> @@ -2033,8 +2033,7 @@ dc_pnic_rx_bug_war(struct dc_softc *sc,
> /* If this is the last buffer, break out. */
> if (i == idx || rxstat & DC_RXSTAT_LASTFRAG)
> break;
> - dc_newbuf(sc, i, m);
> - DC_INC(i, DC_RX_LIST_CNT);
> + m_freem(m);
> }
>
> /* Find the length of the actual receive frame. */
> @@ -2058,52 +2057,11 @@ dc_pnic_rx_bug_war(struct dc_softc *sc,
> * the status word to make it look like a successful
> * frame reception.
> */
> - dc_newbuf(sc, i, m);
> + m_freem(m);
> bcopy(ptr, mtod(m, char *), total_len);
> cur_rx->dc_status = htole32(rxstat | DC_RXSTAT_FIRSTFRAG);
> }
>
> -/*
> - * This routine searches the RX ring for dirty descriptors in the
> - * event that the rxeof routine falls out of sync with the chip's
> - * current descriptor pointer. This may happen sometimes as a result
> - * of a "no RX buffer available" condition that happens when the chip
> - * consumes all of the RX buffers before the driver has a chance to
> - * process the RX ring. This routine may need to be called more than
> - * once to bring the driver back in sync with the chip, however we
> - * should still be getting RX DONE interrupts to drive the search
> - * for new packets in the RX ring, so we should catch up eventually.
> - */
> -int
> -dc_rx_resync(struct dc_softc *sc)
> -{
> - u_int32_t stat;
> - int i, pos, offset;
> -
> - pos = sc->dc_cdata.dc_rx_prod;
> -
> - for (i = 0; i < DC_RX_LIST_CNT; i++) {
> -
> - offset = offsetof(struct dc_list_data, dc_rx_list[pos]);
> - bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
> - offset, sizeof(struct dc_desc),
> - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
> -
> - stat = sc->dc_ldata->dc_rx_list[pos].dc_status;
> - if (!(stat & htole32(DC_RXSTAT_OWN)))
> - break;
> - DC_INC(pos, DC_RX_LIST_CNT);
> - }
> -
> - /* If the ring really is empty, then just return. */
> - if (i == DC_RX_LIST_CNT)
> - return (0);
> -
> - /* We've fallen behind the chip: catch it. */
> - sc->dc_cdata.dc_rx_prod = pos;
> -
> - return (EAGAIN);
> -}
>
> /*
> * A frame has been uploaded: pass the resulting mbuf chain up to
> @@ -2119,9 +2077,8 @@ dc_rxeof(struct dc_softc *sc)
> u_int32_t rxstat;
>
> ifp = &sc->sc_arpcom.ac_if;
> - i = sc->dc_cdata.dc_rx_prod;
>
> - for(;;) {
> + for(i = sc->dc_cdata.dc_rx_cons; sc->dc_cdata.dc_rx_cnt > 0; DC_INC(i,DC_RX_LIST_CNT)) {
> struct mbuf *m0 = NULL;
>
> offset = offsetof(struct dc_list_data, dc_rx_list[i]);
> @@ -2145,18 +2102,16 @@ dc_rxeof(struct dc_softc *sc)
> if ((rxstat & DC_WHOLEFRAME) != DC_WHOLEFRAME) {
> if (rxstat & DC_RXSTAT_FIRSTFRAG)
> sc->dc_pnic_rx_bug_save = i;
> - if ((rxstat & DC_RXSTAT_LASTFRAG) == 0) {
> - DC_INC(i, DC_RX_LIST_CNT);
> + if ((rxstat & DC_RXSTAT_LASTFRAG) == 0)
> continue;
> - }
> dc_pnic_rx_bug_war(sc, i);
> rxstat = letoh32(cur_rx->dc_status);
> total_len = DC_RXBYTES(rxstat);
> }
> }
>
> - sc->dc_cdata.dc_rx_chain[i].sd_mbuf = NULL;
> -
> + sc->dc_cdata.dc_rx_chain[i].sd_mbuf = NULL;
> + sc->dc_cdata.dc_rx_cnt--;
> /*
> * If an error occurs, update stats, clear the
> * status word and leave the mbuf cluster in place:
> @@ -2172,9 +2127,8 @@ dc_rxeof(struct dc_softc *sc)
> ifp->if_ierrors++;
> if (rxstat & DC_RXSTAT_COLLSEEN)
> ifp->if_collisions++;
> - dc_newbuf(sc, i, m);
> + m_freem(m);
> if (rxstat & DC_RXSTAT_CRCERR) {
> - DC_INC(i, DC_RX_LIST_CNT);
> continue;
> } else {
> dc_init(sc);
> @@ -2189,8 +2143,7 @@ dc_rxeof(struct dc_softc *sc)
> m->m_pkthdr.rcvif = ifp;
> m0 = m_devget(mtod(m, char *), total_len, ETHER_ALIGN,
> ifp, NULL);
> - dc_newbuf(sc, i, m);
> - DC_INC(i, DC_RX_LIST_CNT);
> + m_freem(m);
> if (m0 == NULL) {
> ifp->if_ierrors++;
> continue;
> @@ -2205,7 +2158,8 @@ dc_rxeof(struct dc_softc *sc)
> ether_input_mbuf(ifp, m);
> }
>
> - sc->dc_cdata.dc_rx_prod = i;
> + sc->dc_cdata.dc_rx_cons = i;
> + dc_fill_rx_ring(sc);
> }
>
> /*
> @@ -2489,15 +2443,8 @@ dc_intr(void *arg)
> claimed = 1;
> CSR_WRITE_4(sc, DC_ISR, status);
>
> - if (status & DC_ISR_RX_OK) {
> - int curpkts;
> - curpkts = ifp->if_ipackets;
> + if (status & DC_ISR_RX_OK)
> dc_rxeof(sc);
> - if (curpkts == ifp->if_ipackets) {
> - while(dc_rx_resync(sc))
> - dc_rxeof(sc);
> - }
> - }
>
> if (status & (DC_ISR_TX_OK|DC_ISR_TX_NOBUF))
> dc_txeof(sc);
> @@ -2514,15 +2461,8 @@ dc_intr(void *arg)
> dc_tx_underrun(sc);
>
> if ((status & DC_ISR_RX_WATDOGTIMEO)
> - || (status & DC_ISR_RX_NOBUF)) {
> - int curpkts;
> - curpkts = ifp->if_ipackets;
> + || (status & DC_ISR_RX_NOBUF))
> dc_rxeof(sc);
> - if (curpkts == ifp->if_ipackets) {
> - while(dc_rx_resync(sc))
> - dc_rxeof(sc);
> - }
> - }
>
> if (status & DC_ISR_BUS_ERR) {
> dc_reset(sc);
> Index: src/sys/dev/ic/dcreg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/dcreg.h,v
> retrieving revision 1.48
> diff -u -p -r1.48 dcreg.h
> --- src/sys/dev/ic/dcreg.h 7 Sep 2010 16:21:42 -0000 1.48
> +++ src/sys/dev/ic/dcreg.h 13 Dec 2010 18:43:43 -0000
> @@ -502,6 +502,8 @@ struct dc_chain_data {
> int dc_tx_cons;
> int dc_tx_cnt;
> int dc_rx_prod;
> + int dc_rx_cons;
> + int dc_rx_cnt;
> };
>
> struct dc_mediainfo {