aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-03-06 15:33:15 -0500
committerDavid S. Miller <davem@davemloft.net>2013-03-06 15:33:15 -0500
commit930df2dfc7073c9ed2d0b47a08e47027ae83c545 (patch)
tree95ee131fb37baac887a824f230ee5f5a1bbeddfc /net
parentc5b3ad4c67989c778e4753be4f91dc7193a04d21 (diff)
parent32cdd592b723fc88ecca699e550197cd48bb4ad6 (diff)
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
John W. Linville says: ==================== This time just passing along a big batch of fixes from Johannes... For the mac80211 bits: "Here I have fixes from Ben Greear for stray work items when deleting interfaces, another idle handling fix from Felix, a fix from Marco ro a mesh PS buffering crash and I have a fix for the VHT MCS calculation in association request frames and more nl80211 feature advertising removal as well as a workaround to increase the dump size if the SKB overhead is too large. For 3.10 I already have a complete fix queued, but that also requires (simple) userspace changes." And for the iwlwifi bits: "The patches from Dor fix a bunch of calibration issues in the new MVM driver, and Emmanuel has a number of fixes there as well. Also, we decided to disable 8k A-MSDU by default, so that's in there. My own patches are addressing an issue we found with the new devices but that seems to also exist on older ones, the DMA writeback the devices do can be delayed and cause issues. The fix is unfortunately relatively large and depends on two other changes (to not be hugely conflicting), but I think it's still worth it at this point." As Johannes says, it is a bit large. But I hope it is still early enough in the cycle to make that worthwhile. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c21
-rw-r--r--net/mac80211/iface.c6
-rw-r--r--net/mac80211/mlme.c28
-rw-r--r--net/mac80211/tx.c3
-rw-r--r--net/wireless/core.c3
-rw-r--r--net/wireless/nl80211.c51
6 files changed, 70 insertions, 42 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 808f5fcd1ce..fb306814576 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3290,14 +3290,19 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
int ret = -ENODATA;
rcu_read_lock();
- if (local->use_chanctx) {
- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (chanctx_conf) {
- *chandef = chanctx_conf->def;
- ret = 0;
- }
- } else if (local->open_count == local->monitors) {
- *chandef = local->monitor_chandef;
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (chanctx_conf) {
+ *chandef = chanctx_conf->def;
+ ret = 0;
+ } else if (local->open_count > 0 &&
+ local->open_count == local->monitors &&
+ sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+ if (local->use_chanctx)
+ *chandef = local->monitor_chandef;
+ else
+ cfg80211_chandef_create(chandef,
+ local->_oper_channel,
+ local->_oper_channel_type);
ret = 0;
}
rcu_read_unlock();
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 640afab304d..baaa8608e52 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -541,6 +541,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
ieee80211_adjust_monitor_flags(sdata, 1);
ieee80211_configure_filter(local);
+ mutex_lock(&local->mtx);
+ ieee80211_recalc_idle(local);
+ mutex_unlock(&local->mtx);
netif_carrier_on(dev);
break;
@@ -812,6 +815,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
ieee80211_adjust_monitor_flags(sdata, -1);
ieee80211_configure_filter(local);
+ mutex_lock(&local->mtx);
+ ieee80211_recalc_idle(local);
+ mutex_unlock(&local->mtx);
break;
case NL80211_IFTYPE_P2P_DEVICE:
/* relies on synchronize_rcu() below */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 9f6464f3e05..141577412d8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -647,6 +647,9 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) &
mask) >> shift;
+ if (our_mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED)
+ continue;
+
switch (ap_mcs) {
default:
if (our_mcs <= ap_mcs)
@@ -3503,6 +3506,14 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
/*
+ * Stop timers before deleting work items, as timers
+ * could race and re-add the work-items. They will be
+ * re-established on connection.
+ */
+ del_timer_sync(&ifmgd->conn_mon_timer);
+ del_timer_sync(&ifmgd->bcn_mon_timer);
+
+ /*
* we need to use atomic bitops for the running bits
* only because both timers might fire at the same
* time -- the code here is properly synchronised.
@@ -3516,13 +3527,9 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
if (del_timer_sync(&ifmgd->timer))
set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
- cancel_work_sync(&ifmgd->chswitch_work);
if (del_timer_sync(&ifmgd->chswitch_timer))
set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
-
- /* these will just be re-established on connection */
- del_timer_sync(&ifmgd->conn_mon_timer);
- del_timer_sync(&ifmgd->bcn_mon_timer);
+ cancel_work_sync(&ifmgd->chswitch_work);
}
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
@@ -4315,6 +4322,17 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ /*
+ * Make sure some work items will not run after this,
+ * they will not do anything but might not have been
+ * cancelled when disconnecting.
+ */
+ cancel_work_sync(&ifmgd->monitor_work);
+ cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+ cancel_work_sync(&ifmgd->request_smps_work);
+ cancel_work_sync(&ifmgd->csa_connection_drop_work);
+ cancel_work_sync(&ifmgd->chswitch_work);
+
mutex_lock(&ifmgd->mtx);
if (ifmgd->assoc_data)
ieee80211_destroy_assoc_data(sdata, false);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ce78d1149f1..8914d2d2881 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2745,7 +2745,8 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
}
- sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
if (!ieee80211_tx_prepare(sdata, &tx, skb))
break;
dev_kfree_skb_any(skb);
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 5ffff039b01..ea4155fe973 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -367,8 +367,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
rdev->wiphy.rts_threshold = (u32) -1;
rdev->wiphy.coverage_class = 0;
- rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH |
- NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
+ rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;
return &rdev->wiphy;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e652d05ff71..d44ab216c0e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -557,18 +557,6 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
if ((chan->flags & IEEE80211_CHAN_RADAR) &&
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
goto nla_put_failure;
- if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
- nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
- goto nla_put_failure;
- if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
- nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
- goto nla_put_failure;
- if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
- nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
- goto nla_put_failure;
- if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
- nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
- goto nla_put_failure;
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
DBM_TO_MBM(chan->max_power)))
@@ -1310,15 +1298,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
dev->wiphy.max_acl_mac_addrs))
goto nla_put_failure;
- if (dev->wiphy.extended_capabilities &&
- (nla_put(msg, NL80211_ATTR_EXT_CAPA,
- dev->wiphy.extended_capabilities_len,
- dev->wiphy.extended_capabilities) ||
- nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
- dev->wiphy.extended_capabilities_len,
- dev->wiphy.extended_capabilities_mask)))
- goto nla_put_failure;
-
return genlmsg_end(msg, hdr);
nla_put_failure:
@@ -1328,7 +1307,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
{
- int idx = 0;
+ int idx = 0, ret;
int start = cb->args[0];
struct cfg80211_registered_device *dev;
@@ -1338,9 +1317,29 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
continue;
if (++idx <= start)
continue;
- if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid,
- cb->nlh->nlmsg_seq, NLM_F_MULTI,
- dev) < 0) {
+ ret = nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq, NLM_F_MULTI,
+ dev);
+ if (ret < 0) {
+ /*
+ * If sending the wiphy data didn't fit (ENOBUFS or
+ * EMSGSIZE returned), this SKB is still empty (so
+ * it's not too big because another wiphy dataset is
+ * already in the skb) and we've not tried to adjust
+ * the dump allocation yet ... then adjust the alloc
+ * size to be bigger, and return 1 but with the empty
+ * skb. This results in an empty message being RX'ed
+ * in userspace, but that is ignored.
+ *
+ * We can then retry with the larger buffer.
+ */
+ if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
+ !skb->len &&
+ cb->min_dump_alloc < 4096) {
+ cb->min_dump_alloc = 4096;
+ mutex_unlock(&cfg80211_mutex);
+ return 1;
+ }
idx--;
break;
}
@@ -1357,7 +1356,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
struct sk_buff *msg;
struct cfg80211_registered_device *dev = info->user_ptr[0];
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ msg = nlmsg_new(4096, GFP_KERNEL);
if (!msg)
return -ENOMEM;