Merge git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
This commit is contained in:
commit
737be10d8c
|
@ -1711,6 +1711,7 @@ enum ieee80211_eid {
|
|||
WLAN_EID_RRM_ENABLED_CAPABILITIES = 70,
|
||||
WLAN_EID_MULTIPLE_BSSID = 71,
|
||||
WLAN_EID_BSS_COEX_2040 = 72,
|
||||
WLAN_EID_BSS_INTOLERANT_CHL_REPORT = 73,
|
||||
WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74,
|
||||
WLAN_EID_RIC_DESCRIPTOR = 75,
|
||||
WLAN_EID_MMIE = 76,
|
||||
|
|
|
@ -188,6 +188,43 @@ struct ieee80211_chanctx_conf {
|
|||
u8 drv_priv[0] __aligned(sizeof(void *));
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ieee80211_chanctx_switch_mode - channel context switch mode
|
||||
* @CHANCTX_SWMODE_REASSIGN_VIF: Both old and new contexts already
|
||||
* exist (and will continue to exist), but the virtual interface
|
||||
* needs to be switched from one to the other.
|
||||
* @CHANCTX_SWMODE_SWAP_CONTEXTS: The old context exists but will stop
|
||||
* to exist with this call, the new context doesn't exist but
|
||||
* will be active after this call, the virtual interface switches
|
||||
* from the old to the new (note that the driver may of course
|
||||
* implement this as an on-the-fly chandef switch of the existing
|
||||
* hardware context, but the mac80211 pointer for the old context
|
||||
* will cease to exist and only the new one will later be used
|
||||
* for changes/removal.)
|
||||
*/
|
||||
enum ieee80211_chanctx_switch_mode {
|
||||
CHANCTX_SWMODE_REASSIGN_VIF,
|
||||
CHANCTX_SWMODE_SWAP_CONTEXTS,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ieee80211_vif_chanctx_switch - vif chanctx switch information
|
||||
*
|
||||
* This is structure is used to pass information about a vif that
|
||||
* needs to switch from one chanctx to another. The
|
||||
* &ieee80211_chanctx_switch_mode defines how the switch should be
|
||||
* done.
|
||||
*
|
||||
* @vif: the vif that should be switched from old_ctx to new_ctx
|
||||
* @old_ctx: the old context to which the vif was assigned
|
||||
* @new_ctx: the new context to which the vif must be assigned
|
||||
*/
|
||||
struct ieee80211_vif_chanctx_switch {
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_chanctx_conf *old_ctx;
|
||||
struct ieee80211_chanctx_conf *new_ctx;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ieee80211_bss_change - BSS change notification flags
|
||||
*
|
||||
|
@ -2736,6 +2773,11 @@ enum ieee80211_roc_type {
|
|||
* to vif. Possible use is for hw queue remapping.
|
||||
* @unassign_vif_chanctx: Notifies device driver about channel context being
|
||||
* unbound from vif.
|
||||
* @switch_vif_chanctx: switch a number of vifs from one chanctx to
|
||||
* another, as specified in the list of
|
||||
* @ieee80211_vif_chanctx_switch passed to the driver, according
|
||||
* to the mode defined in &ieee80211_chanctx_switch_mode.
|
||||
*
|
||||
* @start_ap: Start operation on the AP interface, this is called after all the
|
||||
* information in bss_conf is set and beacon can be retrieved. A channel
|
||||
* context is bound before this is called. Note that if the driver uses
|
||||
|
@ -2952,6 +2994,10 @@ struct ieee80211_ops {
|
|||
void (*unassign_vif_chanctx)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
int (*switch_vif_chanctx)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif_chanctx_switch *vifs,
|
||||
int n_vifs,
|
||||
enum ieee80211_chanctx_switch_mode mode);
|
||||
|
||||
void (*restart_complete)(struct ieee80211_hw *hw);
|
||||
|
||||
|
|
|
@ -34,8 +34,7 @@ static ssize_t ieee80211_if_read(
|
|||
ssize_t ret = -EINVAL;
|
||||
|
||||
read_lock(&dev_base_lock);
|
||||
if (sdata->dev->reg_state == NETREG_REGISTERED)
|
||||
ret = (*format)(sdata, buf, sizeof(buf));
|
||||
ret = (*format)(sdata, buf, sizeof(buf));
|
||||
read_unlock(&dev_base_lock);
|
||||
|
||||
if (ret >= 0)
|
||||
|
@ -62,8 +61,7 @@ static ssize_t ieee80211_if_write(
|
|||
|
||||
ret = -ENODEV;
|
||||
rtnl_lock();
|
||||
if (sdata->dev->reg_state == NETREG_REGISTERED)
|
||||
ret = (*write)(sdata, buf, count);
|
||||
ret = (*write)(sdata, buf, count);
|
||||
rtnl_unlock();
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -1048,6 +1048,59 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
|
|||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
static inline int
|
||||
drv_switch_vif_chanctx(struct ieee80211_local *local,
|
||||
struct ieee80211_vif_chanctx_switch *vifs,
|
||||
int n_vifs,
|
||||
enum ieee80211_chanctx_switch_mode mode)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
if (!local->ops->switch_vif_chanctx)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
struct ieee80211_chanctx *new_ctx =
|
||||
container_of(vifs[i].new_ctx,
|
||||
struct ieee80211_chanctx,
|
||||
conf);
|
||||
struct ieee80211_chanctx *old_ctx =
|
||||
container_of(vifs[i].old_ctx,
|
||||
struct ieee80211_chanctx,
|
||||
conf);
|
||||
|
||||
WARN_ON_ONCE(!old_ctx->driver_present);
|
||||
WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS &&
|
||||
new_ctx->driver_present) ||
|
||||
(mode == CHANCTX_SWMODE_REASSIGN_VIF &&
|
||||
!new_ctx->driver_present));
|
||||
}
|
||||
|
||||
trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode);
|
||||
ret = local->ops->switch_vif_chanctx(&local->hw,
|
||||
vifs, n_vifs, mode);
|
||||
trace_drv_return_int(local, ret);
|
||||
|
||||
if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) {
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
struct ieee80211_chanctx *new_ctx =
|
||||
container_of(vifs[i].new_ctx,
|
||||
struct ieee80211_chanctx,
|
||||
conf);
|
||||
struct ieee80211_chanctx *old_ctx =
|
||||
container_of(vifs[i].old_ctx,
|
||||
struct ieee80211_chanctx,
|
||||
conf);
|
||||
|
||||
new_ctx->driver_present = true;
|
||||
old_ctx->driver_present = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int drv_start_ap(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
|
|
|
@ -1677,6 +1677,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
|||
sdata->u.ibss.control_port = params->control_port;
|
||||
sdata->u.ibss.userspace_handles_dfs = params->userspace_handles_dfs;
|
||||
sdata->u.ibss.basic_rates = params->basic_rates;
|
||||
sdata->u.ibss.last_scan_completed = jiffies;
|
||||
|
||||
/* fix basic_rates if channel does not support these rates */
|
||||
rate_flags = ieee80211_chandef_rate_flags(¶ms->chandef);
|
||||
|
|
|
@ -399,6 +399,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
|||
sdata->vif.type = NL80211_IFTYPE_MONITOR;
|
||||
snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
|
||||
wiphy_name(local->hw.wiphy));
|
||||
sdata->wdev.iftype = NL80211_IFTYPE_MONITOR;
|
||||
|
||||
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||
|
||||
|
@ -1285,6 +1286,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
|
|||
sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
|
||||
sdata->control_port_no_encrypt = false;
|
||||
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||
sdata->vif.bss_conf.idle = true;
|
||||
|
||||
sdata->noack_map = 0;
|
||||
|
||||
|
|
|
@ -240,6 +240,7 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
|
|||
|
||||
sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
|
||||
|
||||
kfree(rcu_dereference_raw(sta->sta.rates));
|
||||
kfree(sta);
|
||||
}
|
||||
|
||||
|
|
|
@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local,
|
|||
*/
|
||||
#define STA_LOST_PKT_THRESHOLD 50
|
||||
|
||||
static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
/* This packet was aggregated but doesn't carry status info */
|
||||
if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
|
||||
!(info->flags & IEEE80211_TX_STAT_AMPDU))
|
||||
return;
|
||||
|
||||
if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
|
||||
return;
|
||||
|
||||
cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
|
||||
sta->lost_packets, GFP_ATOMIC);
|
||||
sta->lost_packets = 0;
|
||||
}
|
||||
|
||||
void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *skb2;
|
||||
|
@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
if (info->flags & IEEE80211_TX_STAT_ACK) {
|
||||
if (sta->lost_packets)
|
||||
sta->lost_packets = 0;
|
||||
} else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
|
||||
cfg80211_cqm_pktloss_notify(sta->sdata->dev,
|
||||
sta->sta.addr,
|
||||
sta->lost_packets,
|
||||
GFP_ATOMIC);
|
||||
sta->lost_packets = 0;
|
||||
} else {
|
||||
ieee80211_lost_packet(sta, skb);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1389,6 +1389,91 @@ TRACE_EVENT(drv_change_chanctx,
|
|||
)
|
||||
);
|
||||
|
||||
#if !defined(__TRACE_VIF_ENTRY)
|
||||
#define __TRACE_VIF_ENTRY
|
||||
struct trace_vif_entry {
|
||||
enum nl80211_iftype vif_type;
|
||||
bool p2p;
|
||||
char vif_name[IFNAMSIZ];
|
||||
} __packed;
|
||||
|
||||
struct trace_chandef_entry {
|
||||
u32 control_freq;
|
||||
u32 chan_width;
|
||||
u32 center_freq1;
|
||||
u32 center_freq2;
|
||||
} __packed;
|
||||
|
||||
struct trace_switch_entry {
|
||||
struct trace_vif_entry vif;
|
||||
struct trace_chandef_entry old_chandef;
|
||||
struct trace_chandef_entry new_chandef;
|
||||
} __packed;
|
||||
|
||||
#define SWITCH_ENTRY_ASSIGN(to, from) local_vifs[i].to = vifs[i].from
|
||||
#endif
|
||||
|
||||
TRACE_EVENT(drv_switch_vif_chanctx,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_vif_chanctx_switch *vifs,
|
||||
int n_vifs, enum ieee80211_chanctx_switch_mode mode),
|
||||
TP_ARGS(local, vifs, n_vifs, mode),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
__field(int, n_vifs)
|
||||
__field(u32, mode)
|
||||
__dynamic_array(u8, vifs,
|
||||
sizeof(struct trace_switch_entry) * n_vifs)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
__entry->n_vifs = n_vifs;
|
||||
__entry->mode = mode;
|
||||
{
|
||||
struct trace_switch_entry *local_vifs =
|
||||
__get_dynamic_array(vifs);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
sdata = container_of(vifs[i].vif,
|
||||
struct ieee80211_sub_if_data,
|
||||
vif);
|
||||
|
||||
SWITCH_ENTRY_ASSIGN(vif.vif_type, vif->type);
|
||||
SWITCH_ENTRY_ASSIGN(vif.p2p, vif->p2p);
|
||||
strncpy(local_vifs[i].vif.vif_name,
|
||||
sdata->name,
|
||||
sizeof(local_vifs[i].vif.vif_name));
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.control_freq,
|
||||
old_ctx->def.chan->center_freq);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.chan_width,
|
||||
old_ctx->def.width);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.center_freq1,
|
||||
old_ctx->def.center_freq1);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.center_freq2,
|
||||
old_ctx->def.center_freq2);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.control_freq,
|
||||
new_ctx->def.chan->center_freq);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.chan_width,
|
||||
new_ctx->def.width);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.center_freq1,
|
||||
new_ctx->def.center_freq1);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.center_freq2,
|
||||
new_ctx->def.center_freq2);
|
||||
}
|
||||
}
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT " n_vifs:%d mode:%d",
|
||||
LOCAL_PR_ARG, __entry->n_vifs, __entry->mode
|
||||
)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(local_sdata_chanctx,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
|
|
|
@ -130,7 +130,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
|
|||
newname))
|
||||
pr_err("failed to rename debugfs dir to %s!\n", newname);
|
||||
|
||||
nl80211_notify_dev_rename(rdev);
|
||||
nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -660,6 +660,8 @@ int wiphy_register(struct wiphy *wiphy)
|
|||
return res;
|
||||
}
|
||||
|
||||
nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_register);
|
||||
|
@ -698,6 +700,7 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||
rfkill_unregister(rdev->rfkill);
|
||||
|
||||
rtnl_lock();
|
||||
nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY);
|
||||
rdev->wiphy.registered = false;
|
||||
|
||||
WARN_ON(!list_empty(&rdev->wdev_list));
|
||||
|
|
|
@ -68,17 +68,7 @@ function parse_reg_rule()
|
|||
sub(/,/, "", units)
|
||||
dfs_cac = $9
|
||||
if (units == "mW") {
|
||||
if (power == 100) {
|
||||
power = 20
|
||||
} else if (power == 200) {
|
||||
power = 23
|
||||
} else if (power == 500) {
|
||||
power = 27
|
||||
} else if (power == 1000) {
|
||||
power = 30
|
||||
} else {
|
||||
print "Unknown power value in database!"
|
||||
}
|
||||
power = 10 * log(power)/log(10)
|
||||
} else {
|
||||
dfs_cac = $8
|
||||
}
|
||||
|
@ -117,7 +107,7 @@ function parse_reg_rule()
|
|||
|
||||
}
|
||||
flags = flags "0"
|
||||
printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
|
||||
printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %.0f, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
|
||||
rules++
|
||||
}
|
||||
|
||||
|
|
|
@ -1226,6 +1226,7 @@ struct nl80211_dump_wiphy_state {
|
|||
};
|
||||
|
||||
static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
||||
enum nl80211_commands cmd,
|
||||
struct sk_buff *msg, u32 portid, u32 seq,
|
||||
int flags, struct nl80211_dump_wiphy_state *state)
|
||||
{
|
||||
|
@ -1240,7 +1241,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
rdev->wiphy.mgmt_stypes;
|
||||
u32 features;
|
||||
|
||||
hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY);
|
||||
hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
|
||||
if (!hdr)
|
||||
return -ENOBUFS;
|
||||
|
||||
|
@ -1254,6 +1255,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
cfg80211_rdev_list_generation))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (cmd != NL80211_CMD_NEW_WIPHY)
|
||||
goto finish;
|
||||
|
||||
switch (state->split_start) {
|
||||
case 0:
|
||||
if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
|
||||
|
@ -1682,6 +1686,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
state->split_start = 0;
|
||||
break;
|
||||
}
|
||||
finish:
|
||||
return genlmsg_end(msg, hdr);
|
||||
|
||||
nla_put_failure:
|
||||
|
@ -1756,7 +1761,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
continue;
|
||||
/* attempt to fit multiple wiphy data chunks into the skb */
|
||||
do {
|
||||
ret = nl80211_send_wiphy(rdev, skb,
|
||||
ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
|
||||
skb,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq,
|
||||
NLM_F_MULTI, state);
|
||||
|
@ -1811,7 +1817,8 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
if (nl80211_send_wiphy(rdev, msg, info->snd_portid, info->snd_seq, 0,
|
||||
if (nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY, msg,
|
||||
info->snd_portid, info->snd_seq, 0,
|
||||
&state) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return -ENOBUFS;
|
||||
|
@ -10101,16 +10108,20 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
|
||||
/* notification functions */
|
||||
|
||||
void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
|
||||
void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
|
||||
enum nl80211_commands cmd)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
struct nl80211_dump_wiphy_state state = {};
|
||||
|
||||
WARN_ON(cmd != NL80211_CMD_NEW_WIPHY &&
|
||||
cmd != NL80211_CMD_DEL_WIPHY);
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, &state) < 0) {
|
||||
if (nl80211_send_wiphy(rdev, cmd, msg, 0, 0, 0, &state) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
int nl80211_init(void);
|
||||
void nl80211_exit(void);
|
||||
void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
|
||||
void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
|
||||
enum nl80211_commands cmd);
|
||||
void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev);
|
||||
struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
|
||||
|
|
Loading…
Reference in New Issue