aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/vge
diff options
context:
space:
mode:
authorPyun YongHyeon <yongari@FreeBSD.org>2009-12-16 19:32:44 +0000
committerPyun YongHyeon <yongari@FreeBSD.org>2009-12-16 19:32:44 +0000
commit5f07fd19e201d74680f5a3166f50c75b0698dcc0 (patch)
treeaf0da6d45b0c8851a791463d7b10df9fb9206863 /sys/dev/vge
parent53638988bccb2a6f3f5d688d7161aa95108188b0 (diff)
downloadsrc-5f07fd19e201d74680f5a3166f50c75b0698dcc0.tar.gz
src-5f07fd19e201d74680f5a3166f50c75b0698dcc0.zip
Rewrite RX filter setup and simplify code.
Now promiscuous mode and multicast handling is performed in single function, vge_rxfilter().
Notes
Notes: svn path=/head/; revision=200613
Diffstat (limited to 'sys/dev/vge')
-rw-r--r--sys/dev/vge/if_vge.c101
1 files changed, 44 insertions, 57 deletions
diff --git a/sys/dev/vge/if_vge.c b/sys/dev/vge/if_vge.c
index 0c9718ab4f8e..0c7cc61bd179 100644
--- a/sys/dev/vge/if_vge.c
+++ b/sys/dev/vge/if_vge.c
@@ -179,7 +179,7 @@ static void vge_read_eeprom(struct vge_softc *, caddr_t, int, int, int);
static void vge_reset(struct vge_softc *);
static int vge_rx_list_init(struct vge_softc *);
static int vge_rxeof(struct vge_softc *, int);
-static void vge_setmulti(struct vge_softc *);
+static void vge_rxfilter(struct vge_softc *);
static void vge_setvlan(struct vge_softc *);
static void vge_start(struct ifnet *);
static void vge_start_locked(struct ifnet *);
@@ -528,32 +528,43 @@ vge_setvlan(struct vge_softc *sc)
* we use the hash filter instead.
*/
static void
-vge_setmulti(struct vge_softc *sc)
+vge_rxfilter(struct vge_softc *sc)
{
struct ifnet *ifp;
- int error = 0/*, h = 0*/;
struct ifmultiaddr *ifma;
- uint32_t h, hashes[2] = { 0, 0 };
+ uint32_t h, hashes[2];
+ uint8_t rxcfg;
+ int error = 0;
VGE_LOCK_ASSERT(sc);
- ifp = sc->vge_ifp;
-
/* First, zot all the multicast entries. */
- vge_cam_clear(sc);
- CSR_WRITE_4(sc, VGE_MAR0, 0);
- CSR_WRITE_4(sc, VGE_MAR1, 0);
+ hashes[0] = 0;
+ hashes[1] = 0;
+ rxcfg = CSR_READ_1(sc, VGE_RXCTL);
+ rxcfg &= ~(VGE_RXCTL_RX_MCAST | VGE_RXCTL_RX_BCAST |
+ VGE_RXCTL_RX_PROMISC);
/*
- * If the user wants allmulti or promisc mode, enable reception
- * of all multicast frames.
+ * Always allow VLAN oversized frames and frames for
+ * this host.
*/
- if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
- CSR_WRITE_4(sc, VGE_MAR0, 0xFFFFFFFF);
- CSR_WRITE_4(sc, VGE_MAR1, 0xFFFFFFFF);
- return;
+ rxcfg |= VGE_RXCTL_RX_GIANT | VGE_RXCTL_RX_UCAST;
+
+ ifp = sc->vge_ifp;
+ if ((ifp->if_flags & IFF_BROADCAST) != 0)
+ rxcfg |= VGE_RXCTL_RX_BCAST;
+ if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) {
+ if ((ifp->if_flags & IFF_PROMISC) != 0)
+ rxcfg |= VGE_RXCTL_RX_PROMISC;
+ if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
+ hashes[0] = 0xFFFFFFFF;
+ hashes[1] = 0xFFFFFFFF;
+ }
+ goto done;
}
+ vge_cam_clear(sc);
/* Now program new ones */
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
@@ -579,11 +590,15 @@ vge_setmulti(struct vge_softc *sc)
else
hashes[1] |= (1 << (h - 32));
}
-
- CSR_WRITE_4(sc, VGE_MAR0, hashes[0]);
- CSR_WRITE_4(sc, VGE_MAR1, hashes[1]);
}
if_maddr_runlock(ifp);
+
+done:
+ if (hashes[0] != 0 || hashes[1] != 0)
+ rxcfg |= VGE_RXCTL_RX_MCAST;
+ CSR_WRITE_4(sc, VGE_MAR0, hashes[0]);
+ CSR_WRITE_4(sc, VGE_MAR1, hashes[1]);
+ CSR_WRITE_1(sc, VGE_RXCTL, rxcfg);
}
static void
@@ -2068,29 +2083,11 @@ vge_init_locked(struct vge_softc *sc)
/* Enable the TX descriptor queue */
CSR_WRITE_2(sc, VGE_TXQCSRS, VGE_TXQCSR_RUN0);
- /* Set up the receive filter -- allow large frames for VLANs. */
- CSR_WRITE_1(sc, VGE_RXCTL, VGE_RXCTL_RX_UCAST|VGE_RXCTL_RX_GIANT);
-
- /* If we want promiscuous mode, set the allframes bit. */
- if (ifp->if_flags & IFF_PROMISC) {
- CSR_SETBIT_1(sc, VGE_RXCTL, VGE_RXCTL_RX_PROMISC);
- }
-
- /* Set capture broadcast bit to capture broadcast frames. */
- if (ifp->if_flags & IFF_BROADCAST) {
- CSR_SETBIT_1(sc, VGE_RXCTL, VGE_RXCTL_RX_BCAST);
- }
-
- /* Set multicast bit to capture multicast frames. */
- if (ifp->if_flags & IFF_MULTICAST) {
- CSR_SETBIT_1(sc, VGE_RXCTL, VGE_RXCTL_RX_MCAST);
- }
-
/* Init the cam filter. */
vge_cam_clear(sc);
- /* Init the multicast filter. */
- vge_setmulti(sc);
+ /* Set up receiver filter. */
+ vge_rxfilter(sc);
vge_setvlan(sc);
/* Enable flow control */
@@ -2272,25 +2269,15 @@ vge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
break;
case SIOCSIFFLAGS:
VGE_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- ifp->if_flags & IFF_PROMISC &&
- !(sc->vge_if_flags & IFF_PROMISC)) {
- CSR_SETBIT_1(sc, VGE_RXCTL,
- VGE_RXCTL_RX_PROMISC);
- vge_setmulti(sc);
- } else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- !(ifp->if_flags & IFF_PROMISC) &&
- sc->vge_if_flags & IFF_PROMISC) {
- CSR_CLRBIT_1(sc, VGE_RXCTL,
- VGE_RXCTL_RX_PROMISC);
- vge_setmulti(sc);
- } else
+ if ((ifp->if_flags & IFF_UP) != 0) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
+ ((ifp->if_flags ^ sc->vge_if_flags) &
+ (IFF_PROMISC | IFF_ALLMULTI)) != 0)
+ vge_rxfilter(sc);
+ else
vge_init_locked(sc);
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- vge_stop(sc);
- }
+ } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ vge_stop(sc);
sc->vge_if_flags = ifp->if_flags;
VGE_UNLOCK(sc);
break;
@@ -2298,7 +2285,7 @@ vge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
case SIOCDELMULTI:
VGE_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- vge_setmulti(sc);
+ vge_rxfilter(sc);
VGE_UNLOCK(sc);
break;
case SIOCGIFMEDIA: