summaryrefslogtreecommitdiff
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
commit62b8c978ee6b8d135d9e7953221de58000dba986 (patch)
tree683b04b2e627f6710c22c151b23c8cc9a165315e /net/mac80211/util.c
parent78fd82238d0e5716578c326404184a27ba67fd6e (diff)
downloadlinux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c286
1 files changed, 55 insertions, 231 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 592a181..69e4ef5 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -300,6 +300,9 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
if (!sdata->dev)
continue;
+ if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
+ continue;
+
if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE &&
local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
continue;
@@ -564,15 +567,18 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
IEEE80211_QUEUE_STOP_REASON_FLUSH);
}
-static void __iterate_active_interfaces(struct ieee80211_local *local,
- u32 iter_flags,
- void (*iterator)(void *data, u8 *mac,
- struct ieee80211_vif *vif),
- void *data)
+void ieee80211_iterate_active_interfaces(
+ struct ieee80211_hw *hw, u32 iter_flags,
+ void (*iterator)(void *data, u8 *mac,
+ struct ieee80211_vif *vif),
+ void *data)
{
+ struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ mutex_lock(&local->iflist_mtx);
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
switch (sdata->vif.type) {
case NL80211_IFTYPE_MONITOR:
if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
@@ -591,25 +597,13 @@ static void __iterate_active_interfaces(struct ieee80211_local *local,
&sdata->vif);
}
- sdata = rcu_dereference_check(local->monitor_sdata,
- lockdep_is_held(&local->iflist_mtx) ||
- lockdep_rtnl_is_held());
+ sdata = rcu_dereference_protected(local->monitor_sdata,
+ lockdep_is_held(&local->iflist_mtx));
if (sdata &&
(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL ||
sdata->flags & IEEE80211_SDATA_IN_DRIVER))
iterator(data, sdata->vif.addr, &sdata->vif);
-}
-
-void ieee80211_iterate_active_interfaces(
- struct ieee80211_hw *hw, u32 iter_flags,
- void (*iterator)(void *data, u8 *mac,
- struct ieee80211_vif *vif),
- void *data)
-{
- struct ieee80211_local *local = hw_to_local(hw);
- mutex_lock(&local->iflist_mtx);
- __iterate_active_interfaces(local, iter_flags, iterator, data);
mutex_unlock(&local->iflist_mtx);
}
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
@@ -621,26 +615,38 @@ void ieee80211_iterate_active_interfaces_atomic(
void *data)
{
struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata;
rcu_read_lock();
- __iterate_active_interfaces(local, iter_flags, iterator, data);
- rcu_read_unlock();
-}
-EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
-void ieee80211_iterate_active_interfaces_rtnl(
- struct ieee80211_hw *hw, u32 iter_flags,
- void (*iterator)(void *data, u8 *mac,
- struct ieee80211_vif *vif),
- void *data)
-{
- struct ieee80211_local *local = hw_to_local(hw);
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_MONITOR:
+ if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
+ continue;
+ break;
+ case NL80211_IFTYPE_AP_VLAN:
+ continue;
+ default:
+ break;
+ }
+ if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) &&
+ !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
+ continue;
+ if (ieee80211_sdata_running(sdata))
+ iterator(data, sdata->vif.addr,
+ &sdata->vif);
+ }
- ASSERT_RTNL();
+ sdata = rcu_dereference(local->monitor_sdata);
+ if (sdata &&
+ (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL ||
+ sdata->flags & IEEE80211_SDATA_IN_DRIVER))
+ iterator(data, sdata->vif.addr, &sdata->vif);
- __iterate_active_interfaces(local, iter_flags, iterator, data);
+ rcu_read_unlock();
}
-EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl);
+EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
/*
* Nothing should have been stuffed into the workqueue during
@@ -740,7 +746,6 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
case WLAN_EID_TIMEOUT_INTERVAL:
case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
- case WLAN_EID_CHAN_SWITCH_PARAM:
/*
* not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
* that if the content gets bigger it might be needed more than once
@@ -906,14 +911,6 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
}
elems->sec_chan_offs = (void *)pos;
break;
- case WLAN_EID_CHAN_SWITCH_PARAM:
- if (elen !=
- sizeof(*elems->mesh_chansw_params_ie)) {
- elem_parse_failed = true;
- break;
- }
- elems->mesh_chansw_params_ie = (void *)pos;
- break;
case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
if (!action ||
elen != sizeof(*elems->wide_bw_chansw_ie)) {
@@ -1010,21 +1007,14 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
*/
enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION);
- /* Set defaults according to 802.11-2007 Table 7-37 */
- aCWmax = 1023;
- if (use_11b)
- aCWmin = 31;
- else
- aCWmin = 15;
-
- /* Confiure old 802.11b/g medium access rules. */
- qparam.cw_max = aCWmax;
- qparam.cw_min = aCWmin;
- qparam.txop = 0;
- qparam.aifs = 2;
-
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- /* Update if QoS is enabled. */
+ /* Set defaults according to 802.11-2007 Table 7-37 */
+ aCWmax = 1023;
+ if (use_11b)
+ aCWmin = 31;
+ else
+ aCWmin = 15;
+
if (enable_qos) {
switch (ac) {
case IEEE80211_AC_BK:
@@ -1060,6 +1050,12 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
qparam.aifs = 2;
break;
}
+ } else {
+ /* Confiure old 802.11b/g medium access rules. */
+ qparam.cw_max = aCWmax;
+ qparam.cw_min = aCWmin;
+ qparam.txop = 0;
+ qparam.aifs = 2;
}
qparam.uapsd = false;
@@ -1088,8 +1084,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt;
int err;
- /* 24 + 6 = header + auth_algo + auth_transaction + status_code */
- skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 6 + extra_len);
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+ sizeof(*mgmt) + 6 + extra_len);
if (!skb)
return;
@@ -2300,175 +2296,3 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw)
ieee80211_queue_work(hw, &local->radar_detected_work);
}
EXPORT_SYMBOL(ieee80211_radar_detected);
-
-u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c)
-{
- u32 ret;
- int tmp;
-
- switch (c->width) {
- case NL80211_CHAN_WIDTH_20:
- c->width = NL80211_CHAN_WIDTH_20_NOHT;
- ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
- break;
- case NL80211_CHAN_WIDTH_40:
- c->width = NL80211_CHAN_WIDTH_20;
- c->center_freq1 = c->chan->center_freq;
- ret = IEEE80211_STA_DISABLE_40MHZ |
- IEEE80211_STA_DISABLE_VHT;
- break;
- case NL80211_CHAN_WIDTH_80:
- tmp = (30 + c->chan->center_freq - c->center_freq1)/20;
- /* n_P40 */
- tmp /= 2;
- /* freq_P40 */
- c->center_freq1 = c->center_freq1 - 20 + 40 * tmp;
- c->width = NL80211_CHAN_WIDTH_40;
- ret = IEEE80211_STA_DISABLE_VHT;
- break;
- case NL80211_CHAN_WIDTH_80P80:
- c->center_freq2 = 0;
- c->width = NL80211_CHAN_WIDTH_80;
- ret = IEEE80211_STA_DISABLE_80P80MHZ |
- IEEE80211_STA_DISABLE_160MHZ;
- break;
- case NL80211_CHAN_WIDTH_160:
- /* n_P20 */
- tmp = (70 + c->chan->center_freq - c->center_freq1)/20;
- /* n_P80 */
- tmp /= 4;
- c->center_freq1 = c->center_freq1 - 40 + 80 * tmp;
- c->width = NL80211_CHAN_WIDTH_80;
- ret = IEEE80211_STA_DISABLE_80P80MHZ |
- IEEE80211_STA_DISABLE_160MHZ;
- break;
- default:
- case NL80211_CHAN_WIDTH_20_NOHT:
- WARN_ON_ONCE(1);
- c->width = NL80211_CHAN_WIDTH_20_NOHT;
- ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
- break;
- case NL80211_CHAN_WIDTH_5:
- case NL80211_CHAN_WIDTH_10:
- WARN_ON_ONCE(1);
- /* keep c->width */
- ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
- break;
- }
-
- WARN_ON_ONCE(!cfg80211_chandef_valid(c));
-
- return ret;
-}
-
-/*
- * Returns true if smps_mode_new is strictly more restrictive than
- * smps_mode_old.
- */
-bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old,
- enum ieee80211_smps_mode smps_mode_new)
-{
- if (WARN_ON_ONCE(smps_mode_old == IEEE80211_SMPS_AUTOMATIC ||
- smps_mode_new == IEEE80211_SMPS_AUTOMATIC))
- return false;
-
- switch (smps_mode_old) {
- case IEEE80211_SMPS_STATIC:
- return false;
- case IEEE80211_SMPS_DYNAMIC:
- return smps_mode_new == IEEE80211_SMPS_STATIC;
- case IEEE80211_SMPS_OFF:
- return smps_mode_new != IEEE80211_SMPS_OFF;
- default:
- WARN_ON(1);
- }
-
- return false;
-}
-
-int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
- struct cfg80211_csa_settings *csa_settings)
-{
- struct sk_buff *skb;
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_local *local = sdata->local;
- int freq;
- int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) +
- sizeof(mgmt->u.action.u.chan_switch);
- u8 *pos;
-
- if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
- sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
- return -EOPNOTSUPP;
-
- skb = dev_alloc_skb(local->tx_headroom + hdr_len +
- 5 + /* channel switch announcement element */
- 3 + /* secondary channel offset element */
- 8); /* mesh channel switch parameters element */
- if (!skb)
- return -ENOMEM;
-
- skb_reserve(skb, local->tx_headroom);
- mgmt = (struct ieee80211_mgmt *)skb_put(skb, hdr_len);
- memset(mgmt, 0, hdr_len);
- mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_ACTION);
-
- eth_broadcast_addr(mgmt->da);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
- if (ieee80211_vif_is_mesh(&sdata->vif)) {
- memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
- } else {
- struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
- }
- mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
- mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
- pos = skb_put(skb, 5);
- *pos++ = WLAN_EID_CHANNEL_SWITCH; /* EID */
- *pos++ = 3; /* IE length */
- *pos++ = csa_settings->block_tx ? 1 : 0; /* CSA mode */
- freq = csa_settings->chandef.chan->center_freq;
- *pos++ = ieee80211_frequency_to_channel(freq); /* channel */
- *pos++ = csa_settings->count; /* count */
-
- if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_40) {
- enum nl80211_channel_type ch_type;
-
- skb_put(skb, 3);
- *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */
- *pos++ = 1; /* IE length */
- ch_type = cfg80211_get_chandef_type(&csa_settings->chandef);
- if (ch_type == NL80211_CHAN_HT40PLUS)
- *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- else
- *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- }
-
- if (ieee80211_vif_is_mesh(&sdata->vif)) {
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- __le16 pre_value;
-
- skb_put(skb, 8);
- *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; /* EID */
- *pos++ = 6; /* IE length */
- *pos++ = sdata->u.mesh.mshcfg.dot11MeshTTL; /* Mesh TTL */
- *pos = 0x00; /* Mesh Flag: Tx Restrict, Initiator, Reason */
- *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
- *pos++ |= csa_settings->block_tx ?
- WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
- put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
- pos += 2;
- if (!ifmsh->pre_value)
- ifmsh->pre_value = 1;
- else
- ifmsh->pre_value++;
- pre_value = cpu_to_le16(ifmsh->pre_value);
- memcpy(pos, &pre_value, 2); /* Precedence Value */
- pos += 2;
- ifmsh->chsw_init = true;
- }
-
- ieee80211_tx_skb(sdata, skb);
- return 0;
-}