Commit 5ba0eb4a authored by John W. Linville's avatar John W. Linville
parents 46602698 801d929c
...@@ -3290,14 +3290,19 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, ...@@ -3290,14 +3290,19 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
int ret = -ENODATA; int ret = -ENODATA;
rcu_read_lock(); rcu_read_lock();
if (local->use_chanctx) { chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (chanctx_conf) {
if (chanctx_conf) { *chandef = chanctx_conf->def;
*chandef = chanctx_conf->def; ret = 0;
ret = 0; } else if (local->open_count > 0 &&
} local->open_count == local->monitors &&
} else if (local->open_count == local->monitors) { sdata->vif.type == NL80211_IFTYPE_MONITOR) {
*chandef = local->monitor_chandef; if (local->use_chanctx)
*chandef = local->monitor_chandef;
else
cfg80211_chandef_create(chandef,
local->_oper_channel,
local->_oper_channel_type);
ret = 0; ret = 0;
} }
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -541,6 +541,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) ...@@ -541,6 +541,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
ieee80211_adjust_monitor_flags(sdata, 1); ieee80211_adjust_monitor_flags(sdata, 1);
ieee80211_configure_filter(local); ieee80211_configure_filter(local);
mutex_lock(&local->mtx);
ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx);
netif_carrier_on(dev); netif_carrier_on(dev);
break; break;
...@@ -812,6 +815,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ...@@ -812,6 +815,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
ieee80211_adjust_monitor_flags(sdata, -1); ieee80211_adjust_monitor_flags(sdata, -1);
ieee80211_configure_filter(local); ieee80211_configure_filter(local);
mutex_lock(&local->mtx);
ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx);
break; break;
case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_P2P_DEVICE:
/* relies on synchronize_rcu() below */ /* relies on synchronize_rcu() below */
......
...@@ -647,6 +647,9 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, ...@@ -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) & our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) &
mask) >> shift; mask) >> shift;
if (our_mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED)
continue;
switch (ap_mcs) { switch (ap_mcs) {
default: default:
if (our_mcs <= ap_mcs) if (our_mcs <= ap_mcs)
...@@ -3502,6 +3505,14 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) ...@@ -3502,6 +3505,14 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 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 * we need to use atomic bitops for the running bits
* only because both timers might fire at the same * only because both timers might fire at the same
...@@ -3516,13 +3527,9 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) ...@@ -3516,13 +3527,9 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
if (del_timer_sync(&ifmgd->timer)) if (del_timer_sync(&ifmgd->timer))
set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
cancel_work_sync(&ifmgd->chswitch_work);
if (del_timer_sync(&ifmgd->chswitch_timer)) if (del_timer_sync(&ifmgd->chswitch_timer))
set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
cancel_work_sync(&ifmgd->chswitch_work);
/* these will just be re-established on connection */
del_timer_sync(&ifmgd->conn_mon_timer);
del_timer_sync(&ifmgd->bcn_mon_timer);
} }
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
...@@ -4315,6 +4322,17 @@ void ieee80211_mgd_stop(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; 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); mutex_lock(&ifmgd->mtx);
if (ifmgd->assoc_data) if (ifmgd->assoc_data)
ieee80211_destroy_assoc_data(sdata, false); ieee80211_destroy_assoc_data(sdata, false);
......
...@@ -2755,7 +2755,8 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, ...@@ -2755,7 +2755,8 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
cpu_to_le16(IEEE80211_FCTL_MOREDATA); 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)) if (!ieee80211_tx_prepare(sdata, &tx, skb))
break; break;
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
......
...@@ -367,8 +367,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) ...@@ -367,8 +367,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
rdev->wiphy.rts_threshold = (u32) -1; rdev->wiphy.rts_threshold = (u32) -1;
rdev->wiphy.coverage_class = 0; rdev->wiphy.coverage_class = 0;
rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH | rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;
NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
return &rdev->wiphy; return &rdev->wiphy;
} }
......
...@@ -557,18 +557,6 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, ...@@ -557,18 +557,6 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
if ((chan->flags & IEEE80211_CHAN_RADAR) && if ((chan->flags & IEEE80211_CHAN_RADAR) &&
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
goto nla_put_failure; 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, if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
DBM_TO_MBM(chan->max_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 ...@@ -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)) dev->wiphy.max_acl_mac_addrs))
goto nla_put_failure; 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); return genlmsg_end(msg, hdr);
nla_put_failure: nla_put_failure:
...@@ -1328,7 +1307,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag ...@@ -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) 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]; int start = cb->args[0];
struct cfg80211_registered_device *dev; struct cfg80211_registered_device *dev;
...@@ -1338,9 +1317,29 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1338,9 +1317,29 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
continue; continue;
if (++idx <= start) if (++idx <= start)
continue; continue;
if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid, ret = nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh->nlmsg_seq, NLM_F_MULTI,
dev) < 0) { 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--; idx--;
break; break;
} }
...@@ -1357,7 +1356,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) ...@@ -1357,7 +1356,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
struct sk_buff *msg; struct sk_buff *msg;
struct cfg80211_registered_device *dev = info->user_ptr[0]; 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) if (!msg)
return -ENOMEM; return -ENOMEM;
......
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