Merge remote-tracking branch 'mac80211/master' into HEAD
There are a few things that would otherwise conflict. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
commit
c0f3a317f2
6 changed files with 120 additions and 120 deletions
|
@ -3285,6 +3285,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
|
||||||
struct cfg80211_chan_def *chandef)
|
struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||||
|
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
int ret = -ENODATA;
|
int ret = -ENODATA;
|
||||||
|
|
||||||
|
@ -3293,6 +3294,16 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
|
||||||
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 &&
|
||||||
|
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();
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
|
||||||
|
|
||||||
lockdep_assert_held(&local->mtx);
|
lockdep_assert_held(&local->mtx);
|
||||||
|
|
||||||
active = !list_empty(&local->chanctx_list);
|
active = !list_empty(&local->chanctx_list) || local->monitors;
|
||||||
|
|
||||||
if (!local->ops->remain_on_channel) {
|
if (!local->ops->remain_on_channel) {
|
||||||
list_for_each_entry(roc, &local->roc_list, list) {
|
list_for_each_entry(roc, &local->roc_list, list) {
|
||||||
|
@ -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,
|
||||||
|
|
||||||
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,
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
|
@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
|
||||||
if (local->queue_stop_reasons[q] ||
|
if (local->queue_stop_reasons[q] ||
|
||||||
(!txpending && !skb_queue_empty(&local->pending[q]))) {
|
(!txpending && !skb_queue_empty(&local->pending[q]))) {
|
||||||
if (unlikely(info->flags &
|
if (unlikely(info->flags &
|
||||||
IEEE80211_TX_INTFL_OFFCHAN_TX_OK &&
|
IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
|
||||||
local->queue_stop_reasons[q] &
|
if (local->queue_stop_reasons[q] &
|
||||||
~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) {
|
~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
|
||||||
|
/*
|
||||||
|
* Drop off-channel frames if queues
|
||||||
|
* are stopped for any reason other
|
||||||
|
* than off-channel operation. Never
|
||||||
|
* queue them.
|
||||||
|
*/
|
||||||
|
spin_unlock_irqrestore(
|
||||||
|
&local->queue_stop_reason_lock,
|
||||||
|
flags);
|
||||||
|
ieee80211_purge_tx_queue(&local->hw,
|
||||||
|
skbs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drop off-channel frames if queues are stopped
|
* Since queue is stopped, queue up frames for
|
||||||
* for any reason other than off-channel
|
* later transmission from the tx-pending
|
||||||
* operation. Never queue them.
|
* tasklet when the queue is woken again.
|
||||||
*/
|
*/
|
||||||
spin_unlock_irqrestore(
|
if (txpending)
|
||||||
&local->queue_stop_reason_lock, flags);
|
skb_queue_splice_init(skbs,
|
||||||
ieee80211_purge_tx_queue(&local->hw, skbs);
|
&local->pending[q]);
|
||||||
return true;
|
else
|
||||||
|
skb_queue_splice_tail_init(skbs,
|
||||||
|
&local->pending[q]);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&local->queue_stop_reason_lock,
|
||||||
|
flags);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Since queue is stopped, queue up frames for later
|
|
||||||
* transmission from the tx-pending tasklet when the
|
|
||||||
* queue is woken again.
|
|
||||||
*/
|
|
||||||
if (txpending)
|
|
||||||
skb_queue_splice_init(skbs, &local->pending[q]);
|
|
||||||
else
|
|
||||||
skb_queue_splice_tail_init(skbs,
|
|
||||||
&local->pending[q]);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock,
|
|
||||||
flags);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||||
|
|
||||||
|
@ -1844,9 +1850,24 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_multicast_ether_addr(skb->data)) {
|
if (!is_multicast_ether_addr(skb->data)) {
|
||||||
|
struct sta_info *next_hop;
|
||||||
|
bool mpp_lookup = true;
|
||||||
|
|
||||||
mpath = mesh_path_lookup(sdata, skb->data);
|
mpath = mesh_path_lookup(sdata, skb->data);
|
||||||
if (!mpath)
|
if (mpath) {
|
||||||
|
mpp_lookup = false;
|
||||||
|
next_hop = rcu_dereference(mpath->next_hop);
|
||||||
|
if (!next_hop ||
|
||||||
|
!(mpath->flags & (MESH_PATH_ACTIVE |
|
||||||
|
MESH_PATH_RESOLVING)))
|
||||||
|
mpp_lookup = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mpp_lookup)
|
||||||
mppath = mpp_path_lookup(sdata, skb->data);
|
mppath = mpp_path_lookup(sdata, skb->data);
|
||||||
|
|
||||||
|
if (mppath && mpath)
|
||||||
|
mesh_path_del(mpath->sdata, mpath->dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2350,9 +2371,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
|
||||||
if (local->tim_in_locked_section) {
|
if (local->tim_in_locked_section) {
|
||||||
__ieee80211_beacon_add_tim(sdata, ps, skb);
|
__ieee80211_beacon_add_tim(sdata, ps, skb);
|
||||||
} else {
|
} else {
|
||||||
spin_lock(&local->tim_lock);
|
spin_lock_bh(&local->tim_lock);
|
||||||
__ieee80211_beacon_add_tim(sdata, ps, skb);
|
__ieee80211_beacon_add_tim(sdata, ps, skb);
|
||||||
spin_unlock(&local->tim_lock);
|
spin_unlock_bh(&local->tim_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2724,7 +2745,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)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -554,27 +554,8 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
|
||||||
if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
|
if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
|
||||||
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))
|
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
if (chan->flags & IEEE80211_CHAN_RADAR) {
|
if ((chan->flags & IEEE80211_CHAN_RADAR) &&
|
||||||
u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered);
|
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
|
||||||
if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
|
|
||||||
goto nla_put_failure;
|
|
||||||
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE,
|
|
||||||
chan->dfs_state))
|
|
||||||
goto nla_put_failure;
|
|
||||||
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time))
|
|
||||||
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;
|
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,
|
||||||
|
@ -900,9 +881,6 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
|
||||||
nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
|
nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
|
||||||
c->max_interfaces))
|
c->max_interfaces))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
|
|
||||||
c->radar_detect_widths))
|
|
||||||
goto nla_put_failure;
|
|
||||||
|
|
||||||
nla_nest_end(msg, nl_combi);
|
nla_nest_end(msg, nl_combi);
|
||||||
}
|
}
|
||||||
|
@ -914,48 +892,6 @@ nla_put_failure:
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
|
||||||
static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev,
|
|
||||||
struct sk_buff *msg)
|
|
||||||
{
|
|
||||||
const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp;
|
|
||||||
struct nlattr *nl_tcp;
|
|
||||||
|
|
||||||
if (!tcp)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
|
|
||||||
if (!nl_tcp)
|
|
||||||
return -ENOBUFS;
|
|
||||||
|
|
||||||
if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
|
|
||||||
tcp->data_payload_max))
|
|
||||||
return -ENOBUFS;
|
|
||||||
|
|
||||||
if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD,
|
|
||||||
tcp->data_payload_max))
|
|
||||||
return -ENOBUFS;
|
|
||||||
|
|
||||||
if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ))
|
|
||||||
return -ENOBUFS;
|
|
||||||
|
|
||||||
if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
|
|
||||||
sizeof(*tcp->tok), tcp->tok))
|
|
||||||
return -ENOBUFS;
|
|
||||||
|
|
||||||
if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
|
|
||||||
tcp->data_interval_max))
|
|
||||||
return -ENOBUFS;
|
|
||||||
|
|
||||||
if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
|
|
||||||
tcp->wake_payload_max))
|
|
||||||
return -ENOBUFS;
|
|
||||||
|
|
||||||
nla_nest_end(msg, nl_tcp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags,
|
static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags,
|
||||||
struct cfg80211_registered_device *dev)
|
struct cfg80211_registered_device *dev)
|
||||||
{
|
{
|
||||||
|
@ -1330,9 +1266,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nl80211_send_wowlan_tcp_caps(dev, msg))
|
|
||||||
goto nla_put_failure;
|
|
||||||
|
|
||||||
nla_nest_end(msg, nl_wowlan);
|
nla_nest_end(msg, nl_wowlan);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1365,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:
|
||||||
|
@ -1383,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;
|
||||||
|
|
||||||
|
@ -1393,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;
|
||||||
}
|
}
|
||||||
|
@ -1412,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;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue