/*- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * Copyright (c) 2004-2005 Atheros Communications, Inc. * Copyright (c) 2006 Devicescape Software, Inc. * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> * Copyright (c) 2010 Bruno Randolf <br1@einfach.org> * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. *
*/
/* Don't allow other interfaces if one ad-hoc is configured. * TODO: Fix the problems with ad-hoc and multiple other interfaces. * We would need to operate the HW in ad-hoc mode to allow TSF updates * for the IBSS, but this breaks with additional AP or STA interfaces
* at the moment. */ if (ah->num_adhoc_vifs ||
(ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
ret = -ELNRNG; goto end;
}
switch (vif->type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT:
avf->opmode = vif->type; break; default:
ret = -EOPNOTSUPP; goto end;
}
/* Assign the vap/adhoc to a beacon xmit slot. */ if ((avf->opmode == NL80211_IFTYPE_AP) ||
(avf->opmode == NL80211_IFTYPE_ADHOC) ||
(avf->opmode == NL80211_IFTYPE_MESH_POINT)) { int slot;
for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++)
ath5k_hw_set_tx_retry_limits(ah, i);
}
/* TODO: * 1) Move this on config_interface and handle each case * separately eg. when we have only one STA vif, use * AR5K_ANTMODE_SINGLE_AP * * 2) Allow the user to change antenna mode eg. when only * one antenna is present * * 3) Allow the user to set default/tx antenna when possible * * 4) Default mode should handle 90% of the cases, together * with fixed a/b and single AP modes we should be able to * handle 99%. Sectored modes are extreme cases and i still * haven't found a usage for them. If we decide to support them, * then we must allow the user to set how many tx antennas we * have available
*/
ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
if (changes & BSS_CHANGED_BSSID) { /* Cache for later use during resets */
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
common->curaid = 0;
ath5k_hw_set_bssid(ah);
}
if (changes & BSS_CHANGED_BEACON_INT)
ah->bintval = bss_conf->beacon_int;
if (changes & BSS_CHANGED_ERP_SLOT) { int slot_time;
if (changes & BSS_CHANGED_ASSOC) {
avf->assoc = vif->cfg.assoc; if (vif->cfg.assoc)
ah->assoc = vif->cfg.assoc; else
ah->assoc = ath5k_any_vif_assoc(ah);
if (ah->opmode == NL80211_IFTYPE_STATION)
ath5k_set_beacon_filter(hw, ah->assoc);
ath5k_hw_set_ledstate(ah, ah->assoc ?
AR5K_LED_ASSOC : AR5K_LED_INIT); if (vif->cfg.assoc) {
ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "Bss Info ASSOC %d, bssid: %pM\n",
vif->cfg.aid, common->curbssid);
common->curaid = vif->cfg.aid;
ath5k_hw_set_bssid(ah); /* Once ANI is available you would start it here */
}
}
if (changes & BSS_CHANGED_BEACON) {
spin_lock_bh(&ah->block);
ath5k_beacon_update(hw, vif);
spin_unlock_bh(&ah->block);
}
if (changes & BSS_CHANGED_BEACON_ENABLED)
ah->enable_beacon = bss_conf->enable_beacon;
if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_BEACON_INT))
ath5k_beacon_config(ah);
netdev_hw_addr_list_for_each(ha, mc_list) { /* calculate XOR of eight 6-bit values */
val = get_unaligned_le32(ha->addr + 0);
pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
val = get_unaligned_le32(ha->addr + 3);
pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
pos &= 0x3f;
mfilt[pos / 32] |= (1 << (pos % 32)); /* XXX: we might be able to just do this instead, * but not sure, needs testing, if we do use this we'd
* need to inform below not to reset the mcast */ /* ath5k_hw_set_mcast_filterindex(ah,
* ha->addr[5]); */
}
return ((u64)(mfilt[1]) << 32) | mfilt[0];
}
/* * o always accept unicast, broadcast, and multicast traffic * o multicast traffic for all BSSIDs will be enabled if mac80211 * says it should be * o maintain current state of phy ofdm or phy cck error reception. * If the hardware detects any of these type of errors then * ath5k_hw_get_rx_filter() will pass to us the respective * hardware filters to be able to receive these type of frames. * o probe request frames are accepted only when operating in * hostap, adhoc, or monitor modes * o enable promiscuous mode according to the interface state * o accept beacons: * - when operating in adhoc mode so the 802.11 layer creates * node table entries for peers, * - when operating in station mode for collecting rssi data when * the station is otherwise quiet, or * - when scanning
*/ staticvoid
ath5k_configure_filter(struct ieee80211_hw *hw, unsignedint changed_flags, unsignedint *new_flags, u64 multicast)
{ #define SUPPORTED_FIF_FLAGS \
(FIF_ALLMULTI | FIF_FCSFAIL | \
FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
FIF_BCN_PRBRESP_PROMISC)
struct ath5k_hw *ah = hw->priv;
u32 mfilt[2], rfilt; struct ath5k_vif_iter_data iter_data; /* to count STA interfaces */
mutex_lock(&ah->lock);
mfilt[0] = multicast;
mfilt[1] = multicast >> 32;
/* Only deal with supported flags */
*new_flags &= SUPPORTED_FIF_FLAGS;
/* If HW detects any phy or radar errors, leave those filters on. * Also, always enable Unicast, Broadcasts and Multicast
* XXX: move unicast, bssid broadcasts and multicast to mac80211 */
rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) |
(AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
AR5K_RX_FILTER_MCAST);
/* Note, AR5K_RX_FILTER_MCAST is already enabled */ if (*new_flags & FIF_ALLMULTI) {
mfilt[0] = ~0;
mfilt[1] = ~0;
}
/* This is the best we can do */ if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))
rfilt |= AR5K_RX_FILTER_PHYERR;
/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
* and probes for any BSSID */ if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (ah->nvifs > 1))
rfilt |= AR5K_RX_FILTER_BEACON;
/* FIF_CONTROL doc says we should only pass on control frames for this * station. This needs testing. I believe right now this * enables *all* control frames, which is OK.. but
* we should see if we can improve on granularity */ if (*new_flags & FIF_CONTROL)
rfilt |= AR5K_RX_FILTER_CONTROL;
/* Additional settings per mode -- this is per ath5k */
/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
switch (ah->opmode) { case NL80211_IFTYPE_MESH_POINT:
rfilt |= AR5K_RX_FILTER_CONTROL |
AR5K_RX_FILTER_BEACON |
AR5K_RX_FILTER_PROBEREQ |
AR5K_RX_FILTER_PROM; break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_ADHOC:
rfilt |= AR5K_RX_FILTER_PROBEREQ |
AR5K_RX_FILTER_BEACON; break; case NL80211_IFTYPE_STATION: if (ah->assoc)
rfilt |= AR5K_RX_FILTER_BEACON; break; default: break;
}
/* Set up RX Filter */ if (iter_data.n_stas > 1) { /* If you have multiple STA interfaces connected to * different APs, ARPs are not received (most of the time?) * Enabling PROMISC appears to fix that problem.
*/
rfilt |= AR5K_RX_FILTER_PROM;
}
/* Set filters */
ath5k_hw_set_rx_filter(ah, rfilt);
/* Set multicast bits */
ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); /* Set the cached hw filter flags, this will later actually
* be set in HW */
ah->filter_flags = rfilt; /* Store current FIF filter flags */
ah->fif_filter_flags = *new_flags;
if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) return -EOPNOTSUPP;
if (vif->type == NL80211_IFTYPE_ADHOC &&
(key->cipher == WLAN_CIPHER_SUITE_TKIP ||
key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { /* don't program group keys when using IBSS_RSN */ return -EOPNOTSUPP;
}
switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_TKIP: break; case WLAN_CIPHER_SUITE_CCMP: if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM) break; return -EOPNOTSUPP; default: return -EOPNOTSUPP;
}
mutex_lock(&ah->lock);
switch (cmd) { case SET_KEY:
ret = ath_key_config(common, vif, sta, key); if (ret >= 0) {
key->hw_key_idx = ret; /* push IV and Michael MIC generation to stack */
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
ret = 0;
} break; case DISABLE_KEY:
ath_key_delete(common, key->hw_key_idx); break; default:
ret = -EINVAL;
}
/* * in IBSS mode we need to update the beacon timers too. * this will also reset the TSF if we call it with 0
*/ if (ah->opmode == NL80211_IFTYPE_ADHOC)
ath5k_beacon_update_timers(ah, 0); else
ath5k_hw_reset_tsf(ah);
}
/** * ath5k_set_coverage_class - Set IEEE 802.11 coverage class * * @hw: struct ieee80211_hw pointer * @radio_idx: Radio index * @coverage_class: IEEE 802.11 coverage class number * * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given * coverage class. The values are persistent, they are restored after device * reset.
*/ staticvoid
ath5k_set_coverage_class(struct ieee80211_hw *hw, int radio_idx,
s16 coverage_class)
{ struct ath5k_hw *ah = hw->priv;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.