Page MenuHomeFreeBSD

D21943.id63103.diff
No OneTemporary

D21943.id63103.diff

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

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)

Event Timeline