static void arn_opmode_init(struct arn_softc *sc) { struct ath_hal *ah = sc->sc_ah; uint32_t rfilt; uint32_t mfilt[2]; ieee80211com_t *ic = (ieee80211com_t *)sc; /* configure rx filter */ rfilt = arn_calcrxfilter(sc); ath9k_hw_setrxfilter(ah, rfilt); /* configure bssid mask */ if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) (void) ath9k_hw_setbssidmask(ah, sc->sc_bssidmask); /* configure operational mode */ ath9k_hw_setopmode(ah); /* Handle any link-level address change. */ (void) ath9k_hw_setmac(ah, sc->sc_myaddr); /* calculate and install multicast filter */ mfilt[0] = ~((uint32_t)0); /* LINT */ mfilt[1] = ~((uint32_t)0); /* LINT */ ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); ARN_DBG((ARN_DBG_RECV, "arn: arn_opmode_init(): " "mode = %d RX filter 0x%x, MC filter %08x:%08x\n", ic->ic_opmode, rfilt, mfilt[0], mfilt[1])); }
void ath9k_set_bssid_mask(struct ieee80211_hw *hw) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath9k_vif_iter_data iter_data; int i, j; u8 mask[ETH_ALEN]; /* * Add primary MAC address even if it is not in active use since it * will be configured to the hardware as the starting point and the * BSSID mask will need to be changed if another address is active. */ iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC); if (iter_data.addr) { memcpy(iter_data.addr, sc->sc_ah->macaddr, ETH_ALEN); iter_data.count = 1; } else iter_data.count = 0; /* Get list of all active MAC addresses */ spin_lock_bh(&sc->wiphy_lock); ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, &iter_data); for (i = 0; i < sc->num_sec_wiphy; i++) { if (sc->sec_wiphy[i] == NULL) continue; ieee80211_iterate_active_interfaces_atomic( sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data); } spin_unlock_bh(&sc->wiphy_lock); /* Generate an address mask to cover all active addresses */ memset(mask, 0, ETH_ALEN); for (i = 0; i < iter_data.count; i++) { u8 *a1 = iter_data.addr + i * ETH_ALEN; for (j = i + 1; j < iter_data.count; j++) { u8 *a2 = iter_data.addr + j * ETH_ALEN; mask[0] |= a1[0] ^ a2[0]; mask[1] |= a1[1] ^ a2[1]; mask[2] |= a1[2] ^ a2[2]; mask[3] |= a1[3] ^ a2[3]; mask[4] |= a1[4] ^ a2[4]; mask[5] |= a1[5] ^ a2[5]; } } kfree(iter_data.addr); /* Invert the mask and configure hardware */ sc->bssidmask[0] = ~mask[0]; sc->bssidmask[1] = ~mask[1]; sc->bssidmask[2] = ~mask[2]; sc->bssidmask[3] = ~mask[3]; sc->bssidmask[4] = ~mask[4]; sc->bssidmask[5] = ~mask[5]; ath9k_hw_setbssidmask(sc); }