PR/31130: FUKAUMI Naoki: Fix vge(4) SIOC{ADD,DEL}MULTI handling

This commit is contained in:
christos 2005-09-08 18:18:10 +00:00
parent 5b3a55a74a
commit e4efddfa8b
1 changed files with 35 additions and 13 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_vge.c,v 1.5 2005/05/02 15:34:32 yamt Exp $ */
/* $NetBSD: if_vge.c,v 1.6 2005/09/08 18:18:10 christos Exp $ */
/*-
* Copyright (c) 2004
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_vge.c,v 1.5 2005/05/02 15:34:32 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_vge.c,v 1.6 2005/09/08 18:18:10 christos Exp $");
/*
* VIA Networking Technologies VT612x PCI gigabit ethernet NIC driver.
@ -549,15 +549,17 @@ vge_setmulti(sc)
vge_cam_clear(sc);
CSR_WRITE_4(sc, VGE_MAR0, 0);
CSR_WRITE_4(sc, VGE_MAR1, 0);
ifp->if_flags &= ~IFF_ALLMULTI;
/*
* If the user wants allmulti or promisc mode, enable reception
* of all multicast frames.
*/
if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
if (ifp->if_flags & IFF_PROMISC) {
allmulti:
CSR_WRITE_4(sc, VGE_MAR0, 0xFFFFFFFF);
CSR_WRITE_4(sc, VGE_MAR1, 0xFFFFFFFF);
ifp->if_flags |= IFF_ALLMULTI;
return;
}
@ -571,8 +573,7 @@ vge_setmulti(sc)
ETHER_ADDR_LEN) != 0)
goto allmulti;
error = vge_cam_set(sc,
LLADDR((struct sockaddr_dl *)enm->enm_addrlo));
error = vge_cam_set(sc, enm->enm_addrlo);
if (error)
break;
@ -585,12 +586,18 @@ vge_setmulti(sc)
ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
while(enm != NULL) {
h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
enm->enm_addrlo), ETHER_ADDR_LEN) >> 26;
if (h < 32)
hashes[0] |= (1 << h);
else
hashes[1] |= (1 << (h - 32));
/*
* If multicast range, fall back to ALLMULTI.
*/
if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
ETHER_ADDR_LEN) != 0)
goto allmulti;
h = ether_crc32_be(enm->enm_addrlo,
ETHER_ADDR_LEN) >> 26;
hashes[h >> 5] |= 1 << (h & 0x1f);
ETHER_NEXT_MULTI(step, enm);
}
CSR_WRITE_4(sc, VGE_MAR0, hashes[0]);
@ -2060,7 +2067,9 @@ vge_ioctl(ifp, command, data)
struct vge_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
struct mii_data *mii;
int error = 0;
int s, error = 0;
s = splnet();
switch (command) {
case SIOCSIFMTU:
@ -2092,7 +2101,19 @@ vge_ioctl(ifp, command, data)
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
vge_setmulti(sc);
error = (command == SIOCADDMULTI) ?
ether_addmulti(ifr, &sc->sc_ethercom) :
ether_delmulti(ifr, &sc->sc_ethercom);
if (error == ENETRESET) {
/*
* Multicast list has changed; set the hardware filter
* accordingly.
*/
if (ifp->if_flags & IFF_RUNNING)
vge_setmulti(sc);
error = 0;
}
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
@ -2104,6 +2125,7 @@ vge_ioctl(ifp, command, data)
break;
}
splx(s);
return (error);
}