usbnet drivers: Stop abusing ifp->if_flags & IFF_ALLMULTI.
This legacy flag is a figment of userland's imagination. The actual kernel state is ec->ec_flags & ETHER_F_ALLMULTI, protected by the ETHER_LOCK, so that multicast filter updates -- which run without IFNET_LOCK -- need not attempt to write racily to ifp->if_flags.
This commit is contained in:
parent
2a987a0a95
commit
4f98063591
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_aue.c,v 1.179 2022/03/03 05:53:04 riastradh Exp $ */
|
||||
/* $NetBSD: if_aue.c,v 1.180 2022/03/03 05:53:14 riastradh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998, 1999, 2000
|
||||
|
@ -76,7 +76,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_aue.c,v 1.179 2022/03/03 05:53:04 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_aue.c,v 1.180 2022/03/03 05:53:14 riastradh Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_usb.h"
|
||||
|
@ -627,21 +627,20 @@ aue_uno_mcast(struct ifnet *ifp)
|
|||
usbnet_isowned_core(un);
|
||||
|
||||
if (ifp->if_flags & IFF_PROMISC) {
|
||||
ETHER_LOCK(ec);
|
||||
allmulti:
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
ec->ec_flags |= ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI);
|
||||
return;
|
||||
}
|
||||
|
||||
AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI);
|
||||
|
||||
/* now program new ones */
|
||||
ETHER_LOCK(ec);
|
||||
ETHER_FIRST_MULTI(step, ec, enm);
|
||||
while (enm != NULL) {
|
||||
if (memcmp(enm->enm_addrlo,
|
||||
enm->enm_addrhi, ETHER_ADDR_LEN) != 0) {
|
||||
ETHER_UNLOCK(ec);
|
||||
goto allmulti;
|
||||
}
|
||||
|
||||
|
@ -649,13 +648,14 @@ allmulti:
|
|||
hashtbl[h >> 3] |= 1 << (h & 0x7);
|
||||
ETHER_NEXT_MULTI(step, enm);
|
||||
}
|
||||
ec->ec_flags &= ~ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
|
||||
AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI);
|
||||
|
||||
/* write the hashtable */
|
||||
for (i = 0; i < 8; i++)
|
||||
aue_csr_write_1(sc, AUE_MAR0 + i, hashtbl[i]);
|
||||
|
||||
ifp->if_flags &= ~IFF_ALLMULTI;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_cue.c,v 1.99 2022/03/03 05:53:04 riastradh Exp $ */
|
||||
/* $NetBSD: if_cue.c,v 1.100 2022/03/03 05:53:14 riastradh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998, 1999, 2000
|
||||
|
@ -57,7 +57,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_cue.c,v 1.99 2022/03/03 05:53:04 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_cue.c,v 1.100 2022/03/03 05:53:14 riastradh Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -370,8 +370,10 @@ cue_uno_mcast(struct ifnet *ifp)
|
|||
device_xname(un->un_dev), ifp->if_flags));
|
||||
|
||||
if (ifp->if_flags & IFF_PROMISC) {
|
||||
ETHER_LOCK(ec);
|
||||
allmulti:
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
ec->ec_flags |= ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
|
||||
sc->cue_mctab[i] = 0xFF;
|
||||
cue_mem(un, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
|
||||
|
@ -389,7 +391,6 @@ allmulti:
|
|||
while (enm != NULL) {
|
||||
if (memcmp(enm->enm_addrlo,
|
||||
enm->enm_addrhi, ETHER_ADDR_LEN) != 0) {
|
||||
ETHER_UNLOCK(ec);
|
||||
goto allmulti;
|
||||
}
|
||||
|
||||
|
@ -397,10 +398,9 @@ allmulti:
|
|||
sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
|
||||
ETHER_NEXT_MULTI(step, enm);
|
||||
}
|
||||
ec->ec_flags &= ~ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
|
||||
ifp->if_flags &= ~IFF_ALLMULTI;
|
||||
|
||||
/*
|
||||
* Also include the broadcast address in the filter
|
||||
* so we can receive broadcast frames.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_kue.c,v 1.112 2022/03/03 05:53:04 riastradh Exp $ */
|
||||
/* $NetBSD: if_kue.c,v 1.113 2022/03/03 05:53:14 riastradh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998, 1999, 2000
|
||||
|
@ -71,7 +71,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_kue.c,v 1.112 2022/03/03 05:53:04 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_kue.c,v 1.113 2022/03/03 05:53:14 riastradh Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -336,8 +336,10 @@ kue_uno_mcast(struct ifnet *ifp)
|
|||
sc->kue_rxfilt &= ~KUE_RXFILT_PROMISC;
|
||||
|
||||
if (ifp->if_flags & IFF_PROMISC) {
|
||||
ETHER_LOCK(ec);
|
||||
allmulti:
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
ec->ec_flags |= ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI|KUE_RXFILT_PROMISC;
|
||||
sc->kue_rxfilt &= ~KUE_RXFILT_MULTICAST;
|
||||
kue_setword(un, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt);
|
||||
|
@ -353,7 +355,6 @@ allmulti:
|
|||
if (i == KUE_MCFILTCNT(sc) ||
|
||||
memcmp(enm->enm_addrlo, enm->enm_addrhi,
|
||||
ETHER_ADDR_LEN) != 0) {
|
||||
ETHER_UNLOCK(ec);
|
||||
goto allmulti;
|
||||
}
|
||||
|
||||
|
@ -361,10 +362,9 @@ allmulti:
|
|||
ETHER_NEXT_MULTI(step, enm);
|
||||
i++;
|
||||
}
|
||||
ec->ec_flags &= ~ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
|
||||
ifp->if_flags &= ~IFF_ALLMULTI;
|
||||
|
||||
sc->kue_rxfilt |= KUE_RXFILT_MULTICAST;
|
||||
kue_ctl(un, KUE_CTL_WRITE, KUE_CMD_SET_MCAST_FILTERS,
|
||||
i, sc->kue_mcfilters, i * ETHER_ADDR_LEN);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_mue.c,v 1.72 2022/03/03 05:53:04 riastradh Exp $ */
|
||||
/* $NetBSD: if_mue.c,v 1.73 2022/03/03 05:53:14 riastradh Exp $ */
|
||||
/* $OpenBSD: if_mue.c,v 1.3 2018/08/04 16:42:46 jsg Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -20,7 +20,7 @@
|
|||
/* Driver for Microchip LAN7500/LAN7800 chipsets. */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_mue.c,v 1.72 2022/03/03 05:53:04 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_mue.c,v 1.73 2022/03/03 05:53:14 riastradh Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_usb.h"
|
||||
|
@ -1023,10 +1023,11 @@ mue_uno_mcast(struct ifnet *ifp)
|
|||
/* Always accept broadcast frames. */
|
||||
rxfilt |= MUE_RFE_CTL_BROADCAST;
|
||||
|
||||
ETHER_LOCK(ec);
|
||||
if (ifp->if_flags & IFF_PROMISC) {
|
||||
rxfilt |= MUE_RFE_CTL_UNICAST;
|
||||
allmulti: rxfilt |= MUE_RFE_CTL_MULTICAST;
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
ec->ec_flags |= ETHER_F_ALLMULTI;
|
||||
if (ifp->if_flags & IFF_PROMISC)
|
||||
DPRINTF(un, "promisc\n");
|
||||
else
|
||||
|
@ -1036,7 +1037,6 @@ allmulti: rxfilt |= MUE_RFE_CTL_MULTICAST;
|
|||
pfiltbl[0][0] = MUE_ENADDR_HI(enaddr) | MUE_ADDR_FILTX_VALID;
|
||||
pfiltbl[0][1] = MUE_ENADDR_LO(enaddr);
|
||||
i = 1;
|
||||
ETHER_LOCK(ec);
|
||||
ETHER_FIRST_MULTI(step, ec, enm);
|
||||
while (enm != NULL) {
|
||||
if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
|
||||
|
@ -1044,7 +1044,6 @@ allmulti: rxfilt |= MUE_RFE_CTL_MULTICAST;
|
|||
memset(pfiltbl, 0, sizeof(pfiltbl));
|
||||
memset(hashtbl, 0, sizeof(hashtbl));
|
||||
rxfilt &= ~MUE_RFE_CTL_MULTICAST_HASH;
|
||||
ETHER_UNLOCK(ec);
|
||||
goto allmulti;
|
||||
}
|
||||
if (i < MUE_NUM_ADDR_FILTX) {
|
||||
|
@ -1062,14 +1061,14 @@ allmulti: rxfilt |= MUE_RFE_CTL_MULTICAST;
|
|||
i++;
|
||||
ETHER_NEXT_MULTI(step, enm);
|
||||
}
|
||||
ETHER_UNLOCK(ec);
|
||||
ec->ec_flags &= ~ETHER_F_ALLMULTI;
|
||||
rxfilt |= MUE_RFE_CTL_PERFECT;
|
||||
ifp->if_flags &= ~IFF_ALLMULTI;
|
||||
if (rxfilt & MUE_RFE_CTL_MULTICAST_HASH)
|
||||
DPRINTF(un, "perfect filter and hash tables\n");
|
||||
else
|
||||
DPRINTF(un, "perfect filter\n");
|
||||
}
|
||||
ETHER_UNLOCK(ec);
|
||||
|
||||
for (i = 0; i < MUE_NUM_ADDR_FILTX; i++) {
|
||||
hireg = (un->un_flags & LAN7500) ?
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_smsc.c,v 1.81 2022/03/03 05:53:04 riastradh Exp $ */
|
||||
/* $NetBSD: if_smsc.c,v 1.82 2022/03/03 05:53:14 riastradh Exp $ */
|
||||
|
||||
/* $OpenBSD: if_smsc.c,v 1.4 2012/09/27 12:38:11 jsg Exp $ */
|
||||
/* $FreeBSD: src/sys/dev/usb/net/if_smsc.c,v 1.1 2012/08/15 04:03:55 gonzo Exp $ */
|
||||
|
@ -61,7 +61,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_smsc.c,v 1.81 2022/03/03 05:53:04 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_smsc.c,v 1.82 2022/03/03 05:53:14 riastradh Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_usb.h"
|
||||
|
@ -427,8 +427,11 @@ smsc_uno_mcast(struct ifnet *ifp)
|
|||
if (usbnet_isdying(un))
|
||||
return;
|
||||
|
||||
if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
|
||||
if (ifp->if_flags & IFF_PROMISC) {
|
||||
ETHER_LOCK(ec);
|
||||
allmulti:
|
||||
ec->ec_flags |= ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
DPRINTF("receive all multicast enabled", 0, 0, 0, 0);
|
||||
sc->sc_mac_csr |= SMSC_MAC_CSR_MCPAS;
|
||||
sc->sc_mac_csr &= ~SMSC_MAC_CSR_HPFILT;
|
||||
|
@ -443,7 +446,6 @@ allmulti:
|
|||
ETHER_FIRST_MULTI(step, ec, enm);
|
||||
while (enm != NULL) {
|
||||
if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
|
||||
ETHER_UNLOCK(ec);
|
||||
goto allmulti;
|
||||
}
|
||||
|
||||
|
@ -451,6 +453,7 @@ allmulti:
|
|||
hashtbl[hash >> 5] |= 1 << (hash & 0x1F);
|
||||
ETHER_NEXT_MULTI(step, enm);
|
||||
}
|
||||
ec->ec_flags &= ~ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
|
||||
/* Debug */
|
||||
|
@ -463,7 +466,6 @@ allmulti:
|
|||
/* Write the hash table and mac control registers */
|
||||
|
||||
//XXX should we be doing this?
|
||||
ifp->if_flags &= ~IFF_ALLMULTI;
|
||||
smsc_writereg(un, SMSC_HASHH, hashtbl[1]);
|
||||
smsc_writereg(un, SMSC_HASHL, hashtbl[0]);
|
||||
smsc_writereg(un, SMSC_MAC_CSR, sc->sc_mac_csr);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_udav.c,v 1.86 2022/03/03 05:53:04 riastradh Exp $ */
|
||||
/* $NetBSD: if_udav.c,v 1.87 2022/03/03 05:53:14 riastradh Exp $ */
|
||||
/* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -45,7 +45,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.86 2022/03/03 05:53:04 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.87 2022/03/03 05:53:14 riastradh Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_usb.h"
|
||||
|
@ -598,11 +598,16 @@ udav_uno_mcast(struct ifnet *ifp)
|
|||
}
|
||||
|
||||
if (ifp->if_flags & IFF_PROMISC) {
|
||||
ETHER_LOCK(ec);
|
||||
ec->ec_flags |= ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC);
|
||||
return;
|
||||
} else if (ifp->if_flags & IFF_ALLMULTI) {
|
||||
} else if (ifp->if_flags & IFF_ALLMULTI) { /* XXX ??? Can't happen? */
|
||||
ETHER_LOCK(ec);
|
||||
allmulti:
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
ec->ec_flags |= ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_ALL);
|
||||
UDAV_CLRBIT(un, UDAV_RCR, UDAV_RCR_PRMSC);
|
||||
return;
|
||||
|
@ -619,7 +624,6 @@ allmulti:
|
|||
while (enm != NULL) {
|
||||
if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
|
||||
ETHER_ADDR_LEN) != 0) {
|
||||
ETHER_UNLOCK(ec);
|
||||
goto allmulti;
|
||||
}
|
||||
|
||||
|
@ -627,10 +631,10 @@ allmulti:
|
|||
hashes[h>>3] |= 1 << (h & 0x7);
|
||||
ETHER_NEXT_MULTI(step, enm);
|
||||
}
|
||||
ec->ec_flags &= ~ETHER_F_ALLMULTI;
|
||||
ETHER_UNLOCK(ec);
|
||||
|
||||
/* disable all multicast */
|
||||
ifp->if_flags &= ~IFF_ALLMULTI;
|
||||
UDAV_CLRBIT(un, UDAV_RCR, UDAV_RCR_ALL);
|
||||
|
||||
/* write hash value to the register */
|
||||
|
|
Loading…
Reference in New Issue