mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 16:41:58 +00:00
Some fixes for the current cycle:
1. Arik introduced an rtnl-locked regulatory API to be able to differentiate between place do/don't have the RTNL; this fixes missing locking in some of the code paths 2. Two small mesh bugfixes from Bob, one to avoid treating a certain malformed over-the-air frame and one to avoid sending a garbage field over the air. 3. A fix for powersave during WoWLAN suspend from Krishna Chaitanya. 4. A fix for a powersave vs. aggregation teardown race, from Michal. 5. Thomas reduced the loglevel of CRDA messages to avoid spamming the kernel log with mostly irrelevant information. 6. Tom fixed a dangling debugfs directory pointer that could cause crashes if subsequent addition of the same interface to debugfs failed for some reason. 7. A fix from myself for a list corruption issue in mac80211 during combined interface shutdown/removal - shut down interfaces first and only then remove them to avoid that. -----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJVqQMwAAoJEDBSmw7B7bqrZzkQAIjMKojlJRouN/N/aF7ym2pC eAboLMC+XHubQoq2H01k5ZOSrLL1kElhkB7pLas+q00gTFyavLzEcEiFqCNuLwPH lQEwLXTDUeiaVWekOYJev/ONtaDdwUXoB4BPAA3Ih4EAk9fEBtcWiWeLDgOLOS8P eYVqcMV733cOTjhYImEQnhnm3qrcwSCF1vTOJaN4Gf/qqw6j2ilq5wU1TvPyh0TA 1EP5Elb9hy1sud5X6shrsOBqkBrPoO1p3V4EeoHkxl8welqxXdqGvmA3K0sloGZT 7RiL8PD4QVyISy1NrBDnNMRRgj6BD1aLC+clmECmmgYvGGcqbzLtB3CWUCV6oQmb TC4NmgJkKNVTvQnoqxQEL8JYSs/E2ITRKyMi3sfIYAyz1dVuQf1RkZZzB22rQWT2 PaLq/k+vpS7E3OD3XB53flB/k7Y6j/OwJb/rE7i2vqSn3kcbua8H7dzd7p+AE5FA ZF//u2GBDgZeMaA9BvifByWy2+yvAEcD5/U9XkWqJ7t+HohKteLJj/scHT89pto3 n0NZ7RVRMNQ9mz14UJiVnFOL/81AjmiU123S5UIIMkmVE5Zrn7VTZlN6fVY4Fcsh AtxHQesOlCw8T4lFLxgyKkEl7bxATQ2OMR6vWsZQraRHSqIuK8JDABRokIlzoFn/ xC/Yn1vTaBuj+2nif/F0 =US5Y -----END PGP SIGNATURE----- Merge tag 'mac80211-for-davem-2015-07-17' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 Johannes Berg says: ==================== Some fixes for the current cycle: 1. Arik introduced an rtnl-locked regulatory API to be able to differentiate between place do/don't have the RTNL; this fixes missing locking in some of the code paths 2. Two small mesh bugfixes from Bob, one to avoid treating a certain malformed over-the-air frame and one to avoid sending a garbage field over the air. 3. A fix for powersave during WoWLAN suspend from Krishna Chaitanya. 4. A fix for a powersave vs. aggregation teardown race, from Michal. 5. Thomas reduced the loglevel of CRDA messages to avoid spamming the kernel log with mostly irrelevant information. 6. Tom fixed a dangling debugfs directory pointer that could cause crashes if subsequent addition of the same interface to debugfs failed for some reason. 7. A fix from myself for a list corruption issue in mac80211 during combined interface shutdown/removal - shut down interfaces first and only then remove them to avoid that. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
27dfead164
@ -4868,6 +4868,23 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_iftype iftype);
|
||||
|
||||
/**
|
||||
* cfg80211_reg_can_beacon_relax - check if beaconing is allowed with relaxation
|
||||
* @wiphy: the wiphy
|
||||
* @chandef: the channel definition
|
||||
* @iftype: interface type
|
||||
*
|
||||
* Return: %true if there is no secondary channel or the secondary channel(s)
|
||||
* can be used for beaconing (i.e. is not a radar channel etc.). This version
|
||||
* also checks if IR-relaxation conditions apply, to allow beaconing under
|
||||
* more permissive conditions.
|
||||
*
|
||||
* Requires the RTNL to be held.
|
||||
*/
|
||||
bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_iftype iftype);
|
||||
|
||||
/*
|
||||
* cfg80211_ch_switch_notify - update wdev channel and notify userspace
|
||||
* @dev: the device which switched channels
|
||||
|
@ -723,6 +723,7 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
debugfs_remove_recursive(sdata->vif.debugfs_dir);
|
||||
sdata->vif.debugfs_dir = NULL;
|
||||
sdata->debugfs.subdir_stations = NULL;
|
||||
}
|
||||
|
||||
void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
|
||||
|
@ -1863,10 +1863,6 @@ void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata)
|
||||
ieee80211_teardown_sdata(sdata);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all interfaces, may only be called at hardware unregistration
|
||||
* time because it doesn't do RCU-safe list removals.
|
||||
*/
|
||||
void ieee80211_remove_interfaces(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata, *tmp;
|
||||
@ -1875,14 +1871,21 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
/*
|
||||
* Close all AP_VLAN interfaces first, as otherwise they
|
||||
* might be closed while the AP interface they belong to
|
||||
* is closed, causing unregister_netdevice_many() to crash.
|
||||
/* Before destroying the interfaces, make sure they're all stopped so
|
||||
* that the hardware is stopped. Otherwise, the driver might still be
|
||||
* iterating the interfaces during the shutdown, e.g. from a worker
|
||||
* or from RX processing or similar, and if it does so (using atomic
|
||||
* iteration) while we're manipulating the list, the iteration will
|
||||
* crash.
|
||||
*
|
||||
* After this, the hardware should be stopped and the driver should
|
||||
* have stopped all of its activities, so that we can do RCU-unaware
|
||||
* manipulations of the interface list below.
|
||||
*/
|
||||
list_for_each_entry(sdata, &local->interfaces, list)
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
dev_close(sdata->dev);
|
||||
cfg80211_shutdown_all_interfaces(local->hw.wiphy);
|
||||
|
||||
WARN(local->open_count, "%s: open count remains %d\n",
|
||||
wiphy_name(local->hw.wiphy), local->open_count);
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
|
||||
|
@ -306,7 +306,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
|
||||
if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
|
||||
/* AID */
|
||||
pos = skb_put(skb, 2);
|
||||
put_unaligned_le16(plid, pos + 2);
|
||||
put_unaligned_le16(plid, pos);
|
||||
}
|
||||
if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
|
||||
ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
|
||||
@ -1122,6 +1122,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
|
||||
WLAN_SP_MESH_PEERING_CONFIRM) {
|
||||
baseaddr += 4;
|
||||
baselen += 4;
|
||||
|
||||
if (baselen > len)
|
||||
return;
|
||||
}
|
||||
ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems);
|
||||
mesh_process_plink_frame(sdata, mgmt, &elems);
|
||||
|
@ -76,6 +76,22 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
continue;
|
||||
ieee80211_mgd_quiesce(sdata);
|
||||
/* If suspended during TX in progress, and wowlan
|
||||
* is enabled (connection will be active) there
|
||||
* can be a race where the driver is put out
|
||||
* of power-save due to TX and during suspend
|
||||
* dynamic_ps_timer is cancelled and TX packet
|
||||
* is flushed, leaving the driver in ACTIVE even
|
||||
* after resuming until dynamic_ps_timer puts
|
||||
* driver back in DOZE.
|
||||
*/
|
||||
if (sdata->u.mgd.associated &&
|
||||
sdata->u.mgd.powersave &&
|
||||
!(local->hw.conf.flags & IEEE80211_CONF_PS)) {
|
||||
local->hw.conf.flags |= IEEE80211_CONF_PS;
|
||||
ieee80211_hw_config(local,
|
||||
IEEE80211_CONF_CHANGE_PS);
|
||||
}
|
||||
}
|
||||
|
||||
err = drv_suspend(local, wowlan);
|
||||
|
@ -60,6 +60,7 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_channel *ch;
|
||||
struct cfg80211_chan_def chandef;
|
||||
int i, subband_start;
|
||||
struct wiphy *wiphy = sdata->local->hw.wiphy;
|
||||
|
||||
for (i = start; i <= end; i += spacing) {
|
||||
if (!ch_cnt)
|
||||
@ -70,9 +71,8 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata,
|
||||
/* we will be active on the channel */
|
||||
cfg80211_chandef_create(&chandef, ch,
|
||||
NL80211_CHAN_NO_HT);
|
||||
if (cfg80211_reg_can_beacon(sdata->local->hw.wiphy,
|
||||
&chandef,
|
||||
sdata->wdev.iftype)) {
|
||||
if (cfg80211_reg_can_beacon_relax(wiphy, &chandef,
|
||||
sdata->wdev.iftype)) {
|
||||
ch_cnt++;
|
||||
/*
|
||||
* check if the next channel is also part of
|
||||
|
@ -1117,7 +1117,9 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
|
||||
queued = true;
|
||||
info->control.vif = &tx->sdata->vif;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
|
||||
info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS |
|
||||
IEEE80211_TX_CTL_NO_PS_BUFFER |
|
||||
IEEE80211_TX_STATUS_EOSP;
|
||||
__skb_queue_tail(&tid_tx->pending, skb);
|
||||
if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
|
||||
purge_skb = __skb_dequeue(&tid_tx->pending);
|
||||
|
@ -797,23 +797,18 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_iftype iftype)
|
||||
static bool _cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_iftype iftype,
|
||||
bool check_no_ir)
|
||||
{
|
||||
bool res;
|
||||
u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
|
||||
IEEE80211_CHAN_RADAR;
|
||||
|
||||
trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype);
|
||||
trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
|
||||
|
||||
/*
|
||||
* Under certain conditions suggested by some regulatory bodies a
|
||||
* GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag
|
||||
* only if such relaxations are not enabled and the conditions are not
|
||||
* met.
|
||||
*/
|
||||
if (!cfg80211_ir_permissive_chan(wiphy, iftype, chandef->chan))
|
||||
if (check_no_ir)
|
||||
prohibited_flags |= IEEE80211_CHAN_NO_IR;
|
||||
|
||||
if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 &&
|
||||
@ -827,8 +822,36 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||
trace_cfg80211_return_bool(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_iftype iftype)
|
||||
{
|
||||
return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, true);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_reg_can_beacon);
|
||||
|
||||
bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_iftype iftype)
|
||||
{
|
||||
bool check_no_ir;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
/*
|
||||
* Under certain conditions suggested by some regulatory bodies a
|
||||
* GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag
|
||||
* only if such relaxations are not enabled and the conditions are not
|
||||
* met.
|
||||
*/
|
||||
check_no_ir = !cfg80211_ir_permissive_chan(wiphy, iftype,
|
||||
chandef->chan);
|
||||
|
||||
return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_reg_can_beacon_relax);
|
||||
|
||||
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
|
@ -2003,7 +2003,8 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
|
||||
switch (iftype) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, iftype)) {
|
||||
if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
|
||||
iftype)) {
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
@ -3403,8 +3404,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
|
||||
return -EINVAL;
|
||||
|
||||
if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef,
|
||||
wdev->iftype))
|
||||
if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef,
|
||||
wdev->iftype))
|
||||
return -EINVAL;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
|
||||
@ -6492,8 +6493,8 @@ skip_beacons:
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef,
|
||||
wdev->iftype))
|
||||
if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef,
|
||||
wdev->iftype))
|
||||
return -EINVAL;
|
||||
|
||||
err = cfg80211_chandef_dfs_required(wdev->wiphy,
|
||||
@ -10170,7 +10171,8 @@ static int nl80211_tdls_channel_switch(struct sk_buff *skb,
|
||||
return -EINVAL;
|
||||
|
||||
/* we will be active on the TDLS link */
|
||||
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, wdev->iftype))
|
||||
if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
|
||||
wdev->iftype))
|
||||
return -EINVAL;
|
||||
|
||||
/* don't allow switching to DFS channels */
|
||||
|
@ -544,15 +544,15 @@ static int call_crda(const char *alpha2)
|
||||
reg_regdb_query(alpha2);
|
||||
|
||||
if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) {
|
||||
pr_info("Exceeded CRDA call max attempts. Not calling CRDA\n");
|
||||
pr_debug("Exceeded CRDA call max attempts. Not calling CRDA\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!is_world_regdom((char *) alpha2))
|
||||
pr_info("Calling CRDA for country: %c%c\n",
|
||||
pr_debug("Calling CRDA for country: %c%c\n",
|
||||
alpha2[0], alpha2[1]);
|
||||
else
|
||||
pr_info("Calling CRDA to update world regulatory domain\n");
|
||||
pr_debug("Calling CRDA to update world regulatory domain\n");
|
||||
|
||||
return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env);
|
||||
}
|
||||
@ -1589,7 +1589,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
return cfg80211_reg_can_beacon(wiphy, &chandef, iftype);
|
||||
return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
return cfg80211_chandef_usable(wiphy, &chandef,
|
||||
|
@ -2358,20 +2358,23 @@ TRACE_EVENT(cfg80211_cqm_rssi_notify,
|
||||
|
||||
TRACE_EVENT(cfg80211_reg_can_beacon,
|
||||
TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
|
||||
enum nl80211_iftype iftype),
|
||||
TP_ARGS(wiphy, chandef, iftype),
|
||||
enum nl80211_iftype iftype, bool check_no_ir),
|
||||
TP_ARGS(wiphy, chandef, iftype, check_no_ir),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
CHAN_DEF_ENTRY
|
||||
__field(enum nl80211_iftype, iftype)
|
||||
__field(bool, check_no_ir)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
CHAN_DEF_ASSIGN(chandef);
|
||||
__entry->iftype = iftype;
|
||||
__entry->check_no_ir = check_no_ir;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d",
|
||||
WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype)
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d check_no_ir=%s",
|
||||
WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype,
|
||||
BOOL_TO_STR(__entry->check_no_ir))
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_chandef_dfs_required,
|
||||
|
Loading…
Reference in New Issue
Block a user