diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
commit | 62b8c978ee6b8d135d9e7953221de58000dba986 (patch) | |
tree | 683b04b2e627f6710c22c151b23c8cc9a165315e /net/mac80211/util.c | |
parent | 78fd82238d0e5716578c326404184a27ba67fd6e (diff) | |
download | linux-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.c | 286 |
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; -} |