Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144470914
D21943.id63103.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
189 KB
Referenced Files
None
Subscribers
None
D21943.id63103.diff
View Options
Index: sys/arm/allwinner/if_awg.c
===================================================================
--- sys/arm/allwinner/if_awg.c
+++ sys/arm/allwinner/if_awg.c
@@ -675,12 +675,25 @@
return (x >> 16) | (x << 16);
}
+static u_int
+awg_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t crc, hashreg, hashbit, *hash = arg;
+
+ crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN) & 0x7f;
+ crc = bitrev32(~crc) >> 26;
+ hashreg = (crc >> 5);
+ hashbit = (crc & 0x1f);
+ hash[hashreg] |= (1 << hashbit);
+
+ return (1);
+}
+
static void
awg_setup_rxfilter(struct awg_softc *sc)
{
- uint32_t val, crc, hashreg, hashbit, hash[2], machi, maclo;
- int mc_count, mcnt, i;
- uint8_t *eaddr, *mta;
+ uint32_t val, hash[2], machi, maclo;
+ uint8_t *eaddr;
if_t ifp;
AWG_ASSERT_LOCKED(sc);
@@ -689,37 +702,14 @@
val = 0;
hash[0] = hash[1] = 0;
- mc_count = if_multiaddr_count(ifp, -1);
-
if (if_getflags(ifp) & IFF_PROMISC)
val |= DIS_ADDR_FILTER;
else if (if_getflags(ifp) & IFF_ALLMULTI) {
val |= RX_ALL_MULTICAST;
hash[0] = hash[1] = ~0;
- } else if (mc_count > 0) {
+ } else if (if_foreach_llmaddr(ifp, awg_hash_maddr, hash) > 0)
val |= HASH_MULTICAST;
- mta = malloc(sizeof(unsigned char) * ETHER_ADDR_LEN * mc_count,
- M_DEVBUF, M_NOWAIT);
- if (mta == NULL) {
- if_printf(ifp,
- "failed to allocate temporary multicast list\n");
- return;
- }
-
- if_multiaddr_array(ifp, mta, &mcnt, mc_count);
- for (i = 0; i < mcnt; i++) {
- crc = ether_crc32_le(mta + (i * ETHER_ADDR_LEN),
- ETHER_ADDR_LEN) & 0x7f;
- crc = bitrev32(~crc) >> 26;
- hashreg = (crc >> 5);
- hashbit = (crc & 0x1f);
- hash[hashreg] |= (1 << hashbit);
- }
-
- free(mta, M_DEVBUF);
- }
-
/* Write our unicast address */
eaddr = IF_LLADDR(ifp);
machi = (eaddr[5] << 8) | eaddr[4];
Index: sys/arm/allwinner/if_emac.c
===================================================================
--- sys/arm/allwinner/if_emac.c
+++ sys/arm/allwinner/if_emac.c
@@ -218,12 +218,22 @@
printf("MAC address: %s\n", ether_sprintf(hwaddr));
}
+static u_int
+emac_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t h, *hashes = arg;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ hashes[h >> 5] |= 1 << (h & 0x1f);
+
+ return (1);
+}
+
static void
emac_set_rx_mode(struct emac_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t h, hashes[2];
+ uint32_t hashes[2];
uint32_t rcr = 0;
EMAC_ASSERT_LOCKED(sc);
@@ -241,17 +251,8 @@
if (ifp->if_flags & IFF_ALLMULTI) {
hashes[0] = 0xffffffff;
hashes[1] = 0xffffffff;
- } else {
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &sc->emac_ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- hashes[h >> 5] |= 1 << (h & 0x1f);
- }
- if_maddr_runlock(ifp);
- }
+ } else
+ if_foreach_llmaddr(ifp, emac_hash_maddr, hashes);
rcr |= EMAC_RX_MCO;
rcr |= EMAC_RX_MHF;
EMAC_WRITE_REG(sc, EMAC_RX_HASH0, hashes[0]);
Index: sys/arm/ralink/if_fv.c
===================================================================
--- sys/arm/ralink/if_fv.c
+++ sys/arm/ralink/if_fv.c
@@ -200,8 +200,25 @@
DRIVER_MODULE(mdio, fvmdio, mdio_driver, mdio_devclass, 0, 0);
#endif
-/* setup frame code refer dc code */
+static u_int
+fv_set_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint16_t *sp = arg;
+ uint8_t *ma;
+ int i;
+
+ ma = LLADDR(sdl);
+ i = cnt * 6;
+ sp[i] = sp[i+1] = (ma[1] << 8 | ma[0]);
+ i += 2;
+ sp[i] = sp[i+1] = (ma[3] << 8 | ma[2]);
+ i += 2;
+ sp[i] = sp[i+1] = (ma[5] << 8 | ma[4]);
+
+ return (1);
+}
+/* setup frame code refer dc code */
static void
fv_setfilt(struct fv_softc *sc)
{
@@ -209,9 +226,7 @@
struct fv_desc *sframe;
int i;
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
uint16_t *sp;
- uint8_t *ma;
ifp = sc->fv_ifp;
@@ -225,20 +240,7 @@
sframe->fv_addr = sc->fv_rdata.fv_sf_paddr;
sframe->fv_devcs = ADCTL_Tx_SETUP | FV_DMASIZE(FV_SFRAME_LEN);
- i = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- ma = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
- sp[i] = sp[i+1] = (ma[1] << 8 | ma[0]);
- i += 2;
- sp[i] = sp[i+1] = (ma[3] << 8 | ma[2]);
- i += 2;
- sp[i] = sp[i+1] = (ma[5] << 8 | ma[4]);
- i += 2;
- }
- if_maddr_runlock(ifp);
+ i = if_foreach_llmaddr(ifp, fv_set_maddr, sp) * 6;
bcopy(IF_LLADDR(sc->fv_ifp), eaddr, ETHER_ADDR_LEN);
sp[90] = sp[91] = eaddr[0];
Index: sys/arm/ti/cpsw/if_cpsw.c
===================================================================
--- sys/arm/ti/cpsw/if_cpsw.c
+++ sys/arm/ti/cpsw/if_cpsw.c
@@ -2425,12 +2425,27 @@
printf("\n");
}
+static u_int
+cpswp_set_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct cpswp_softc *sc = arg;
+ uint32_t portmask;
+
+ if (sc->swsc->dualemac)
+ portmask = 1 << (sc->unit + 1) | 1 << 0;
+ else
+ portmask = 7;
+
+ cpsw_ale_mc_entry_set(sc->swsc, portmask, sc->vlan, LLADDR(sdl));
+
+ return (1);
+}
+
static int
cpswp_ale_update_addresses(struct cpswp_softc *sc, int purge)
{
uint8_t *mac;
uint32_t ale_entry[3], ale_type, portmask;
- struct ifmultiaddr *ifma;
if (sc->swsc->dualemac) {
ale_type = ALE_TYPE_VLAN_ADDR << 28 | sc->vlan << 16;
@@ -2445,7 +2460,6 @@
* For simplicity, keep this entry at table index 0 for port 1 and
* at index 2 for port 2 in the ALE.
*/
- if_addr_rlock(sc->ifp);
mac = LLADDR((struct sockaddr_dl *)sc->ifp->if_addr->ifa_addr);
ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
ale_entry[1] = ale_type | mac[0] << 8 | mac[1]; /* addr entry + mac */
@@ -2457,7 +2471,6 @@
mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0]);
cpsw_write_4(sc->swsc, CPSW_PORT_P_SA_LO(sc->unit + 1),
mac[5] << 8 | mac[4]);
- if_addr_runlock(sc->ifp);
/* Keep the broadcast address at table entry 1 (or 3). */
ale_entry[0] = 0xffffffff; /* Lower 32 bits of MAC */
@@ -2472,14 +2485,7 @@
cpsw_ale_remove_all_mc_entries(sc->swsc);
/* Set other multicast addrs desired. */
- if_maddr_rlock(sc->ifp);
- CK_STAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- cpsw_ale_mc_entry_set(sc->swsc, portmask, sc->vlan,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- }
- if_maddr_runlock(sc->ifp);
+ if_foreach_llmaddr(sc->ifp, cpswp_set_maddr, sc);
return (0);
}
Index: sys/dev/ae/if_ae.c
===================================================================
--- sys/dev/ae/if_ae.c
+++ sys/dev/ae/if_ae.c
@@ -2031,12 +2031,21 @@
AE_WRITE_4(sc, AE_MAC_REG, val);
}
+static u_int
+ae_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t crc, *mchash = arg;
+
+ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+ mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
+
+ return (1);
+}
+
static void
ae_rxfilter(ae_softc_t *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t crc;
uint32_t mchash[2];
uint32_t rxcfg;
@@ -2072,15 +2081,7 @@
* Load multicast tables.
*/
bzero(mchash, sizeof(mchash));
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, ae_hash_maddr, &mchash);
AE_WRITE_4(sc, AE_REG_MHT0, mchash[0]);
AE_WRITE_4(sc, AE_REG_MHT1, mchash[1]);
AE_WRITE_4(sc, AE_MAC_REG, rxcfg);
Index: sys/dev/age/if_age.c
===================================================================
--- sys/dev/age/if_age.c
+++ sys/dev/age/if_age.c
@@ -3140,12 +3140,22 @@
CSR_WRITE_4(sc, AGE_MAC_CFG, reg);
}
+static u_int
+age_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *mchash = arg;
+ uint32_t crc;
+
+ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+ mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
+
+ return (1);
+}
+
static void
age_rxfilter(struct age_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t crc;
uint32_t mchash[2];
uint32_t rxcfg;
@@ -3170,16 +3180,7 @@
/* Program new filter. */
bzero(mchash, sizeof(mchash));
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &sc->age_ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, age_hash_maddr, mchash);
CSR_WRITE_4(sc, AGE_MAR0, mchash[0]);
CSR_WRITE_4(sc, AGE_MAR1, mchash[1]);
Index: sys/dev/al_eth/al_eth.c
===================================================================
--- sys/dev/al_eth/al_eth.c
+++ sys/dev/al_eth/al_eth.c
@@ -603,7 +603,7 @@
static void
al_eth_mac_table_unicast_add(struct al_eth_adapter *adapter,
- uint8_t idx, uint8_t *addr, uint8_t udma_mask)
+ uint8_t idx, uint8_t udma_mask)
{
struct al_eth_fwd_mac_table_entry entry = { { 0 } };
@@ -2876,6 +2876,30 @@
}
}
+static u_int
+al_count_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ unsigned char *mac;
+
+ mac = LLADDR(sdl);
+ /* default mc address inside mac address */
+ if (mac[3] != 0 && mac[4] != 0 && mac[5] != 1)
+ return (1);
+ else
+ return (0);
+}
+
+static u_int
+al_program_addr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct al_eth_adapter *adapter = arg;
+
+ al_eth_mac_table_unicast_add(adapter,
+ AL_ETH_MAC_TABLE_UNICAST_IDX_BASE + 1 + cnt, 1);
+
+ return (1);
+}
+
/*
* Unicast, Multicast and Promiscuous mode set
*
@@ -2884,43 +2908,16 @@
* responsible for configuring the hardware for proper unicast, multicast,
* promiscuous mode, and all-multi behavior.
*/
-#define MAX_NUM_MULTICAST_ADDRESSES 32
-#define MAX_NUM_ADDRESSES 32
-
static void
al_eth_set_rx_mode(struct al_eth_adapter *adapter)
{
struct ifnet *ifp = adapter->netdev;
- struct ifmultiaddr *ifma; /* multicast addresses configured */
- struct ifaddr *ifua; /* unicast address */
- int mc = 0;
- int uc = 0;
+ int mc, uc;
uint8_t i;
- unsigned char *mac;
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (mc == MAX_NUM_MULTICAST_ADDRESSES)
- break;
- mac = LLADDR((struct sockaddr_dl *) ifma->ifma_addr);
- /* default mc address inside mac address */
- if (mac[3] != 0 && mac[4] != 0 && mac[5] != 1)
- mc++;
- }
- if_maddr_runlock(ifp);
-
- if_addr_rlock(ifp);
- CK_STAILQ_FOREACH(ifua, &ifp->if_addrhead, ifa_link) {
- if (ifua->ifa_addr->sa_family != AF_LINK)
- continue;
- if (uc == MAX_NUM_ADDRESSES)
- break;
- uc++;
- }
- if_addr_runlock(ifp);
+ /* XXXGL: why generic count won't work? */
+ mc = if_foreach_llmaddr(ifp, al_count_maddr, NULL);
+ uc = if_lladdr_count(ifp);
if ((ifp->if_flags & IFF_PROMISC) != 0) {
al_eth_mac_table_promiscuous_set(adapter, true);
@@ -2957,18 +2954,7 @@
}
/* set new addresses */
- i = AL_ETH_MAC_TABLE_UNICAST_IDX_BASE + 1;
- if_addr_rlock(ifp);
- CK_STAILQ_FOREACH(ifua, &ifp->if_addrhead, ifa_link) {
- if (ifua->ifa_addr->sa_family != AF_LINK) {
- continue;
- }
- al_eth_mac_table_unicast_add(adapter, i,
- (unsigned char *)ifua->ifa_addr, 1);
- i++;
- }
- if_addr_runlock(ifp);
-
+ if_foreach_lladdr(ifp, al_program_addr, adapter);
}
al_eth_mac_table_promiscuous_set(adapter, false);
}
@@ -3001,7 +2987,7 @@
* MAC address and all broadcast. all the rest will be dropped.
*/
al_eth_mac_table_unicast_add(adapter, AL_ETH_MAC_TABLE_UNICAST_IDX_BASE,
- adapter->mac_addr, 1);
+ 1);
al_eth_mac_table_broadcast_add(adapter, AL_ETH_MAC_TABLE_BROADCAST_IDX, 1);
al_eth_mac_table_promiscuous_set(adapter, false);
Index: sys/dev/alc/if_alc.c
===================================================================
--- sys/dev/alc/if_alc.c
+++ sys/dev/alc/if_alc.c
@@ -4581,12 +4581,22 @@
CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
}
+static u_int
+alc_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *mchash = arg;
+ uint32_t crc;
+
+ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+ mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
+
+ return (1);
+}
+
static void
alc_rxfilter(struct alc_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t crc;
uint32_t mchash[2];
uint32_t rxcfg;
@@ -4609,15 +4619,7 @@
goto chipit;
}
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &sc->alc_ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, alc_hash_maddr, mchash);
chipit:
CSR_WRITE_4(sc, ALC_MAR0, mchash[0]);
Index: sys/dev/ale/if_ale.c
===================================================================
--- sys/dev/ale/if_ale.c
+++ sys/dev/ale/if_ale.c
@@ -3008,12 +3008,21 @@
CSR_WRITE_4(sc, ALE_MAC_CFG, reg);
}
+static u_int
+ale_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t crc, *mchash = arg;
+
+ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+ mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
+
+ return (1);
+}
+
static void
ale_rxfilter(struct ale_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t crc;
uint32_t mchash[2];
uint32_t rxcfg;
@@ -3038,16 +3047,7 @@
/* Program new filter. */
bzero(mchash, sizeof(mchash));
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &sc->ale_ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, ale_hash_maddr, &mchash);
CSR_WRITE_4(sc, ALE_MAR0, mchash[0]);
CSR_WRITE_4(sc, ALE_MAR1, mchash[1]);
Index: sys/dev/altera/atse/if_atse.c
===================================================================
--- sys/dev/altera/atse/if_atse.c
+++ sys/dev/altera/atse/if_atse.c
@@ -427,12 +427,14 @@
return (0);
}
-static uint8_t
-atse_mchash(struct atse_softc *sc __unused, const uint8_t *addr)
+static u_int
+atse_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
{
- uint8_t x, y;
+ uint64_t *h = arg;
+ uint8_t *addr, x, y;
int i, j;
+ addr = LLADDR(sdl);
x = 0;
for (i = 0; i < ETHER_ADDR_LEN; i++) {
y = addr[i] & 0x01;
@@ -440,14 +442,14 @@
y ^= (addr[i] >> j) & 0x01;
x |= (y << i);
}
+ *h |= (1 << x);
- return (x);
+ return (1);
}
static int
atse_rxfilter_locked(struct atse_softc *sc)
{
- struct ifmultiaddr *ifma;
struct ifnet *ifp;
uint32_t val4;
int i;
@@ -478,22 +480,13 @@
*/
uint64_t h;
- h = 0;
/*
* Re-build and re-program hash table. First build the
* bit-field "yes" or "no" for each slot per address, then
* do all the programming afterwards.
*/
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK) {
- continue;
- }
-
- h |= (1 << atse_mchash(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
- }
- if_maddr_runlock(ifp);
+ h = 0;
+ (void)if_foreach_llmaddr(ifp, atse_hash_maddr, &h);
for (i = 0; i <= MHASH_LEN; i++) {
CSR_WRITE_4(sc, MHASH_START + i,
(h & (1 << i)) ? 0x01 : 0x00);
Index: sys/dev/ath/if_ath.c
===================================================================
--- sys/dev/ath/if_ath.c
+++ sys/dev/ath/if_ath.c
@@ -3591,6 +3591,25 @@
DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x\n", __func__, rfilt);
}
+static u_int
+ath_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t val, *mfilt = arg;
+ char *dl;
+ uint8_t pos;
+
+ /* calculate XOR of eight 6bit values */
+ dl = LLADDR(sdl);
+ val = le32dec(dl + 0);
+ pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+ val = le32dec(dl + 3);
+ pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+ pos &= 0x3f;
+ mfilt[pos / 32] |= (1 << (pos % 32));
+
+ return (1);
+}
+
/*
* Driver-internal mcast update call.
*
@@ -3605,35 +3624,13 @@
/* calculate and install multicast filter */
if (ic->ic_allmulti == 0) {
struct ieee80211vap *vap;
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
/*
* Merge multicast addresses to form the hardware filter.
*/
mfilt[0] = mfilt[1] = 0;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
- ifp = vap->iv_ifp;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- caddr_t dl;
- uint32_t val;
- uint8_t pos;
-
- /* calculate XOR of eight 6bit values */
- dl = LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr);
- val = le32dec(dl + 0);
- pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^
- val;
- val = le32dec(dl + 3);
- pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^
- val;
- pos &= 0x3f;
- mfilt[pos / 32] |= (1 << (pos % 32));
- }
- if_maddr_runlock(ifp);
- }
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if_foreach_llmaddr(vap->iv_ifp, ath_hash_maddr, &mfilt);
} else
mfilt[0] = mfilt[1] = ~0;
Index: sys/dev/bce/if_bce.c
===================================================================
--- sys/dev/bce/if_bce.c
+++ sys/dev/bce/if_bce.c
@@ -8065,14 +8065,25 @@
/* Returns: */
/* Nothing. */
/****************************************************************************/
+static u_int
+bce_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ u32 *hashes = arg;
+ int h;
+
+ h = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN) & 0xFF;
+ hashes[(h & 0xE0) >> 5] |= 1 << (h & 0x1F);
+
+ return (1);
+}
+
static void
bce_set_rx_mode(struct bce_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
u32 hashes[NUM_MC_HASH_REGISTERS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
u32 rx_mode, sort_mode;
- int h, i;
+ int i;
DBENTER(BCE_VERBOSE_MISC);
@@ -8115,16 +8126,7 @@
} else {
/* Accept one or more multicast(s). */
DBPRINT(sc, BCE_INFO_MISC, "Enabling selective multicast mode.\n");
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_le(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) & 0xFF;
- hashes[(h & 0xE0) >> 5] |= 1 << (h & 0x1F);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, bce_hash_maddr, hashes);
for (i = 0; i < NUM_MC_HASH_REGISTERS; i++)
REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4), hashes[i]);
Index: sys/dev/bfe/if_bfe.c
===================================================================
--- sys/dev/bfe/if_bfe.c
+++ sys/dev/bfe/if_bfe.c
@@ -1080,13 +1080,21 @@
bfe_wait_bit(sc, BFE_CAM_CTRL, BFE_CAM_BUSY, 10000, 1);
}
+static u_int
+bfe_write_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct bfe_softc *sc = arg;
+
+ bfe_cam_write(sc, LLADDR(sdl), cnt + 1);
+
+ return (1);
+}
+
static void
bfe_set_rx_mode(struct bfe_softc *sc)
{
struct ifnet *ifp = sc->bfe_ifp;
- struct ifmultiaddr *ifma;
u_int32_t val;
- int i = 0;
BFE_LOCK_ASSERT(sc);
@@ -1104,20 +1112,13 @@
CSR_WRITE_4(sc, BFE_CAM_CTRL, 0);
- bfe_cam_write(sc, IF_LLADDR(sc->bfe_ifp), i++);
+ bfe_cam_write(sc, IF_LLADDR(sc->bfe_ifp), 0);
if (ifp->if_flags & IFF_ALLMULTI)
val |= BFE_RXCONF_ALLMULTI;
else {
val &= ~BFE_RXCONF_ALLMULTI;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- bfe_cam_write(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr), i++);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, bfe_write_maddr, sc);
}
CSR_WRITE_4(sc, BFE_RXCONF, val);
Index: sys/dev/bge/if_bge.c
===================================================================
--- sys/dev/bge/if_bge.c
+++ sys/dev/bge/if_bge.c
@@ -1621,33 +1621,32 @@
BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC);
}
+static u_int
+bge_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *hashes = arg;
+ int h;
+
+ h = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN) & 0x7F;
+ hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F);
+
+ return (1);
+}
+
static void
bge_setmulti(struct bge_softc *sc)
{
if_t ifp;
- int mc_count = 0;
uint32_t hashes[4] = { 0, 0, 0, 0 };
- int h, i, mcnt;
- unsigned char *mta;
+ int i;
BGE_LOCK_ASSERT(sc);
ifp = sc->bge_ifp;
- mc_count = if_multiaddr_count(ifp, -1);
- mta = malloc(sizeof(unsigned char) * ETHER_ADDR_LEN *
- mc_count, M_DEVBUF, M_NOWAIT);
-
- if(mta == NULL) {
- device_printf(sc->bge_dev,
- "Failed to allocated temp mcast list\n");
- return;
- }
-
if (if_getflags(ifp) & IFF_ALLMULTI || if_getflags(ifp) & IFF_PROMISC) {
for (i = 0; i < 4; i++)
CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0xFFFFFFFF);
- free(mta, M_DEVBUF);
return;
}
@@ -1655,17 +1654,10 @@
for (i = 0; i < 4; i++)
CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0);
- if_multiaddr_array(ifp, mta, &mcnt, mc_count);
- for(i = 0; i < mcnt; i++) {
- h = ether_crc32_le(mta + (i * ETHER_ADDR_LEN),
- ETHER_ADDR_LEN) & 0x7F;
- hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F);
- }
+ if_foreach_llmaddr(ifp, bge_hash_maddr, hashes);
for (i = 0; i < 4; i++)
CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]);
-
- free(mta, M_DEVBUF);
}
static void
Index: sys/dev/bnxt/if_bnxt.c
===================================================================
--- sys/dev/bnxt/if_bnxt.c
+++ sys/dev/bnxt/if_bnxt.c
@@ -46,6 +46,7 @@
#include <dev/pci/pcivar.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_var.h>
#include <net/ethernet.h>
@@ -1185,30 +1186,41 @@
return;
}
+static u_int
+bnxt_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint8_t *mta = arg;
+
+ if (cnt == BNXT_MAX_MC_ADDRS)
+ return (1);
+
+ bcopy(LLADDR(sdl), &mta[cnt * ETHER_ADDR_LEN], ETHER_ADDR_LEN);
+
+ return (1);
+}
+
static void
bnxt_multi_set(if_ctx_t ctx)
{
struct bnxt_softc *softc = iflib_get_softc(ctx);
if_t ifp = iflib_get_ifp(ctx);
uint8_t *mta;
- int cnt, mcnt;
+ int mcnt;
- mcnt = if_multiaddr_count(ifp, -1);
+ mta = softc->vnic_info.mc_list.idi_vaddr;
+ bzero(mta, softc->vnic_info.mc_list.idi_size);
+ mcnt = if_foreach_llmaddr(ifp, bnxt_copy_maddr, mta);
if (mcnt > BNXT_MAX_MC_ADDRS) {
softc->vnic_info.rx_mask |=
HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info);
- }
- else {
+ } else {
softc->vnic_info.rx_mask &=
~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
- mta = softc->vnic_info.mc_list.idi_vaddr;
- bzero(mta, softc->vnic_info.mc_list.idi_size);
- if_multiaddr_array(ifp, mta, &cnt, mcnt);
bus_dmamap_sync(softc->vnic_info.mc_list.idi_tag,
softc->vnic_info.mc_list.idi_map, BUS_DMASYNC_PREWRITE);
- softc->vnic_info.mc_list_count = cnt;
+ softc->vnic_info.mc_list_count = mcnt;
softc->vnic_info.rx_mask |=
HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_MCAST;
if (bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info))
@@ -1370,7 +1382,7 @@
int rc;
if (ifp->if_flags & IFF_ALLMULTI ||
- if_multiaddr_count(ifp, -1) > BNXT_MAX_MC_ADDRS)
+ if_llmaddr_count(ifp) > BNXT_MAX_MC_ADDRS)
softc->vnic_info.rx_mask |=
HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
else
Index: sys/dev/bxe/bxe.h
===================================================================
--- sys/dev/bxe/bxe.h
+++ sys/dev/bxe/bxe.h
@@ -1492,29 +1492,8 @@
#define BXE_STATS_UNLOCK(sc) mtx_unlock(&sc->stats_mtx)
#define BXE_STATS_LOCK_ASSERT(sc) mtx_assert(&sc->stats_mtx, MA_OWNED)
-#if __FreeBSD_version < 800000
-#define BXE_MCAST_LOCK(sc) \
- do { \
- mtx_lock(&sc->mcast_mtx); \
- IF_ADDR_LOCK(sc->ifp); \
- } while (0)
-#define BXE_MCAST_UNLOCK(sc) \
- do { \
- IF_ADDR_UNLOCK(sc->ifp); \
- mtx_unlock(&sc->mcast_mtx); \
- } while (0)
-#else
-#define BXE_MCAST_LOCK(sc) \
- do { \
- mtx_lock(&sc->mcast_mtx); \
- if_maddr_rlock(sc->ifp); \
- } while (0)
-#define BXE_MCAST_UNLOCK(sc) \
- do { \
- if_maddr_runlock(sc->ifp); \
- mtx_unlock(&sc->mcast_mtx); \
- } while (0)
-#endif
+#define BXE_MCAST_LOCK(sc) mtx_lock(&sc->mcast_mtx);
+#define BXE_MCAST_UNLOCK(sc) mtx_unlock(&sc->mcast_mtx);
#define BXE_MCAST_LOCK_ASSERT(sc) mtx_assert(&sc->mcast_mtx, MA_OWNED)
int dmae_ready;
Index: sys/dev/bxe/bxe.c
===================================================================
--- sys/dev/bxe/bxe.c
+++ sys/dev/bxe/bxe.c
@@ -12065,27 +12065,31 @@
return (rc);
}
-/* must be called under IF_ADDR_LOCK */
+static u_int
+bxe_push_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct ecore_mcast_list_elem *mc_mac = arg;
+
+ mc_mac += cnt;
+ mc_mac->mac = (uint8_t *)LLADDR(sdl);
+
+ return (1);
+}
+
static int
bxe_init_mcast_macs_list(struct bxe_softc *sc,
struct ecore_mcast_ramrod_params *p)
{
if_t ifp = sc->ifp;
- int mc_count = 0;
- struct ifmultiaddr *ifma;
+ int mc_count;
struct ecore_mcast_list_elem *mc_mac;
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK) {
- continue;
- }
-
- mc_count++;
- }
-
ECORE_LIST_INIT(&p->mcast_list);
p->mcast_list_len = 0;
+ /* XXXGL: multicast count may change later */
+ mc_count = if_llmaddr_count(ifp);
+
if (!mc_count) {
return (0);
}
@@ -12097,20 +12101,15 @@
return (-1);
}
bzero(mc_mac, (sizeof(*mc_mac) * mc_count));
+ if_foreach_llmaddr(ifp, bxe_push_maddr, mc_mac);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK) {
- continue;
- }
-
- mc_mac->mac = (uint8_t *)LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
- ECORE_LIST_PUSH_TAIL(&mc_mac->link, &p->mcast_list);
-
+ for (int i = 0; i < mc_count; i ++) {
+ ECORE_LIST_PUSH_TAIL(&mc_mac[i].link, &p->mcast_list);
BLOGD(sc, DBG_LOAD,
"Setting MCAST %02X:%02X:%02X:%02X:%02X:%02X and mc_count %d\n",
- mc_mac->mac[0], mc_mac->mac[1], mc_mac->mac[2],
- mc_mac->mac[3], mc_mac->mac[4], mc_mac->mac[5], mc_count);
- mc_mac++;
+ mc_mac[i].mac[0], mc_mac[i].mac[1], mc_mac[i].mac[2],
+ mc_mac[i].mac[3], mc_mac[i].mac[4], mc_mac[i].mac[5],
+ mc_count);
}
p->mcast_list_len = mc_count;
@@ -12171,69 +12170,59 @@
return (rc);
}
+struct bxe_set_addr_ctx {
+ struct bxe_softc *sc;
+ unsigned long ramrod_flags;
+ int rc;
+};
+
+static u_int
+bxe_set_addr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct bxe_set_addr_ctx *ctx = arg;
+ struct ecore_vlan_mac_obj *mac_obj = &ctx->sc->sp_objs->mac_obj;
+ int rc;
+
+ if (ctx->rc < 0)
+ return (0);
+
+ rc = bxe_set_mac_one(ctx->sc, (uint8_t *)LLADDR(sdl), mac_obj, TRUE,
+ ECORE_UC_LIST_MAC, &ctx->ramrod_flags);
+
+ /* do not treat adding same MAC as an error */
+ if (rc == -EEXIST)
+ BLOGD(ctx->sc, DBG_SP, "Failed to schedule ADD operations (EEXIST)\n");
+ else if (rc < 0) {
+ BLOGE(ctx->sc, "Failed to schedule ADD operations (%d)\n", rc);
+ ctx->rc = rc;
+ }
+
+ return (1);
+}
+
static int
bxe_set_uc_list(struct bxe_softc *sc)
{
if_t ifp = sc->ifp;
struct ecore_vlan_mac_obj *mac_obj = &sc->sp_objs->mac_obj;
- struct ifaddr *ifa;
- unsigned long ramrod_flags = 0;
+ struct bxe_set_addr_ctx ctx = { sc, 0, 0 };
int rc;
-#if __FreeBSD_version < 800000
- IF_ADDR_LOCK(ifp);
-#else
- if_addr_rlock(ifp);
-#endif
-
/* first schedule a cleanup up of old configuration */
rc = bxe_del_all_macs(sc, mac_obj, ECORE_UC_LIST_MAC, FALSE);
if (rc < 0) {
BLOGE(sc, "Failed to schedule delete of all ETH MACs (%d)\n", rc);
-#if __FreeBSD_version < 800000
- IF_ADDR_UNLOCK(ifp);
-#else
- if_addr_runlock(ifp);
-#endif
return (rc);
}
- ifa = if_getifaddr(ifp); /* XXX Is this structure */
- while (ifa) {
- if (ifa->ifa_addr->sa_family != AF_LINK) {
- ifa = CK_STAILQ_NEXT(ifa, ifa_link);
- continue;
- }
-
- rc = bxe_set_mac_one(sc, (uint8_t *)LLADDR((struct sockaddr_dl *)ifa->ifa_addr),
- mac_obj, TRUE, ECORE_UC_LIST_MAC, &ramrod_flags);
- if (rc == -EEXIST) {
- BLOGD(sc, DBG_SP, "Failed to schedule ADD operations (EEXIST)\n");
- /* do not treat adding same MAC as an error */
- rc = 0;
- } else if (rc < 0) {
- BLOGE(sc, "Failed to schedule ADD operations (%d)\n", rc);
-#if __FreeBSD_version < 800000
- IF_ADDR_UNLOCK(ifp);
-#else
- if_addr_runlock(ifp);
-#endif
- return (rc);
- }
-
- ifa = CK_STAILQ_NEXT(ifa, ifa_link);
- }
-
-#if __FreeBSD_version < 800000
- IF_ADDR_UNLOCK(ifp);
-#else
- if_addr_runlock(ifp);
-#endif
+ if_foreach_lladdr(ifp, bxe_set_addr, &ctx);
+ if (ctx.rc < 0)
+ return (ctx.rc);
/* Execute the pending commands */
- bit_set(&ramrod_flags, RAMROD_CONT);
+ bit_set(&ctx.ramrod_flags, RAMROD_CONT);
return (bxe_set_mac_one(sc, NULL, mac_obj, FALSE /* don't care */,
- ECORE_UC_LIST_MAC, &ramrod_flags));
+ ECORE_UC_LIST_MAC, &ctx.ramrod_flags));
}
static void
Index: sys/dev/cadence/if_cgem.c
===================================================================
--- sys/dev/cadence/if_cgem.c
+++ sys/dev/cadence/if_cgem.c
@@ -299,6 +299,21 @@
return hash;
}
+static u_int
+cgem_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *hashes = arg;
+ int index;
+
+ index = cgem_mac_hash(LLADDR(sdl));
+ if (index > 31)
+ hashes[0] |= (1 << (index - 32));
+ else
+ hashes[1] |= (1 << index);
+
+ return (1);
+}
+
/* After any change in rx flags or multi-cast addresses, set up
* hash registers and net config register bits.
*/
@@ -306,15 +321,9 @@
cgem_rx_filter(struct cgem_softc *sc)
{
if_t ifp = sc->ifp;
- u_char *mta;
-
- int index, i, mcnt;
- uint32_t hash_hi, hash_lo;
+ uint32_t hashes[2] = { 0, 0 };
uint32_t net_cfg;
- hash_hi = 0;
- hash_lo = 0;
-
net_cfg = RD4(sc, CGEM_NET_CFG);
net_cfg &= ~(CGEM_NET_CFG_MULTI_HASH_EN |
@@ -327,36 +336,17 @@
if ((if_getflags(ifp) & IFF_BROADCAST) == 0)
net_cfg |= CGEM_NET_CFG_NO_BCAST;
if ((if_getflags(ifp) & IFF_ALLMULTI) != 0) {
- hash_hi = 0xffffffff;
- hash_lo = 0xffffffff;
- } else {
- mcnt = if_multiaddr_count(ifp, -1);
- mta = malloc(ETHER_ADDR_LEN * mcnt, M_DEVBUF,
- M_NOWAIT);
- if (mta == NULL) {
- device_printf(sc->dev,
- "failed to allocate temp mcast list\n");
- return;
- }
- if_multiaddr_array(ifp, mta, &mcnt, mcnt);
- for (i = 0; i < mcnt; i++) {
- index = cgem_mac_hash(
- LLADDR((struct sockaddr_dl *)
- (mta + (i * ETHER_ADDR_LEN))));
- if (index > 31)
- hash_hi |= (1 << (index - 32));
- else
- hash_lo |= (1 << index);
- }
- free(mta, M_DEVBUF);
- }
+ hashes[0] = 0xffffffff;
+ hashes[1] = 0xffffffff;
+ } else
+ if_foreach_llmaddr(ifp, cgem_hash_maddr, hashes);
- if (hash_hi != 0 || hash_lo != 0)
+ if (hashes[0] != 0 || hashes[1] != 0)
net_cfg |= CGEM_NET_CFG_MULTI_HASH_EN;
}
- WR4(sc, CGEM_HASH_TOP, hash_hi);
- WR4(sc, CGEM_HASH_BOT, hash_lo);
+ WR4(sc, CGEM_HASH_TOP, hashes[0]);
+ WR4(sc, CGEM_HASH_BOT, hashes[1]);
WR4(sc, CGEM_NET_CFG, net_cfg);
}
Index: sys/dev/cas/if_cas.c
===================================================================
--- sys/dev/cas/if_cas.c
+++ sys/dev/cas/if_cas.c
@@ -2498,14 +2498,27 @@
return (error);
}
+static u_int
+cas_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t crc, *hash = arg;
+
+ crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN);
+ /* We just want the 8 most significant bits. */
+ crc >>= 24;
+ /* Set the corresponding bit in the filter. */
+ hash[crc >> 4] |= 1 << (15 - (crc & 15));
+
+ return (1);
+}
+
static void
cas_setladrf(struct cas_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
- struct ifmultiaddr *inm;
int i;
uint32_t hash[16];
- uint32_t crc, v;
+ uint32_t v;
CAS_LOCK_ASSERT(sc, MA_OWNED);
@@ -2542,23 +2555,8 @@
* is the MSB).
*/
- /* Clear the hash table. */
memset(hash, 0, sizeof(hash));
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) {
- if (inm->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
- inm->ifma_addr), ETHER_ADDR_LEN);
-
- /* We just want the 8 most significant bits. */
- crc >>= 24;
-
- /* Set the corresponding bit in the filter. */
- hash[crc >> 4] |= 1 << (15 - (crc & 15));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, cas_hash_maddr, &hash);
v |= CAS_MAC_RX_CONF_HFILTER;
Index: sys/dev/cxgb/common/cxgb_xgmac.c
===================================================================
--- sys/dev/cxgb/common/cxgb_xgmac.c
+++ sys/dev/cxgb/common/cxgb_xgmac.c
@@ -408,9 +408,32 @@
* Configures the MAC Rx mode (promiscuity, etc) and exact and hash
* address filters.
*/
+struct t3_mcaddr_ctx {
+ struct cmac *mac;
+ u32 hash_lo, hash_hi;
+};
+
+static u_int
+t3_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct t3_mcaddr_ctx *ctx = arg;
+ int hash;
+
+ if (ctx->mac->nucast + cnt < EXACT_ADDR_FILTERS)
+ set_addr_filter(ctx->mac, ctx->mac->nucast + cnt, LLADDR(sdl));
+ else {
+ hash = hash_hw_addr(LLADDR(sdl));
+ if (hash < 32)
+ ctx->hash_lo |= (1 << hash);
+ else
+ ctx->hash_hi |= (1 << (hash - 32));
+ }
+ return (1);
+}
+
int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm)
{
- u32 hash_lo, hash_hi;
+ struct t3_mcaddr_ctx ctx;
adapter_t *adap = mac->adapter;
unsigned int oft = mac->offset;
@@ -422,27 +445,15 @@
mac->promisc_map ? F_COPYALLFRAMES : 0);
if (allmulti_rx_mode(rm) || mac->multiport)
- hash_lo = hash_hi = 0xffffffff;
+ ctx.hash_lo = ctx.hash_hi = 0xffffffff;
else {
- u8 *addr;
- int exact_addr_idx = mac->nucast;
-
- hash_lo = hash_hi = 0;
- while ((addr = t3_get_next_mcaddr(rm)))
- if (exact_addr_idx < EXACT_ADDR_FILTERS)
- set_addr_filter(mac, exact_addr_idx++, addr);
- else {
- int hash = hash_hw_addr(addr);
-
- if (hash < 32)
- hash_lo |= (1 << hash);
- else
- hash_hi |= (1 << (hash - 32));
- }
+ ctx.mac = mac;
+ ctx.hash_lo = ctx.hash_hi = 0;
+ if_foreach_llmaddr(rm->port->ifp, t3_hash_maddr, &ctx);
}
- t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo);
- t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi);
+ t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, ctx.hash_lo);
+ t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, ctx.hash_hi);
return 0;
}
Index: sys/dev/cxgb/cxgb_adapter.h
===================================================================
--- sys/dev/cxgb/cxgb_adapter.h
+++ sys/dev/cxgb/cxgb_adapter.h
@@ -463,30 +463,6 @@
pci_write_config(adapter->dev, reg, val, 2);
}
-static __inline uint8_t *
-t3_get_next_mcaddr(struct t3_rx_mode *rm)
-{
- uint8_t *macaddr = NULL;
- struct ifnet *ifp = rm->port->ifp;
- struct ifmultiaddr *ifma;
- int i = 0;
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (i == rm->idx) {
- macaddr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
- break;
- }
- i++;
- }
- if_maddr_runlock(ifp);
-
- rm->idx++;
- return (macaddr);
-}
-
static __inline void
t3_init_rx_mode(struct t3_rx_mode *rm, struct port_info *port)
{
Index: sys/dev/cxgbe/t4_main.c
===================================================================
--- sys/dev/cxgbe/t4_main.c
+++ sys/dev/cxgbe/t4_main.c
@@ -4782,6 +4782,54 @@
}
#define FW_MAC_EXACT_CHUNK 7
+struct mcaddr_ctx {
+ struct ifnet *ifp;
+ const uint8_t *mcaddr[FW_MAC_EXACT_CHUNK];
+ uint64_t hash;
+ int i;
+ int del;
+ int rc;
+};
+
+static u_int
+add_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct mcaddr_ctx *ctx = arg;
+ struct vi_info *vi = ctx->ifp->if_softc;
+ struct port_info *pi = vi->pi;
+ struct adapter *sc = pi->adapter;
+
+ if (ctx->rc < 0)
+ return (0);
+
+ ctx->mcaddr[ctx->i] = LLADDR(sdl);
+ MPASS(ETHER_IS_MULTICAST(ctx->mcaddr[ctx->i]));
+ ctx->i++;
+
+ if (ctx->i == FW_MAC_EXACT_CHUNK) {
+ ctx->rc = t4_alloc_mac_filt(sc, sc->mbox, vi->viid, ctx->del,
+ ctx->i, ctx->mcaddr, NULL, &ctx->hash, 0);
+ if (ctx->rc < 0) {
+ int j;
+
+ for (j = 0; j < ctx->i; j++) {
+ if_printf(ctx->ifp,
+ "failed to add mc address"
+ " %02x:%02x:%02x:"
+ "%02x:%02x:%02x rc=%d\n",
+ ctx->mcaddr[j][0], ctx->mcaddr[j][1],
+ ctx->mcaddr[j][2], ctx->mcaddr[j][3],
+ ctx->mcaddr[j][4], ctx->mcaddr[j][5],
+ -ctx->rc);
+ }
+ return (0);
+ }
+ ctx->del = 0;
+ ctx->i = 0;
+ }
+
+ return (1);
+}
/*
* Program the port's XGMAC based on parameters in ifnet. The caller also
@@ -4838,66 +4886,51 @@
}
if (flags & XGMAC_MCADDRS) {
- const uint8_t *mcaddr[FW_MAC_EXACT_CHUNK];
- int del = 1;
- uint64_t hash = 0;
- struct ifmultiaddr *ifma;
- int i = 0, j;
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- mcaddr[i] =
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
- MPASS(ETHER_IS_MULTICAST(mcaddr[i]));
- i++;
-
- if (i == FW_MAC_EXACT_CHUNK) {
- rc = t4_alloc_mac_filt(sc, sc->mbox, vi->viid,
- del, i, mcaddr, NULL, &hash, 0);
- if (rc < 0) {
- rc = -rc;
- for (j = 0; j < i; j++) {
- if_printf(ifp,
- "failed to add mc address"
- " %02x:%02x:%02x:"
- "%02x:%02x:%02x rc=%d\n",
- mcaddr[j][0], mcaddr[j][1],
- mcaddr[j][2], mcaddr[j][3],
- mcaddr[j][4], mcaddr[j][5],
- rc);
- }
- goto mcfail;
- }
- del = 0;
- i = 0;
- }
+ struct epoch_tracker et;
+ struct mcaddr_ctx ctx;
+ int j;
+
+ ctx.ifp = ifp;
+ ctx.hash = 0;
+ ctx.i = 0;
+ ctx.del = 1;
+ /*
+ * Unlike other drivers, we accumulate list of pointers into
+ * interface address lists and we need to keep it safe even
+ * after if_foreach_llmaddr() returns, thus we must enter the
+ * network epoch.
+ */
+ NET_EPOCH_ENTER(et);
+ if_foreach_llmaddr(ifp, add_maddr, &ctx);
+ if (ctx.rc < 0) {
+ NET_EPOCH_EXIT(et);
+ rc = -ctx.rc;
+ return (rc);
}
- if (i > 0) {
- rc = t4_alloc_mac_filt(sc, sc->mbox, vi->viid, del, i,
- mcaddr, NULL, &hash, 0);
+ if (ctx.i > 0) {
+ rc = t4_alloc_mac_filt(sc, sc->mbox, vi->viid,
+ ctx.del, ctx.i, ctx.mcaddr, NULL, &ctx.hash, 0);
+ NET_EPOCH_EXIT(et);
if (rc < 0) {
rc = -rc;
- for (j = 0; j < i; j++) {
+ for (j = 0; j < ctx.i; j++) {
if_printf(ifp,
"failed to add mc address"
" %02x:%02x:%02x:"
"%02x:%02x:%02x rc=%d\n",
- mcaddr[j][0], mcaddr[j][1],
- mcaddr[j][2], mcaddr[j][3],
- mcaddr[j][4], mcaddr[j][5],
+ ctx.mcaddr[j][0], ctx.mcaddr[j][1],
+ ctx.mcaddr[j][2], ctx.mcaddr[j][3],
+ ctx.mcaddr[j][4], ctx.mcaddr[j][5],
rc);
}
- goto mcfail;
+ return (rc);
}
- }
+ } else
+ NET_EPOCH_EXIT(et);
- rc = -t4_set_addr_hash(sc, sc->mbox, vi->viid, 0, hash, 0);
+ rc = -t4_set_addr_hash(sc, sc->mbox, vi->viid, 0, ctx.hash, 0);
if (rc != 0)
if_printf(ifp, "failed to set mc address hash: %d", rc);
-mcfail:
- if_maddr_runlock(ifp);
}
return (rc);
Index: sys/dev/dc/if_dc.c
===================================================================
--- sys/dev/dc/if_dc.c
+++ sys/dev/dc/if_dc.c
@@ -962,13 +962,24 @@
* frames. We also sneak the broadcast address into the hash filter since
* we need that too.
*/
+static u_int
+dc_hash_maddr_21143(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct dc_softc *sc = arg;
+ uint32_t h;
+
+ h = dc_mchash_le(sc, LLADDR(sdl));
+ sc->dc_cdata.dc_sbuf[h >> 4] |= htole32(1 << (h & 0xF));
+
+ return (1);
+}
+
static void
dc_setfilt_21143(struct dc_softc *sc)
{
uint16_t eaddr[(ETHER_ADDR_LEN+1)/2];
struct dc_desc *sframe;
uint32_t h, *sp;
- struct ifmultiaddr *ifma;
struct ifnet *ifp;
int i;
@@ -998,15 +1009,7 @@
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = dc_mchash_le(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- sp[h >> 4] |= htole32(1 << (h & 0xF));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, dc_hash_maddr_21143, sp);
if (ifp->if_flags & IFF_BROADCAST) {
h = dc_mchash_le(sc, ifp->if_broadcastaddr);
@@ -1036,14 +1039,47 @@
sc->dc_wdog_timer = 5;
}
+static u_int
+dc_hash_maddr_admtek_be(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *hashes = arg;
+ int h = 0;
+
+ h = dc_mchash_be(LLADDR(sdl));
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+
+ return (1);
+}
+
+struct dc_hash_maddr_admtek_le_ctx {
+ struct dc_softc *sc;
+ uint32_t hashes[2];
+};
+
+static u_int
+dc_hash_maddr_admtek_le(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct dc_hash_maddr_admtek_le_ctx *ctx = arg;
+ int h = 0;
+
+ h = dc_mchash_le(ctx->sc, LLADDR(sdl));
+ if (h < 32)
+ ctx->hashes[0] |= (1 << h);
+ else
+ ctx->hashes[1] |= (1 << (h - 32));
+
+ return (1);
+}
+
static void
dc_setfilt_admtek(struct dc_softc *sc)
{
uint8_t eaddr[ETHER_ADDR_LEN];
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- int h = 0;
- uint32_t hashes[2] = { 0, 0 };
+ struct dc_hash_maddr_admtek_le_ctx ctx = { sc, { 0, 0 }};
ifp = sc->dc_ifp;
@@ -1076,25 +1112,13 @@
return;
/* Now program new ones. */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (DC_IS_CENTAUR(sc))
- h = dc_mchash_le(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- else
- h = dc_mchash_be(
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- }
- if_maddr_runlock(ifp);
+ if (DC_IS_CENTAUR(sc))
+ if_foreach_llmaddr(ifp, dc_hash_maddr_admtek_le, &ctx);
+ else
+ if_foreach_llmaddr(ifp, dc_hash_maddr_admtek_be, &ctx.hashes);
- CSR_WRITE_4(sc, DC_AL_MAR0, hashes[0]);
- CSR_WRITE_4(sc, DC_AL_MAR1, hashes[1]);
+ CSR_WRITE_4(sc, DC_AL_MAR0, ctx.hashes[0]);
+ CSR_WRITE_4(sc, DC_AL_MAR1, ctx.hashes[1]);
}
static void
@@ -1102,8 +1126,6 @@
{
uint32_t eaddr[(ETHER_ADDR_LEN+3)/4];
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- int h = 0;
uint32_t hashes[2] = { 0, 0 };
ifp = sc->dc_ifp;
@@ -1149,17 +1171,7 @@
return;
/* now program new ones */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = dc_mchash_be(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, dc_hash_maddr_admtek_be, hashes);
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0);
CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[0]);
@@ -1167,15 +1179,29 @@
CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[1]);
}
+static u_int
+dc_hash_maddr_uli(void *arg, struct sockaddr_dl *sdl, u_int mcnt)
+{
+ uint32_t **sp = arg;
+ uint8_t *ma;
+
+ if (mcnt == DC_ULI_FILTER_NPERF)
+ return (0);
+ ma = LLADDR(sdl);
+ *(*sp)++ = DC_SP_MAC(ma[1] << 8 | ma[0]);
+ *(*sp)++ = DC_SP_MAC(ma[3] << 8 | ma[2]);
+ *(*sp)++ = DC_SP_MAC(ma[5] << 8 | ma[4]);
+
+ return (1);
+}
+
static void
dc_setfilt_uli(struct dc_softc *sc)
{
uint8_t eaddr[ETHER_ADDR_LEN];
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
struct dc_desc *sframe;
uint32_t filter, *sp;
- uint8_t *ma;
int i, mcnt;
ifp = sc->dc_ifp;
@@ -1209,28 +1235,16 @@
filter &= ~(DC_NETCFG_RX_PROMISC | DC_NETCFG_RX_ALLMULTI);
/* Now build perfect filters. */
- mcnt = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (mcnt >= DC_ULI_FILTER_NPERF) {
- filter |= DC_NETCFG_RX_ALLMULTI;
- break;
- }
- ma = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
- *sp++ = DC_SP_MAC(ma[1] << 8 | ma[0]);
- *sp++ = DC_SP_MAC(ma[3] << 8 | ma[2]);
- *sp++ = DC_SP_MAC(ma[5] << 8 | ma[4]);
- mcnt++;
- }
- if_maddr_runlock(ifp);
+ mcnt = if_foreach_llmaddr(ifp, dc_hash_maddr_uli, &sp);
- for (; mcnt < DC_ULI_FILTER_NPERF; mcnt++) {
- *sp++ = DC_SP_MAC(0xFFFF);
- *sp++ = DC_SP_MAC(0xFFFF);
- *sp++ = DC_SP_MAC(0xFFFF);
- }
+ if (mcnt == DC_ULI_FILTER_NPERF)
+ filter |= DC_NETCFG_RX_ALLMULTI;
+ else
+ for (; mcnt < DC_ULI_FILTER_NPERF; mcnt++) {
+ *sp++ = DC_SP_MAC(0xFFFF);
+ *sp++ = DC_SP_MAC(0xFFFF);
+ *sp++ = DC_SP_MAC(0xFFFF);
+ }
if (filter & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON))
CSR_WRITE_4(sc, DC_NETCFG,
@@ -1258,12 +1272,22 @@
sc->dc_wdog_timer = 5;
}
+static u_int
+dc_hash_maddr_xircom(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct dc_softc *sc = arg;
+ uint32_t h;
+
+ h = dc_mchash_le(sc, LLADDR(sdl));
+ sc->dc_cdata.dc_sbuf[h >> 4] |= htole32(1 << (h & 0xF));
+ return (1);
+}
+
static void
dc_setfilt_xircom(struct dc_softc *sc)
{
uint16_t eaddr[(ETHER_ADDR_LEN+1)/2];
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
struct dc_desc *sframe;
uint32_t h, *sp;
int i;
@@ -1295,15 +1319,7 @@
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = dc_mchash_le(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- sp[h >> 4] |= htole32(1 << (h & 0xF));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, dc_hash_maddr_xircom, &sp);
if (ifp->if_flags & IFF_BROADCAST) {
h = dc_mchash_le(sc, ifp->if_broadcastaddr);
Index: sys/dev/dwc/if_dwc.c
===================================================================
--- sys/dev/dwc/if_dwc.c
+++ sys/dev/dwc/if_dwc.c
@@ -581,13 +581,37 @@
return (nibbletab[x & 0xf] << 4) | nibbletab[x >> 4];
}
+struct dwc_hash_maddr_ctx {
+ struct dwc_softc *sc;
+ uint32_t hash[8];
+};
+
+static u_int
+dwc_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct dwc_hash_maddr_ctx *ctx = arg;
+ uint32_t crc, hashbit, hashreg;
+ uint8_t val;
+
+ crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN);
+ /* Take lower 8 bits and reverse it */
+ val = bitreverse(~crc & 0xff);
+ if (ctx->sc->mactype == DWC_GMAC_ALT_DESC)
+ val >>= 2; /* Only need lower 6 bits */
+ hashreg = (val >> 5);
+ hashbit = (val & 31);
+ ctx->hash[hashreg] |= (1 << hashbit);
+
+ return (1);
+}
+
static void
dwc_setup_rxfilter(struct dwc_softc *sc)
{
- struct ifmultiaddr *ifma;
+ struct dwc_hash_maddr_ctx ctx;
struct ifnet *ifp;
- uint8_t *eaddr, val;
- uint32_t crc, ffval, hashbit, hashreg, hi, lo, hash[8];
+ uint8_t *eaddr;
+ uint32_t ffval, hi, lo;
int nhash, i;
DWC_ASSERT_LOCKED(sc);
@@ -601,27 +625,13 @@
if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
ffval = (FRAME_FILTER_PM);
for (i = 0; i < nhash; i++)
- hash[i] = ~0;
+ ctx.hash[i] = ~0;
} else {
ffval = (FRAME_FILTER_HMC);
for (i = 0; i < nhash; i++)
- hash[i] = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
-
- /* Take lower 8 bits and reverse it */
- val = bitreverse(~crc & 0xff);
- if (sc->mactype == DWC_GMAC_ALT_DESC)
- val >>= nhash; /* Only need lower 6 bits */
- hashreg = (val >> 5);
- hashbit = (val & 31);
- hash[hashreg] |= (1 << hashbit);
- }
- if_maddr_runlock(ifp);
+ ctx.hash[i] = 0;
+ ctx.sc = sc;
+ if_foreach_llmaddr(ifp, dwc_hash_maddr, &ctx);
}
/*
@@ -641,11 +651,11 @@
WRITE4(sc, MAC_ADDRESS_HIGH(0), hi);
WRITE4(sc, MAC_FRAME_FILTER, ffval);
if (sc->mactype == DWC_GMAC_ALT_DESC) {
- WRITE4(sc, GMAC_MAC_HTLOW, hash[0]);
- WRITE4(sc, GMAC_MAC_HTHIGH, hash[1]);
+ WRITE4(sc, GMAC_MAC_HTLOW, ctx.hash[0]);
+ WRITE4(sc, GMAC_MAC_HTHIGH, ctx.hash[1]);
} else {
for (i = 0; i < nhash; i++)
- WRITE4(sc, HASH_TABLE_REG(i), hash[i]);
+ WRITE4(sc, HASH_TABLE_REG(i), ctx.hash[i]);
}
}
Index: sys/dev/e1000/if_em.c
===================================================================
--- sys/dev/e1000/if_em.c
+++ sys/dev/e1000/if_em.c
@@ -1656,7 +1656,7 @@
if (if_getflags(ifp) & IFF_ALLMULTI)
mcnt = MAX_NUM_MULTICAST_ADDRESSES;
else
- mcnt = if_multiaddr_count(ifp, MAX_NUM_MULTICAST_ADDRESSES);
+ mcnt = if_llmaddr_count(ifp);
/* Don't disable if in MAX groups */
if (mcnt < MAX_NUM_MULTICAST_ADDRESSES)
reg_rctl &= (~E1000_RCTL_MPE);
@@ -1665,6 +1665,19 @@
}
+static u_int
+em_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ u8 *mta = arg;
+
+ if (cnt == MAX_NUM_MULTICAST_ADDRESSES)
+ return (1);
+
+ bcopy(LLADDR(sdl), &mta[cnt * ETH_ADDR_LEN], ETH_ADDR_LEN);
+
+ return (1);
+}
+
/*********************************************************************
* Multicast Update
*
@@ -1696,7 +1709,7 @@
msec_delay(5);
}
- if_multiaddr_array(ifp, mta, &mcnt, MAX_NUM_MULTICAST_ADDRESSES);
+ mcnt = if_foreach_llmaddr(ifp, em_copy_maddr, mta);
if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) {
reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
Index: sys/dev/et/if_et.c
===================================================================
--- sys/dev/et/if_et.c
+++ sys/dev/et/if_et.c
@@ -1560,13 +1560,36 @@
}
}
+static u_int
+et_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t h, *hp, *hash = arg;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+ h = (h & 0x3f800000) >> 23;
+
+ hp = &hash[0];
+ if (h >= 32 && h < 64) {
+ h -= 32;
+ hp = &hash[1];
+ } else if (h >= 64 && h < 96) {
+ h -= 64;
+ hp = &hash[2];
+ } else if (h >= 96) {
+ h -= 96;
+ hp = &hash[3];
+ }
+ *hp |= (1 << h);
+
+ return (1);
+}
+
static void
et_setmulti(struct et_softc *sc)
{
struct ifnet *ifp;
uint32_t hash[4] = { 0, 0, 0, 0 };
uint32_t rxmac_ctrl, pktfilt;
- struct ifmultiaddr *ifma;
int i, count;
ET_LOCK_ASSERT(sc);
@@ -1581,34 +1604,7 @@
goto back;
}
- count = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- uint32_t *hp, h;
-
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- h = (h & 0x3f800000) >> 23;
-
- hp = &hash[0];
- if (h >= 32 && h < 64) {
- h -= 32;
- hp = &hash[1];
- } else if (h >= 64 && h < 96) {
- h -= 64;
- hp = &hash[2];
- } else if (h >= 96) {
- h -= 96;
- hp = &hash[3];
- }
- *hp |= (1 << h);
-
- ++count;
- }
- if_maddr_runlock(ifp);
+ count = if_foreach_llmaddr(ifp, et_hash_maddr, &hash);
for (i = 0; i < 4; ++i)
CSR_WRITE_4(sc, ET_MULTI_HASH + (i * 4), hash[i]);
Index: sys/dev/ffec/if_ffec.c
===================================================================
--- sys/dev/ffec/if_ffec.c
+++ sys/dev/ffec/if_ffec.c
@@ -974,13 +974,24 @@
}
}
+static u_int
+ffec_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint64_t *ghash = arg;
+ uint32_t crc;
+
+ /* 6 bits from MSB in LE CRC32 are used for hash. */
+ crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN);
+ *ghash |= 1LLU << (((uint8_t *)&crc)[3] >> 2);
+
+ return (1);
+}
+
static void
ffec_setup_rxfilter(struct ffec_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
uint8_t *eaddr;
- uint32_t crc;
uint64_t ghash, ihash;
FFEC_ASSERT_LOCKED(sc);
@@ -994,16 +1005,7 @@
ghash = 0xffffffffffffffffLLU;
else {
ghash = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- /* 6 bits from MSB in LE CRC32 are used for hash. */
- crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- ghash |= 1LLU << (((uint8_t *)&crc)[3] >> 2);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, ffec_hash_maddr, &ghash);
}
WR4(sc, FEC_GAUR_REG, (uint32_t)(ghash >> 32));
WR4(sc, FEC_GALR_REG, (uint32_t)ghash);
Index: sys/dev/fxp/if_fxp.c
===================================================================
--- sys/dev/fxp/if_fxp.c
+++ sys/dev/fxp/if_fxp.c
@@ -245,7 +245,7 @@
struct fxp_rx *rxp);
static int fxp_new_rfabuf(struct fxp_softc *sc,
struct fxp_rx *rxp);
-static int fxp_mc_addrs(struct fxp_softc *sc);
+static void fxp_mc_addrs(struct fxp_softc *sc);
static void fxp_mc_setup(struct fxp_softc *sc);
static uint16_t fxp_eeprom_getword(struct fxp_softc *sc, int offset,
int autosize);
@@ -2976,27 +2976,37 @@
return (error);
}
+static u_int
+fxp_setup_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct fxp_softc *sc = arg;
+ struct fxp_cb_mcs *mcsp = sc->mcsp;
+
+ if (mcsp->mc_cnt < MAXMCADDR)
+ bcopy(LLADDR(sdl), mcsp->mc_addr[mcsp->mc_cnt * ETHER_ADDR_LEN],
+ ETHER_ADDR_LEN);
+ mcsp->mc_cnt++;
+ return (1);
+}
+
/*
* Fill in the multicast address list and return number of entries.
*/
-static int
+static void
fxp_mc_addrs(struct fxp_softc *sc)
{
struct fxp_cb_mcs *mcsp = sc->mcsp;
if_t ifp = sc->ifp;
- int nmcasts = 0;
if ((if_getflags(ifp) & IFF_ALLMULTI) == 0) {
- if_maddr_rlock(ifp);
- if_setupmultiaddr(ifp, mcsp->mc_addr, &nmcasts, MAXMCADDR);
- if (nmcasts >= MAXMCADDR) {
+ mcsp->mc_cnt = 0;
+ if_foreach_llmaddr(sc->ifp, fxp_setup_maddr, sc);
+ if (mcsp->mc_cnt >= MAXMCADDR) {
if_setflagbits(ifp, IFF_ALLMULTI, 0);
- nmcasts = 0;
+ mcsp->mc_cnt = 0;
}
- if_maddr_runlock(ifp);
}
- mcsp->mc_cnt = htole16(nmcasts * ETHER_ADDR_LEN);
- return (nmcasts);
+ mcsp->mc_cnt = htole16(mcsp->mc_cnt * ETHER_ADDR_LEN);
}
/*
Index: sys/dev/gem/if_gem.c
===================================================================
--- sys/dev/gem/if_gem.c
+++ sys/dev/gem/if_gem.c
@@ -2202,14 +2202,27 @@
return (error);
}
+static u_int
+gem_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t crc, *hash = arg;
+
+ crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN);
+ /* We just want the 8 most significant bits. */
+ crc >>= 24;
+ /* Set the corresponding bit in the filter. */
+ hash[crc >> 4] |= 1 << (15 - (crc & 15));
+
+ return (1);
+}
+
static void
gem_setladrf(struct gem_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
- struct ifmultiaddr *inm;
int i;
uint32_t hash[16];
- uint32_t crc, v;
+ uint32_t v;
GEM_LOCK_ASSERT(sc, MA_OWNED);
@@ -2245,23 +2258,8 @@
* is the MSB).
*/
- /* Clear the hash table. */
memset(hash, 0, sizeof(hash));
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) {
- if (inm->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
- inm->ifma_addr), ETHER_ADDR_LEN);
-
- /* We just want the 8 most significant bits. */
- crc >>= 24;
-
- /* Set the corresponding bit in the filter. */
- hash[crc >> 4] |= 1 << (15 - (crc & 15));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, gem_hash_maddr, hash);
v |= GEM_MAC_RX_HASH_FILTER;
Index: sys/dev/hme/if_hme.c
===================================================================
--- sys/dev/hme/if_hme.c
+++ sys/dev/hme/if_hme.c
@@ -1656,6 +1656,20 @@
return (error);
}
+static u_int
+hme_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t crc, *hash = arg;
+
+ crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN);
+ /* Just want the 6 most significant bits. */
+ crc >>= 26;
+ /* Set the corresponding bit in the filter. */
+ hash[crc >> 4] |= 1 << (crc & 0xf);
+
+ return (1);
+}
+
/*
* Set up the logical address filter.
*/
@@ -1663,8 +1677,6 @@
hme_setladrf(struct hme_softc *sc, int reenable)
{
struct ifnet *ifp = sc->sc_ifp;
- struct ifmultiaddr *inm;
- u_int32_t crc;
u_int32_t hash[4];
u_int32_t macc;
@@ -1721,21 +1733,7 @@
* selects the word, while the rest of the bits select the bit within
* the word.
*/
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) {
- if (inm->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
- inm->ifma_addr), ETHER_ADDR_LEN);
-
- /* Just want the 6 most significant bits. */
- crc >>= 26;
-
- /* Set the corresponding bit in the filter. */
- hash[crc >> 4] |= 1 << (crc & 0xf);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, hme_hash_maddr, &hash);
chipit:
/* Now load the hash table into the chip */
Index: sys/dev/if_ndis/if_ndis.c
===================================================================
--- sys/dev/if_ndis/if_ndis.c
+++ sys/dev/if_ndis/if_ndis.c
@@ -282,6 +282,22 @@
return (error);
}
+struct mclist_ctx {
+ uint8_t *mclist;
+ int mclistsz;
+};
+
+static u_int
+ndis_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct mclist_ctx *ctx = arg;
+
+ if (cnt < ctx->mclistsz)
+ bcopy(LLADDR(sdl), ctx->mclist + (ETHER_ADDR_LEN * cnt),
+ ETHER_ADDR_LEN);
+ return (1);
+}
+
/*
* Program the 64-bit multicast hash filter.
*/
@@ -290,9 +306,8 @@
struct ndis_softc *sc;
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- int len, mclistsz, error;
- uint8_t *mclist;
+ struct mclist_ctx ctx;
+ int len, error;
if (!NDIS_INITIALIZED(sc))
@@ -313,40 +328,31 @@
return;
}
- if (CK_STAILQ_EMPTY(&ifp->if_multiaddrs))
+ if (if_llmaddr_count(ifp) == 0)
return;
- len = sizeof(mclistsz);
- ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
+ len = sizeof(ctx.mclistsz);
+ ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &ctx.mclistsz, &len);
- mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT|M_ZERO);
+ ctx.mclist = malloc(ETHER_ADDR_LEN * ctx.mclistsz, M_TEMP,
+ M_NOWAIT | M_ZERO);
- if (mclist == NULL) {
+ if (ctx.mclist == NULL) {
sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
goto out;
}
sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
- len = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
- len++;
- if (len > mclistsz) {
- if_maddr_runlock(ifp);
- sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
- sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
+ len = if_foreach_llmaddr(ifp, ndis_copy_maddr, &ctx);
+ if (len > ctx.mclistsz) {
+ sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
+ sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
goto out;
- }
}
- if_maddr_runlock(ifp);
len = len * ETHER_ADDR_LEN;
- error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
+ error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, ctx.mclist, &len);
if (error) {
device_printf(sc->ndis_dev, "set mclist failed: %d\n", error);
sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
@@ -354,7 +360,7 @@
}
out:
- free(mclist, M_TEMP);
+ free(ctx.mclist, M_TEMP);
len = sizeof(sc->ndis_filter);
error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
Index: sys/dev/ixgbe/if_ix.c
===================================================================
--- sys/dev/ixgbe/if_ix.c
+++ sys/dev/ixgbe/if_ix.c
@@ -2333,7 +2333,7 @@
if (ifp->if_flags & IFF_ALLMULTI)
mcnt = MAX_NUM_MULTICAST_ADDRESSES;
else {
- mcnt = if_multiaddr_count(ifp, MAX_NUM_MULTICAST_ADDRESSES);
+ mcnt = min(if_llmaddr_count(ifp), MAX_NUM_MULTICAST_ADDRESSES);
}
if (mcnt < MAX_NUM_MULTICAST_ADDRESSES)
rctl &= (~IXGBE_FCTRL_MPE);
@@ -3207,18 +3207,15 @@
*
* Called whenever multicast address list is updated.
************************************************************************/
-static int
-ixgbe_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count)
+static u_int
+ixgbe_mc_filter_apply(void *arg, struct sockaddr_dl *sdl, u_int count)
{
struct adapter *adapter = arg;
struct ixgbe_mc_addr *mta = adapter->mta;
- if (ifma->ifma_addr->sa_family != AF_LINK)
- return (0);
if (count == MAX_NUM_MULTICAST_ADDRESSES)
return (0);
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- mta[count].addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
+ bcopy(LLADDR(sdl), mta[count].addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
mta[count].vmdq = adapter->pool;
return (1);
@@ -3231,15 +3228,16 @@
struct ixgbe_mc_addr *mta;
struct ifnet *ifp = iflib_get_ifp(ctx);
u8 *update_ptr;
- int mcnt = 0;
u32 fctrl;
+ u_int mcnt;
IOCTL_DEBUGOUT("ixgbe_if_multi_set: begin");
mta = adapter->mta;
bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES);
- mcnt = if_multi_apply(iflib_get_ifp(ctx), ixgbe_mc_filter_apply, adapter);
+ mcnt = if_foreach_llmaddr(iflib_get_ifp(ctx), ixgbe_mc_filter_apply,
+ adapter);
fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
Index: sys/dev/ixl/if_iavf.c
===================================================================
--- sys/dev/ixl/if_iavf.c
+++ sys/dev/ixl/if_iavf.c
@@ -1225,18 +1225,13 @@
iavf_enable_adminq_irq(hw);
}
-static int
-iavf_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count __unused)
+static u_int
+iavf_mc_filter_apply(void *arg, struct sockaddr_dl *sdl, u_int count __unused)
{
struct iavf_sc *sc = arg;
- int error = 0;
-
- if (ifma->ifma_addr->sa_family != AF_LINK)
- return (0);
- error = iavf_add_mac_filter(sc,
- (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
- IXL_FILTER_MC);
+ int error;
+ error = iavf_add_mac_filter(sc, (u8*)LLADDR(sdl), IXL_FILTER_MC);
return (!error);
}
@@ -1244,12 +1239,11 @@
iavf_if_multi_set(if_ctx_t ctx)
{
struct iavf_sc *sc = iflib_get_softc(ctx);
- int mcnt = 0;
IOCTL_DEBUGOUT("iavf_if_multi_set: begin");
- mcnt = if_multiaddr_count(iflib_get_ifp(ctx), MAX_MULTICAST_ADDR);
- if (__predict_false(mcnt == MAX_MULTICAST_ADDR)) {
+ if (__predict_false(if_llmaddr_count(iflib_get_ifp(ctx)) >=
+ MAX_MULTICAST_ADDR)) {
/* Delete MC filters and enable mulitcast promisc instead */
iavf_init_multi(sc);
sc->promisc_flags |= FLAG_VF_MULTICAST_PROMISC;
@@ -1261,9 +1255,8 @@
iavf_init_multi(sc);
/* And (re-)install filters for all mcast addresses */
- mcnt = if_multi_apply(iflib_get_ifp(ctx), iavf_mc_filter_apply, sc);
-
- if (mcnt > 0)
+ if (if_foreach_llmaddr(iflib_get_ifp(ctx), iavf_mc_filter_apply, sc) >
+ 0)
iavf_send_vc_msg(sc, IAVF_FLAG_AQ_ADD_MAC_FILTER);
}
@@ -1358,8 +1351,8 @@
sc->promisc_flags = 0;
- if (flags & IFF_ALLMULTI ||
- if_multiaddr_count(ifp, MAX_MULTICAST_ADDR) == MAX_MULTICAST_ADDR)
+ if (flags & IFF_ALLMULTI || if_llmaddr_count(ifp) >=
+ MAX_MULTICAST_ADDR)
sc->promisc_flags |= FLAG_VF_MULTICAST_PROMISC;
if (flags & IFF_PROMISC)
sc->promisc_flags |= FLAG_VF_UNICAST_PROMISC;
Index: sys/dev/ixl/if_ixl.c
===================================================================
--- sys/dev/ixl/if_ixl.c
+++ sys/dev/ixl/if_ixl.c
@@ -122,7 +122,7 @@
#endif
/*** Other ***/
-static int ixl_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int);
+static u_int ixl_mc_filter_apply(void *, struct sockaddr_dl *, u_int);
static void ixl_save_pf_tunables(struct ixl_pf *);
static int ixl_allocate_pci_resources(struct ixl_pf *);
@@ -1298,12 +1298,12 @@
struct ixl_pf *pf = iflib_get_softc(ctx);
struct ixl_vsi *vsi = &pf->vsi;
struct i40e_hw *hw = vsi->hw;
- int mcnt = 0, flags;
+ int mcnt, flags;
int del_mcnt;
IOCTL_DEBUGOUT("ixl_if_multi_set: begin");
- mcnt = if_multiaddr_count(iflib_get_ifp(ctx), MAX_MULTICAST_ADDR);
+ mcnt = min(if_llmaddr_count(iflib_get_ifp(ctx)), MAX_MULTICAST_ADDR);
/* Delete filters for removed multicast addresses */
del_mcnt = ixl_del_multi(vsi);
vsi->num_macs -= del_mcnt;
@@ -1315,8 +1315,7 @@
}
/* (re-)install filters for all mcast addresses */
/* XXX: This bypasses filter count tracking code! */
- mcnt = if_multi_apply(iflib_get_ifp(ctx), ixl_mc_filter_apply, vsi);
-
+ mcnt = if_foreach_llmaddr(iflib_get_ifp(ctx), ixl_mc_filter_apply, vsi);
if (mcnt > 0) {
vsi->num_macs += mcnt;
flags = (IXL_FILTER_ADD | IXL_FILTER_USED | IXL_FILTER_MC);
@@ -1504,8 +1503,8 @@
if (flags & IFF_PROMISC)
uni = multi = TRUE;
- else if (flags & IFF_ALLMULTI ||
- if_multiaddr_count(ifp, MAX_MULTICAST_ADDR) == MAX_MULTICAST_ADDR)
+ else if (flags & IFF_ALLMULTI || if_llmaddr_count(ifp) >=
+ MAX_MULTICAST_ADDR)
multi = TRUE;
err = i40e_aq_set_vsi_unicast_promiscuous(hw,
@@ -1634,15 +1633,12 @@
return (error);
}
-static int
-ixl_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count __unused)
+static u_int
+ixl_mc_filter_apply(void *arg, struct sockaddr_dl *sdl, u_int count __unused)
{
struct ixl_vsi *vsi = arg;
- if (ifma->ifma_addr->sa_family != AF_LINK)
- return (0);
- ixl_add_mc_filter(vsi,
- (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr));
+ ixl_add_mc_filter(vsi, (u8*)LLADDR(sdl));
return (1);
}
Index: sys/dev/ixl/ixl_pf_main.c
===================================================================
--- sys/dev/ixl/ixl_pf_main.c
+++ sys/dev/ixl/ixl_pf_main.c
@@ -637,6 +637,16 @@
return (FILTER_HANDLED);
}
+static u_int
+ixl_add_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct ixl_vsi *vsi = arg;
+
+ ixl_add_mc_filter(vsi, (u8*)LLADDR(sdl));
+
+ return (1);
+}
+
/*********************************************************************
* Filter Routines
*
@@ -646,25 +656,17 @@
void
ixl_add_multi(struct ixl_vsi *vsi)
{
- struct ifmultiaddr *ifma;
struct ifnet *ifp = vsi->ifp;
struct i40e_hw *hw = vsi->hw;
int mcnt = 0, flags;
IOCTL_DEBUGOUT("ixl_add_multi: begin");
- if_maddr_rlock(ifp);
/*
** First just get a count, to decide if we
** we simply use multicast promiscuous.
*/
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- mcnt++;
- }
- if_maddr_runlock(ifp);
-
+ mcnt = if_llmaddr_count(ifp);
if (__predict_false(mcnt >= MAX_MULTICAST_ADDR)) {
/* delete existing MC filters */
ixl_del_hw_filters(vsi, mcnt);
@@ -673,16 +675,7 @@
return;
}
- mcnt = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- ixl_add_mc_filter(vsi,
- (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr));
- mcnt++;
- }
- if_maddr_runlock(ifp);
+ mcnt = if_foreach_llmaddr(ifp, ixl_add_maddr, vsi);
if (mcnt > 0) {
flags = (IXL_FILTER_ADD | IXL_FILTER_USED | IXL_FILTER_MC);
ixl_add_hw_filters(vsi, flags, mcnt);
@@ -691,38 +684,33 @@
IOCTL_DEBUGOUT("ixl_add_multi: end");
}
+static u_int
+ixl_match_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct ixl_mac_filter *f = arg;
+
+ if (cmp_etheraddr(f->macaddr, (u8 *)LLADDR(sdl)))
+ return (1);
+ else
+ return (0);
+}
+
int
ixl_del_multi(struct ixl_vsi *vsi)
{
struct ifnet *ifp = vsi->ifp;
- struct ifmultiaddr *ifma;
struct ixl_mac_filter *f;
int mcnt = 0;
- bool match = FALSE;
IOCTL_DEBUGOUT("ixl_del_multi: begin");
- /* Search for removed multicast addresses */
- if_maddr_rlock(ifp);
- SLIST_FOREACH(f, &vsi->ftl, next) {
- if ((f->flags & IXL_FILTER_USED) && (f->flags & IXL_FILTER_MC)) {
- match = FALSE;
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- u8 *mc_addr = (u8 *)LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
- if (cmp_etheraddr(f->macaddr, mc_addr)) {
- match = TRUE;
- break;
- }
- }
- if (match == FALSE) {
- f->flags |= IXL_FILTER_DEL;
- mcnt++;
- }
+ SLIST_FOREACH(f, &vsi->ftl, next)
+ if ((f->flags & IXL_FILTER_USED) &&
+ (f->flags & IXL_FILTER_MC) &&
+ (if_foreach_llmaddr(ifp, ixl_match_maddr, f) == 0)) {
+ f->flags |= IXL_FILTER_DEL;
+ mcnt++;
}
- }
- if_maddr_runlock(ifp);
if (mcnt > 0)
ixl_del_hw_filters(vsi, mcnt);
Index: sys/dev/jme/if_jme.c
===================================================================
--- sys/dev/jme/if_jme.c
+++ sys/dev/jme/if_jme.c
@@ -3236,12 +3236,26 @@
CSR_WRITE_4(sc, JME_RXMAC, reg);
}
+static u_int
+jme_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t crc, *mchash = arg;
+
+ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+
+ /* Just want the 6 least significant bits. */
+ crc &= 0x3f;
+
+ /* Set the corresponding bit in the hash table. */
+ mchash[crc >> 5] |= 1 << (crc & 0x1f);
+
+ return (1);
+}
+
static void
jme_set_filter(struct jme_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t crc;
uint32_t mchash[2];
uint32_t rxcfg;
@@ -3276,21 +3290,7 @@
*/
rxcfg |= RXMAC_MULTICAST;
bzero(mchash, sizeof(mchash));
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &sc->jme_ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
-
- /* Just want the 6 least significant bits. */
- crc &= 0x3f;
-
- /* Set the corresponding bit in the hash table. */
- mchash[crc >> 5] |= 1 << (crc & 0x1f);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, jme_hash_maddr, &mchash);
CSR_WRITE_4(sc, JME_MAR0, mchash[0]);
CSR_WRITE_4(sc, JME_MAR1, mchash[1]);
Index: sys/dev/le/lance.c
===================================================================
--- sys/dev/le/lance.c
+++ sys/dev/le/lance.c
@@ -577,6 +577,27 @@
return (error);
}
+struct lance_hash_maddr_ctx {
+ struct lance_softc *sc;
+ uint16_t *af;
+};
+
+static u_int
+lance_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct lance_hash_maddr_ctx *ctx = arg;
+ struct lance_softc *sc = ctx->sc;
+ uint32_t crc;
+
+ crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN);
+ /* Just want the 6 most significant bits. */
+ crc >>= 26;
+ /* Set the corresponding bit in the filter. */
+ ctx->af[crc >> 4] |= LE_HTOLE16(1 << (crc & 0xf));
+
+ return (1);
+}
+
/*
* Set up the logical address filter.
*/
@@ -584,8 +605,7 @@
lance_setladrf(struct lance_softc *sc, uint16_t *af)
{
struct ifnet *ifp = sc->sc_ifp;
- struct ifmultiaddr *ifma;
- uint32_t crc;
+ struct lance_hash_maddr_ctx ctx = { sc, af };
/*
* Set up multicast address filter by passing all multicast addresses
@@ -601,21 +621,7 @@
}
af[0] = af[1] = af[2] = af[3] = 0x0000;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
-
- /* Just want the 6 most significant bits. */
- crc >>= 26;
-
- /* Set the corresponding bit in the filter. */
- af[crc >> 4] |= LE_HTOLE16(1 << (crc & 0xf));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, lance_hash_maddr, &ctx);
}
/*
Index: sys/dev/lge/if_lge.c
===================================================================
--- sys/dev/lge/if_lge.c
+++ sys/dev/lge/if_lge.c
@@ -367,13 +367,25 @@
return;
}
+static u_int
+lge_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int count)
+{
+ uint32_t h, *hashes = arg;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+ return (1);
+}
+
static void
lge_setmulti(sc)
struct lge_softc *sc;
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- u_int32_t h = 0, hashes[2] = { 0, 0 };
+ uint32_t hashes[2] = { 0, 0 };
ifp = sc->lge_ifp;
LGE_LOCK_ASSERT(sc);
@@ -392,18 +404,7 @@
CSR_WRITE_4(sc, LGE_MAR1, 0);
/* now program new ones */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, lge_hash_maddr, hashes);
CSR_WRITE_4(sc, LGE_MAR0, hashes[0]);
CSR_WRITE_4(sc, LGE_MAR1, hashes[1]);
Index: sys/dev/liquidio/lio_ioctl.c
===================================================================
--- sys/dev/liquidio/lio_ioctl.c
+++ sys/dev/liquidio/lio_ioctl.c
@@ -491,6 +491,22 @@
return (f);
}
+static u_int
+lio_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint64_t *mc = arg;
+
+ if (cnt == LIO_MAX_MULTICAST_ADDR)
+ return (0);
+
+ mc += cnt;
+ *mc = 0;
+ memcpy(((uint8_t *)mc) + 2, LLADDR(sdl), ETHER_ADDR_LEN);
+ /* no need to swap bytes */
+
+ return (1);
+}
+
/* @param ifp network device */
static int
lio_set_mcast_list(struct ifnet *ifp)
@@ -498,9 +514,7 @@
struct lio *lio = if_getsoftc(ifp);
struct octeon_device *oct = lio->oct_dev;
struct lio_ctrl_pkt nctrl;
- struct ifmultiaddr *ifma;
- uint64_t *mc;
- int mc_count = 0;
+ int mc_count;
int ret;
bzero(&nctrl, sizeof(struct lio_ctrl_pkt));
@@ -514,26 +528,7 @@
nctrl.cb_fn = lio_ctrl_cmd_completion;
/* copy all the addresses into the udd */
- mc = &nctrl.udd[0];
-
- /* to protect access to if_multiaddrs */
- if_maddr_rlock(ifp);
-
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- *mc = 0;
- memcpy(((uint8_t *)mc) + 2,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- ETHER_ADDR_LEN);
- /* no need to swap bytes */
-
- mc_count++;
- if (++mc > &nctrl.udd[LIO_MAX_MULTICAST_ADDR])
- break;
- }
-
- if_maddr_runlock(ifp);
+ mc_count = if_foreach_llmaddr(ifp, lio_copy_maddr, &nctrl.udd[0]);
/*
* Apparently, any activity in this call from the kernel has to
Index: sys/dev/malo/if_malo.c
===================================================================
--- sys/dev/malo/if_malo.c
+++ sys/dev/malo/if_malo.c
@@ -1510,49 +1510,46 @@
ieee80211_start_all(ic); /* start all vap's */
}
+struct malo_copy_maddr_ctx {
+ uint8_t macs[IEEE80211_ADDR_LEN * MALO_HAL_MCAST_MAX];
+ int nmc;
+};
+
+static u_int
+malo_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int nmc)
+{
+ struct malo_copy_maddr_ctx *ctx = arg;
+
+ if (ctx->nmc == MALO_HAL_MCAST_MAX)
+ return (0);
+
+ IEEE80211_ADDR_COPY(ctx->macs + (ctx->nmc * IEEE80211_ADDR_LEN),
+ LLADDR(sdl));
+ ctx->nmc++;
+
+ return (1);
+}
+
/*
* Set the multicast filter contents into the hardware.
*/
static void
malo_setmcastfilter(struct malo_softc *sc)
{
+ struct malo_copy_maddr_ctx ctx;
struct ieee80211com *ic = &sc->malo_ic;
struct ieee80211vap *vap;
- uint8_t macs[IEEE80211_ADDR_LEN * MALO_HAL_MCAST_MAX];
- uint8_t *mp;
- int nmc;
- mp = macs;
- nmc = 0;
if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 ||
ic->ic_promisc > 0)
goto all;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
-
- ifp = vap->iv_ifp;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- if (nmc == MALO_HAL_MCAST_MAX) {
- ifp->if_flags |= IFF_ALLMULTI;
- if_maddr_runlock(ifp);
- goto all;
- }
- IEEE80211_ADDR_COPY(mp,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
-
- mp += IEEE80211_ADDR_LEN, nmc++;
- }
- if_maddr_runlock(ifp);
- }
+ ctx.nmc = 0;
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if_foreach_llmaddr(vap->iv_ifp, malo_copy_maddr, &ctx);
- malo_hal_setmcast(sc->malo_mh, nmc, macs);
+ malo_hal_setmcast(sc->malo_mh, ctx.nmc, ctx.macs);
all:
/*
Index: sys/dev/mge/if_mge.c
===================================================================
--- sys/dev/mge/if_mge.c
+++ sys/dev/mge/if_mge.c
@@ -2032,45 +2032,51 @@
return(crc);
}
+struct mge_hash_maddr_ctx {
+ uint32_t smt[MGE_MCAST_REG_NUMBER];
+ uint32_t omt[MGE_MCAST_REG_NUMBER];
+};
+
+static u_int
+mge_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ static const uint8_t special[5] = { 0x01, 0x00, 0x5E, 0x00, 0x00 };
+ struct mge_hash_maddr_ctx *ctx = arg;
+ static const uint8_t v = (MGE_RX_DEFAULT_QUEUE << 1) | 1;
+ uint8_t *mac;
+ int i;
+
+ mac = LLADDR(sdl);
+ if (memcmp(mac, special, sizeof(special)) == 0) {
+ i = mac[5];
+ ctx->smt[i >> 2] |= v << ((i & 0x03) << 3);
+ } else {
+ i = mge_crc8(mac, ETHER_ADDR_LEN);
+ ctx->omt[i >> 2] |= v << ((i & 0x03) << 3);
+ }
+ return (1);
+}
+
static void
mge_setup_multicast(struct mge_softc *sc)
{
- uint8_t special[5] = { 0x01, 0x00, 0x5E, 0x00, 0x00 };
- uint8_t v = (MGE_RX_DEFAULT_QUEUE << 1) | 1;
- uint32_t smt[MGE_MCAST_REG_NUMBER];
- uint32_t omt[MGE_MCAST_REG_NUMBER];
+ struct mge_hash_maddr_ctx ctx;
struct ifnet *ifp = sc->ifp;
- struct ifmultiaddr *ifma;
- uint8_t *mac;
+ static const uint8_t v = (MGE_RX_DEFAULT_QUEUE << 1) | 1;
int i;
if (ifp->if_flags & IFF_ALLMULTI) {
for (i = 0; i < MGE_MCAST_REG_NUMBER; i++)
- smt[i] = omt[i] = (v << 24) | (v << 16) | (v << 8) | v;
+ ctx.smt[i] = ctx.omt[i] =
+ (v << 24) | (v << 16) | (v << 8) | v;
} else {
- memset(smt, 0, sizeof(smt));
- memset(omt, 0, sizeof(omt));
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- mac = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
- if (memcmp(mac, special, sizeof(special)) == 0) {
- i = mac[5];
- smt[i >> 2] |= v << ((i & 0x03) << 3);
- } else {
- i = mge_crc8(mac, ETHER_ADDR_LEN);
- omt[i >> 2] |= v << ((i & 0x03) << 3);
- }
- }
- if_maddr_runlock(ifp);
+ memset(&ctx, 0, sizeof(ctx));
+ if_foreach_llmaddr(ifp, mge_hash_maddr, &ctx);
}
for (i = 0; i < MGE_MCAST_REG_NUMBER; i++) {
- MGE_WRITE(sc, MGE_DA_FILTER_SPEC_MCAST(i), smt[i]);
- MGE_WRITE(sc, MGE_DA_FILTER_OTH_MCAST(i), omt[i]);
+ MGE_WRITE(sc, MGE_DA_FILTER_SPEC_MCAST(i), ctx.smt[i]);
+ MGE_WRITE(sc, MGE_DA_FILTER_OTH_MCAST(i), ctx.omt[i]);
}
}
Index: sys/dev/mlx4/mlx4_en/mlx4_en_netdev.c
===================================================================
--- sys/dev/mlx4/mlx4_en/mlx4_en_netdev.c
+++ sys/dev/mlx4/mlx4_en/mlx4_en_netdev.c
@@ -617,31 +617,30 @@
}
}
+static u_int mlx4_copy_addr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct mlx4_en_priv *priv = arg;
+ struct mlx4_en_addr_list *tmp;
+
+ if (sdl->sdl_alen != ETHER_ADDR_LEN) /* XXXGL: can that happen? */
+ return (0);
+ tmp = kzalloc(sizeof(struct mlx4_en_addr_list), GFP_ATOMIC);
+ if (tmp == NULL) {
+ en_err(priv, "Failed to allocate address list\n");
+ return (0);
+ }
+ memcpy(tmp->addr, LLADDR(sdl), ETH_ALEN);
+ list_add_tail(&tmp->list, &priv->uc_list);
+
+ return (1);
+}
+
static void mlx4_en_cache_uclist(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_addr_list *tmp;
- struct ifaddr *ifa;
mlx4_en_clear_uclist(dev);
-
- if_addr_rlock(dev);
- CK_STAILQ_FOREACH(ifa, &dev->if_addrhead, ifa_link) {
- if (ifa->ifa_addr->sa_family != AF_LINK)
- continue;
- if (((struct sockaddr_dl *)ifa->ifa_addr)->sdl_alen !=
- ETHER_ADDR_LEN)
- continue;
- tmp = kzalloc(sizeof(struct mlx4_en_addr_list), GFP_ATOMIC);
- if (tmp == NULL) {
- en_err(priv, "Failed to allocate address list\n");
- break;
- }
- memcpy(tmp->addr,
- LLADDR((struct sockaddr_dl *)ifa->ifa_addr), ETH_ALEN);
- list_add_tail(&tmp->list, &priv->uc_list);
- }
- if_addr_runlock(dev);
+ if_foreach_lladdr(dev, mlx4_copy_addr, priv);
}
static void mlx4_en_clear_mclist(struct net_device *dev)
@@ -655,31 +654,29 @@
}
}
+static u_int mlx4_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int count)
+{
+ struct mlx4_en_priv *priv = arg;
+ struct mlx4_en_addr_list *tmp;
+
+ if (sdl->sdl_alen != ETHER_ADDR_LEN) /* XXXGL: can that happen? */
+ return (0);
+ tmp = kzalloc(sizeof(struct mlx4_en_addr_list), GFP_ATOMIC);
+ if (tmp == NULL) {
+ en_err(priv, "Failed to allocate address list\n");
+ return (0);
+ }
+ memcpy(tmp->addr, LLADDR(sdl), ETH_ALEN);
+ list_add_tail(&tmp->list, &priv->mc_list);
+ return (1);
+}
+
static void mlx4_en_cache_mclist(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_addr_list *tmp;
- struct ifmultiaddr *ifma;
mlx4_en_clear_mclist(dev);
-
- if_maddr_rlock(dev);
- CK_STAILQ_FOREACH(ifma, &dev->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (((struct sockaddr_dl *)ifma->ifma_addr)->sdl_alen !=
- ETHER_ADDR_LEN)
- continue;
- tmp = kzalloc(sizeof(struct mlx4_en_addr_list), GFP_ATOMIC);
- if (tmp == NULL) {
- en_err(priv, "Failed to allocate address list\n");
- break;
- }
- memcpy(tmp->addr,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr), ETH_ALEN);
- list_add_tail(&tmp->list, &priv->mc_list);
- }
- if_maddr_runlock(dev);
+ if_foreach_llmaddr(dev, mlx4_copy_maddr, priv);
}
static void update_addr_list_flags(struct mlx4_en_priv *priv,
Index: sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
===================================================================
--- sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
+++ sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
@@ -787,43 +787,47 @@
return (hn);
}
+struct mlx5e_copy_addr_ctx {
+ struct mlx5e_eth_addr_hash_head *free;
+ struct mlx5e_eth_addr_hash_head *fill;
+ bool success;
+};
+
+static u_int
+mlx5e_copy_addr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct mlx5e_copy_addr_ctx *ctx = arg;
+ struct mlx5e_eth_addr_hash_node *hn;
+
+ hn = mlx5e_move_hn(ctx->free, ctx->fill);
+ if (hn == NULL) {
+ ctx->success = false;
+ return (0);
+ }
+ ether_addr_copy(hn->ai.addr, LLADDR(sdl));
+
+ return (1);
+}
+
static void
mlx5e_sync_ifp_addr(struct mlx5e_priv *priv)
{
+ struct mlx5e_copy_addr_ctx ctx;
struct mlx5e_eth_addr_hash_head head_free;
struct mlx5e_eth_addr_hash_head head_uc;
struct mlx5e_eth_addr_hash_head head_mc;
struct mlx5e_eth_addr_hash_node *hn;
struct ifnet *ifp = priv->ifp;
- struct ifaddr *ifa;
- struct ifmultiaddr *ifma;
- bool success = false;
size_t x;
size_t num;
PRIV_ASSERT_LOCKED(priv);
+retry:
LIST_INIT(&head_free);
LIST_INIT(&head_uc);
LIST_INIT(&head_mc);
-retry:
- num = 1;
-
- if_addr_rlock(ifp);
- CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- if (ifa->ifa_addr->sa_family != AF_LINK)
- continue;
- num++;
- }
- if_addr_runlock(ifp);
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- num++;
- }
- if_maddr_runlock(ifp);
+ num = 1 + if_lladdr_count(ifp) + if_llmaddr_count(ifp);
/* allocate place holders */
for (x = 0; x != num; x++) {
@@ -834,38 +838,21 @@
}
hn = mlx5e_move_hn(&head_free, &head_uc);
- if (hn == NULL)
- goto cleanup;
+ MPASS(hn != NULL);
ether_addr_copy(hn->ai.addr,
LLADDR((struct sockaddr_dl *)(ifp->if_addr->ifa_addr)));
- if_addr_rlock(ifp);
- CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- if (ifa->ifa_addr->sa_family != AF_LINK)
- continue;
- hn = mlx5e_move_hn(&head_free, &head_uc);
- if (hn == NULL)
- break;
- ether_addr_copy(hn->ai.addr,
- LLADDR((struct sockaddr_dl *)ifa->ifa_addr));
- }
- if_addr_runlock(ifp);
- if (ifa != NULL)
+ ctx.free = &head_free;
+ ctx.fill = &head_uc;
+ ctx.success = true;
+ if_foreach_lladdr(ifp, mlx5e_copy_addr, &ctx);
+ if (ctx.success == false)
goto cleanup;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- hn = mlx5e_move_hn(&head_free, &head_mc);
- if (hn == NULL)
- break;
- ether_addr_copy(hn->ai.addr,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- }
- if_maddr_runlock(ifp);
- if (ifma != NULL)
+ ctx.fill = &head_mc;
+ if_foreach_llmaddr(ifp, mlx5e_copy_addr, &ctx);
+ if (ctx.success == false)
goto cleanup;
/* insert L2 unicast addresses into hash list */
@@ -884,8 +871,6 @@
continue;
}
- success = true;
-
cleanup:
while ((hn = mlx5e_remove_hn(&head_uc)) != NULL)
free(hn, M_MLX5EN);
@@ -894,7 +879,7 @@
while ((hn = mlx5e_remove_hn(&head_free)) != NULL)
free(hn, M_MLX5EN);
- if (success == false)
+ if (ctx.success == false)
goto retry;
}
Index: sys/dev/msk/if_msk.c
===================================================================
--- sys/dev/msk/if_msk.c
+++ sys/dev/msk/if_msk.c
@@ -573,14 +573,27 @@
}
}
+static u_int
+msk_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *mchash = arg;
+ uint32_t crc;
+
+ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+ /* Just want the 6 least significant bits. */
+ crc &= 0x3f;
+ /* Set the corresponding bit in the hash table. */
+ mchash[crc >> 5] |= 1 << (crc & 0x1f);
+
+ return (1);
+}
+
static void
msk_rxfilter(struct msk_if_softc *sc_if)
{
struct msk_softc *sc;
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
uint32_t mchash[2];
- uint32_t crc;
uint16_t mode;
sc = sc_if->msk_softc;
@@ -599,18 +612,7 @@
mchash[1] = 0xffff;
} else {
mode |= GM_RXCR_UCF_ENA;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- /* Just want the 6 least significant bits. */
- crc &= 0x3f;
- /* Set the corresponding bit in the hash table. */
- mchash[crc >> 5] |= 1 << (crc & 0x1f);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, msk_hash_maddr, mchash);
if (mchash[0] != 0 || mchash[1] != 0)
mode |= GM_RXCR_MCF_ENA;
}
Index: sys/dev/mxge/if_mxge.c
===================================================================
--- sys/dev/mxge/if_mxge.c
+++ sys/dev/mxge/if_mxge.c
@@ -1091,12 +1091,35 @@
}
}
+struct mxge_add_maddr_ctx {
+ mxge_softc_t *sc;
+ int error;
+};
+
+static u_int
+mxge_add_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct mxge_add_maddr_ctx *ctx = arg;
+ mxge_cmd_t cmd;
+
+ if (ctx->error != 0)
+ return (0);
+ bcopy(LLADDR(sdl), &cmd.data0, 4);
+ bcopy(LLADDR(sdl) + 4, &cmd.data1, 2);
+ cmd.data0 = htonl(cmd.data0);
+ cmd.data1 = htonl(cmd.data1);
+
+ ctx->error = mxge_send_cmd(ctx->sc, MXGEFW_JOIN_MULTICAST_GROUP, &cmd);
+
+ return (1);
+}
+
static void
mxge_set_multicast_list(mxge_softc_t *sc)
{
- mxge_cmd_t cmd;
- struct ifmultiaddr *ifma;
+ struct mxge_add_maddr_ctx ctx;
struct ifnet *ifp = sc->ifp;
+ mxge_cmd_t cmd;
int err;
/* This firmware is known to not support multicast */
@@ -1129,28 +1152,16 @@
}
/* Walk the multicast list, and add each address */
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- &cmd.data0, 4);
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr) + 4,
- &cmd.data1, 2);
- cmd.data0 = htonl(cmd.data0);
- cmd.data1 = htonl(cmd.data1);
- err = mxge_send_cmd(sc, MXGEFW_JOIN_MULTICAST_GROUP, &cmd);
- if (err != 0) {
- device_printf(sc->dev, "Failed "
- "MXGEFW_JOIN_MULTICAST_GROUP, error status:"
- "%d\t", err);
- /* abort, leaving multicast filtering off */
- if_maddr_runlock(ifp);
- return;
- }
+ ctx.sc = sc;
+ ctx.error = 0;
+ if_foreach_llmaddr(ifp, mxge_add_maddr, &ctx);
+ if (ctx.error != 0) {
+ device_printf(sc->dev, "Failed MXGEFW_JOIN_MULTICAST_GROUP, "
+ "error status:" "%d\t", ctx.error);
+ /* abort, leaving multicast filtering off */
+ return;
}
- if_maddr_runlock(ifp);
+
/* Enable multicast filtering */
err = mxge_send_cmd(sc, MXGEFW_DISABLE_ALLMULTI, &cmd);
if (err != 0) {
Index: sys/dev/my/if_my.c
===================================================================
--- sys/dev/my/if_my.c
+++ sys/dev/my/if_my.c
@@ -304,7 +304,20 @@
return;
}
+static u_int
+my_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *hashes = arg;
+ int h;
+
+ h = ~ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+ return (1);
+}
/*
* Program the 64-bit multicast hash filter.
*/
@@ -312,11 +325,8 @@
my_setmulti(struct my_softc * sc)
{
struct ifnet *ifp;
- int h = 0;
u_int32_t hashes[2] = {0, 0};
- struct ifmultiaddr *ifma;
u_int32_t rxfilt;
- int mcnt = 0;
MY_LOCK_ASSERT(sc);
@@ -337,28 +347,13 @@
CSR_WRITE_4(sc, MY_MAR1, 0);
/* now program new ones */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ~ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- mcnt++;
- }
- if_maddr_runlock(ifp);
-
- if (mcnt)
+ if (if_foreach_llmaddr(ifp, my_hash_maddr, hashes) > 0)
rxfilt |= MY_AM;
else
rxfilt &= ~MY_AM;
CSR_WRITE_4(sc, MY_MAR0, hashes[0]);
CSR_WRITE_4(sc, MY_MAR1, hashes[1]);
CSR_WRITE_4(sc, MY_TCRRCR, rxfilt);
- return;
}
/*
Index: sys/dev/nfe/if_nfe.c
===================================================================
--- sys/dev/nfe/if_nfe.c
+++ sys/dev/nfe/if_nfe.c
@@ -2557,75 +2557,67 @@
return (0);
}
+struct nfe_hash_maddr_ctx {
+ uint8_t addr[ETHER_ADDR_LEN];
+ uint8_t mask[ETHER_ADDR_LEN];
+};
+
+static u_int
+nfe_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct nfe_hash_maddr_ctx *ctx = arg;
+ uint8_t *addrp, mcaddr;
+ int j;
+
+ addrp = LLADDR(sdl);
+ for (j = 0; j < ETHER_ADDR_LEN; j++) {
+ mcaddr = addrp[j];
+ ctx->addr[j] &= mcaddr;
+ ctx->mask[j] &= ~mcaddr;
+ }
+
+ return (1);
+}
static void
nfe_setmulti(struct nfe_softc *sc)
{
if_t ifp = sc->nfe_ifp;
- int i, mc_count, mcnt;
+ struct nfe_hash_maddr_ctx ctx;
uint32_t filter;
- uint8_t addr[ETHER_ADDR_LEN], mask[ETHER_ADDR_LEN];
uint8_t etherbroadcastaddr[ETHER_ADDR_LEN] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
- uint8_t *mta;
+ int i;
NFE_LOCK_ASSERT(sc);
if ((if_getflags(ifp) & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
- bzero(addr, ETHER_ADDR_LEN);
- bzero(mask, ETHER_ADDR_LEN);
- goto done;
- }
-
- bcopy(etherbroadcastaddr, addr, ETHER_ADDR_LEN);
- bcopy(etherbroadcastaddr, mask, ETHER_ADDR_LEN);
-
- mc_count = if_multiaddr_count(ifp, -1);
- mta = malloc(sizeof(uint8_t) * ETHER_ADDR_LEN * mc_count, M_DEVBUF,
- M_NOWAIT);
-
- /* Unable to get memory - process without filtering */
- if (mta == NULL) {
- device_printf(sc->nfe_dev, "nfe_setmulti: failed to allocate"
- "temp multicast buffer!\n");
-
- bzero(addr, ETHER_ADDR_LEN);
- bzero(mask, ETHER_ADDR_LEN);
+ bzero(ctx.addr, ETHER_ADDR_LEN);
+ bzero(ctx.mask, ETHER_ADDR_LEN);
goto done;
}
- if_multiaddr_array(ifp, mta, &mcnt, mc_count);
-
- for (i = 0; i < mcnt; i++) {
- uint8_t *addrp;
- int j;
-
- addrp = mta + (i * ETHER_ADDR_LEN);
- for (j = 0; j < ETHER_ADDR_LEN; j++) {
- u_int8_t mcaddr = addrp[j];
- addr[j] &= mcaddr;
- mask[j] &= ~mcaddr;
- }
- }
+ bcopy(etherbroadcastaddr, ctx.addr, ETHER_ADDR_LEN);
+ bcopy(etherbroadcastaddr, ctx.mask, ETHER_ADDR_LEN);
- free(mta, M_DEVBUF);
+ if_foreach_llmaddr(ifp, nfe_hash_maddr, &ctx);
for (i = 0; i < ETHER_ADDR_LEN; i++) {
- mask[i] |= addr[i];
+ ctx.mask[i] |= ctx.addr[i];
}
done:
- addr[0] |= 0x01; /* make sure multicast bit is set */
+ ctx.addr[0] |= 0x01; /* make sure multicast bit is set */
- NFE_WRITE(sc, NFE_MULTIADDR_HI,
- addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]);
+ NFE_WRITE(sc, NFE_MULTIADDR_HI, ctx.addr[3] << 24 | ctx.addr[2] << 16 |
+ ctx.addr[1] << 8 | ctx.addr[0]);
NFE_WRITE(sc, NFE_MULTIADDR_LO,
- addr[5] << 8 | addr[4]);
- NFE_WRITE(sc, NFE_MULTIMASK_HI,
- mask[3] << 24 | mask[2] << 16 | mask[1] << 8 | mask[0]);
+ ctx.addr[5] << 8 | ctx.addr[4]);
+ NFE_WRITE(sc, NFE_MULTIMASK_HI, ctx.mask[3] << 24 | ctx.mask[2] << 16 |
+ ctx.mask[1] << 8 | ctx.mask[0]);
NFE_WRITE(sc, NFE_MULTIMASK_LO,
- mask[5] << 8 | mask[4]);
+ ctx.mask[5] << 8 | ctx.mask[4]);
filter = NFE_READ(sc, NFE_RXFILTER);
filter &= NFE_PFF_RX_PAUSE;
Index: sys/dev/nge/if_nge.c
===================================================================
--- sys/dev/nge/if_nge.c
+++ sys/dev/nge/if_nge.c
@@ -661,13 +661,33 @@
CSR_READ_4(sc, NGE_GPIO) & ~NGE_GPIO_GP3_OUT);
}
+static u_int
+nge_write_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct nge_softc *sc = arg;
+ uint32_t h;
+ int bit, index;
+
+ /*
+ * From the 11 bits returned by the crc routine, the top 7
+ * bits represent the 16-bit word in the mcast hash table
+ * that needs to be updated, and the lower 4 bits represent
+ * which bit within that byte needs to be set.
+ */
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 21;
+ index = (h >> 4) & 0x7F;
+ bit = h & 0xF;
+ CSR_WRITE_4(sc, NGE_RXFILT_CTL, NGE_FILTADDR_MCAST_LO + (index * 2));
+ NGE_SETBIT(sc, NGE_RXFILT_DATA, (1 << bit));
+
+ return (1);
+}
+
static void
nge_rxfilter(struct nge_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t h, i, rxfilt;
- int bit, index;
+ uint32_t i, rxfilt;
NGE_LOCK_ASSERT(sc);
ifp = sc->nge_ifp;
@@ -720,26 +740,7 @@
CSR_WRITE_4(sc, NGE_RXFILT_DATA, 0);
}
- /*
- * From the 11 bits returned by the crc routine, the top 7
- * bits represent the 16-bit word in the mcast hash table
- * that needs to be updated, and the lower 4 bits represent
- * which bit within that byte needs to be set.
- */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 21;
- index = (h >> 4) & 0x7F;
- bit = h & 0xF;
- CSR_WRITE_4(sc, NGE_RXFILT_CTL,
- NGE_FILTADDR_MCAST_LO + (index * 2));
- NGE_SETBIT(sc, NGE_RXFILT_DATA, (1 << bit));
- }
- if_maddr_runlock(ifp);
-
+ if_foreach_llmaddr(ifp, nge_write_maddr, sc);
done:
CSR_WRITE_4(sc, NGE_RXFILT_CTL, rxfilt);
/* Turn the receive filter on. */
Index: sys/dev/oce/oce_hw.c
===================================================================
--- sys/dev/oce/oce_hw.c
+++ sys/dev/oce/oce_hw.c
@@ -544,6 +544,20 @@
}
+static u_int
+oce_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct mbx_set_common_iface_multicast *req = arg;
+
+ if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE)
+ return (0);
+
+ bcopy(LLADDR(sdl), &req->params.req.mac[req->params.req.num_mac++],
+ ETH_ADDR_LEN);
+
+ return (1);
+}
+
/**
* @brief Function for hardware update multicast filter
@@ -553,7 +567,6 @@
oce_hw_update_multicast(POCE_SOFTC sc)
{
struct ifnet *ifp = sc->ifp;
- struct ifmultiaddr *ifma;
struct mbx_set_common_iface_multicast *req = NULL;
OCE_DMA_MEM dma;
int rc = 0;
@@ -566,29 +579,15 @@
req = OCE_DMAPTR(&dma, struct mbx_set_common_iface_multicast);
bzero(req, sizeof(struct mbx_set_common_iface_multicast));
-#if __FreeBSD_version > 800000
- if_maddr_rlock(ifp);
-#endif
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE) {
- /*More multicast addresses than our hardware table
- So Enable multicast promiscus in our hardware to
- accept all multicat packets
- */
- req->params.req.promiscuous = 1;
- break;
- }
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- &req->params.req.mac[req->params.req.num_mac],
- ETH_ADDR_LEN);
- req->params.req.num_mac = req->params.req.num_mac + 1;
+ if_foreach_llmaddr(ifp, oce_copy_maddr, req);
+ if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE) {
+ /*More multicast addresses than our hardware table
+ So Enable multicast promiscus in our hardware to
+ accept all multicat packets
+ */
+ req->params.req.promiscuous = 1;
}
-#if __FreeBSD_version > 800000
- if_maddr_runlock(ifp);
-#endif
+
req->params.req.if_id = sc->if_id;
rc = oce_update_multicast(sc, &dma);
oce_dma_free(sc, &dma);
Index: sys/dev/otus/if_otus.c
===================================================================
--- sys/dev/otus/if_otus.c
+++ sys/dev/otus/if_otus.c
@@ -2308,63 +2308,63 @@
return 0;
}
+static u_int
+otus_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t val, *hashes = arg;
+
+ val = le32dec(LLADDR(sdl) + 4);
+ /* Get address byte 5 */
+ val = val & 0x0000ff00;
+ val = val >> 8;
+
+ /* As per below, shift it >> 2 to get only 6 bits */
+ val = val >> 2;
+ if (val < 32)
+ hashes[0] |= 1 << val;
+ else
+ hashes[1] |= 1 << (val - 32);
+
+ return (1);
+}
+
+
int
otus_set_multi(struct otus_softc *sc)
{
- uint32_t lo, hi;
struct ieee80211com *ic = &sc->sc_ic;
+ uint32_t hashes[2];
int r;
if (ic->ic_allmulti > 0 || ic->ic_promisc > 0 ||
ic->ic_opmode == IEEE80211_M_MONITOR) {
- lo = 0xffffffff;
- hi = 0xffffffff;
+ hashes[0] = 0xffffffff;
+ hashes[1] = 0xffffffff;
} else {
struct ieee80211vap *vap;
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
-
- lo = hi = 0;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
- ifp = vap->iv_ifp;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- caddr_t dl;
- uint32_t val;
-
- dl = LLADDR((struct sockaddr_dl *) ifma->ifma_addr);
- val = le32dec(dl + 4);
- /* Get address byte 5 */
- val = val & 0x0000ff00;
- val = val >> 8;
-
- /* As per below, shift it >> 2 to get only 6 bits */
- val = val >> 2;
- if (val < 32)
- lo |= 1 << val;
- else
- hi |= 1 << (val - 32);
- }
- if_maddr_runlock(ifp);
- }
+
+ hashes[0] = hashes[1] = 0;
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if_foreach_llmaddr(vap->iv_ifp, otus_hash_maddr,
+ hashes);
}
#if 0
/* XXX openbsd code */
while (enm != NULL) {
bit = enm->enm_addrlo[5] >> 2;
if (bit < 32)
- lo |= 1 << bit;
+ hashes[0] |= 1 << bit;
else
- hi |= 1 << (bit - 32);
+ hashes[1] |= 1 << (bit - 32);
ETHER_NEXT_MULTI(step, enm);
}
#endif
- hi |= 1U << 31; /* Make sure the broadcast bit is set. */
+ hashes[1] |= 1U << 31; /* Make sure the broadcast bit is set. */
OTUS_LOCK(sc);
- otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, lo);
- otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hi);
+ otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, hashes[0]);
+ otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hashes[1]);
r = otus_write_barrier(sc);
/* XXX operating mode? filter? */
OTUS_UNLOCK(sc);
Index: sys/dev/qlnx/qlnxe/qlnx_os.c
===================================================================
--- sys/dev/qlnx/qlnxe/qlnx_os.c
+++ sys/dev/qlnx/qlnxe/qlnx_os.c
@@ -2644,42 +2644,36 @@
}
-#define QLNX_MCAST_ADDRS_SIZE (QLNX_MAX_NUM_MULTICAST_ADDRS * ETHER_HDR_LEN)
-static int
-qlnx_set_multi(qlnx_host_t *ha, uint32_t add_multi)
+static u_int
+qlnx_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int mcnt)
{
- uint8_t mta[QLNX_MCAST_ADDRS_SIZE];
- struct ifmultiaddr *ifma;
- int mcnt = 0;
- struct ifnet *ifp = ha->ifp;
- int ret = 0;
+ uint8_t *mta = arg;
- if (qlnx_vf_device(ha) == 0)
+ if (mcnt == QLNX_MAX_NUM_MULTICAST_ADDRS)
return (0);
- if_maddr_rlock(ifp);
+ bcopy(LLADDR(sdl), &mta[mcnt * ETHER_HDR_LEN], ETHER_HDR_LEN);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- if (mcnt == QLNX_MAX_NUM_MULTICAST_ADDRS)
- break;
+ return (1);
+}
- bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
- &mta[mcnt * ETHER_HDR_LEN], ETHER_HDR_LEN);
+static int
+qlnx_set_multi(qlnx_host_t *ha, uint32_t add_multi)
+{
+ uint8_t mta[QLNX_MAX_NUM_MULTICAST_ADDRS * ETHER_HDR_LEN];
+ struct ifnet *ifp = ha->ifp;
+ u_int mcnt;
- mcnt++;
- }
+ if (qlnx_vf_device(ha) == 0)
+ return (0);
- if_maddr_runlock(ifp);
+ mcnt = if_foreach_llmaddr(ifp, qlnx_copy_maddr, mta);
QLNX_LOCK(ha);
qlnx_hw_set_multi(ha, mta, mcnt, add_multi);
QLNX_UNLOCK(ha);
- return (ret);
+ return (0);
}
static int
Index: sys/dev/qlxgb/qla_os.c
===================================================================
--- sys/dev/qlxgb/qla_os.c
+++ sys/dev/qlxgb/qla_os.c
@@ -763,32 +763,26 @@
QL_DPRINT2((ha->pci_dev, "%s: exit\n", __func__));
}
+static u_int
+qla_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int mcnt)
+{
+ uint8_t *mta = arg;
+
+ if (mcnt == Q8_MAX_NUM_MULTICAST_ADDRS)
+ return (0);
+ bcopy(LLADDR(sdl), &mta[mcnt * Q8_MAC_ADDR_LEN], Q8_MAC_ADDR_LEN);
+
+ return (1);
+}
+
static void
qla_set_multi(qla_host_t *ha, uint32_t add_multi)
{
uint8_t mta[Q8_MAX_NUM_MULTICAST_ADDRS * Q8_MAC_ADDR_LEN];
- struct ifmultiaddr *ifma;
- int mcnt = 0;
struct ifnet *ifp = ha->ifp;
+ int mcnt;
- if_maddr_rlock(ifp);
-
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- if (mcnt == Q8_MAX_NUM_MULTICAST_ADDRS)
- break;
-
- bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
- &mta[mcnt * Q8_MAC_ADDR_LEN], Q8_MAC_ADDR_LEN);
-
- mcnt++;
- }
-
- if_maddr_runlock(ifp);
-
+ mcnt = if_foreach_llmaddr(ifp, qla_copy_maddr, mta);
qla_hw_set_multi(ha, mta, mcnt, add_multi);
return;
Index: sys/dev/qlxgbe/ql_os.c
===================================================================
--- sys/dev/qlxgbe/ql_os.c
+++ sys/dev/qlxgbe/ql_os.c
@@ -977,32 +977,28 @@
QL_DPRINT2(ha, (ha->pci_dev, "%s: exit\n", __func__));
}
+static u_int
+qla_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int mcnt)
+{
+ uint8_t *mta = arg;
+
+ if (mcnt == Q8_MAX_NUM_MULTICAST_ADDRS)
+ return (0);
+
+ bcopy(LLADDR(sdl), &mta[mcnt * Q8_MAC_ADDR_LEN], Q8_MAC_ADDR_LEN);
+
+ return (1);
+}
+
static int
qla_set_multi(qla_host_t *ha, uint32_t add_multi)
{
uint8_t mta[Q8_MAX_NUM_MULTICAST_ADDRS * Q8_MAC_ADDR_LEN];
- struct ifmultiaddr *ifma;
int mcnt = 0;
struct ifnet *ifp = ha->ifp;
int ret = 0;
- if_maddr_rlock(ifp);
-
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- if (mcnt == Q8_MAX_NUM_MULTICAST_ADDRS)
- break;
-
- bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
- &mta[mcnt * Q8_MAC_ADDR_LEN], Q8_MAC_ADDR_LEN);
-
- mcnt++;
- }
-
- if_maddr_runlock(ifp);
+ mcnt = if_foreach_llmaddr(ifp, qla_copy_maddr, mta);
if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT,
QLA_LOCK_NO_SLEEP) != 0)
Index: sys/dev/qlxge/qls_os.c
===================================================================
--- sys/dev/qlxge/qls_os.c
+++ sys/dev/qlxge/qls_os.c
@@ -835,31 +835,27 @@
QL_DPRINT2((ha->pci_dev, "%s: exit\n", __func__));
}
-static void
-qls_set_multi(qla_host_t *ha, uint32_t add_multi)
+static u_int
+qls_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int mcnt)
{
- uint8_t mta[Q8_MAX_NUM_MULTICAST_ADDRS * Q8_MAC_ADDR_LEN];
- struct ifmultiaddr *ifma;
- int mcnt = 0;
- struct ifnet *ifp = ha->ifp;
+ uint8_t *mta = arg;
- if_maddr_rlock(ifp);
+ if (mcnt == Q8_MAX_NUM_MULTICAST_ADDRS)
+ return (0);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- if (mcnt == Q8_MAX_NUM_MULTICAST_ADDRS)
- break;
+ bcopy(LLADDR(sdl), &mta[mcnt * Q8_MAC_ADDR_LEN], Q8_MAC_ADDR_LEN);
- bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
- &mta[mcnt * Q8_MAC_ADDR_LEN], Q8_MAC_ADDR_LEN);
+ return (1);
+}
- mcnt++;
- }
+static void
+qls_set_multi(qla_host_t *ha, uint32_t add_multi)
+{
+ uint8_t mta[Q8_MAX_NUM_MULTICAST_ADDRS * Q8_MAC_ADDR_LEN];
+ struct ifnet *ifp = ha->ifp;
+ int mcnt;
- if_maddr_runlock(ifp);
+ mcnt = if_foreach_llmaddr(ifp, qls_copy_maddr, mta);
if (QLA_LOCK(ha, __func__, 1) == 0) {
qls_hw_set_multi(ha, mta, mcnt, add_multi);
Index: sys/dev/re/if_re.c
===================================================================
--- sys/dev/re/if_re.c
+++ sys/dev/re/if_re.c
@@ -650,6 +650,20 @@
*/
}
+static u_int
+re_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t h, *hashes = arg;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+
+ return (1);
+}
+
/*
* Set the RX configuration and 64-bit multicast hash filter.
*/
@@ -657,9 +671,8 @@
re_set_rxmode(struct rl_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t hashes[2] = { 0, 0 };
- uint32_t h, rxfilt;
+ uint32_t h, hashes[2] = { 0, 0 };
+ uint32_t rxfilt;
RL_LOCK_ASSERT(sc);
@@ -684,18 +697,7 @@
goto done;
}
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, re_hash_maddr, hashes);
if (hashes[0] != 0 || hashes[1] != 0) {
/*
Index: sys/dev/rl/if_rl.c
===================================================================
--- sys/dev/rl/if_rl.c
+++ sys/dev/rl/if_rl.c
@@ -509,6 +509,21 @@
*/
}
+static u_int
+rl_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *hashes = arg;
+ int h;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+
+ return (1);
+}
+
/*
* Program the 64-bit multicast hash filter.
*/
@@ -516,9 +531,7 @@
rl_rxfilter(struct rl_softc *sc)
{
struct ifnet *ifp = sc->rl_ifp;
- int h = 0;
uint32_t hashes[2] = { 0, 0 };
- struct ifmultiaddr *ifma;
uint32_t rxfilt;
RL_LOCK_ASSERT(sc);
@@ -539,18 +552,7 @@
hashes[1] = 0xFFFFFFFF;
} else {
/* Now program new ones. */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, rl_hash_maddr, hashes);
if (hashes[0] != 0 || hashes[1] != 0)
rxfilt |= RL_RXCFG_RX_MULTI;
}
Index: sys/dev/rtwn/if_rtwn_rx.c
===================================================================
--- sys/dev/rtwn/if_rtwn_rx.c
+++ sys/dev/rtwn/if_rtwn_rx.c
@@ -366,6 +366,18 @@
return (pos);
}
+static u_int
+rtwm_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *mfilt = arg;
+ uint8_t pos;
+
+ pos = rtwn_get_multi_pos(LLADDR(sdl));
+ mfilt[pos / 32] |= (1 << (pos % 32));
+
+ return (1);
+}
+
void
rtwn_set_multi(struct rtwn_softc *sc)
{
@@ -377,28 +389,13 @@
/* general structure was copied from ath(4). */
if (ic->ic_allmulti == 0) {
struct ieee80211vap *vap;
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
/*
* Merge multicast addresses to form the hardware filter.
*/
mfilt[0] = mfilt[1] = 0;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
- ifp = vap->iv_ifp;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- caddr_t dl;
- uint8_t pos;
-
- dl = LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr);
- pos = rtwn_get_multi_pos(dl);
-
- mfilt[pos / 32] |= (1 << (pos % 32));
- }
- if_maddr_runlock(ifp);
- }
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if_foreach_llmaddr(vap->iv_ifp, rtwm_hash_maddr, mfilt);
} else
mfilt[0] = mfilt[1] = ~0;
Index: sys/dev/sfxge/sfxge_port.c
===================================================================
--- sys/dev/sfxge/sfxge_port.c
+++ sys/dev/sfxge/sfxge_port.c
@@ -358,36 +358,35 @@
SFXGE_PORT_UNLOCK(port);
}
+static u_int
+sfxge_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint8_t *mcast_addr = arg;
+
+ if (cnt == EFX_MAC_MULTICAST_LIST_MAX)
+ return (0);
+
+ memcpy(mcast_addr + (cnt * EFX_MAC_ADDR_LEN), LLADDR(sdl),
+ EFX_MAC_ADDR_LEN);
+
+ return (1);
+}
+
static int
sfxge_mac_multicast_list_set(struct sfxge_softc *sc)
{
struct ifnet *ifp = sc->ifnet;
struct sfxge_port *port = &sc->port;
- uint8_t *mcast_addr = port->mcast_addrs;
- struct ifmultiaddr *ifma;
- struct sockaddr_dl *sa;
int rc = 0;
mtx_assert(&port->lock, MA_OWNED);
- port->mcast_count = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family == AF_LINK) {
- if (port->mcast_count == EFX_MAC_MULTICAST_LIST_MAX) {
- device_printf(sc->dev,
- "Too many multicast addresses\n");
- rc = EINVAL;
- break;
- }
-
- sa = (struct sockaddr_dl *)ifma->ifma_addr;
- memcpy(mcast_addr, LLADDR(sa), EFX_MAC_ADDR_LEN);
- mcast_addr += EFX_MAC_ADDR_LEN;
- ++port->mcast_count;
- }
+ port->mcast_count = if_foreach_llmaddr(ifp, sfxge_copy_maddr,
+ port->mcast_addrs);
+ if (port->mcast_count == EFX_MAC_MULTICAST_LIST_MAX) {
+ device_printf(sc->dev, "Too many multicast addresses\n");
+ rc = EINVAL;
}
- if_maddr_runlock(ifp);
if (rc == 0) {
rc = efx_mac_multicast_list_set(sc->enp, port->mcast_addrs,
@@ -485,6 +484,7 @@
sfxge_port_start(struct sfxge_softc *sc)
{
uint8_t mac_addr[ETHER_ADDR_LEN];
+ struct epoch_tracker et;
struct ifnet *ifp = sc->ifnet;
struct sfxge_port *port;
efx_nic_t *enp;
@@ -518,10 +518,10 @@
goto fail3;
/* Set the unicast address */
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
bcopy(LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr),
mac_addr, sizeof(mac_addr));
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
if ((rc = efx_mac_addr_set(enp, mac_addr)) != 0)
goto fail4;
Index: sys/dev/sge/if_sge.c
===================================================================
--- sys/dev/sge/if_sge.c
+++ sys/dev/sge/if_sge.c
@@ -442,12 +442,22 @@
}
}
+static u_int
+sge_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int count)
+{
+ uint32_t crc, *hashes = arg;
+
+ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+ hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
+
+ return (1);
+}
+
static void
sge_rxfilter(struct sge_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t crc, hashes[2];
+ uint32_t hashes[2];
uint16_t rxfilt;
SGE_LOCK_ASSERT(sc);
@@ -468,15 +478,7 @@
rxfilt |= AcceptMulticast;
hashes[0] = hashes[1] = 0;
/* Now program new ones. */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, sge_hash_maddr, hashes);
}
CSR_WRITE_2(sc, RxMacControl, rxfilt);
CSR_WRITE_4(sc, RxHashTable, hashes[0]);
Index: sys/dev/sis/if_sis.c
===================================================================
--- sys/dev/sis/if_sis.c
+++ sys/dev/sis/if_sis.c
@@ -694,13 +694,29 @@
sis_rxfilter_sis(sc);
}
+static u_int
+sis_write_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct sis_softc *sc = arg;
+ uint32_t h;
+ int bit, index;
+
+ h = sis_mchash(sc, LLADDR(sdl));
+ index = h >> 3;
+ bit = h & 0x1F;
+ CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + index);
+ if (bit > 0xF)
+ bit -= 0x10;
+ SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << bit));
+
+ return (1);
+}
+
static void
sis_rxfilter_ns(struct sis_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t h, i, filter;
- int bit, index;
+ uint32_t i, filter;
ifp = sc->sis_ifp;
filter = CSR_READ_4(sc, SIS_RXFILT_CTL);
@@ -743,21 +759,7 @@
CSR_WRITE_4(sc, SIS_RXFILT_DATA, 0);
}
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = sis_mchash(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- index = h >> 3;
- bit = h & 0x1F;
- CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO +
- index);
- if (bit > 0xF)
- bit -= 0x10;
- SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << bit));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, sis_write_maddr, sc);
}
/* Turn the receive filter on */
@@ -765,13 +767,29 @@
CSR_READ_4(sc, SIS_RXFILT_CTL);
}
+struct sis_hash_maddr_ctx {
+ struct sis_softc *sc;
+ uint16_t hashes[16];
+};
+
+static u_int
+sis_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct sis_hash_maddr_ctx *ctx = arg;
+ uint32_t h;
+
+ h = sis_mchash(ctx->sc, LLADDR(sdl));
+ ctx->hashes[h >> 4] |= 1 << (h & 0xf);
+
+ return (1);
+}
+
static void
sis_rxfilter_sis(struct sis_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t filter, h, i, n;
- uint16_t hashes[16];
+ struct sis_hash_maddr_ctx ctx;
+ uint32_t filter, i, n;
ifp = sc->sis_ifp;
@@ -796,31 +814,21 @@
if (ifp->if_flags & IFF_PROMISC)
filter |= SIS_RXFILTCTL_ALLPHYS;
for (i = 0; i < n; i++)
- hashes[i] = ~0;
+ ctx.hashes[i] = ~0;
} else {
for (i = 0; i < n; i++)
- hashes[i] = 0;
- i = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = sis_mchash(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- hashes[h >> 4] |= 1 << (h & 0xf);
- i++;
- }
- if_maddr_runlock(ifp);
- if (i > n) {
+ ctx.hashes[i] = 0;
+ ctx.sc = sc;
+ if (if_foreach_llmaddr(ifp, sis_hash_maddr, &ctx) > n) {
filter |= SIS_RXFILTCTL_ALLMULTI;
for (i = 0; i < n; i++)
- hashes[i] = ~0;
+ ctx.hashes[i] = ~0;
}
}
for (i = 0; i < n; i++) {
CSR_WRITE_4(sc, SIS_RXFILT_CTL, (4 + i) << 16);
- CSR_WRITE_4(sc, SIS_RXFILT_DATA, hashes[i]);
+ CSR_WRITE_4(sc, SIS_RXFILT_DATA, ctx.hashes[i]);
}
/* Turn the receive filter on */
Index: sys/dev/sk/if_sk.c
===================================================================
--- sys/dev/sk/if_sk.c
+++ sys/dev/sk/if_sk.c
@@ -718,21 +718,49 @@
sk_rxfilter_yukon(sc_if);
}
+struct sk_add_maddr_genesis_ctx {
+ struct sk_if_softc *sc_if;
+ uint32_t hashes[2];
+ uint32_t mode;
+};
+
+static u_int
+sk_add_maddr_genesis(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct sk_add_maddr_genesis_ctx *ctx = arg;
+ int h;
+
+ /*
+ * Program the first XM_RXFILT_MAX multicast groups
+ * into the perfect filter.
+ */
+ if (cnt + 1 < XM_RXFILT_MAX) {
+ sk_setfilt(ctx->sc_if, (uint16_t *)LLADDR(sdl), cnt + 1);
+ ctx->mode |= XM_MODE_RX_USE_PERFECT;
+ return (1);
+ }
+ h = sk_xmchash((const uint8_t *)LLADDR(sdl));
+ if (h < 32)
+ ctx->hashes[0] |= (1 << h);
+ else
+ ctx->hashes[1] |= (1 << (h - 32));
+ ctx->mode |= XM_MODE_RX_USE_HASH;
+
+ return (1);
+}
+
static void
-sk_rxfilter_genesis(sc_if)
- struct sk_if_softc *sc_if;
+sk_rxfilter_genesis(struct sk_if_softc *sc_if)
{
struct ifnet *ifp = sc_if->sk_ifp;
- u_int32_t hashes[2] = { 0, 0 }, mode;
- int h = 0, i;
- struct ifmultiaddr *ifma;
+ struct sk_add_maddr_genesis_ctx ctx = { sc_if, { 0, 0 } };
+ int i;
u_int16_t dummy[] = { 0, 0, 0 };
- u_int16_t maddr[(ETHER_ADDR_LEN+1)/2];
SK_IF_LOCK_ASSERT(sc_if);
- mode = SK_XM_READ_4(sc_if, XM_MODE);
- mode &= ~(XM_MODE_RX_PROMISC | XM_MODE_RX_USE_HASH |
+ ctx.mode = SK_XM_READ_4(sc_if, XM_MODE);
+ ctx.mode &= ~(XM_MODE_RX_PROMISC | XM_MODE_RX_USE_HASH |
XM_MODE_RX_USE_PERFECT);
/* First, zot all the existing perfect filters. */
for (i = 1; i < XM_RXFILT_MAX; i++)
@@ -741,53 +769,39 @@
/* Now program new ones. */
if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
if (ifp->if_flags & IFF_ALLMULTI)
- mode |= XM_MODE_RX_USE_HASH;
+ ctx.mode |= XM_MODE_RX_USE_HASH;
if (ifp->if_flags & IFF_PROMISC)
- mode |= XM_MODE_RX_PROMISC;
- hashes[0] = 0xFFFFFFFF;
- hashes[1] = 0xFFFFFFFF;
- } else {
- i = 1;
- if_maddr_rlock(ifp);
+ ctx.mode |= XM_MODE_RX_PROMISC;
+ ctx.hashes[0] = 0xFFFFFFFF;
+ ctx.hashes[1] = 0xFFFFFFFF;
+ } else
/* XXX want to maintain reverse semantics */
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs,
- ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- /*
- * Program the first XM_RXFILT_MAX multicast groups
- * into the perfect filter.
- */
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- maddr, ETHER_ADDR_LEN);
- if (i < XM_RXFILT_MAX) {
- sk_setfilt(sc_if, maddr, i);
- mode |= XM_MODE_RX_USE_PERFECT;
- i++;
- continue;
- }
- h = sk_xmchash((const uint8_t *)maddr);
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- mode |= XM_MODE_RX_USE_HASH;
- }
- if_maddr_runlock(ifp);
- }
+ if_foreach_llmaddr(ifp, sk_add_maddr_genesis, &ctx);
- SK_XM_WRITE_4(sc_if, XM_MODE, mode);
- SK_XM_WRITE_4(sc_if, XM_MAR0, hashes[0]);
- SK_XM_WRITE_4(sc_if, XM_MAR2, hashes[1]);
+ SK_XM_WRITE_4(sc_if, XM_MODE, ctx.mode);
+ SK_XM_WRITE_4(sc_if, XM_MAR0, ctx.hashes[0]);
+ SK_XM_WRITE_4(sc_if, XM_MAR2, ctx.hashes[1]);
+}
+
+static u_int
+sk_hash_maddr_yukon(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t crc, *hashes = arg;
+
+ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+ /* Just want the 6 least significant bits. */
+ crc &= 0x3f;
+ /* Set the corresponding bit in the hash table. */
+ hashes[crc >> 5] |= 1 << (crc & 0x1f);
+
+ return (1);
}
static void
-sk_rxfilter_yukon(sc_if)
- struct sk_if_softc *sc_if;
+sk_rxfilter_yukon(struct sk_if_softc *sc_if)
{
struct ifnet *ifp;
- u_int32_t crc, hashes[2] = { 0, 0 }, mode;
- struct ifmultiaddr *ifma;
+ uint32_t hashes[2] = { 0, 0 }, mode;
SK_IF_LOCK_ASSERT(sc_if);
@@ -801,18 +815,7 @@
hashes[1] = 0xFFFFFFFF;
} else {
mode |= YU_RCR_UFLEN;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- /* Just want the 6 least significant bits. */
- crc &= 0x3f;
- /* Set the corresponding bit in the hash table. */
- hashes[crc >> 5] |= 1 << (crc & 0x1f);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, sk_hash_maddr_yukon, hashes);
if (hashes[0] != 0 || hashes[1] != 0)
mode |= YU_RCR_MUFLEN;
}
Index: sys/dev/ste/if_ste.c
===================================================================
--- sys/dev/ste/if_ste.c
+++ sys/dev/ste/if_ste.c
@@ -405,14 +405,27 @@
return (err ? 1 : 0);
}
+static u_int
+ste_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *hashes = arg;
+ int h;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) & 0x3F;
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+
+ return (1);
+}
+
static void
ste_rxfilter(struct ste_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
uint32_t hashes[2] = { 0, 0 };
uint8_t rxcfg;
- int h;
STE_LOCK_ASSERT(sc);
@@ -433,18 +446,7 @@
rxcfg |= STE_RXMODE_MULTIHASH;
/* Now program new ones. */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) & 0x3F;
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, ste_hash_maddr, hashes);
chipit:
CSR_WRITE_2(sc, STE_MAR0, hashes[0] & 0xFFFF);
Index: sys/dev/stge/if_stge.c
===================================================================
--- sys/dev/stge/if_stge.c
+++ sys/dev/stge/if_stge.c
@@ -2507,12 +2507,24 @@
CSR_WRITE_2(sc, STGE_ReceiveMode, mode);
}
+static u_int
+stge_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t crc, *mchash = arg;
+
+ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+ /* Just want the 6 least significant bits. */
+ crc &= 0x3f;
+ /* Set the corresponding bit in the hash table. */
+ mchash[crc >> 5] |= 1 << (crc & 0x1f);
+
+ return (1);
+}
+
static void
stge_set_multi(struct stge_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t crc;
uint32_t mchash[2];
uint16_t mode;
int count;
@@ -2542,25 +2554,8 @@
* high order bits select the register, while the rest of the bits
* select the bit within the register.
*/
-
bzero(mchash, sizeof(mchash));
-
- count = 0;
- if_maddr_rlock(sc->sc_ifp);
- CK_STAILQ_FOREACH(ifma, &sc->sc_ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
-
- /* Just want the 6 least significant bits. */
- crc &= 0x3f;
-
- /* Set the corresponding bit in the hash table. */
- mchash[crc >> 5] |= 1 << (crc & 0x1f);
- count++;
- }
- if_maddr_runlock(ifp);
+ count = if_foreach_llmaddr(ifp, stge_hash_maddr, mchash);
mode &= ~(RM_ReceiveMulticast | RM_ReceiveAllFrames);
if (count > 0)
Index: sys/dev/ti/if_ti.c
===================================================================
--- sys/dev/ti/if_ti.c
+++ sys/dev/ti/if_ti.c
@@ -207,8 +207,8 @@
static uint8_t ti_eeprom_getbyte(struct ti_softc *, int, uint8_t *);
static int ti_read_eeprom(struct ti_softc *, caddr_t, int, int);
-static void ti_add_mcast(struct ti_softc *, struct ether_addr *);
-static void ti_del_mcast(struct ti_softc *, struct ether_addr *);
+static u_int ti_add_mcast(void *, struct sockaddr_dl *, u_int);
+static u_int ti_del_mcast(void *, struct sockaddr_dl *, u_int);
static void ti_setmulti(struct ti_softc *);
static void ti_mem_read(struct ti_softc *, uint32_t, uint32_t, void *);
@@ -1878,14 +1878,15 @@
* but we have to support the old way too so that Tigon 1 cards will
* work.
*/
-static void
-ti_add_mcast(struct ti_softc *sc, struct ether_addr *addr)
+static u_int
+ti_add_mcast(void *arg, struct sockaddr_dl *sdl, u_int count)
{
+ struct ti_softc *sc = arg;
struct ti_cmd_desc cmd;
uint16_t *m;
uint32_t ext[2] = {0, 0};
- m = (uint16_t *)&addr->octet[0];
+ m = (uint16_t *)LLADDR(sdl);
switch (sc->ti_hwrev) {
case TI_HWREV_TIGON:
@@ -1900,18 +1901,20 @@
break;
default:
device_printf(sc->ti_dev, "unknown hwrev\n");
- break;
+ return (0);
}
+ return (1);
}
-static void
-ti_del_mcast(struct ti_softc *sc, struct ether_addr *addr)
+static u_int
+ti_del_mcast(void *arg, struct sockaddr_dl *sdl, u_int count)
{
+ struct ti_softc *sc = arg;
struct ti_cmd_desc cmd;
uint16_t *m;
uint32_t ext[2] = {0, 0};
- m = (uint16_t *)&addr->octet[0];
+ m = (uint16_t *)LLADDR(sdl);
switch (sc->ti_hwrev) {
case TI_HWREV_TIGON:
@@ -1926,8 +1929,10 @@
break;
default:
device_printf(sc->ti_dev, "unknown hwrev\n");
- break;
+ return (0);
}
+
+ return (1);
}
/*
@@ -1948,9 +1953,7 @@
ti_setmulti(struct ti_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
struct ti_cmd_desc cmd;
- struct ti_mc_entry *mc;
uint32_t intrs;
TI_LOCK_ASSERT(sc);
@@ -1969,30 +1972,10 @@
CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
/* First, zot all the existing filters. */
- while (SLIST_FIRST(&sc->ti_mc_listhead) != NULL) {
- mc = SLIST_FIRST(&sc->ti_mc_listhead);
- ti_del_mcast(sc, &mc->mc_addr);
- SLIST_REMOVE_HEAD(&sc->ti_mc_listhead, mc_entries);
- free(mc, M_DEVBUF);
- }
+ if_foreach_llmaddr(ifp, ti_del_mcast, sc);
/* Now program new ones. */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- mc = malloc(sizeof(struct ti_mc_entry), M_DEVBUF, M_NOWAIT);
- if (mc == NULL) {
- device_printf(sc->ti_dev,
- "no memory for mcast filter entry\n");
- continue;
- }
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- (char *)&mc->mc_addr, ETHER_ADDR_LEN);
- SLIST_INSERT_HEAD(&sc->ti_mc_listhead, mc, mc_entries);
- ti_add_mcast(sc, &mc->mc_addr);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, ti_add_mcast, sc);
/* Re-enable interrupts. */
CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs);
Index: sys/dev/ti/if_tireg.h
===================================================================
--- sys/dev/ti/if_tireg.h
+++ sys/dev/ti/if_tireg.h
@@ -1010,11 +1010,6 @@
#define TI_TIMEOUT 1000
#define TI_TXCONS_UNSET 0xFFFF /* impossible value */
-struct ti_mc_entry {
- struct ether_addr mc_addr;
- SLIST_ENTRY(ti_mc_entry) mc_entries;
-};
-
typedef enum {
TI_FLAG_NONE = 0x00,
TI_FLAG_DEBUGING = 0x01,
@@ -1048,7 +1043,6 @@
int ti_std; /* current std ring head */
int ti_mini; /* current mini ring head */
int ti_jumbo; /* current jumo ring head */
- SLIST_HEAD(__ti_mchead, ti_mc_entry) ti_mc_listhead;
uint32_t ti_stat_ticks;
uint32_t ti_rx_coal_ticks;
uint32_t ti_tx_coal_ticks;
Index: sys/dev/tsec/if_tsec.c
===================================================================
--- sys/dev/tsec/if_tsec.c
+++ sys/dev/tsec/if_tsec.c
@@ -1886,13 +1886,22 @@
m_adj(m, sizeof(struct tsec_rx_fcb));
}
+static u_int
+tsec_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t h, *hashtable = arg;
+
+ h = (ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 24) & 0xFF;
+ hashtable[(h >> 5)] |= 1 << (0x1F - (h & 0x1F));
+
+ return (1);
+}
+
static void
tsec_setup_multicast(struct tsec_softc *sc)
{
uint32_t hashtable[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
struct ifnet *ifp = sc->tsec_ifp;
- struct ifmultiaddr *ifma;
- uint32_t h;
int i;
TSEC_GLOBAL_LOCK_ASSERT(sc);
@@ -1904,18 +1913,7 @@
return;
}
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- h = (ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 24) & 0xFF;
-
- hashtable[(h >> 5)] |= 1 << (0x1F - (h & 0x1F));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, tsec_hash_maddr, &hashtable);
for (i = 0; i < 8; i++)
TSEC_WRITE(sc, TSEC_REG_GADDR(i), hashtable[i]);
Index: sys/dev/usb/net/if_aue.c
===================================================================
--- sys/dev/usb/net/if_aue.c
+++ sys/dev/usb/net/if_aue.c
@@ -540,13 +540,23 @@
}
#define AUE_BITS 6
+static u_int
+aue_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint8_t *hashtbl = arg;
+ uint32_t h;
+
+ h = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN) & ((1 << AUE_BITS) - 1);
+ hashtbl[(h >> 3)] |= 1 << (h & 0x7);
+
+ return (1);
+}
+
static void
aue_setmulti(struct usb_ether *ue)
{
struct aue_softc *sc = uether_getsc(ue);
struct ifnet *ifp = uether_getifp(ue);
- struct ifmultiaddr *ifma;
- uint32_t h = 0;
uint32_t i;
uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -560,15 +570,7 @@
AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI);
/* now program new ones */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_le(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) & ((1 << AUE_BITS) - 1);
- hashtbl[(h >> 3)] |= 1 << (h & 0x7);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, aue_hash_maddr, hashtbl);
/* write the hashtable */
for (i = 0; i != 8; i++)
Index: sys/dev/usb/net/if_axe.c
===================================================================
--- sys/dev/usb/net/if_axe.c
+++ sys/dev/usb/net/if_axe.c
@@ -481,13 +481,23 @@
AXE_UNLOCK(sc);
}
+static u_int
+axe_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint8_t *hashtbl = arg;
+ uint32_t h;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ hashtbl[h / 8] |= 1 << (h % 8);
+
+ return (1);
+}
+
static void
axe_setmulti(struct usb_ether *ue)
{
struct axe_softc *sc = uether_getsc(ue);
struct ifnet *ifp = uether_getifp(ue);
- struct ifmultiaddr *ifma;
- uint32_t h = 0;
uint16_t rxmode;
uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -503,16 +513,7 @@
}
rxmode &= ~AXE_RXCMD_ALLMULTI;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
- {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- hashtbl[h / 8] |= 1 << (h % 8);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, axe_hash_maddr, &hashtbl);
axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, (void *)&hashtbl);
axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
Index: sys/dev/usb/net/if_axge.c
===================================================================
--- sys/dev/usb/net/if_axge.c
+++ sys/dev/usb/net/if_axge.c
@@ -756,19 +756,28 @@
mii_tick(mii);
}
+static u_int
+axge_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint8_t *hashtbl = arg;
+ uint32_t h;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ hashtbl[h / 8] |= 1 << (h % 8);
+
+ return (1);
+}
+
static void
axge_rxfilter(struct usb_ether *ue)
{
struct axge_softc *sc;
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t h;
uint16_t rxmode;
uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
sc = uether_getsc(ue);
ifp = uether_getifp(ue);
- h = 0;
AXGE_LOCK_ASSERT(sc, MA_OWNED);
/*
@@ -791,15 +800,7 @@
}
rxmode |= RCR_ACPT_MCAST;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- hashtbl[h / 8] |= 1 << (h % 8);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, axge_hash_maddr, &hashtbl);
axge_write_mem(sc, AXGE_ACCESS_MAC, 8, AXGE_MFA, (void *)&hashtbl, 8);
axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode);
Index: sys/dev/usb/net/if_cue.c
===================================================================
--- sys/dev/usb/net/if_cue.c
+++ sys/dev/usb/net/if_cue.c
@@ -307,13 +307,24 @@
cue_setmulti(ue);
}
+static u_int
+cue_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint8_t *hashtbl = arg;
+ uint32_t h;
+
+ h = cue_mchash(LLADDR(sdl));
+ hashtbl[h >> 3] |= 1 << (h & 0x7);
+
+ return (1);
+}
+
static void
cue_setmulti(struct usb_ether *ue)
{
struct cue_softc *sc = uether_getsc(ue);
struct ifnet *ifp = uether_getifp(ue);
- struct ifmultiaddr *ifma;
- uint32_t h = 0, i;
+ uint32_t h, i;
uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
CUE_LOCK_ASSERT(sc, MA_OWNED);
@@ -327,15 +338,7 @@
}
/* now program new ones */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
- {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = cue_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- hashtbl[h >> 3] |= 1 << (h & 0x7);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, cue_hash_maddr, hashtbl);
/*
* Also include the broadcast address in the filter
Index: sys/dev/usb/net/if_kue.c
===================================================================
--- sys/dev/usb/net/if_kue.c
+++ sys/dev/usb/net/if_kue.c
@@ -357,13 +357,25 @@
kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->sc_rxfilt);
}
+static u_int
+kue_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct kue_softc *sc = arg;
+
+ if (cnt >= KUE_MCFILTCNT(sc))
+ return (1);
+
+ memcpy(KUE_MCFILT(sc, cnt), LLADDR(sdl), ETHER_ADDR_LEN);
+
+ return (1);
+}
+
static void
kue_setmulti(struct usb_ether *ue)
{
struct kue_softc *sc = uether_getsc(ue);
struct ifnet *ifp = uether_getifp(ue);
- struct ifmultiaddr *ifma;
- int i = 0;
+ int i;
KUE_LOCK_ASSERT(sc, MA_OWNED);
@@ -376,25 +388,9 @@
sc->sc_rxfilt &= ~KUE_RXFILT_ALLMULTI;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
- {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- /*
- * If there are too many addresses for the
- * internal filter, switch over to allmulti mode.
- */
- if (i == KUE_MCFILTCNT(sc))
- break;
- memcpy(KUE_MCFILT(sc, i),
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- ETHER_ADDR_LEN);
- i++;
- }
- if_maddr_runlock(ifp);
+ i = if_foreach_llmaddr(ifp, kue_copy_maddr, sc);
- if (i == KUE_MCFILTCNT(sc))
+ if (i >= KUE_MCFILTCNT(sc))
sc->sc_rxfilt |= KUE_RXFILT_ALLMULTI;
else {
sc->sc_rxfilt |= KUE_RXFILT_MULTICAST;
Index: sys/dev/usb/net/if_mos.c
===================================================================
--- sys/dev/usb/net/if_mos.c
+++ sys/dev/usb/net/if_mos.c
@@ -589,16 +589,23 @@
mos_reg_write_1(sc, MOS_CTL, rxmode);
}
+static u_int
+mos_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint8_t *hashtbl = arg;
+ uint32_t h;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ hashtbl[h / 8] |= 1 << (h % 8);
+ return (1);
+}
static void
mos_setmulti(struct usb_ether *ue)
{
struct mos_softc *sc = uether_getsc(ue);
struct ifnet *ifp = uether_getifp(ue);
- struct ifmultiaddr *ifma;
-
- uint32_t h = 0;
uint8_t rxmode;
uint8_t hashtbl[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int allmulti = 0;
@@ -611,17 +618,7 @@
allmulti = 1;
/* get all new ones */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK) {
- allmulti = 1;
- continue;
- }
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- hashtbl[h / 8] |= 1 << (h % 8);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, mos_hash_maddr, &hashtbl);
/* now program new ones */
if (allmulti == 1) {
Index: sys/dev/usb/net/if_muge.c
===================================================================
--- sys/dev/usb/net/if_muge.c
+++ sys/dev/usb/net/if_muge.c
@@ -1862,6 +1862,24 @@
return (ether_crc32_be(addr, ETHER_ADDR_LEN) >> 23) & 0x1ff;
}
+static u_int
+muge_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct muge_softc *sc = arg;
+ uint32_t bitnum;
+
+ /* First fill up the perfect address table. */
+ if (cnt < 32 /* XXX */)
+ muge_set_addr_filter(sc, cnt + 1, LLADDR(sdl));
+ else {
+ bitnum = muge_hash(LLADDR(sdl));
+ sc->sc_mchash_table[bitnum / 32] |= (1 << (bitnum % 32));
+ sc->sc_rfe_ctl |= ETH_RFE_CTL_MCAST_HASH_;
+ }
+
+ return (1);
+}
+
/**
* muge_setmulti - Setup multicast
* @ue: usb ethernet device context
@@ -1877,8 +1895,7 @@
{
struct muge_softc *sc = uether_getsc(ue);
struct ifnet *ifp = uether_getifp(ue);
- uint8_t i, *addr;
- struct ifmultiaddr *ifma;
+ uint8_t i;
MUGE_LOCK_ASSERT(sc, MA_OWNED);
@@ -1904,28 +1921,7 @@
muge_dbg_printf(sc, "receive all multicast enabled\n");
sc->sc_rfe_ctl |= ETH_RFE_CTL_MCAST_EN_;
} else {
- /* Lock the mac address list before hashing each of them. */
- if_maddr_rlock(ifp);
- if (!CK_STAILQ_EMPTY(&ifp->if_multiaddrs)) {
- i = 1;
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs,
- ifma_link) {
- /* First fill up the perfect address table. */
- addr = LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr);
- if (i < 33 /* XXX */) {
- muge_set_addr_filter(sc, i, addr);
- } else {
- uint32_t bitnum = muge_hash(addr);
- sc->sc_mchash_table[bitnum / 32] |=
- (1 << (bitnum % 32));
- sc->sc_rfe_ctl |=
- ETH_RFE_CTL_MCAST_HASH_;
- }
- i++;
- }
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, muge_hash_maddr, sc);
muge_multicast_write(sc);
}
lan78xx_write_reg(sc, ETH_RFE_CTL, sc->sc_rfe_ctl);
Index: sys/dev/usb/net/if_rue.c
===================================================================
--- sys/dev/usb/net/if_rue.c
+++ sys/dev/usb/net/if_rue.c
@@ -473,6 +473,21 @@
RUE_CLRBIT(sc, RUE_RCR, RUE_RCR_AAP);
}
+static u_int
+rue_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *hashes = arg;
+ int h;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+
+ return (1);
+}
+
/*
* Program the 64-bit multicast hash filter.
*/
@@ -482,10 +497,8 @@
struct rue_softc *sc = uether_getsc(ue);
struct ifnet *ifp = uether_getifp(ue);
uint16_t rxcfg;
- int h = 0;
uint32_t hashes[2] = { 0, 0 };
- struct ifmultiaddr *ifma;
- int mcnt = 0;
+ int mcnt;
RUE_LOCK_ASSERT(sc, MA_OWNED);
@@ -505,20 +518,7 @@
rue_csr_write_4(sc, RUE_MAR4, 0);
/* now program new ones */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link)
- {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- mcnt++;
- }
- if_maddr_runlock(ifp);
+ mcnt = if_foreach_llmaddr(ifp, rue_hash_maddr, &hashes);
if (mcnt)
rxcfg |= RUE_RCR_AM;
Index: sys/dev/usb/net/if_smsc.c
===================================================================
--- sys/dev/usb/net/if_smsc.c
+++ sys/dev/usb/net/if_smsc.c
@@ -691,6 +691,18 @@
return (ether_crc32_be(addr, ETHER_ADDR_LEN) >> 26) & 0x3f;
}
+static u_int
+smsc_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t hash, *hashtbl = arg;
+
+ hash = smsc_hash(LLADDR(sdl));
+ hashtbl[hash >> 5] |= 1 << (hash & 0x1F);
+
+ return (1);
+}
+
+
/**
* smsc_setmulti - Setup multicast
* @ue: usb ethernet device context
@@ -706,9 +718,7 @@
{
struct smsc_softc *sc = uether_getsc(ue);
struct ifnet *ifp = uether_getifp(ue);
- struct ifmultiaddr *ifma;
uint32_t hashtbl[2] = { 0, 0 };
- uint32_t hash;
SMSC_LOCK_ASSERT(sc, MA_OWNED);
@@ -718,29 +728,19 @@
sc->sc_mac_csr &= ~SMSC_MAC_CSR_HPFILT;
} else {
- /* Take the lock of the mac address list before hashing each of them */
- if_maddr_rlock(ifp);
-
- if (!CK_STAILQ_EMPTY(&ifp->if_multiaddrs)) {
- /* We are filtering on a set of address so calculate hashes of each
- * of the address and set the corresponding bits in the register.
+ if (if_foreach_llmaddr(ifp, smsc_hash_maddr, &hashtbl) > 0) {
+ /* We are filtering on a set of address so calculate
+ * hashes of each of the address and set the
+ * corresponding bits in the register.
*/
sc->sc_mac_csr |= SMSC_MAC_CSR_HPFILT;
sc->sc_mac_csr &= ~(SMSC_MAC_CSR_PRMS | SMSC_MAC_CSR_MCPAS);
-
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- hash = smsc_hash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- hashtbl[hash >> 5] |= 1 << (hash & 0x1F);
- }
} else {
- /* Only receive packets with destination set to our mac address */
+ /* Only receive packets with destination set to
+ * our mac address
+ */
sc->sc_mac_csr &= ~(SMSC_MAC_CSR_MCPAS | SMSC_MAC_CSR_HPFILT);
}
-
- if_maddr_runlock(ifp);
/* Debug */
if (sc->sc_mac_csr & SMSC_MAC_CSR_HPFILT)
Index: sys/dev/usb/net/if_udav.c
===================================================================
--- sys/dev/usb/net/if_udav.c
+++ sys/dev/usb/net/if_udav.c
@@ -504,15 +504,24 @@
uether_pause(&sc->sc_ue, hz / 100);
}
-#define UDAV_BITS 6
+static u_int
+udav_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint8_t *hashtbl = arg;
+ int h;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ hashtbl[h / 8] |= 1 << (h % 8);
+
+ return (1);
+}
+
static void
udav_setmulti(struct usb_ether *ue)
{
struct udav_softc *sc = ue->ue_sc;
struct ifnet *ifp = uether_getifp(&sc->sc_ue);
- struct ifmultiaddr *ifma;
uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- int h = 0;
UDAV_LOCK_ASSERT(sc, MA_OWNED);
@@ -527,16 +536,7 @@
udav_csr_write(sc, UDAV_MAR, hashtbl, sizeof(hashtbl));
/* now program new ones */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
- {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- hashtbl[h / 8] |= 1 << (h % 8);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, udav_hash_maddr, hashtbl);
/* disable all multicast */
UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
Index: sys/dev/usb/net/if_ure.c
===================================================================
--- sys/dev/usb/net/if_ure.c
+++ sys/dev/usb/net/if_ure.c
@@ -792,6 +792,19 @@
}
}
+static u_int
+ure_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t h, *hashes = arg;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+ return (1);
+}
+
/*
* Program the 64-bit multicast hash filter.
*/
@@ -800,9 +813,8 @@
{
struct ure_softc *sc = uether_getsc(ue);
struct ifnet *ifp = uether_getifp(ue);
- struct ifmultiaddr *ifma;
- uint32_t h, rxmode;
- uint32_t hashes[2] = { 0, 0 };
+ uint32_t rxmode;
+ uint32_t h, hashes[2] = { 0, 0 };
URE_LOCK_ASSERT(sc, MA_OWNED);
@@ -818,18 +830,7 @@
}
rxmode |= URE_RCR_AM;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, ure_hash_maddr, &hashes);
h = bswap32(hashes[0]);
hashes[0] = bswap32(hashes[1]);
Index: sys/dev/usb/wlan/if_rsu.c
===================================================================
--- sys/dev/usb/wlan/if_rsu.c
+++ sys/dev/usb/wlan/if_rsu.c
@@ -857,6 +857,18 @@
return (pos);
}
+static u_int
+rsu_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *mfilt = arg;
+ uint8_t pos;
+
+ pos = rsu_get_multi_pos(LLADDR(sdl));
+ mfilt[pos / 32] |= (1 << (pos % 32));
+
+ return (1);
+}
+
static void
rsu_set_multi(struct rsu_softc *sc)
{
@@ -868,28 +880,13 @@
/* general structure was copied from ath(4). */
if (ic->ic_allmulti == 0) {
struct ieee80211vap *vap;
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
/*
* Merge multicast addresses to form the hardware filter.
*/
mfilt[0] = mfilt[1] = 0;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
- ifp = vap->iv_ifp;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- caddr_t dl;
- uint8_t pos;
-
- dl = LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr);
- pos = rsu_get_multi_pos(dl);
-
- mfilt[pos / 32] |= (1 << (pos % 32));
- }
- if_maddr_runlock(ifp);
- }
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if_foreach_llmaddr(vap->iv_ifp, rsu_hash_maddr, &mfilt);
} else
mfilt[0] = mfilt[1] = ~0;
Index: sys/dev/usb/wlan/if_zyd.c
===================================================================
--- sys/dev/usb/wlan/if_zyd.c
+++ sys/dev/usb/wlan/if_zyd.c
@@ -1970,49 +1970,48 @@
return (error);
}
+static u_int
+zyd_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *hash = arg;
+ uint8_t v;
+
+ v = ((uint8_t *)LLADDR(sdl))[5] >> 2;
+ if (v < 32)
+ hash[0] |= 1 << v;
+ else
+ hash[1] |= 1 << (v - 32);
+
+ return (1);
+}
+
static void
zyd_set_multi(struct zyd_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
- uint32_t low, high;
+ uint32_t hash[2];
int error;
if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0)
return;
- low = 0x00000000;
- high = 0x80000000;
+ hash[0] = 0x00000000;
+ hash[1] = 0x80000000;
if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 ||
ic->ic_promisc > 0) {
- low = 0xffffffff;
- high = 0xffffffff;
+ hash[0] = 0xffffffff;
+ hash[1] = 0xffffffff;
} else {
struct ieee80211vap *vap;
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint8_t v;
-
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
- ifp = vap->iv_ifp;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- v = ((uint8_t *)LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr))[5] >> 2;
- if (v < 32)
- low |= 1 << v;
- else
- high |= 1 << (v - 32);
- }
- if_maddr_runlock(ifp);
- }
+
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if_foreach_llmaddr(vap->iv_ifp, zyd_hash_maddr, &hash);
}
/* reprogram multicast global hash table */
- zyd_write32_m(sc, ZYD_MAC_GHTBL, low);
- zyd_write32_m(sc, ZYD_MAC_GHTBH, high);
+ zyd_write32_m(sc, ZYD_MAC_GHTBL, hash[0]);
+ zyd_write32_m(sc, ZYD_MAC_GHTBH, hash[1]);
fail:
if (error != 0)
device_printf(sc->sc_dev,
Index: sys/dev/vge/if_vge.c
===================================================================
--- sys/dev/vge/if_vge.c
+++ sys/dev/vge/if_vge.c
@@ -529,6 +529,34 @@
CSR_WRITE_1(sc, VGE_RXCFG, cfg);
}
+static u_int
+vge_set_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct vge_softc *sc = arg;
+
+ if (sc->vge_camidx == VGE_CAM_MAXADDRS)
+ return (0);
+
+ (void )vge_cam_set(sc, LLADDR(sdl));
+
+ return (1);
+}
+
+static u_int
+vge_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t h, *hashes = arg;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+
+ return (1);
+}
+
+
/*
* Program the multicast filter. We use the 64-entry CAM filter
* for perfect filtering. If there's more than 64 multicast addresses,
@@ -538,10 +566,8 @@
vge_rxfilter(struct vge_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint32_t h, hashes[2];
+ uint32_t hashes[2];
uint8_t rxcfg;
- int error = 0;
VGE_LOCK_ASSERT(sc);
@@ -572,33 +598,15 @@
}
vge_cam_clear(sc);
+
/* Now program new ones */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- error = vge_cam_set(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- if (error)
- break;
- }
+ if_foreach_llmaddr(ifp, vge_set_maddr, sc);
/* If there were too many addresses, use the hash filter. */
- if (error) {
+ if (sc->vge_camidx == VGE_CAM_MAXADDRS) {
vge_cam_clear(sc);
-
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- }
+ if_foreach_llmaddr(ifp, vge_hash_maddr, hashes);
}
- if_maddr_runlock(ifp);
done:
if (hashes[0] != 0 || hashes[1] != 0)
Index: sys/dev/virtio/network/if_vtnet.c
===================================================================
--- sys/dev/virtio/network/if_vtnet.c
+++ sys/dev/virtio/network/if_vtnet.c
@@ -3285,6 +3285,34 @@
ifp->if_flags & IFF_ALLMULTI ? "enable" : "disable");
}
+static u_int
+vtnet_copy_ifaddr(void *arg, struct sockaddr_dl *sdl, u_int ucnt)
+{
+ struct vtnet_softc *sc = arg;
+
+ if (memcmp(LLADDR(sdl), sc->vtnet_hwaddr, ETHER_ADDR_LEN) == 0)
+ return (0);
+
+ if (ucnt < VTNET_MAX_MAC_ENTRIES)
+ bcopy(LLADDR(sdl),
+ &sc->vtnet_mac_filter->vmf_unicast.macs[ucnt],
+ ETHER_ADDR_LEN);
+
+ return (1);
+}
+
+static u_int
+vtnet_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int mcnt)
+{
+ struct vtnet_mac_filter *filter = arg;
+
+ if (mcnt < VTNET_MAX_MAC_ENTRIES)
+ bcopy(LLADDR(sdl), &filter->vmf_multicast.macs[mcnt],
+ ETHER_ADDR_LEN);
+
+ return (1);
+}
+
static void
vtnet_rx_filter_mac(struct vtnet_softc *sc)
{
@@ -3293,42 +3321,23 @@
struct sglist_seg segs[4];
struct sglist sg;
struct ifnet *ifp;
- struct ifaddr *ifa;
- struct ifmultiaddr *ifma;
- int ucnt, mcnt, promisc, allmulti, error;
+ bool promisc, allmulti;
+ u_int ucnt, mcnt;
+ int error;
uint8_t ack;
ifp = sc->vtnet_ifp;
filter = sc->vtnet_mac_filter;
- ucnt = 0;
- mcnt = 0;
- promisc = 0;
- allmulti = 0;
VTNET_CORE_LOCK_ASSERT(sc);
KASSERT(sc->vtnet_flags & VTNET_FLAG_CTRL_RX,
("%s: CTRL_RX feature not negotiated", __func__));
/* Unicast MAC addresses: */
- if_addr_rlock(ifp);
- CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- if (ifa->ifa_addr->sa_family != AF_LINK)
- continue;
- else if (memcmp(LLADDR((struct sockaddr_dl *)ifa->ifa_addr),
- sc->vtnet_hwaddr, ETHER_ADDR_LEN) == 0)
- continue;
- else if (ucnt == VTNET_MAX_MAC_ENTRIES) {
- promisc = 1;
- break;
- }
+ ucnt = if_foreach_lladdr(ifp, vtnet_copy_ifaddr, sc);
+ promisc = (ucnt > VTNET_MAX_MAC_ENTRIES);
- bcopy(LLADDR((struct sockaddr_dl *)ifa->ifa_addr),
- &filter->vmf_unicast.macs[ucnt], ETHER_ADDR_LEN);
- ucnt++;
- }
- if_addr_runlock(ifp);
-
- if (promisc != 0) {
+ if (promisc) {
filter->vmf_unicast.nentries = 0;
if_printf(ifp, "more than %d MAC addresses assigned, "
"falling back to promiscuous mode\n",
@@ -3337,22 +3346,10 @@
filter->vmf_unicast.nentries = ucnt;
/* Multicast MAC addresses: */
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- else if (mcnt == VTNET_MAX_MAC_ENTRIES) {
- allmulti = 1;
- break;
- }
-
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- &filter->vmf_multicast.macs[mcnt], ETHER_ADDR_LEN);
- mcnt++;
- }
- if_maddr_runlock(ifp);
+ mcnt = if_foreach_llmaddr(ifp, vtnet_copy_maddr, filter);
+ allmulti = (mcnt > VTNET_MAX_MAC_ENTRIES);
- if (allmulti != 0) {
+ if (allmulti) {
filter->vmf_multicast.nentries = 0;
if_printf(ifp, "more than %d multicast MAC addresses "
"assigned, falling back to all-multicast mode\n",
@@ -3360,7 +3357,7 @@
} else
filter->vmf_multicast.nentries = mcnt;
- if (promisc != 0 && allmulti != 0)
+ if (promisc && allmulti)
goto out;
hdr.class = VIRTIO_NET_CTRL_MAC;
Index: sys/dev/vmware/vmxnet3/if_vmx.c
===================================================================
--- sys/dev/vmware/vmxnet3/if_vmx.c
+++ sys/dev/vmware/vmxnet3/if_vmx.c
@@ -1995,12 +1995,23 @@
vmxnet3_update_vlan_filter(iflib_get_softc(ctx), 0, tag);
}
+static u_int
+vmxnet3_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int count)
+{
+ struct vmxnet3_softc *sc = arg;
+
+ if (count < VMXNET3_MULTICAST_MAX)
+ bcopy(LLADDR(sdl), &sc->vmx_mcast[count * ETHER_ADDR_LEN],
+ ETHER_ADDR_LEN);
+
+ return (1);
+}
+
static void
vmxnet3_set_rxfilter(struct vmxnet3_softc *sc, int flags)
{
struct ifnet *ifp;
struct vmxnet3_driver_shared *ds;
- struct ifmultiaddr *ifma;
u_int mode;
ifp = sc->vmx_ifp;
@@ -2012,24 +2023,10 @@
if (flags & IFF_ALLMULTI)
mode |= VMXNET3_RXMODE_ALLMULTI;
else {
- int cnt = 0, overflow = 0;
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- else if (cnt == VMXNET3_MULTICAST_MAX) {
- overflow = 1;
- break;
- }
-
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- &sc->vmx_mcast[cnt*ETHER_ADDR_LEN], ETHER_ADDR_LEN);
- cnt++;
- }
- if_maddr_runlock(ifp);
+ int cnt;
- if (overflow != 0) {
+ cnt = if_foreach_llmaddr(ifp, vmxnet3_hash_maddr, sc);
+ if (cnt >= VMXNET3_MULTICAST_MAX) {
cnt = 0;
mode |= VMXNET3_RXMODE_ALLMULTI;
} else if (cnt > 0)
Index: sys/dev/vr/if_vr.c
===================================================================
--- sys/dev/vr/if_vr.c
+++ sys/dev/vr/if_vr.c
@@ -432,6 +432,44 @@
return (i == VR_TIMEOUT ? ETIMEDOUT : 0);
}
+struct vr_hash_maddr_cam_ctx {
+ struct vr_softc *sc;
+ uint32_t mask;
+ int error;
+};
+
+static u_int
+vr_hash_maddr_cam(void *arg, struct sockaddr_dl *sdl, u_int mcnt)
+{
+ struct vr_hash_maddr_cam_ctx *ctx = arg;
+
+ if (ctx->error != 0)
+ return (0);
+ ctx->error = vr_cam_data(ctx->sc, VR_MCAST_CAM, mcnt, LLADDR(sdl));
+ if (ctx->error != 0) {
+ ctx->mask = 0;
+ return (0);
+ }
+ ctx->mask |= 1 << mcnt;
+
+ return (1);
+}
+
+static u_int
+vr_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint32_t *hashes = arg;
+ int h;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+
+ return (1);
+}
+
/*
* Program the 64-bit multicast hash filter.
*/
@@ -439,12 +477,9 @@
vr_set_filter(struct vr_softc *sc)
{
struct ifnet *ifp;
- int h;
uint32_t hashes[2] = { 0, 0 };
- struct ifmultiaddr *ifma;
uint8_t rxfilt;
int error, mcnt;
- uint32_t cam_mask;
VR_LOCK_ASSERT(sc);
@@ -466,27 +501,18 @@
/* Now program new ones. */
error = 0;
- mcnt = 0;
- if_maddr_rlock(ifp);
if ((sc->vr_quirks & VR_Q_CAM) != 0) {
+ struct vr_hash_maddr_cam_ctx ctx;
+
/*
* For hardwares that have CAM capability, use
* 32 entries multicast perfect filter.
*/
- cam_mask = 0;
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- error = vr_cam_data(sc, VR_MCAST_CAM, mcnt,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- if (error != 0) {
- cam_mask = 0;
- break;
- }
- cam_mask |= 1 << mcnt;
- mcnt++;
- }
- vr_cam_mask(sc, VR_MCAST_CAM, cam_mask);
+ ctx.sc = sc;
+ ctx.mask = 0;
+ ctx.error = 0;
+ mcnt = if_foreach_llmaddr(ifp, vr_hash_maddr_cam, &ctx);
+ vr_cam_mask(sc, VR_MCAST_CAM, ctx.mask);
}
if ((sc->vr_quirks & VR_Q_CAM) == 0 || error != 0) {
@@ -495,20 +521,8 @@
* setting multicast CAM filter failed, use hash
* table based filtering.
*/
- mcnt = 0;
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- mcnt++;
- }
+ mcnt = if_foreach_llmaddr(ifp, vr_hash_maddr, hashes);
}
- if_maddr_runlock(ifp);
if (mcnt > 0)
rxfilt |= VR_RXCFG_RX_MULTI;
Index: sys/dev/vte/if_vte.c
===================================================================
--- sys/dev/vte/if_vte.c
+++ sys/dev/vte/if_vte.c
@@ -1955,27 +1955,57 @@
return (0);
}
+struct vte_maddr_ctx {
+ uint16_t rxfilt_perf[VTE_RXFILT_PERFECT_CNT][3];
+ uint16_t mchash[4];
+ u_int nperf;
+};
+
+static u_int
+vte_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct vte_maddr_ctx *ctx = arg;
+ uint8_t *eaddr;
+ uint32_t crc;
+
+ /*
+ * Program the first 3 multicast groups into the perfect filter.
+ * For all others, use the hash table.
+ */
+ if (ctx->nperf < VTE_RXFILT_PERFECT_CNT) {
+ eaddr = LLADDR(sdl);
+ ctx->rxfilt_perf[ctx->nperf][0] = eaddr[1] << 8 | eaddr[0];
+ ctx->rxfilt_perf[ctx->nperf][1] = eaddr[3] << 8 | eaddr[2];
+ ctx->rxfilt_perf[ctx->nperf][2] = eaddr[5] << 8 | eaddr[4];
+ ctx->nperf++;
+
+ return (1);
+ }
+ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN);
+ ctx->mchash[crc >> 30] |= 1 << ((crc >> 26) & 0x0F);
+
+ return (1);
+}
+
static void
vte_rxfilter(struct vte_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint8_t *eaddr;
- uint32_t crc;
- uint16_t rxfilt_perf[VTE_RXFILT_PERFECT_CNT][3];
- uint16_t mchash[4], mcr;
- int i, nperf;
+ struct vte_maddr_ctx ctx;
+ uint16_t mcr;
+ int i;
VTE_LOCK_ASSERT(sc);
ifp = sc->vte_ifp;
- bzero(mchash, sizeof(mchash));
+ bzero(ctx.mchash, sizeof(ctx.mchash));
for (i = 0; i < VTE_RXFILT_PERFECT_CNT; i++) {
- rxfilt_perf[i][0] = 0xFFFF;
- rxfilt_perf[i][1] = 0xFFFF;
- rxfilt_perf[i][2] = 0xFFFF;
+ ctx.rxfilt_perf[i][0] = 0xFFFF;
+ ctx.rxfilt_perf[i][1] = 0xFFFF;
+ ctx.rxfilt_perf[i][2] = 0xFFFF;
}
+ ctx.nperf = 0;
mcr = CSR_READ_2(sc, VTE_MCR0);
mcr &= ~(MCR0_PROMISC | MCR0_MULTICAST);
@@ -1987,54 +2017,32 @@
mcr |= MCR0_PROMISC;
if ((ifp->if_flags & IFF_ALLMULTI) != 0)
mcr |= MCR0_MULTICAST;
- mchash[0] = 0xFFFF;
- mchash[1] = 0xFFFF;
- mchash[2] = 0xFFFF;
- mchash[3] = 0xFFFF;
+ ctx.mchash[0] = 0xFFFF;
+ ctx.mchash[1] = 0xFFFF;
+ ctx.mchash[2] = 0xFFFF;
+ ctx.mchash[3] = 0xFFFF;
goto chipit;
}
- nperf = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &sc->vte_ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- /*
- * Program the first 3 multicast groups into
- * the perfect filter. For all others, use the
- * hash table.
- */
- if (nperf < VTE_RXFILT_PERFECT_CNT) {
- eaddr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
- rxfilt_perf[nperf][0] = eaddr[1] << 8 | eaddr[0];
- rxfilt_perf[nperf][1] = eaddr[3] << 8 | eaddr[2];
- rxfilt_perf[nperf][2] = eaddr[5] << 8 | eaddr[4];
- nperf++;
- continue;
- }
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- mchash[crc >> 30] |= 1 << ((crc >> 26) & 0x0F);
- }
- if_maddr_runlock(ifp);
- if (mchash[0] != 0 || mchash[1] != 0 || mchash[2] != 0 ||
- mchash[3] != 0)
+ if_foreach_llmaddr(ifp, vte_hash_maddr, &ctx);
+ if (ctx.mchash[0] != 0 || ctx.mchash[1] != 0 ||
+ ctx.mchash[2] != 0 || ctx.mchash[3] != 0)
mcr |= MCR0_MULTICAST;
chipit:
/* Program multicast hash table. */
- CSR_WRITE_2(sc, VTE_MAR0, mchash[0]);
- CSR_WRITE_2(sc, VTE_MAR1, mchash[1]);
- CSR_WRITE_2(sc, VTE_MAR2, mchash[2]);
- CSR_WRITE_2(sc, VTE_MAR3, mchash[3]);
+ CSR_WRITE_2(sc, VTE_MAR0, ctx.mchash[0]);
+ CSR_WRITE_2(sc, VTE_MAR1, ctx.mchash[1]);
+ CSR_WRITE_2(sc, VTE_MAR2, ctx.mchash[2]);
+ CSR_WRITE_2(sc, VTE_MAR3, ctx.mchash[3]);
/* Program perfect filter table. */
for (i = 0; i < VTE_RXFILT_PERFECT_CNT; i++) {
CSR_WRITE_2(sc, VTE_RXFILTER_PEEFECT_BASE + 8 * i + 0,
- rxfilt_perf[i][0]);
+ ctx.rxfilt_perf[i][0]);
CSR_WRITE_2(sc, VTE_RXFILTER_PEEFECT_BASE + 8 * i + 2,
- rxfilt_perf[i][1]);
+ ctx.rxfilt_perf[i][1]);
CSR_WRITE_2(sc, VTE_RXFILTER_PEEFECT_BASE + 8 * i + 4,
- rxfilt_perf[i][2]);
+ ctx.rxfilt_perf[i][2]);
}
CSR_WRITE_2(sc, VTE_MCR0, mcr);
CSR_READ_2(sc, VTE_MCR0);
Index: sys/dev/wi/if_wi.c
===================================================================
--- sys/dev/wi/if_wi.c
+++ sys/dev/wi/if_wi.c
@@ -1506,41 +1506,45 @@
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
}
+struct wi_mcast_ctx {
+ struct wi_mcast mlist;
+ int mcnt;
+};
+
+static u_int
+wi_copy_mcast(void *arg, struct sockaddr_dl *sdl, u_int count)
+{
+ struct wi_mcast_ctx *ctx = arg;
+
+ if (ctx->mcnt >= 16)
+ return (0);
+ IEEE80211_ADDR_COPY(&ctx->mlist.wi_mcast[ctx->mcnt++], LLADDR(sdl));
+
+ return (1);
+}
+
static int
wi_write_multi(struct wi_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap;
- struct wi_mcast mlist;
- int n;
+ struct wi_mcast_ctx ctx;
if (ic->ic_allmulti > 0 || ic->ic_promisc > 0) {
allmulti:
- memset(&mlist, 0, sizeof(mlist));
- return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
- sizeof(mlist));
+ memset(&ctx.mlist, 0, sizeof(ctx.mlist));
+ return wi_write_rid(sc, WI_RID_MCAST_LIST, &ctx.mlist,
+ sizeof(ctx.mlist));
}
- n = 0;
+ ctx.mcnt = 0;
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
-
- ifp = vap->iv_ifp;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (n >= 16)
- goto allmulti;
- IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
- (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
- n++;
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(vap->iv_ifp, wi_copy_mcast, &ctx);
+ if (ctx.mcnt >= 16)
+ goto allmulti;
}
- return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
- IEEE80211_ADDR_LEN * n);
+ return wi_write_rid(sc, WI_RID_MCAST_LIST, &ctx.mlist,
+ IEEE80211_ADDR_LEN * ctx.mcnt);
}
static void
Index: sys/dev/xilinx/if_xae.c
===================================================================
--- sys/dev/xilinx/if_xae.c
+++ sys/dev/xilinx/if_xae.c
@@ -514,14 +514,40 @@
return (error);
}
+static u_int
+xae_write_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct xae_softc *sc = arg;
+ uint32_t reg;
+ uint8_t *ma;
+
+ if (cnt >= XAE_MULTICAST_TABLE_SIZE)
+ return (1);
+
+ ma = LLADDR(sdl);
+
+ reg = READ4(sc, XAE_FFC) & 0xffffff00;
+ reg |= cnt;
+ WRITE4(sc, XAE_FFC, reg);
+
+ reg = (ma[0]);
+ reg |= (ma[1] << 8);
+ reg |= (ma[2] << 16);
+ reg |= (ma[3] << 24);
+ WRITE4(sc, XAE_FFV(0), reg);
+
+ reg = ma[4];
+ reg |= ma[5] << 8;
+ WRITE4(sc, XAE_FFV(1), reg);
+
+ return (1);
+}
+
static void
xae_setup_rxfilter(struct xae_softc *sc)
{
- struct ifmultiaddr *ifma;
struct ifnet *ifp;
uint32_t reg;
- uint8_t *ma;
- int i;
XAE_ASSERT_LOCKED(sc);
@@ -539,33 +565,7 @@
reg &= ~FFC_PM;
WRITE4(sc, XAE_FFC, reg);
- if_maddr_rlock(ifp);
-
- i = 0;
- CK_STAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- if (i >= XAE_MULTICAST_TABLE_SIZE)
- break;
-
- ma = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
-
- reg = READ4(sc, XAE_FFC) & 0xffffff00;
- reg |= i++;
- WRITE4(sc, XAE_FFC, reg);
-
- reg = (ma[0]);
- reg |= (ma[1] << 8);
- reg |= (ma[2] << 16);
- reg |= (ma[3] << 24);
- WRITE4(sc, XAE_FFV(0), reg);
-
- reg = ma[4];
- reg |= ma[5] << 8;
- WRITE4(sc, XAE_FFV(1), reg);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, xae_write_maddr, sc);
}
/*
Index: sys/dev/xl/if_xl.c
===================================================================
--- sys/dev/xl/if_xl.c
+++ sys/dev/xl/if_xl.c
@@ -606,11 +606,20 @@
* NICs older than the 3c905B have only one multicast option, which
* is to enable reception of all multicast frames.
*/
+static u_int
+xl_check_maddr_90x(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ uint8_t *rxfilt = arg;
+
+ *rxfilt |= XL_RXFILTER_ALLMULTI;
+
+ return (1);
+}
+
static void
xl_rxfilter_90x(struct xl_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
u_int8_t rxfilt;
XL_LOCK_ASSERT(sc);
@@ -634,16 +643,8 @@
rxfilt |= XL_RXFILTER_ALLFRAMES;
if (ifp->if_flags & IFF_ALLMULTI)
rxfilt |= XL_RXFILTER_ALLMULTI;
- } else {
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- rxfilt |= XL_RXFILTER_ALLMULTI;
- break;
- }
- if_maddr_runlock(ifp);
- }
+ } else
+ if_foreach_llmaddr(sc->xl_ifp, xl_check_maddr_90x, &rxfilt);
CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT);
XL_SEL_WIN(7);
@@ -651,14 +652,34 @@
/*
* 3c905B adapters have a hash filter that we can program.
+ * Note: the 3c905B currently only supports a 64-bit
+ * hash table, which means we really only need 6 bits,
+ * but the manual indicates that future chip revisions
+ * will have a 256-bit hash table, hence the routine
+ * is set up to calculate 8 bits of position info in
+ * case we need it some day.
+ * Note II, The Sequel: _CURRENT_ versions of the
+ * 3c905B have a 256 bit hash table. This means we have
+ * to use all 8 bits regardless. On older cards, the
+ * upper 2 bits will be ignored. Grrrr....
*/
+static u_int
+xl_check_maddr_90xB(void *arg, struct sockaddr_dl *sdl, u_int count)
+{
+ struct xl_softc *sc = arg;
+ uint16_t h;
+
+ h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) & 0xFF;
+ CSR_WRITE_2(sc, XL_COMMAND, h | XL_CMD_RX_SET_HASH | XL_HASH_SET);
+
+ return (1);
+}
+
static void
xl_rxfilter_90xB(struct xl_softc *sc)
{
struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- int i, mcnt;
- u_int16_t h;
+ int i;
u_int8_t rxfilt;
XL_LOCK_ASSERT(sc);
@@ -689,31 +710,7 @@
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH | i);
/* Now program new ones. */
- mcnt = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- /*
- * Note: the 3c905B currently only supports a 64-bit
- * hash table, which means we really only need 6 bits,
- * but the manual indicates that future chip revisions
- * will have a 256-bit hash table, hence the routine
- * is set up to calculate 8 bits of position info in
- * case we need it some day.
- * Note II, The Sequel: _CURRENT_ versions of the
- * 3c905B have a 256 bit hash table. This means we have
- * to use all 8 bits regardless. On older cards, the
- * upper 2 bits will be ignored. Grrrr....
- */
- h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN) & 0xFF;
- CSR_WRITE_2(sc, XL_COMMAND,
- h | XL_CMD_RX_SET_HASH | XL_HASH_SET);
- mcnt++;
- }
- if_maddr_runlock(ifp);
- if (mcnt > 0)
+ if (if_foreach_llmaddr(sc->xl_ifp, xl_check_maddr_90xB, sc) > 0)
rxfilt |= XL_RXFILTER_MULTIHASH;
}
Index: sys/kern/init_main.c
===================================================================
--- sys/kern/init_main.c
+++ sys/kern/init_main.c
@@ -514,7 +514,6 @@
td->td_pflags = TDP_KTHREAD;
td->td_cpuset = cpuset_thread0();
td->td_domain.dr_policy = td->td_cpuset->cs_domain;
- epoch_thread_init(td);
prison0_init();
p->p_peers = 0;
p->p_leader = p;
Index: sys/kern/kern_thread.c
===================================================================
--- sys/kern/kern_thread.c
+++ sys/kern/kern_thread.c
@@ -273,7 +273,6 @@
td->td_rlqe = NULL;
EVENTHANDLER_DIRECT_INVOKE(thread_init, td);
umtx_thread_init(td);
- epoch_thread_init(td);
td->td_kstack = 0;
td->td_sel = NULL;
return (0);
@@ -293,7 +292,6 @@
turnstile_free(td->td_turnstile);
sleepq_free(td->td_sleepqueue);
umtx_thread_fini(td);
- epoch_thread_fini(td);
seltdfini(td);
}
Index: sys/kern/subr_epoch.c
===================================================================
--- sys/kern/subr_epoch.c
+++ sys/kern/subr_epoch.c
@@ -829,17 +829,3 @@
PICKUP_GIANT();
}
-
-void
-epoch_thread_init(struct thread *td)
-{
-
- td->td_et = malloc(sizeof(struct epoch_tracker), M_EPOCH, M_WAITOK);
-}
-
-void
-epoch_thread_fini(struct thread *td)
-{
-
- free(td->td_et, M_EPOCH);
-}
Index: sys/net/if.c
===================================================================
--- sys/net/if.c
+++ sys/net/if.c
@@ -1775,40 +1775,6 @@
ifd->ifi_noproto = ifp->if_get_counter(ifp, IFCOUNTER_NOPROTO);
}
-/*
- * Wrapper functions for struct ifnet address list locking macros. These are
- * used by kernel modules to avoid encoding programming interface or binary
- * interface assumptions that may be violated when kernel-internal locking
- * approaches change.
- */
-void
-if_addr_rlock(struct ifnet *ifp)
-{
-
- epoch_enter_preempt(net_epoch_preempt, curthread->td_et);
-}
-
-void
-if_addr_runlock(struct ifnet *ifp)
-{
-
- epoch_exit_preempt(net_epoch_preempt, curthread->td_et);
-}
-
-void
-if_maddr_rlock(if_t ifp)
-{
-
- epoch_enter_preempt(net_epoch_preempt, curthread->td_et);
-}
-
-void
-if_maddr_runlock(if_t ifp)
-{
-
- epoch_exit_preempt(net_epoch_preempt, curthread->td_et);
-}
-
/*
* Initialization, destruction and refcounting functions for ifaddrs.
*/
@@ -4263,6 +4229,89 @@
return (((struct ifnet *)ifp)->if_mtu);
}
+/*
+ * Methods for drivers to access interface unicast and multicast
+ * link level addresses. Driver shall not know 'struct ifaddr' neither
+ * 'struct ifmultiaddr'.
+ */
+u_int
+if_lladdr_count(if_t ifp)
+{
+ struct epoch_tracker et;
+ struct ifaddr *ifa;
+ u_int count;
+
+ count = 0;
+ NET_EPOCH_ENTER(et);
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
+ if (ifa->ifa_addr->sa_family == AF_LINK)
+ count++;
+ NET_EPOCH_EXIT(et);
+
+ return (count);
+}
+
+u_int
+if_foreach_lladdr(if_t ifp, iflladdr_cb_t cb, void *cb_arg)
+{
+ struct epoch_tracker et;
+ struct ifaddr *ifa;
+ u_int count;
+
+ MPASS(cb);
+
+ count = 0;
+ NET_EPOCH_ENTER(et);
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (ifa->ifa_addr->sa_family != AF_LINK)
+ continue;
+ count += (*cb)(cb_arg, (struct sockaddr_dl *)ifa->ifa_addr,
+ count);
+ }
+ NET_EPOCH_EXIT(et);
+
+ return (count);
+}
+
+u_int
+if_llmaddr_count(if_t ifp)
+{
+ struct epoch_tracker et;
+ struct ifmultiaddr *ifma;
+ int count;
+
+ count = 0;
+ NET_EPOCH_ENTER(et);
+ CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
+ if (ifma->ifma_addr->sa_family == AF_LINK)
+ count++;
+ NET_EPOCH_EXIT(et);
+
+ return (count);
+}
+
+u_int
+if_foreach_llmaddr(if_t ifp, iflladdr_cb_t cb, void *cb_arg)
+{
+ struct epoch_tracker et;
+ struct ifmultiaddr *ifma;
+ u_int count;
+
+ MPASS(cb);
+
+ count = 0;
+ NET_EPOCH_ENTER(et);
+ CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ count += (*cb)(cb_arg, (struct sockaddr_dl *)ifma->ifma_addr,
+ count);
+ }
+ NET_EPOCH_EXIT(et);
+
+ return (count);
+}
+
int
if_setsoftc(if_t ifp, void *softc)
{
@@ -4346,77 +4395,6 @@
}
-/* XXX */
-#ifndef ETH_ADDR_LEN
-#define ETH_ADDR_LEN 6
-#endif
-
-int
-if_setupmultiaddr(if_t ifp, void *mta, int *cnt, int max)
-{
- struct ifmultiaddr *ifma;
- uint8_t *lmta = (uint8_t *)mta;
- int mcnt = 0;
-
- CK_STAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- if (mcnt == max)
- break;
-
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- &lmta[mcnt * ETH_ADDR_LEN], ETH_ADDR_LEN);
- mcnt++;
- }
- *cnt = mcnt;
-
- return (0);
-}
-
-int
-if_multiaddr_array(if_t ifp, void *mta, int *cnt, int max)
-{
- int error;
-
- if_maddr_rlock(ifp);
- error = if_setupmultiaddr(ifp, mta, cnt, max);
- if_maddr_runlock(ifp);
- return (error);
-}
-
-int
-if_multiaddr_count(if_t ifp, int max)
-{
- struct ifmultiaddr *ifma;
- int count;
-
- count = 0;
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- count++;
- if (count == max)
- break;
- }
- if_maddr_runlock(ifp);
- return (count);
-}
-
-int
-if_multi_apply(struct ifnet *ifp, int (*filter)(void *, struct ifmultiaddr *, int), void *arg)
-{
- struct ifmultiaddr *ifma;
- int cnt = 0;
-
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
- cnt += filter(arg, ifma, cnt);
- if_maddr_runlock(ifp);
- return (cnt);
-}
-
struct mbuf *
if_dequeue(if_t ifp)
{
Index: sys/net/if_spppsubr.c
===================================================================
--- sys/net/if_spppsubr.c
+++ sys/net/if_spppsubr.c
@@ -4818,6 +4818,7 @@
void
sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask)
{
+ struct epoch_tracker et;
struct ifnet *ifp = SP2IFP(sp);
struct ifaddr *ifa;
struct sockaddr_in *si, *sm;
@@ -4830,7 +4831,7 @@
* aliases don't make any sense on a p2p link anyway.
*/
si = NULL;
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (ifa->ifa_addr->sa_family == AF_INET) {
si = (struct sockaddr_in *)ifa->ifa_addr;
@@ -4849,7 +4850,7 @@
if (si && si->sin_addr.s_addr)
ddst = si->sin_addr.s_addr;
}
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
if (dst) *dst = ntohl(ddst);
if (src) *src = ntohl(ssrc);
@@ -4863,6 +4864,7 @@
sppp_set_ip_addr(struct sppp *sp, u_long src)
{
STDDCL;
+ struct epoch_tracker et;
struct ifaddr *ifa;
struct sockaddr_in *si;
struct in_ifaddr *ia;
@@ -4872,7 +4874,7 @@
* aliases don't make any sense on a p2p link anyway.
*/
si = NULL;
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family == AF_INET) {
si = (struct sockaddr_in *)ifa->ifa_addr;
@@ -4882,7 +4884,7 @@
}
}
}
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
if (ifa != NULL) {
int error;
@@ -4921,6 +4923,7 @@
sppp_get_ip6_addrs(struct sppp *sp, struct in6_addr *src, struct in6_addr *dst,
struct in6_addr *srcmask)
{
+ struct epoch_tracker et;
struct ifnet *ifp = SP2IFP(sp);
struct ifaddr *ifa;
struct sockaddr_in6 *si, *sm;
@@ -4934,7 +4937,7 @@
* aliases don't make any sense on a p2p link anyway.
*/
si = NULL;
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (ifa->ifa_addr->sa_family == AF_INET6) {
si = (struct sockaddr_in6 *)ifa->ifa_addr;
@@ -4960,7 +4963,7 @@
bcopy(&ddst, dst, sizeof(*dst));
if (src)
bcopy(&ssrc, src, sizeof(*src));
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
}
#ifdef IPV6CP_MYIFID_DYN
@@ -4980,6 +4983,7 @@
sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src)
{
STDDCL;
+ struct epoch_tracker et;
struct ifaddr *ifa;
struct sockaddr_in6 *sin6;
@@ -4989,7 +4993,7 @@
*/
sin6 = NULL;
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family == AF_INET6) {
sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
@@ -4999,7 +5003,7 @@
}
}
}
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
if (ifa != NULL) {
int error;
Index: sys/net/if_stf.c
===================================================================
--- sys/net/if_stf.c
+++ sys/net/if_stf.c
@@ -374,7 +374,8 @@
struct sockaddr_in6 *sin6;
struct in_addr in;
- if_addr_rlock(ifp);
+ NET_EPOCH_ASSERT();
+
CK_STAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) {
if (ia->ifa_addr->sa_family != AF_INET6)
continue;
@@ -395,10 +396,8 @@
*addr = sin6->sin6_addr;
*mask = ia6->ia_prefixmask.sin6_addr;
- if_addr_runlock(ifp);
return (0);
}
- if_addr_runlock(ifp);
return (ENOENT);
}
Index: sys/net/if_tuntap.c
===================================================================
--- sys/net/if_tuntap.c
+++ sys/net/if_tuntap.c
@@ -1151,6 +1151,7 @@
{
struct tuntap_softc *tp = ifp->if_softc;
#ifdef INET
+ struct epoch_tracker et;
struct ifaddr *ifa;
#endif
@@ -1162,7 +1163,7 @@
ifp->if_flags |= IFF_UP;
getmicrotime(&ifp->if_lastchange);
#ifdef INET
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family == AF_INET) {
struct sockaddr_in *si;
@@ -1176,7 +1177,7 @@
tp->tun_flags |= TUN_DSTADDR;
}
}
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
#endif
TUN_UNLOCK(tp);
} else {
Index: sys/net/if_var.h
===================================================================
--- sys/net/if_var.h
+++ sys/net/if_var.h
@@ -449,16 +449,6 @@
#define NET_EPOCH_WAIT() epoch_wait_preempt(net_epoch_preempt)
#define NET_EPOCH_ASSERT() MPASS(in_epoch(net_epoch_preempt))
-/*
- * Function variations on locking macros intended to be used by loadable
- * kernel modules in order to divorce them from the internals of address list
- * locking.
- */
-void if_addr_rlock(struct ifnet *ifp); /* if_addrhead */
-void if_addr_runlock(struct ifnet *ifp); /* if_addrhead */
-void if_maddr_rlock(if_t ifp); /* if_multiaddrs */
-void if_maddr_runlock(if_t ifp); /* if_multiaddrs */
-
#ifdef _KERNEL
/* interface link layer address change event */
typedef void (*iflladdr_event_handler_t)(void *, struct ifnet *);
@@ -765,11 +755,16 @@
void if_etherbpfmtap(if_t ifp, struct mbuf *m);
void if_vlancap(if_t ifp);
-int if_setupmultiaddr(if_t ifp, void *mta, int *cnt, int max);
-int if_multiaddr_array(if_t ifp, void *mta, int *cnt, int max);
-int if_multiaddr_count(if_t ifp, int max);
+/*
+ * Traversing through interface address lists.
+ */
+struct sockaddr_dl;
+typedef u_int iflladdr_cb_t(void *, struct sockaddr_dl *, u_int);
+u_int if_foreach_lladdr(if_t, iflladdr_cb_t, void *);
+u_int if_foreach_llmaddr(if_t, iflladdr_cb_t, void *);
+u_int if_lladdr_count(if_t);
+u_int if_llmaddr_count(if_t);
-int if_multi_apply(struct ifnet *ifp, int (*filter)(void *, struct ifmultiaddr *, int), void *arg);
int if_getamcount(if_t ifp);
struct ifaddr * if_getifaddr(if_t ifp);
Index: sys/net80211/ieee80211_ioctl.c
===================================================================
--- sys/net80211/ieee80211_ioctl.c
+++ sys/net80211/ieee80211_ioctl.c
@@ -3583,6 +3583,8 @@
IEEE80211_UNLOCK(ic);
/* Wait for parent ioctl handler if it was queued */
if (wait) {
+ struct epoch_tracker et;
+
ieee80211_waitfor_parent(ic);
/*
@@ -3592,13 +3594,13 @@
* NB: device may be detached during initialization;
* use if_ioctl for existence check.
*/
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
if (ifp->if_ioctl == ieee80211_ioctl &&
(ifp->if_flags & IFF_UP) == 0 &&
!IEEE80211_ADDR_EQ(vap->iv_myaddr, IF_LLADDR(ifp)))
IEEE80211_ADDR_COPY(vap->iv_myaddr,
IF_LLADDR(ifp));
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
}
break;
case SIOCADDMULTI:
Index: sys/netgraph/ng_eiface.c
===================================================================
--- sys/netgraph/ng_eiface.c
+++ sys/netgraph/ng_eiface.c
@@ -506,18 +506,19 @@
case NGM_EIFACE_GET_IFADDRS:
{
+ struct epoch_tracker et;
struct ifaddr *ifa;
caddr_t ptr;
int buflen;
/* Determine size of response and allocate it */
buflen = 0;
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
buflen += SA_SIZE(ifa->ifa_addr);
NG_MKRESPONSE(resp, msg, buflen, M_NOWAIT);
if (resp == NULL) {
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
error = ENOMEM;
break;
}
@@ -536,7 +537,7 @@
ptr += len;
buflen -= len;
}
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
break;
}
Index: sys/netgraph/ng_ether.c
===================================================================
--- sys/netgraph/ng_ether.c
+++ sys/netgraph/ng_ether.c
@@ -578,6 +578,7 @@
case NGM_ETHER_ADD_MULTI:
{
struct sockaddr_dl sa_dl;
+ struct epoch_tracker et;
struct ifmultiaddr *ifma;
if (msg->header.arglen != ETHER_ADDR_LEN) {
@@ -597,16 +598,16 @@
* lose a race while we check if the membership
* already exists.
*/
- if_maddr_rlock(priv->ifp);
+ NET_EPOCH_ENTER(et);
ifma = if_findmulti(priv->ifp,
(struct sockaddr *)&sa_dl);
- if_maddr_runlock(priv->ifp);
if (ifma != NULL) {
error = EADDRINUSE;
} else {
error = if_addmulti(priv->ifp,
(struct sockaddr *)&sa_dl, &ifma);
}
+ NET_EPOCH_EXIT(et);
break;
}
case NGM_ETHER_DEL_MULTI:
Index: sys/netinet/ip_divert.c
===================================================================
--- sys/netinet/ip_divert.c
+++ sys/netinet/ip_divert.c
@@ -234,7 +234,6 @@
/* Find IP address for receive interface */
ifp = m->m_pkthdr.rcvif;
- if_addr_rlock(ifp);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
@@ -242,7 +241,6 @@
((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
break;
}
- if_addr_runlock(ifp);
}
/*
* Record the incoming interface name whenever we have one.
Index: sys/netpfil/ipfw/ip_fw2.c
===================================================================
--- sys/netpfil/ipfw/ip_fw2.c
+++ sys/netpfil/ipfw/ip_fw2.c
@@ -406,19 +406,21 @@
}
} else {
#if !defined(USERSPACE) && defined(__FreeBSD__) /* and OSX too ? */
+ struct epoch_tracker et;
struct ifaddr *ia;
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) {
if (ia->ifa_addr->sa_family != AF_INET)
continue;
if (cmd->p.ip.s_addr == ((struct sockaddr_in *)
(ia->ifa_addr))->sin_addr.s_addr) {
- if_addr_runlock(ifp);
- return(1); /* match */
+ NET_EPOCH_EXIT(et);
+
+ return (1); /* match */
}
}
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
#endif /* __FreeBSD__ */
}
return(0); /* no match, fail ... */
Index: sys/netpfil/ipfw/ip_fw_nat.c
===================================================================
--- sys/netpfil/ipfw/ip_fw_nat.c
+++ sys/netpfil/ipfw/ip_fw_nat.c
@@ -114,10 +114,12 @@
IPFW_UH_WLOCK(chain);
/* Check every nat entry... */
LIST_FOREACH(ptr, &chain->nat, _next) {
+ struct epoch_tracker et;
+
/* ...using nic 'ifp->if_xname' as dynamic alias address. */
if (strncmp(ptr->if_name, ifp->if_xname, IF_NAMESIZE) != 0)
continue;
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr == NULL)
continue;
@@ -129,7 +131,7 @@
LibAliasSetAddress(ptr->lib, ptr->ip);
IPFW_WUNLOCK(chain);
}
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
}
IPFW_UH_WUNLOCK(chain);
}
Index: sys/netpfil/ipfw/nptv6/nptv6.c
===================================================================
--- sys/netpfil/ipfw/nptv6/nptv6.c
+++ sys/netpfil/ipfw/nptv6/nptv6.c
@@ -534,6 +534,7 @@
nptv6_find_prefix(struct ip_fw_chain *ch, struct nptv6_cfg *cfg,
struct ifnet *ifp)
{
+ struct epoch_tracker et;
struct ifaddr *ifa;
struct in6_ifaddr *ia;
@@ -545,7 +546,7 @@
if (ifp == NULL)
return;
}
- if_addr_rlock(ifp);
+ NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -558,7 +559,7 @@
nptv6_set_external(cfg, &ia->ia_addr.sin6_addr);
break;
}
- if_addr_runlock(ifp);
+ NET_EPOCH_EXIT(et);
if_rele(ifp);
}
Index: sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
===================================================================
--- sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -734,92 +734,102 @@
ipoib_mcast_restart(priv);
}
-void ipoib_mcast_restart(struct ipoib_dev_priv *priv)
+struct ipoib_mcast_ctx {
+ struct ipoib_dev_priv *priv;
+ struct list_head remove_list;
+};
+
+static u_int
+ipoib_process_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
{
- struct ifnet *dev = priv->dev;
- struct ifmultiaddr *ifma;
- struct ipoib_mcast *mcast, *tmcast;
- LIST_HEAD(remove_list);
+ struct ipoib_mcast_ctx *ctx = arg;
+ struct ipoib_dev_priv *priv = ctx->priv;
+ struct ipoib_mcast *mcast;
struct ib_sa_mcmember_rec rec;
+ union ib_gid mgid;
+ uint8_t *addr;
int addrlen;
- ipoib_dbg_mcast(priv, "restarting multicast task flags 0x%lX\n",
- priv->flags);
+ addr = LLADDR(sdl);
+ addrlen = sdl->sdl_alen;
+ if (!ipoib_mcast_addr_is_valid(addr, addrlen,
+ priv->dev->if_broadcastaddr))
+ return (0);
- ipoib_mcast_stop_thread(priv, 0);
+ memcpy(mgid.raw, addr + 4, sizeof mgid);
- if_maddr_rlock(dev);
- spin_lock(&priv->lock);
+ mcast = __ipoib_mcast_find(priv, &mgid);
+ if (!mcast || test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
+ struct ipoib_mcast *nmcast;
- /*
- * Unfortunately, the networking core only gives us a list of all of
- * the multicast hardware addresses. We need to figure out which ones
- * are new and which ones have been removed
- */
+ /* ignore group which is directly joined by userspace */
+ if (test_bit(IPOIB_FLAG_UMCAST, &priv->flags) &&
+ !ib_sa_get_mcmember_rec(priv->ca, priv->port, &mgid, &rec)) {
+ ipoib_dbg_mcast(priv, "ignoring multicast entry for mgid %16D\n",
+ mgid.raw, ":");
+ return (0);
+ }
- /* Clear out the found flag */
- list_for_each_entry(mcast, &priv->multicast_list, list)
- clear_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags);
+ /* Not found or send-only group, let's add a new entry */
+ ipoib_dbg_mcast(priv, "adding multicast entry for mgid %16D\n",
+ mgid.raw, ":");
- /* Mark all of the entries that are found or don't exist */
+ nmcast = ipoib_mcast_alloc(priv, 0);
+ if (!nmcast) {
+ ipoib_warn(priv, "unable to allocate memory for multicast structure\n");
+ return (0);
+ }
+ set_bit(IPOIB_MCAST_FLAG_FOUND, &nmcast->flags);
- CK_STAILQ_FOREACH(ifma, &dev->if_multiaddrs, ifma_link) {
- union ib_gid mgid;
- uint8_t *addr;
+ nmcast->mcmember.mgid = mgid;
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- addr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
- addrlen = ((struct sockaddr_dl *)ifma->ifma_addr)->sdl_alen;
- if (!ipoib_mcast_addr_is_valid(addr, addrlen,
- dev->if_broadcastaddr))
- continue;
+ if (mcast) {
+ /* Destroy the send only entry */
+ list_move_tail(&mcast->list, &ctx->remove_list);
- memcpy(mgid.raw, addr + 4, sizeof mgid);
+ rb_replace_node(&mcast->rb_node,
+ &nmcast->rb_node,
+ &priv->multicast_tree);
+ } else
+ __ipoib_mcast_add(priv, nmcast);
- mcast = __ipoib_mcast_find(priv, &mgid);
- if (!mcast || test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
- struct ipoib_mcast *nmcast;
+ list_add_tail(&nmcast->list, &priv->multicast_list);
+ }
- /* ignore group which is directly joined by userspace */
- if (test_bit(IPOIB_FLAG_UMCAST, &priv->flags) &&
- !ib_sa_get_mcmember_rec(priv->ca, priv->port, &mgid, &rec)) {
- ipoib_dbg_mcast(priv, "ignoring multicast entry for mgid %16D\n",
- mgid.raw, ":");
- continue;
- }
+ if (mcast)
+ set_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags);
- /* Not found or send-only group, let's add a new entry */
- ipoib_dbg_mcast(priv, "adding multicast entry for mgid %16D\n",
- mgid.raw, ":");
+ return (1);
+}
- nmcast = ipoib_mcast_alloc(priv, 0);
- if (!nmcast) {
- ipoib_warn(priv, "unable to allocate memory for multicast structure\n");
- continue;
- }
+void ipoib_mcast_restart(struct ipoib_dev_priv *priv)
+{
+ struct ipoib_mcast_ctx ctx = { priv,
+ { &ctx.remove_list, &ctx.remove_list }};
+ struct ifnet *dev = priv->dev;
+ struct ipoib_mcast *mcast, *tmcast;
- set_bit(IPOIB_MCAST_FLAG_FOUND, &nmcast->flags);
+ ipoib_dbg_mcast(priv, "restarting multicast task flags 0x%lX\n",
+ priv->flags);
- nmcast->mcmember.mgid = mgid;
+ ipoib_mcast_stop_thread(priv, 0);
- if (mcast) {
- /* Destroy the send only entry */
- list_move_tail(&mcast->list, &remove_list);
+ spin_lock(&priv->lock);
- rb_replace_node(&mcast->rb_node,
- &nmcast->rb_node,
- &priv->multicast_tree);
- } else
- __ipoib_mcast_add(priv, nmcast);
+ /*
+ * Unfortunately, the networking core only gives us a list of all of
+ * the multicast hardware addresses. We need to figure out which ones
+ * are new and which ones have been removed
+ */
- list_add_tail(&nmcast->list, &priv->multicast_list);
- }
+ /* Clear out the found flag */
+ list_for_each_entry(mcast, &priv->multicast_list, list)
+ clear_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags);
- if (mcast)
- set_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags);
- }
+ /* Mark all of the entries that are found or don't exist */
+ ctx.priv = priv;
+ if_foreach_llmaddr(dev, ipoib_process_maddr, &ctx);
/* Remove all of the entries don't exist anymore */
list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
@@ -831,15 +841,14 @@
rb_erase(&mcast->rb_node, &priv->multicast_tree);
/* Move to the remove list */
- list_move_tail(&mcast->list, &remove_list);
+ list_move_tail(&mcast->list, &ctx.remove_list);
}
}
spin_unlock(&priv->lock);
- if_maddr_runlock(dev);
/* We have to cancel outside of the spinlock */
- list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
+ list_for_each_entry_safe(mcast, tmcast, &ctx.remove_list, list) {
ipoib_mcast_leave(mcast->priv, mcast);
ipoib_mcast_free(mcast);
}
Index: sys/powerpc/ps3/if_glc.c
===================================================================
--- sys/powerpc/ps3/if_glc.c
+++ sys/powerpc/ps3/if_glc.c
@@ -504,12 +504,31 @@
return (err);
}
+static u_int
+glc_add_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct glc_softc *sc = arg;
+ uint64_t addr;
+
+ /*
+ * Filter can only hold 32 addresses, so fall back to
+ * the IFF_ALLMULTI case if we have too many. +1 is for
+ * broadcast.
+ */
+ if (cnt + 1 == 32)
+ return (0);
+
+ addr = 0;
+ memcpy(&((uint8_t *)(&addr))[2], LLADDR(sdl), ETHER_ADDR_LEN);
+ lv1_net_add_multicast_address(sc->sc_bus, sc->sc_dev, addr, 0);
+
+ return (1);
+}
+
static void
glc_set_multicast(struct glc_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
- struct ifmultiaddr *inm;
- uint64_t addr;
int naddrs;
/* Clear multicast filter */
@@ -522,30 +541,10 @@
if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
lv1_net_add_multicast_address(sc->sc_bus, sc->sc_dev, 0, 1);
} else {
- if_maddr_rlock(ifp);
- naddrs = 1; /* Include broadcast */
- CK_STAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) {
- if (inm->ifma_addr->sa_family != AF_LINK)
- continue;
- addr = 0;
- memcpy(&((uint8_t *)(&addr))[2],
- LLADDR((struct sockaddr_dl *)inm->ifma_addr),
- ETHER_ADDR_LEN);
-
- lv1_net_add_multicast_address(sc->sc_bus, sc->sc_dev,
- addr, 0);
-
- /*
- * Filter can only hold 32 addresses, so fall back to
- * the IFF_ALLMULTI case if we have too many.
- */
- if (++naddrs >= 32) {
- lv1_net_add_multicast_address(sc->sc_bus,
- sc->sc_dev, 0, 1);
- break;
- }
- }
- if_maddr_runlock(ifp);
+ naddrs = if_foreach_llmaddr(ifp, glc_add_maddr, sc);
+ if (naddrs + 1 == 32)
+ lv1_net_add_multicast_address(sc->sc_bus,
+ sc->sc_dev, 0, 1);
}
}
Index: sys/powerpc/pseries/phyp_llan.c
===================================================================
--- sys/powerpc/pseries/phyp_llan.c
+++ sys/powerpc/pseries/phyp_llan.c
@@ -508,28 +508,28 @@
mtx_unlock(&sc->io_lock);
}
+static u_int
+llan_set_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
+{
+ struct llan_softc *sc = arg;
+ uint64_t macaddr = 0;
+
+ memcpy((uint8_t *)&macaddr + 2, LLADDR(sdl), 6);
+ phyp_hcall(H_MULTICAST_CTRL, sc->unit, LLAN_ADD_MULTICAST, macaddr);
+
+ return (1);
+}
+
static int
llan_set_multicast(struct llan_softc *sc)
{
struct ifnet *ifp = sc->ifp;
- struct ifmultiaddr *inm;
- uint64_t macaddr = 0;
mtx_assert(&sc->io_lock, MA_OWNED);
phyp_hcall(H_MULTICAST_CTRL, sc->unit, LLAN_CLEAR_MULTICAST, 0);
- if_maddr_rlock(ifp);
- CK_STAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) {
- if (inm->ifma_addr->sa_family != AF_LINK)
- continue;
-
- memcpy((uint8_t *)&macaddr + 2,
- LLADDR((struct sockaddr_dl *)inm->ifma_addr), 6);
- phyp_hcall(H_MULTICAST_CTRL, sc->unit, LLAN_ADD_MULTICAST,
- macaddr);
- }
- if_maddr_runlock(ifp);
+ if_foreach_llmaddr(ifp, llan_set_maddr, sc);
return (0);
}
Index: sys/sys/epoch.h
===================================================================
--- sys/sys/epoch.h
+++ sys/sys/epoch.h
@@ -92,8 +92,5 @@
void epoch_enter(epoch_t epoch);
void epoch_exit(epoch_t epoch);
-void epoch_thread_init(struct thread *);
-void epoch_thread_fini(struct thread *);
-
#endif /* _KERNEL */
#endif /* _SYS_EPOCH_H_ */
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -365,7 +365,6 @@
int td_lastcpu; /* (t) Last cpu we were on. */
int td_oncpu; /* (t) Which cpu we are on. */
void *td_lkpi_task; /* LinuxKPI task struct pointer */
- struct epoch_tracker *td_et; /* (k) compat KPI spare tracker */
int td_pmcpend;
SLIST_HEAD(, epoch_tracker) td_epochs;
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 3:04 PM (9 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28591658
Default Alt Text
D21943.id63103.diff (189 KB)
Attached To
Mode
D21943: Correct and final KPI to traverse through interface address lists for drivers.Removal of not stack allocated epoch_tracker.
Attached
Detach File
Event Timeline
Log In to Comment