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