On 2010/12/13 13:51, Loganaden Velvindron wrote:
> First of all, big thanks to Christian `naddy` who sent me a dc(4).
> I also managed to get my hands on a PNIC. This diff add mclgeti
> support plus 2 bug fixes that suppress idle timeouts, and autonegocation
> which is broken on the PNIC. As usual, you know who to complain to.

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.


> 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 {

Reply via email to