Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/marvell Various improvements to mvgbe(4). Notable i...



details:   https://anonhg.NetBSD.org/src/rev/808695cc7168
branches:  trunk
changeset: 761595:808695cc7168
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Tue Feb 01 23:40:12 2011 +0000

description:
Various improvements to mvgbe(4).  Notable is improved multicast filtering.

diffstat:

 sys/dev/marvell/if_mvgbe.c |  277 ++++++++++++++++++++++++++------------------
 sys/dev/marvell/mvgbereg.h |   33 +++--
 2 files changed, 181 insertions(+), 129 deletions(-)

diffs (truncated from 596 to 300 lines):

diff -r b57a3af0b867 -r 808695cc7168 sys/dev/marvell/if_mvgbe.c
--- a/sys/dev/marvell/if_mvgbe.c        Tue Feb 01 23:23:52 2011 +0000
+++ b/sys/dev/marvell/if_mvgbe.c        Tue Feb 01 23:40:12 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_mvgbe.c,v 1.4 2011/01/29 01:53:18 jakllsch Exp $    */
+/*     $NetBSD: if_mvgbe.c,v 1.5 2011/02/01 23:40:12 jakllsch Exp $    */
 /*
  * Copyright (c) 2007, 2008 KIYOHARA Takashi
  * All rights reserved.
@@ -25,7 +25,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.4 2011/01/29 01:53:18 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.5 2011/02/01 23:40:12 jakllsch Exp $");
 
 #include "rnd.h"
 
@@ -75,10 +75,10 @@
        bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
 #define MVGBE_WRITE(sc, reg, val) \
        bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
-#define MVGBE_READ_FILTER(sc, reg) \
-       bus_space_read_4((sc)->sc_iot, (sc)->sc_dafh, (reg))
+#define MVGBE_READ_FILTER(sc, reg, val, c) \
+       bus_space_read_region_4((sc)->sc_iot, (sc)->sc_dafh, (reg), (val), (c))
 #define MVGBE_WRITE_FILTER(sc, reg, val, c) \
-       bus_space_set_region_4((sc)->sc_iot, (sc)->sc_dafh, (reg), (val), (c))
+       bus_space_write_region_4((sc)->sc_iot, (sc)->sc_dafh, (reg), (val), (c))
 
 #define MVGBE_TX_RING_CNT      256
 #define MVGBE_TX_RING_MSK      (MVGBE_TX_RING_CNT - 1)
@@ -93,7 +93,7 @@
        (MVGBE_RX_RING_CNT + 1) % MVGBE_RX_RING_CNT);
 
 #define MVGBE_JSLOTS           384     /* XXXX */
-#define MVGBE_JLEN             (MVGBE_MRU + MVGBE_BUF_ALIGN)
+#define MVGBE_JLEN             ((MVGBE_MRU + MVGBE_RXBUF_ALIGN)&~MVGBE_RXBUF_MASK)
 #define MVGBE_NTXSEG           30
 #define MVGBE_JPAGESZ          PAGE_SIZE
 #define MVGBE_RESID \
@@ -249,9 +249,10 @@
 static void mvgbe_stop(struct ifnet *, int);
 static void mvgbe_watchdog(struct ifnet *);
 
-/* MII funcstions */
-static int mvgbe_ifmedia_upd(struct ifnet *);
-static void mvgbe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int mvgbe_ifflags_cb(struct ethercom *);
+
+static int mvgbe_mediachange(struct ifnet *);
+static void mvgbe_mediastatus(struct ifnet *, struct ifmediareq *);
 
 static int mvgbe_init_rx_ring(struct mvgbe_softc *);
 static int mvgbe_init_tx_ring(struct mvgbe_softc *);
@@ -262,7 +263,8 @@
 static int mvgbe_encap(struct mvgbe_softc *, struct mbuf *, uint32_t *);
 static void mvgbe_rxeof(struct mvgbe_softc *);
 static void mvgbe_txeof(struct mvgbe_softc *);
-static void mvgbe_setmulti(struct mvgbe_softc *);
+static uint8_t mvgbe_crc8(const uint8_t *, size_t);
+static void mvgbe_filter_setup(struct mvgbe_softc *);
 #ifdef MVGBE_DEBUG
 static void mvgbe_dump_txdesc(struct mvgbe_tx_desc *, int);
 #endif
@@ -697,17 +699,12 @@
        sc->sc_rdata = (struct mvgbe_ring_data *)kva;
        memset(sc->sc_rdata, 0, sizeof(struct mvgbe_ring_data));
 
-#if 0
        /*
         * We can support 802.1Q VLAN-sized frames and jumbo
         * Ethernet frames.
         */
        sc->sc_ethercom.ec_capabilities |=
-           ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING | ETHERCAP_JUMBO_MTU;
-#else
-       /* XXXX: We don't know the usage of VLAN. */
-       sc->sc_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU;
-#endif
+           ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU;
 
        /* Try to allocate memory for jumbo buffers. */
        if (mvgbe_alloc_jumbo_mem(sc)) {
@@ -730,6 +727,10 @@
            IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx |
            IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |
            IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx;
+       /*
+        * But, IPv6 packets in the stream can cause incorrect TCPv4 Tx sums.
+        */
+       sc->sc_ethercom.ec_if.if_capabilities &= ~IFCAP_CSUM_TCPv4_Tx;
        IFQ_SET_MAXLEN(&ifp->if_snd, max(MVGBE_TX_RING_CNT - 1, IFQ_MAXLEN));
        IFQ_SET_READY(&ifp->if_snd);
        strcpy(ifp->if_xname, device_xname(sc->sc_dev));
@@ -746,7 +747,7 @@
 
        sc->sc_ethercom.ec_mii = &sc->sc_mii;
        ifmedia_init(&sc->sc_mii.mii_media, 0,
-           mvgbe_ifmedia_upd, mvgbe_ifmedia_sts);
+           mvgbe_mediachange, mvgbe_mediastatus);
        mii_attach(self, &sc->sc_mii, 0xffffffff,
            MII_PHY_ANY, MII_OFFSET_ANY, 0);
        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
@@ -763,6 +764,7 @@
        if_attach(ifp);
 
        ether_ifattach(ifp, sc->sc_enaddr);
+       ether_set_ifflags_cb(&sc->sc_ethercom, mvgbe_ifflags_cb);
 
 #if NRND > 0
        rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev),
@@ -898,42 +900,26 @@
 }
 
 static int
-mvgbe_ioctl(struct ifnet *ifp, u_long command, void *data)
+mvgbe_ioctl(struct ifnet *ifp, u_long cmd, void *data)
 {
        struct mvgbe_softc *sc = ifp->if_softc;
        struct ifreq *ifr = data;
-       struct mii_data *mii;
        int s, error = 0;
 
        s = splnet();
 
-       switch (command) {
-       case SIOCSIFFLAGS:
-               DPRINTFN(2, ("mvgbe_ioctl IFFLAGS\n"));
-               if (ifp->if_flags & IFF_UP)
-                       mvgbe_init(ifp);
-               else
-                       if (ifp->if_flags & IFF_RUNNING)
-                               mvgbe_stop(ifp, 0);
-               sc->sc_if_flags = ifp->if_flags;
-               error = 0;
-               break;
-
+       switch (cmd) {
        case SIOCGIFMEDIA:
        case SIOCSIFMEDIA:
                DPRINTFN(2, ("mvgbe_ioctl MEDIA\n"));
-               mii = &sc->sc_mii;
-               error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+               error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
                break;
-
        default:
                DPRINTFN(2, ("mvgbe_ioctl ETHER\n"));
-               error = ether_ioctl(ifp, command, data);
+               error = ether_ioctl(ifp, cmd, data);
                if (error == ENETRESET) {
                        if (ifp->if_flags & IFF_RUNNING) {
-                               mvgbe_setmulti(sc);
-                               DPRINTFN(2,
-                                   ("mvgbe_ioctl setmulti called\n"));
+                               mvgbe_filter_setup(sc);
                        }
                        error = 0;
                }
@@ -945,6 +931,9 @@
        return error;
 }
 
+int mvgbe_rximt = 0;
+int mvgbe_tximt = 0;
+
 static int
 mvgbe_init(struct ifnet *ifp)
 {
@@ -952,17 +941,10 @@
        struct mvgbec_softc *csc = device_private(device_parent(sc->sc_dev));
        struct mii_data *mii = &sc->sc_mii;
        uint32_t reg;
-       int i, s;
+       int i;
 
        DPRINTFN(2, ("mvgbe_init\n"));
 
-       s = splnet();
-
-       if (ifp->if_flags & IFF_RUNNING) {
-               splx(s);
-               return 0;
-       }
-
        /* Cancel pending I/O and free all RX/TX buffers. */
        mvgbe_stop(ifp, 0);
 
@@ -974,13 +956,11 @@
        if (mvgbe_init_tx_ring(sc) == ENOBUFS) {
                aprint_error_ifnet(ifp,
                    "initialization failed: no memory for tx buffers\n");
-               splx(s);
                return ENOBUFS;
        }
        if (mvgbe_init_rx_ring(sc) == ENOBUFS) {
                aprint_error_ifnet(ifp,
                    "initialization failed: no memory for rx buffers\n");
-               splx(s);
                return ENOBUFS;
        }
 
@@ -988,7 +968,7 @@
            MVGBE_PSC_ANFC |                    /* Enable Auto-Neg Flow Ctrl */
            MVGBE_PSC_RESERVED |                /* Must be set to 1 */
            MVGBE_PSC_FLFAIL |                  /* Do NOT Force Link Fail */
-           MVGBE_PSC_MRU(MVGBE_PSC_MRU_9700) | /* Always 9700 OK */
+           MVGBE_PSC_MRU(MVGBE_PSC_MRU_9022) | /* we want 9k */
            MVGBE_PSC_SETFULLDX);               /* Set_FullDx */
        /* XXXX: mvgbe(4) always use RGMII. */
        MVGBE_WRITE(sc, MVGBE_PSC1,
@@ -1026,7 +1006,11 @@
            MVGBE_SDC_BLMR |    /* Big/Little Endian Receive Mode: No swap */
            MVGBE_SDC_BLMT |    /* Big/Little Endian Transmit Mode: No swap */
 #endif
+           MVGBE_SDC_IPGINTRX(mvgbe_rximt) |
            MVGBE_SDC_TXBSZ_16_64BITWORDS);
+       MVGBE_WRITE(sc, MVGBE_PTFUT, MVGBE_PTFUT_IPGINTTX(mvgbe_tximt));
+
+       mvgbe_filter_setup(sc);
 
        mii_mediachg(mii);
 
@@ -1056,8 +1040,6 @@
        ifp->if_flags |= IFF_RUNNING;
        ifp->if_flags &= ~IFF_OACTIVE;
 
-       splx(s);
-
        return 0;
 }
 
@@ -1178,30 +1160,41 @@
        }
 }
 
+static int
+mvgbe_ifflags_cb(struct ethercom *ec)
+{
+       struct ifnet *ifp = &ec->ec_if;
+       struct mvgbe_softc *sc = ifp->if_softc;
+       int change = ifp->if_flags ^ sc->sc_if_flags;
+
+       if (change != 0)
+               sc->sc_if_flags = ifp->if_flags;
+
+       if ((change & ~(IFF_CANTCHANGE|IFF_DEBUG)) != 0)
+               return ENETRESET;
+
+       if ((change & IFF_PROMISC) != 0)
+               mvgbe_filter_setup(sc);
+
+       return 0;
+}
 
 /*
  * Set media options.
  */
 static int
-mvgbe_ifmedia_upd(struct ifnet *ifp)
+mvgbe_mediachange(struct ifnet *ifp)
 {
-       struct mvgbe_softc *sc = ifp->if_softc;
-
-       mii_mediachg(&sc->sc_mii);
-       return 0;
+       return ether_mediachange(ifp);
 }
 
 /*
  * Report current media status.
  */
 static void
-mvgbe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+mvgbe_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
 {
-       struct mvgbe_softc *sc = ifp->if_softc;
-
-       mii_pollstat(&sc->sc_mii);
-       ifmr->ifm_active = sc->sc_mii.mii_media_active;
-       ifmr->ifm_status = sc->sc_mii.mii_media_status;
+       ether_mediastatus(ifp, ifmr);
 }
 
 
@@ -1212,7 +1205,7 @@
        struct mvgbe_ring_data *rd = sc->sc_rdata;
        int i;
 
-       bzero((char *)rd->mvgbe_rx_ring,
+       memset(rd->mvgbe_rx_ring, 0,
            sizeof(struct mvgbe_rx_desc) * MVGBE_RX_RING_CNT);
 
        for (i = 0; i < MVGBE_RX_RING_CNT; i++) {
@@ -1252,7 +1245,7 @@
        struct mvgbe_ring_data *rd = sc->sc_rdata;
        int i;
 
-       bzero((char *)sc->sc_rdata->mvgbe_tx_ring,



Home | Main Index | Thread Index | Old Index