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 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAlusvBUACgkQB8qZga/f l8RGlg/+LeQVHh62PJcawXxxa7UyxBhapgkrXC/Np8hnd39xUL41SNMz2wIt7snu W2iY+5DOJZ9UyrVL70hMZ26lOLonoafhRdH0utQX3U13iD+3g35Xrps/NETlZxcy QftxstUeh9ojdKcOmTtOlHt3PkLCSVa6kS6TsfFGXnMeAgpbmBlPpJQhsCf1x2M4 ZBUn92sdQu4c8goFUIj8XhgccJbIuAi9pOgQDOE7EXTrxq+Y1SBl1qYCH1bjOkPd O5lvV74Sr1SPWfWE6IgUPyRGTEjrImfKm5M/1aegcQ6KRk3LZYtNfjxcrRQg9uzA 5FMO6zNpu5EEyspS18F1F/9cLo5meqVW4A+Qr6FQ8NwAJ7O31CerEFHUwSHtLfgL EjMuWfoKbFaj8YOeShdR3N305Eitc5/uF4m+FVee1tig3GnmUEFzNB0ngMqwFmed esHbLlVPDYqoKzN7wZYFB/rTDcQxtcHX8m1SQfMqRgmLVkfKS1AUHk0kql++pivW ZzNlePz3gzacurTeU8FqktxXQfdB8CRyeLqKapTE+3mY9HgYZxnKz1wV6lyoMGiM yfn0FjsRaYgNXeB0hJ8J6w/+DJWRwahVyas1QbCZKjcY9A67LRpiRlUwEGVGtu/j OaNWDFLPVkERYNg/7qhMym5h0RyvcBumYd9TVzwupnTiV3T1ScY= =ySdv -----END PGP SIGNATURE----- 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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
05c5e9ff22
|
@ -520,7 +520,6 @@ struct mac80211_hwsim_data {
|
|||
int channels, idx;
|
||||
bool use_chanctx;
|
||||
bool destroy_on_close;
|
||||
struct work_struct destroy_work;
|
||||
u32 portid;
|
||||
char alpha2[2];
|
||||
const struct ieee80211_regdomain *regd;
|
||||
|
@ -2935,8 +2934,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
|||
hwsim_radios_generation++;
|
||||
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;
|
||||
|
||||
|
@ -3565,30 +3563,27 @@ static struct genl_family hwsim_genl_family __ro_after_init = {
|
|||
.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)
|
||||
{
|
||||
struct mac80211_hwsim_data *entry, *tmp;
|
||||
LIST_HEAD(list);
|
||||
|
||||
spin_lock_bh(&hwsim_radio_lock);
|
||||
list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) {
|
||||
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,
|
||||
hwsim_rht_params);
|
||||
INIT_WORK(&entry->destroy_work, destroy_radio);
|
||||
queue_work(hwsim_wq, &entry->destroy_work);
|
||||
hwsim_radios_generation++;
|
||||
}
|
||||
}
|
||||
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,
|
||||
|
@ -3646,6 +3641,7 @@ static __net_init int hwsim_init_net(struct net *net)
|
|||
static void __net_exit hwsim_exit_net(struct net *net)
|
||||
{
|
||||
struct mac80211_hwsim_data *data, *tmp;
|
||||
LIST_HEAD(list);
|
||||
|
||||
spin_lock_bh(&hwsim_radio_lock);
|
||||
list_for_each_entry_safe(data, tmp, &hwsim_radios, list) {
|
||||
|
@ -3656,17 +3652,19 @@ static void __net_exit hwsim_exit_net(struct net *net)
|
|||
if (data->netgroup == hwsim_net_get_netgroup(&init_net))
|
||||
continue;
|
||||
|
||||
list_del(&data->list);
|
||||
list_move(&data->list, &list);
|
||||
rhashtable_remove_fast(&hwsim_radios_rht, &data->rht,
|
||||
hwsim_rht_params);
|
||||
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,
|
||||
wiphy_name(data->hw->wiphy),
|
||||
NULL);
|
||||
spin_lock_bh(&hwsim_radio_lock);
|
||||
}
|
||||
spin_unlock_bh(&hwsim_radio_lock);
|
||||
|
||||
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);
|
|||
*
|
||||
* @alpha2: the ISO/IEC 3166 alpha2 wmm rule 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.
|
||||
*
|
||||
* 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,
|
|||
|
||||
if (local->ops->wake_tx_queue &&
|
||||
type != NL80211_IFTYPE_AP_VLAN &&
|
||||
type != NL80211_IFTYPE_MONITOR)
|
||||
(type != NL80211_IFTYPE_MONITOR ||
|
||||
(params->flags & MONITOR_FLAG_ACTIVE)))
|
||||
txq_size += sizeof(struct txq_info) +
|
||||
local->hw.txq_data_size;
|
||||
|
||||
|
|
|
@ -217,7 +217,8 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
|
|||
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211s_init(void);
|
||||
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_teardown_sdata(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,
|
|||
}
|
||||
|
||||
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_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_tx_info *txinfo = st->info;
|
||||
int failed;
|
||||
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
return;
|
||||
|
||||
failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
|
||||
|
||||
/* moving average, scaled to 100.
|
||||
|
|
|
@ -479,11 +479,6 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
|
|||
if (!skb)
|
||||
return;
|
||||
|
||||
if (dropped) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
|
||||
u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
@ -506,6 +501,8 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local,
|
|||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
} else if (dropped) {
|
||||
dev_kfree_skb_any(skb);
|
||||
} else {
|
||||
/* consumes skb */
|
||||
|
@ -811,7 +808,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
|
|||
|
||||
rate_control_tx_status(local, sband, status);
|
||||
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)
|
||||
ieee80211_frame_acked(sta, skb);
|
||||
|
@ -972,6 +969,8 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "ieee80211_i.h"
|
||||
#include "driver-ops.h"
|
||||
#include "rate.h"
|
||||
#include "wme.h"
|
||||
|
||||
/* give usermode some time for retries in setting up the TDLS session */
|
||||
#define TDLS_PEER_SETUP_TIMEOUT (15 * HZ)
|
||||
|
@ -1010,14 +1011,13 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
|
|||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
skb_set_queue_mapping(skb, IEEE80211_AC_BK);
|
||||
skb->priority = 2;
|
||||
skb->priority = 256 + 2;
|
||||
break;
|
||||
default:
|
||||
skb_set_queue_mapping(skb, IEEE80211_AC_VI);
|
||||
skb->priority = 5;
|
||||
skb->priority = 256 + 5;
|
||||
break;
|
||||
}
|
||||
skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
|
||||
|
||||
/*
|
||||
* 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)
|
|||
{
|
||||
struct ieee80211_local *local = tx->local;
|
||||
struct ieee80211_if_managed *ifmgd;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
|
||||
|
||||
/* driver doesn't support power save */
|
||||
if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS))
|
||||
|
@ -242,6 +243,9 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
|
|||
if (tx->sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
return TX_CONTINUE;
|
||||
|
||||
if (unlikely(info->flags & IEEE80211_TX_INTFL_OFFCHAN_TX_OK))
|
||||
return TX_CONTINUE;
|
||||
|
||||
ifmgd = &tx->sdata->u.mgd;
|
||||
|
||||
/*
|
||||
|
@ -1890,7 +1894,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
|
|||
sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
|
||||
|
||||
if (invoke_tx_handlers_early(&tx))
|
||||
return false;
|
||||
return true;
|
||||
|
||||
if (ieee80211_queue_skb(local, sdata, tx.sta, tx.skb))
|
||||
return true;
|
||||
|
|
|
@ -3756,6 +3756,7 @@ static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
|
|||
return false;
|
||||
|
||||
/* check availability */
|
||||
ridx = array_index_nospec(ridx, IEEE80211_HT_MCS_MASK_LEN);
|
||||
if (sband->ht_cap.mcs.rx_mask[ridx] & rbit)
|
||||
mcs[ridx] |= rbit;
|
||||
else
|
||||
|
@ -10230,7 +10231,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
|
|||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
s32 last, low, high;
|
||||
u32 hyst;
|
||||
int i, n;
|
||||
int i, n, low_index;
|
||||
int err;
|
||||
|
||||
/* RSSI reporting disabled? */
|
||||
|
@ -10267,10 +10268,19 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
|
|||
if (last < wdev->cqm_config->rssi_thresholds[i])
|
||||
break;
|
||||
|
||||
low = i > 0 ?
|
||||
(wdev->cqm_config->rssi_thresholds[i - 1] - hyst) : S32_MIN;
|
||||
high = i < n ?
|
||||
(wdev->cqm_config->rssi_thresholds[i] + hyst - 1) : S32_MAX;
|
||||
low_index = i - 1;
|
||||
if (low_index >= 0) {
|
||||
low_index = array_index_nospec(low_index, n);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -2867,6 +2867,7 @@ static int regulatory_hint_core(const char *alpha2)
|
|||
request->alpha2[0] = alpha2[0];
|
||||
request->alpha2[1] = alpha2[1];
|
||||
request->initiator = NL80211_REGDOM_SET_BY_CORE;
|
||||
request->wiphy_idx = WIPHY_IDX_INVALID;
|
||||
|
||||
queue_regulatory_request(request);
|
||||
|
||||
|
|
|
@ -1058,13 +1058,23 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
|
|||
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 *
|
||||
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;
|
||||
u32 freq;
|
||||
int channel_number = -1;
|
||||
struct ieee80211_channel *alt_channel;
|
||||
|
||||
tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen);
|
||||
if (tmp && tmp[1] == 1) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
freq = ieee80211_channel_to_frequency(channel_number, channel->band);
|
||||
channel = ieee80211_get_channel(wiphy, freq);
|
||||
if (!channel)
|
||||
alt_channel = ieee80211_get_channel(wiphy, freq);
|
||||
if (!alt_channel) {
|
||||
if (channel->band == NL80211_BAND_2GHZ) {
|
||||
/*
|
||||
* 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;
|
||||
if (channel->flags & IEEE80211_CHAN_DISABLED)
|
||||
return NULL;
|
||||
return channel;
|
||||
return alt_channel;
|
||||
}
|
||||
|
||||
/* Returned bss is reference counted and must be cleaned up appropriately. */
|
||||
|
@ -1112,7 +1151,8 @@ cfg80211_inform_bss_data(struct wiphy *wiphy,
|
|||
(data->signal < 0 || data->signal > 100)))
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
|
@ -1210,7 +1250,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
|
|||
return NULL;
|
||||
|
||||
channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable,
|
||||
ielen, data->chan);
|
||||
ielen, data->chan, data->scan_width);
|
||||
if (!channel)
|
||||
return NULL;
|
||||
|
||||
|
|
Loading…
Reference in New Issue