Commit 05c5e9ff authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-for-davem-2018-09-27' of...

Merge tag 'mac80211-for-davem-2018-09-27' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211

Johannes Berg says:

====================
More patches than I'd like perhaps, but each seems reasonable:
 * two new spectre-v1 mitigations in nl80211
 * TX status fix in general, and mesh in particular
 * powersave vs. offchannel fix
 * regulatory initialization fix
 * fix for a queue hang due to a bad return value
 * allocate TXQs for active monitor interfaces, fixing my
   earlier patch to avoid unnecessary allocations where I
   missed this case needed them
 * fix TDLS data frames priority assignment
 * fix scan results processing to take into account duplicate
   channel numbers (over different operating classes, but we
   don't necessarily know the operating class)
 * various hwsim fixes for radio destruction and new radio
   announcement messages
 * remove an extraneous kernel-doc line
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5f672090 1222a160
...@@ -520,7 +520,6 @@ struct mac80211_hwsim_data { ...@@ -520,7 +520,6 @@ struct mac80211_hwsim_data {
int channels, idx; int channels, idx;
bool use_chanctx; bool use_chanctx;
bool destroy_on_close; bool destroy_on_close;
struct work_struct destroy_work;
u32 portid; u32 portid;
char alpha2[2]; char alpha2[2];
const struct ieee80211_regdomain *regd; const struct ieee80211_regdomain *regd;
...@@ -2935,8 +2934,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -2935,8 +2934,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
hwsim_radios_generation++; hwsim_radios_generation++;
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
if (idx > 0) hwsim_mcast_new_radio(idx, info, param);
hwsim_mcast_new_radio(idx, info, param);
return idx; return idx;
...@@ -3565,30 +3563,27 @@ static struct genl_family hwsim_genl_family __ro_after_init = { ...@@ -3565,30 +3563,27 @@ static struct genl_family hwsim_genl_family __ro_after_init = {
.n_mcgrps = ARRAY_SIZE(hwsim_mcgrps), .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
}; };
static void destroy_radio(struct work_struct *work)
{
struct mac80211_hwsim_data *data =
container_of(work, struct mac80211_hwsim_data, destroy_work);
hwsim_radios_generation++;
mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), NULL);
}
static void remove_user_radios(u32 portid) static void remove_user_radios(u32 portid)
{ {
struct mac80211_hwsim_data *entry, *tmp; struct mac80211_hwsim_data *entry, *tmp;
LIST_HEAD(list);
spin_lock_bh(&hwsim_radio_lock); spin_lock_bh(&hwsim_radio_lock);
list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) { list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) {
if (entry->destroy_on_close && entry->portid == portid) { if (entry->destroy_on_close && entry->portid == portid) {
list_del(&entry->list); list_move(&entry->list, &list);
rhashtable_remove_fast(&hwsim_radios_rht, &entry->rht, rhashtable_remove_fast(&hwsim_radios_rht, &entry->rht,
hwsim_rht_params); hwsim_rht_params);
INIT_WORK(&entry->destroy_work, destroy_radio); hwsim_radios_generation++;
queue_work(hwsim_wq, &entry->destroy_work);
} }
} }
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
list_for_each_entry_safe(entry, tmp, &list, list) {
list_del(&entry->list);
mac80211_hwsim_del_radio(entry, wiphy_name(entry->hw->wiphy),
NULL);
}
} }
static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, static int mac80211_hwsim_netlink_notify(struct notifier_block *nb,
...@@ -3646,6 +3641,7 @@ static __net_init int hwsim_init_net(struct net *net) ...@@ -3646,6 +3641,7 @@ static __net_init int hwsim_init_net(struct net *net)
static void __net_exit hwsim_exit_net(struct net *net) static void __net_exit hwsim_exit_net(struct net *net)
{ {
struct mac80211_hwsim_data *data, *tmp; struct mac80211_hwsim_data *data, *tmp;
LIST_HEAD(list);
spin_lock_bh(&hwsim_radio_lock); spin_lock_bh(&hwsim_radio_lock);
list_for_each_entry_safe(data, tmp, &hwsim_radios, list) { list_for_each_entry_safe(data, tmp, &hwsim_radios, list) {
...@@ -3656,17 +3652,19 @@ static void __net_exit hwsim_exit_net(struct net *net) ...@@ -3656,17 +3652,19 @@ static void __net_exit hwsim_exit_net(struct net *net)
if (data->netgroup == hwsim_net_get_netgroup(&init_net)) if (data->netgroup == hwsim_net_get_netgroup(&init_net))
continue; continue;
list_del(&data->list); list_move(&data->list, &list);
rhashtable_remove_fast(&hwsim_radios_rht, &data->rht, rhashtable_remove_fast(&hwsim_radios_rht, &data->rht,
hwsim_rht_params); hwsim_rht_params);
hwsim_radios_generation++; hwsim_radios_generation++;
spin_unlock_bh(&hwsim_radio_lock); }
spin_unlock_bh(&hwsim_radio_lock);
list_for_each_entry_safe(data, tmp, &list, list) {
list_del(&data->list);
mac80211_hwsim_del_radio(data, mac80211_hwsim_del_radio(data,
wiphy_name(data->hw->wiphy), wiphy_name(data->hw->wiphy),
NULL); NULL);
spin_lock_bh(&hwsim_radio_lock);
} }
spin_unlock_bh(&hwsim_radio_lock);
ida_simple_remove(&hwsim_netgroup_ida, hwsim_net_get_netgroup(net)); ida_simple_remove(&hwsim_netgroup_ida, hwsim_net_get_netgroup(net));
} }
......
...@@ -4852,8 +4852,6 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator); ...@@ -4852,8 +4852,6 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator);
* *
* @alpha2: the ISO/IEC 3166 alpha2 wmm rule to be queried. * @alpha2: the ISO/IEC 3166 alpha2 wmm rule to be queried.
* @freq: the freqency(in MHz) to be queried. * @freq: the freqency(in MHz) to be queried.
* @ptr: pointer where the regdb wmm data is to be stored (or %NULL if
* irrelevant). This can be used later for deduplication.
* @rule: pointer to store the wmm rule from the regulatory db. * @rule: pointer to store the wmm rule from the regulatory db.
* *
* Self-managed wireless drivers can use this function to query * Self-managed wireless drivers can use this function to query
......
...@@ -1756,7 +1756,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, ...@@ -1756,7 +1756,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
if (local->ops->wake_tx_queue && if (local->ops->wake_tx_queue &&
type != NL80211_IFTYPE_AP_VLAN && type != NL80211_IFTYPE_AP_VLAN &&
type != NL80211_IFTYPE_MONITOR) (type != NL80211_IFTYPE_MONITOR ||
(params->flags & MONITOR_FLAG_ACTIVE)))
txq_size += sizeof(struct txq_info) + txq_size += sizeof(struct txq_info) +
local->hw.txq_data_size; local->hw.txq_data_size;
......
...@@ -217,7 +217,8 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); ...@@ -217,7 +217,8 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void); void ieee80211s_init(void);
void ieee80211s_update_metric(struct ieee80211_local *local, void ieee80211s_update_metric(struct ieee80211_local *local,
struct sta_info *sta, struct sk_buff *skb); struct sta_info *sta,
struct ieee80211_tx_status *st);
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
void ieee80211_mesh_teardown_sdata(struct ieee80211_sub_if_data *sdata); void ieee80211_mesh_teardown_sdata(struct ieee80211_sub_if_data *sdata);
int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
......
...@@ -295,15 +295,12 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, ...@@ -295,15 +295,12 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
} }
void ieee80211s_update_metric(struct ieee80211_local *local, void ieee80211s_update_metric(struct ieee80211_local *local,
struct sta_info *sta, struct sk_buff *skb) struct sta_info *sta,
struct ieee80211_tx_status *st)
{ {
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *txinfo = st->info;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
int failed; int failed;
if (!ieee80211_is_data(hdr->frame_control))
return;
failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK); failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
/* moving average, scaled to 100. /* moving average, scaled to 100.
......
...@@ -479,11 +479,6 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local, ...@@ -479,11 +479,6 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
if (!skb) if (!skb)
return; return;
if (dropped) {
dev_kfree_skb_any(skb);
return;
}
if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie; u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie;
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
...@@ -506,6 +501,8 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local, ...@@ -506,6 +501,8 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
} }
rcu_read_unlock(); rcu_read_unlock();
dev_kfree_skb_any(skb);
} else if (dropped) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
} else { } else {
/* consumes skb */ /* consumes skb */
...@@ -811,7 +808,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, ...@@ -811,7 +808,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
rate_control_tx_status(local, sband, status); rate_control_tx_status(local, sband, status);
if (ieee80211_vif_is_mesh(&sta->sdata->vif)) if (ieee80211_vif_is_mesh(&sta->sdata->vif))
ieee80211s_update_metric(local, sta, skb); ieee80211s_update_metric(local, sta, status);
if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked) if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked)
ieee80211_frame_acked(sta, skb); ieee80211_frame_acked(sta, skb);
...@@ -972,6 +969,8 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw, ...@@ -972,6 +969,8 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
} }
rate_control_tx_status(local, sband, status); rate_control_tx_status(local, sband, status);
if (ieee80211_vif_is_mesh(&sta->sdata->vif))
ieee80211s_update_metric(local, sta, status);
} }
if (acked || noack_success) { if (acked || noack_success) {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "ieee80211_i.h" #include "ieee80211_i.h"
#include "driver-ops.h" #include "driver-ops.h"
#include "rate.h" #include "rate.h"
#include "wme.h"
/* give usermode some time for retries in setting up the TDLS session */ /* give usermode some time for retries in setting up the TDLS session */
#define TDLS_PEER_SETUP_TIMEOUT (15 * HZ) #define TDLS_PEER_SETUP_TIMEOUT (15 * HZ)
...@@ -1010,14 +1011,13 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev, ...@@ -1010,14 +1011,13 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
switch (action_code) { switch (action_code) {
case WLAN_TDLS_SETUP_REQUEST: case WLAN_TDLS_SETUP_REQUEST:
case WLAN_TDLS_SETUP_RESPONSE: case WLAN_TDLS_SETUP_RESPONSE:
skb_set_queue_mapping(skb, IEEE80211_AC_BK); skb->priority = 256 + 2;
skb->priority = 2;
break; break;
default: default:
skb_set_queue_mapping(skb, IEEE80211_AC_VI); skb->priority = 256 + 5;
skb->priority = 5;
break; break;
} }
skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
/* /*
* Set the WLAN_TDLS_TEARDOWN flag to indicate a teardown in progress. * Set the WLAN_TDLS_TEARDOWN flag to indicate a teardown in progress.
......
...@@ -214,6 +214,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) ...@@ -214,6 +214,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
{ {
struct ieee80211_local *local = tx->local; struct ieee80211_local *local = tx->local;
struct ieee80211_if_managed *ifmgd; struct ieee80211_if_managed *ifmgd;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
/* driver doesn't support power save */ /* driver doesn't support power save */
if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS)) if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS))
...@@ -242,6 +243,9 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) ...@@ -242,6 +243,9 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
if (tx->sdata->vif.type != NL80211_IFTYPE_STATION) if (tx->sdata->vif.type != NL80211_IFTYPE_STATION)
return TX_CONTINUE; return TX_CONTINUE;
if (unlikely(info->flags & IEEE80211_TX_INTFL_OFFCHAN_TX_OK))
return TX_CONTINUE;
ifmgd = &tx->sdata->u.mgd; ifmgd = &tx->sdata->u.mgd;
/* /*
...@@ -1890,7 +1894,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, ...@@ -1890,7 +1894,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
if (invoke_tx_handlers_early(&tx)) if (invoke_tx_handlers_early(&tx))
return false; return true;
if (ieee80211_queue_skb(local, sdata, tx.sta, tx.skb)) if (ieee80211_queue_skb(local, sdata, tx.sta, tx.skb))
return true; return true;
......
...@@ -3756,6 +3756,7 @@ static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband, ...@@ -3756,6 +3756,7 @@ static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
return false; return false;
/* check availability */ /* check availability */
ridx = array_index_nospec(ridx, IEEE80211_HT_MCS_MASK_LEN);
if (sband->ht_cap.mcs.rx_mask[ridx] & rbit) if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
mcs[ridx] |= rbit; mcs[ridx] |= rbit;
else else
...@@ -10230,7 +10231,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, ...@@ -10230,7 +10231,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
s32 last, low, high; s32 last, low, high;
u32 hyst; u32 hyst;
int i, n; int i, n, low_index;
int err; int err;
/* RSSI reporting disabled? */ /* RSSI reporting disabled? */
...@@ -10267,10 +10268,19 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, ...@@ -10267,10 +10268,19 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
if (last < wdev->cqm_config->rssi_thresholds[i]) if (last < wdev->cqm_config->rssi_thresholds[i])
break; break;
low = i > 0 ? low_index = i - 1;
(wdev->cqm_config->rssi_thresholds[i - 1] - hyst) : S32_MIN; if (low_index >= 0) {
high = i < n ? low_index = array_index_nospec(low_index, n);
(wdev->cqm_config->rssi_thresholds[i] + hyst - 1) : S32_MAX; low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
} else {
low = S32_MIN;
}
if (i < n) {
i = array_index_nospec(i, n);
high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
} else {
high = S32_MAX;
}
return rdev_set_cqm_rssi_range_config(rdev, dev, low, high); return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
} }
......
...@@ -2867,6 +2867,7 @@ static int regulatory_hint_core(const char *alpha2) ...@@ -2867,6 +2867,7 @@ static int regulatory_hint_core(const char *alpha2)
request->alpha2[0] = alpha2[0]; request->alpha2[0] = alpha2[0];
request->alpha2[1] = alpha2[1]; request->alpha2[1] = alpha2[1];
request->initiator = NL80211_REGDOM_SET_BY_CORE; request->initiator = NL80211_REGDOM_SET_BY_CORE;
request->wiphy_idx = WIPHY_IDX_INVALID;
queue_regulatory_request(request); queue_regulatory_request(request);
......
...@@ -1058,13 +1058,23 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, ...@@ -1058,13 +1058,23 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
return NULL; return NULL;
} }
/*
* Update RX channel information based on the available frame payload
* information. This is mainly for the 2.4 GHz band where frames can be received
* from neighboring channels and the Beacon frames use the DSSS Parameter Set
* element to indicate the current (transmitting) channel, but this might also
* be needed on other bands if RX frequency does not match with the actual
* operating channel of a BSS.
*/
static struct ieee80211_channel * static struct ieee80211_channel *
cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
struct ieee80211_channel *channel) struct ieee80211_channel *channel,
enum nl80211_bss_scan_width scan_width)
{ {
const u8 *tmp; const u8 *tmp;
u32 freq; u32 freq;
int channel_number = -1; int channel_number = -1;
struct ieee80211_channel *alt_channel;
tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen); tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen);
if (tmp && tmp[1] == 1) { if (tmp && tmp[1] == 1) {
...@@ -1078,16 +1088,45 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, ...@@ -1078,16 +1088,45 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
} }
} }
if (channel_number < 0) if (channel_number < 0) {
/* No channel information in frame payload */
return channel; return channel;
}
freq = ieee80211_channel_to_frequency(channel_number, channel->band); freq = ieee80211_channel_to_frequency(channel_number, channel->band);
channel = ieee80211_get_channel(wiphy, freq); alt_channel = ieee80211_get_channel(wiphy, freq);
if (!channel) if (!alt_channel) {
return NULL; if (channel->band == NL80211_BAND_2GHZ) {
if (channel->flags & IEEE80211_CHAN_DISABLED) /*
* Better not allow unexpected channels when that could
* be going beyond the 1-11 range (e.g., discovering
* BSS on channel 12 when radio is configured for
* channel 11.
*/
return NULL;
}
/* No match for the payload channel number - ignore it */
return channel;
}
if (scan_width == NL80211_BSS_CHAN_WIDTH_10 ||
scan_width == NL80211_BSS_CHAN_WIDTH_5) {
/*
* Ignore channel number in 5 and 10 MHz channels where there
* may not be an n:1 or 1:n mapping between frequencies and
* channel numbers.
*/
return channel;
}
/*
* Use the channel determined through the payload channel number
* instead of the RX channel reported by the driver.
*/
if (alt_channel->flags & IEEE80211_CHAN_DISABLED)
return NULL; return NULL;
return channel; return alt_channel;
} }
/* Returned bss is reference counted and must be cleaned up appropriately. */ /* Returned bss is reference counted and must be cleaned up appropriately. */
...@@ -1112,7 +1151,8 @@ cfg80211_inform_bss_data(struct wiphy *wiphy, ...@@ -1112,7 +1151,8 @@ cfg80211_inform_bss_data(struct wiphy *wiphy,
(data->signal < 0 || data->signal > 100))) (data->signal < 0 || data->signal > 100)))
return NULL; return NULL;
channel = cfg80211_get_bss_channel(wiphy, ie, ielen, data->chan); channel = cfg80211_get_bss_channel(wiphy, ie, ielen, data->chan,
data->scan_width);
if (!channel) if (!channel)
return NULL; return NULL;
...@@ -1210,7 +1250,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, ...@@ -1210,7 +1250,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
return NULL; return NULL;
channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable,
ielen, data->chan); ielen, data->chan, data->scan_width);
if (!channel) if (!channel)
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment