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]));
}
Example #2
0
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);
}