Merge git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
commit
737be10d8c
|
@ -1711,6 +1711,7 @@ enum ieee80211_eid {
|
||||||
WLAN_EID_RRM_ENABLED_CAPABILITIES = 70,
|
WLAN_EID_RRM_ENABLED_CAPABILITIES = 70,
|
||||||
WLAN_EID_MULTIPLE_BSSID = 71,
|
WLAN_EID_MULTIPLE_BSSID = 71,
|
||||||
WLAN_EID_BSS_COEX_2040 = 72,
|
WLAN_EID_BSS_COEX_2040 = 72,
|
||||||
|
WLAN_EID_BSS_INTOLERANT_CHL_REPORT = 73,
|
||||||
WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74,
|
WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74,
|
||||||
WLAN_EID_RIC_DESCRIPTOR = 75,
|
WLAN_EID_RIC_DESCRIPTOR = 75,
|
||||||
WLAN_EID_MMIE = 76,
|
WLAN_EID_MMIE = 76,
|
||||||
|
|
|
@ -188,6 +188,43 @@ struct ieee80211_chanctx_conf {
|
||||||
u8 drv_priv[0] __aligned(sizeof(void *));
|
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
|
* 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.
|
* to vif. Possible use is for hw queue remapping.
|
||||||
* @unassign_vif_chanctx: Notifies device driver about channel context being
|
* @unassign_vif_chanctx: Notifies device driver about channel context being
|
||||||
* unbound from vif.
|
* 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
|
* @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
|
* 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
|
* 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,
|
void (*unassign_vif_chanctx)(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_chanctx_conf *ctx);
|
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);
|
void (*restart_complete)(struct ieee80211_hw *hw);
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,7 @@ static ssize_t ieee80211_if_read(
|
||||||
ssize_t ret = -EINVAL;
|
ssize_t ret = -EINVAL;
|
||||||
|
|
||||||
read_lock(&dev_base_lock);
|
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);
|
read_unlock(&dev_base_lock);
|
||||||
|
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
|
@ -62,8 +61,7 @@ static ssize_t ieee80211_if_write(
|
||||||
|
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
if (sdata->dev->reg_state == NETREG_REGISTERED)
|
ret = (*write)(sdata, buf, count);
|
||||||
ret = (*write)(sdata, buf, count);
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -1048,6 +1048,59 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
|
||||||
trace_drv_return_void(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,
|
static inline int drv_start_ap(struct ieee80211_local *local,
|
||||||
struct ieee80211_sub_if_data *sdata)
|
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.control_port = params->control_port;
|
||||||
sdata->u.ibss.userspace_handles_dfs = params->userspace_handles_dfs;
|
sdata->u.ibss.userspace_handles_dfs = params->userspace_handles_dfs;
|
||||||
sdata->u.ibss.basic_rates = params->basic_rates;
|
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 */
|
/* fix basic_rates if channel does not support these rates */
|
||||||
rate_flags = ieee80211_chandef_rate_flags(¶ms->chandef);
|
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;
|
sdata->vif.type = NL80211_IFTYPE_MONITOR;
|
||||||
snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
|
snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
|
||||||
wiphy_name(local->hw.wiphy));
|
wiphy_name(local->hw.wiphy));
|
||||||
|
sdata->wdev.iftype = NL80211_IFTYPE_MONITOR;
|
||||||
|
|
||||||
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
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_protocol = cpu_to_be16(ETH_P_PAE);
|
||||||
sdata->control_port_no_encrypt = false;
|
sdata->control_port_no_encrypt = false;
|
||||||
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||||
|
sdata->vif.bss_conf.idle = true;
|
||||||
|
|
||||||
sdata->noack_map = 0;
|
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);
|
sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
|
||||||
|
|
||||||
|
kfree(rcu_dereference_raw(sta->sta.rates));
|
||||||
kfree(sta);
|
kfree(sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local,
|
||||||
*/
|
*/
|
||||||
#define STA_LOST_PKT_THRESHOLD 50
|
#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)
|
void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb2;
|
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 (info->flags & IEEE80211_TX_STAT_ACK) {
|
||||||
if (sta->lost_packets)
|
if (sta->lost_packets)
|
||||||
sta->lost_packets = 0;
|
sta->lost_packets = 0;
|
||||||
} else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
|
} else {
|
||||||
cfg80211_cqm_pktloss_notify(sta->sdata->dev,
|
ieee80211_lost_packet(sta, skb);
|
||||||
sta->sta.addr,
|
|
||||||
sta->lost_packets,
|
|
||||||
GFP_ATOMIC);
|
|
||||||
sta->lost_packets = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
DECLARE_EVENT_CLASS(local_sdata_chanctx,
|
||||||
TP_PROTO(struct ieee80211_local *local,
|
TP_PROTO(struct ieee80211_local *local,
|
||||||
struct ieee80211_sub_if_data *sdata,
|
struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
|
@ -130,7 +130,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
|
||||||
newname))
|
newname))
|
||||||
pr_err("failed to rename debugfs dir to %s!\n", 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -660,6 +660,8 @@ int wiphy_register(struct wiphy *wiphy)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(wiphy_register);
|
EXPORT_SYMBOL(wiphy_register);
|
||||||
|
@ -698,6 +700,7 @@ void wiphy_unregister(struct wiphy *wiphy)
|
||||||
rfkill_unregister(rdev->rfkill);
|
rfkill_unregister(rdev->rfkill);
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
|
nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY);
|
||||||
rdev->wiphy.registered = false;
|
rdev->wiphy.registered = false;
|
||||||
|
|
||||||
WARN_ON(!list_empty(&rdev->wdev_list));
|
WARN_ON(!list_empty(&rdev->wdev_list));
|
||||||
|
|
|
@ -68,17 +68,7 @@ function parse_reg_rule()
|
||||||
sub(/,/, "", units)
|
sub(/,/, "", units)
|
||||||
dfs_cac = $9
|
dfs_cac = $9
|
||||||
if (units == "mW") {
|
if (units == "mW") {
|
||||||
if (power == 100) {
|
power = 10 * log(power)/log(10)
|
||||||
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!"
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
dfs_cac = $8
|
dfs_cac = $8
|
||||||
}
|
}
|
||||||
|
@ -117,7 +107,7 @@ function parse_reg_rule()
|
||||||
|
|
||||||
}
|
}
|
||||||
flags = flags "0"
|
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++
|
rules++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1226,6 +1226,7 @@ struct nl80211_dump_wiphy_state {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
||||||
|
enum nl80211_commands cmd,
|
||||||
struct sk_buff *msg, u32 portid, u32 seq,
|
struct sk_buff *msg, u32 portid, u32 seq,
|
||||||
int flags, struct nl80211_dump_wiphy_state *state)
|
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;
|
rdev->wiphy.mgmt_stypes;
|
||||||
u32 features;
|
u32 features;
|
||||||
|
|
||||||
hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY);
|
hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
|
||||||
if (!hdr)
|
if (!hdr)
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
|
|
||||||
|
@ -1254,6 +1255,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
||||||
cfg80211_rdev_list_generation))
|
cfg80211_rdev_list_generation))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
if (cmd != NL80211_CMD_NEW_WIPHY)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
switch (state->split_start) {
|
switch (state->split_start) {
|
||||||
case 0:
|
case 0:
|
||||||
if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
|
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;
|
state->split_start = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
finish:
|
||||||
return genlmsg_end(msg, hdr);
|
return genlmsg_end(msg, hdr);
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
|
@ -1756,7 +1761,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
||||||
continue;
|
continue;
|
||||||
/* attempt to fit multiple wiphy data chunks into the skb */
|
/* attempt to fit multiple wiphy data chunks into the skb */
|
||||||
do {
|
do {
|
||||||
ret = nl80211_send_wiphy(rdev, skb,
|
ret = nl80211_send_wiphy(rdev, NL80211_CMD_NEW_WIPHY,
|
||||||
|
skb,
|
||||||
NETLINK_CB(cb->skb).portid,
|
NETLINK_CB(cb->skb).portid,
|
||||||
cb->nlh->nlmsg_seq,
|
cb->nlh->nlmsg_seq,
|
||||||
NLM_F_MULTI, state);
|
NLM_F_MULTI, state);
|
||||||
|
@ -1811,7 +1817,8 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -ENOMEM;
|
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) {
|
&state) < 0) {
|
||||||
nlmsg_free(msg);
|
nlmsg_free(msg);
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
|
@ -10101,16 +10108,20 @@ static const struct genl_ops nl80211_ops[] = {
|
||||||
|
|
||||||
/* notification functions */
|
/* 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 sk_buff *msg;
|
||||||
struct nl80211_dump_wiphy_state state = {};
|
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);
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return;
|
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);
|
nlmsg_free(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
|
|
||||||
int nl80211_init(void);
|
int nl80211_init(void);
|
||||||
void nl80211_exit(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,
|
void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev);
|
struct wireless_dev *wdev);
|
||||||
struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
|
struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
|
||||||
|
|
Loading…
Reference in New Issue