mirror of https://gitee.com/openkylin/linux.git
One more set of new features:
* beacon report (for radio measurement) support in cfg80211/mac80211 * hwsim: allow wmediumd in namespaces * mac80211: extend 160MHz workaround to CSA IEs * mesh: properly encrypt group-addressed privacy action frames * mesh: allow setting peer AID * first steps for MU-MIMO monitor mode * along with various other cleanups and improvements -----BEGIN PGP SIGNATURE----- iQIcBAABCgAGBQJXfSCuAAoJEGt7eEactAAdaugP/ilrcELQRsIN5ZXCAKYZuwXV T01JPwgOaWL9ILu7h1SfG/+j9kzMnyk4WmRpeoj2FGNcyfG2AvULWSLpQJ2abwgQ 8o/emuLinQwRENevaMUTRSOE0HkXoFPCbbq37+a2i6bAv1QSYY3A0xvWpcU5fZ4D 7CKYDYPBAdMXYwEwy1g4nYWfDAYqS4rthr3l3rS1Cy7Q2T1ZlMlD90GjD7oeQAEw orKulhkkDSzvxfvZCYTzXmUoBQE8sNXGDD+OFsJyowyt+ugM/xan+2tmhCaHSnda HpdCS2aRj779UBn9cOfELjffTNpS++PM6KFd8ZDaPcJSMginn/BAHTOeNfNUfL0Q +Enu59I82qMDzbG2z1Qezzjv7OTzyEvyvYzNbLOqljTBSBklDa3rHwhyk+g1oVBH +4xX1Vk5QBLde+Q0NS0gTkcqOQK8KT5+HEqiUfgLSNDETN0lSGsKbtvMfU/ikE1Y aLRkTp7nzUd03qjIFLS6RMf7JjucWWzH1ZXTHvbpDFAG7riOhYRD3Sw+0e7madTd +HXjH9dnOGnGPDL+FyDwtW6iclYwNjcIPQiNdOjwWfMA2Wmr7iq+aFUptRCwQTHB WtgJ3f8OHax2JXcm4grYfxELZip5vbWJJHUC84Drvmzw3X7FRITf+OEWjdNOzsRD Fc7w5ceThh9Id1BvcH2+ =R1qP -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-davem-2016-07-06' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== One more set of new features: * beacon report (for radio measurement) support in cfg80211/mac80211 * hwsim: allow wmediumd in namespaces * mac80211: extend 160MHz workaround to CSA IEs * mesh: properly encrypt group-addressed privacy action frames * mesh: allow setting peer AID * first steps for MU-MIMO monitor mode * along with various other cleanups and improvements ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
a90a6e55f3
|
@ -3858,12 +3858,16 @@ void __ath10k_scan_finish(struct ath10k *ar)
|
|||
break;
|
||||
case ATH10K_SCAN_RUNNING:
|
||||
case ATH10K_SCAN_ABORTING:
|
||||
if (!ar->scan.is_roc)
|
||||
ieee80211_scan_completed(ar->hw,
|
||||
(ar->scan.state ==
|
||||
ATH10K_SCAN_ABORTING));
|
||||
else if (ar->scan.roc_notify)
|
||||
if (!ar->scan.is_roc) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = (ar->scan.state ==
|
||||
ATH10K_SCAN_ABORTING),
|
||||
};
|
||||
|
||||
ieee80211_scan_completed(ar->hw, &info);
|
||||
} else if (ar->scan.roc_notify) {
|
||||
ieee80211_remain_on_channel_expired(ar->hw);
|
||||
}
|
||||
/* fall through */
|
||||
case ATH10K_SCAN_STARTING:
|
||||
ar->scan.state = ATH10K_SCAN_IDLE;
|
||||
|
|
|
@ -859,7 +859,11 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
|
|||
struct ath6kl *ar = vif->ar;
|
||||
|
||||
if (vif->scan_req) {
|
||||
cfg80211_scan_done(vif->scan_req, true);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
cfg80211_scan_done(vif->scan_req, &info);
|
||||
vif->scan_req = NULL;
|
||||
}
|
||||
|
||||
|
@ -1069,6 +1073,9 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
|
|||
void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
|
||||
{
|
||||
struct ath6kl *ar = vif->ar;
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = aborted,
|
||||
};
|
||||
int i;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__,
|
||||
|
@ -1089,7 +1096,7 @@ void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
|
|||
}
|
||||
|
||||
out:
|
||||
cfg80211_scan_done(vif->scan_req, aborted);
|
||||
cfg80211_scan_done(vif->scan_req, &info);
|
||||
vif->scan_req = NULL;
|
||||
}
|
||||
|
||||
|
@ -3614,7 +3621,11 @@ void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready)
|
|||
}
|
||||
|
||||
if (vif->scan_req) {
|
||||
cfg80211_scan_done(vif->scan_req, true);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
cfg80211_scan_done(vif->scan_req, &info);
|
||||
vif->scan_req = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -960,6 +960,9 @@ void ath_roc_complete(struct ath_softc *sc, enum ath_roc_complete_reason reason)
|
|||
void ath_scan_complete(struct ath_softc *sc, bool abort)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = abort,
|
||||
};
|
||||
|
||||
if (abort)
|
||||
ath_dbg(common, CHAN_CTX, "HW scan aborted\n");
|
||||
|
@ -969,7 +972,7 @@ void ath_scan_complete(struct ath_softc *sc, bool abort)
|
|||
sc->offchannel.scan_req = NULL;
|
||||
sc->offchannel.scan_vif = NULL;
|
||||
sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
|
||||
ieee80211_scan_completed(sc->hw, abort);
|
||||
ieee80211_scan_completed(sc->hw, &info);
|
||||
clear_bit(ATH_OP_SCANNING, &common->op_flags);
|
||||
spin_lock_bh(&sc->chan_lock);
|
||||
if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
|
||||
|
|
|
@ -1369,7 +1369,11 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
|
|||
mutex_lock(&wil->mutex);
|
||||
started = wil_p2p_stop_discovery(wil);
|
||||
if (started && wil->scan_request) {
|
||||
cfg80211_scan_done(wil->scan_request, 1);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
cfg80211_scan_done(wil->scan_request, &info);
|
||||
wil->scan_request = NULL;
|
||||
wil->radio_wdev = wil->wdev;
|
||||
}
|
||||
|
|
|
@ -850,10 +850,14 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
mutex_unlock(&wil->wmi_mutex);
|
||||
|
||||
if (wil->scan_request) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
|
||||
wil->scan_request);
|
||||
del_timer_sync(&wil->scan_timer);
|
||||
cfg80211_scan_done(wil->scan_request, true);
|
||||
cfg80211_scan_done(wil->scan_request, &info);
|
||||
wil->scan_request = NULL;
|
||||
}
|
||||
|
||||
|
@ -1049,10 +1053,14 @@ int __wil_down(struct wil6210_priv *wil)
|
|||
(void)wil_p2p_stop_discovery(wil);
|
||||
|
||||
if (wil->scan_request) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
|
||||
wil->scan_request);
|
||||
del_timer_sync(&wil->scan_timer);
|
||||
cfg80211_scan_done(wil->scan_request, true);
|
||||
cfg80211_scan_done(wil->scan_request, &info);
|
||||
wil->scan_request = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -252,8 +252,12 @@ void wil_p2p_search_expired(struct work_struct *work)
|
|||
mutex_unlock(&wil->mutex);
|
||||
|
||||
if (started) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
|
||||
mutex_lock(&wil->p2p_wdev_mutex);
|
||||
cfg80211_scan_done(wil->scan_request, 0);
|
||||
cfg80211_scan_done(wil->scan_request, &info);
|
||||
wil->scan_request = NULL;
|
||||
wil->radio_wdev = wil->wdev;
|
||||
mutex_unlock(&wil->p2p_wdev_mutex);
|
||||
|
|
|
@ -426,15 +426,17 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
|
|||
{
|
||||
if (wil->scan_request) {
|
||||
struct wmi_scan_complete_event *data = d;
|
||||
bool aborted = (data->status != WMI_SCAN_SUCCESS);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = (data->status != WMI_SCAN_SUCCESS),
|
||||
};
|
||||
|
||||
wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
|
||||
wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
|
||||
wil->scan_request, aborted);
|
||||
wil->scan_request, info.aborted);
|
||||
|
||||
del_timer_sync(&wil->scan_timer);
|
||||
mutex_lock(&wil->p2p_wdev_mutex);
|
||||
cfg80211_scan_done(wil->scan_request, aborted);
|
||||
cfg80211_scan_done(wil->scan_request, &info);
|
||||
wil->radio_wdev = wil->wdev;
|
||||
mutex_unlock(&wil->p2p_wdev_mutex);
|
||||
wil->scan_request = NULL;
|
||||
|
|
|
@ -1922,6 +1922,9 @@ static void at76_dwork_hw_scan(struct work_struct *work)
|
|||
{
|
||||
struct at76_priv *priv = container_of(work, struct at76_priv,
|
||||
dwork_hw_scan.work);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (priv->device_unplugged)
|
||||
|
@ -1948,7 +1951,7 @@ static void at76_dwork_hw_scan(struct work_struct *work)
|
|||
|
||||
mutex_unlock(&priv->mtx);
|
||||
|
||||
ieee80211_scan_completed(priv->hw, false);
|
||||
ieee80211_scan_completed(priv->hw, &info);
|
||||
|
||||
ieee80211_wake_queues(priv->hw);
|
||||
}
|
||||
|
|
|
@ -775,9 +775,13 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
|||
if (!aborted)
|
||||
cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
|
||||
} else if (scan_request) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = aborted,
|
||||
};
|
||||
|
||||
brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
|
||||
aborted ? "Aborted" : "Done");
|
||||
cfg80211_scan_done(scan_request, aborted);
|
||||
cfg80211_scan_done(scan_request, &info);
|
||||
}
|
||||
if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
|
||||
brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");
|
||||
|
|
|
@ -1305,10 +1305,14 @@ il_send_scan_abort(struct il_priv *il)
|
|||
static void
|
||||
il_complete_scan(struct il_priv *il, bool aborted)
|
||||
{
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = aborted,
|
||||
};
|
||||
|
||||
/* check if scan was requested from mac80211 */
|
||||
if (il->scan_request) {
|
||||
D_SCAN("Complete scan in mac80211\n");
|
||||
ieee80211_scan_completed(il->hw, aborted);
|
||||
ieee80211_scan_completed(il->hw, &info);
|
||||
}
|
||||
|
||||
il->scan_vif = NULL;
|
||||
|
|
|
@ -94,10 +94,14 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
|
|||
|
||||
static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
|
||||
{
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = aborted,
|
||||
};
|
||||
|
||||
/* check if scan was requested from mac80211 */
|
||||
if (priv->scan_request) {
|
||||
IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
|
||||
ieee80211_scan_completed(priv->hw, aborted);
|
||||
ieee80211_scan_completed(priv->hw, &info);
|
||||
}
|
||||
|
||||
priv->scan_type = IWL_SCAN_NORMAL;
|
||||
|
|
|
@ -391,13 +391,16 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
|
|||
ieee80211_sched_scan_stopped(mvm->hw);
|
||||
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
|
||||
} else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = aborted,
|
||||
};
|
||||
|
||||
IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n",
|
||||
aborted ? "aborted" : "completed",
|
||||
iwl_mvm_ebs_status_str(scan_notif->ebs_status));
|
||||
|
||||
mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
|
||||
ieee80211_scan_completed(mvm->hw,
|
||||
scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);
|
||||
ieee80211_scan_completed(mvm->hw, &info);
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
|
||||
del_timer(&mvm->scan_timer);
|
||||
} else {
|
||||
|
@ -1430,7 +1433,11 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
|
|||
|
||||
/* if the scan is already stopping, we don't need to notify mac80211 */
|
||||
if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) {
|
||||
ieee80211_scan_completed(mvm->hw, aborted);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = aborted,
|
||||
};
|
||||
|
||||
ieee80211_scan_completed(mvm->hw, &info);
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
|
||||
del_timer(&mvm->scan_timer);
|
||||
} else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
|
||||
|
@ -1564,7 +1571,11 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
|
|||
|
||||
uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_REGULAR);
|
||||
if (uid >= 0) {
|
||||
ieee80211_scan_completed(mvm->hw, true);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
ieee80211_scan_completed(mvm->hw, &info);
|
||||
mvm->scan_uid_status[uid] = 0;
|
||||
}
|
||||
uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED);
|
||||
|
@ -1585,8 +1596,13 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
|
|||
mvm->scan_uid_status[i] = 0;
|
||||
}
|
||||
} else {
|
||||
if (mvm->scan_status & IWL_MVM_SCAN_REGULAR)
|
||||
ieee80211_scan_completed(mvm->hw, true);
|
||||
if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
ieee80211_scan_completed(mvm->hw, &info);
|
||||
}
|
||||
|
||||
/* Sched scan will be restarted by mac80211 in
|
||||
* restart_hw, so do not report if FW is about to be
|
||||
|
@ -1629,8 +1645,13 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)
|
|||
*/
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
|
||||
del_timer(&mvm->scan_timer);
|
||||
if (notify)
|
||||
ieee80211_scan_completed(mvm->hw, true);
|
||||
if (notify) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
ieee80211_scan_completed(mvm->hw, &info);
|
||||
}
|
||||
} else if (notify) {
|
||||
ieee80211_sched_scan_stopped(mvm->hw);
|
||||
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
|
||||
|
|
|
@ -237,7 +237,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv,
|
|||
|
||||
scan_abort:
|
||||
if (priv->scan_request) {
|
||||
cfg80211_scan_done(priv->scan_request, abort);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = abort,
|
||||
};
|
||||
|
||||
cfg80211_scan_done(priv->scan_request, &info);
|
||||
priv->scan_request = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +249,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv,
|
|||
void orinoco_scan_done(struct orinoco_private *priv, bool abort)
|
||||
{
|
||||
if (priv->scan_request) {
|
||||
cfg80211_scan_done(priv->scan_request, abort);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = abort,
|
||||
};
|
||||
|
||||
cfg80211_scan_done(priv->scan_request, &info);
|
||||
priv->scan_request = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,8 +41,6 @@ MODULE_AUTHOR("Jouni Malinen");
|
|||
MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static u32 wmediumd_portid;
|
||||
|
||||
static int radios = 2;
|
||||
module_param(radios, int, 0444);
|
||||
MODULE_PARM_DESC(radios, "Number of simulated radios");
|
||||
|
@ -252,12 +250,13 @@ static inline void hwsim_clear_chanctx_magic(struct ieee80211_chanctx_conf *c)
|
|||
cp->magic = 0;
|
||||
}
|
||||
|
||||
static unsigned int hwsim_net_id;
|
||||
static int hwsim_net_id;
|
||||
|
||||
static int hwsim_netgroup;
|
||||
|
||||
struct hwsim_net {
|
||||
int netgroup;
|
||||
u32 wmediumd;
|
||||
};
|
||||
|
||||
static inline int hwsim_net_get_netgroup(struct net *net)
|
||||
|
@ -274,6 +273,20 @@ static inline void hwsim_net_set_netgroup(struct net *net)
|
|||
hwsim_net->netgroup = hwsim_netgroup++;
|
||||
}
|
||||
|
||||
static inline u32 hwsim_net_get_wmediumd(struct net *net)
|
||||
{
|
||||
struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id);
|
||||
|
||||
return hwsim_net->wmediumd;
|
||||
}
|
||||
|
||||
static inline void hwsim_net_set_wmediumd(struct net *net, u32 portid)
|
||||
{
|
||||
struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id);
|
||||
|
||||
hwsim_net->wmediumd = portid;
|
||||
}
|
||||
|
||||
static struct class *hwsim_class;
|
||||
|
||||
static struct net_device *hwsim_mon; /* global monitor netdev */
|
||||
|
@ -444,10 +457,6 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = {
|
|||
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = {
|
||||
{ .max = 8, .types = BIT(NL80211_IFTYPE_AP) },
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_combination hwsim_if_comb[] = {
|
||||
{
|
||||
.limits = hwsim_if_limits,
|
||||
|
@ -455,18 +464,12 @@ static const struct ieee80211_iface_combination hwsim_if_comb[] = {
|
|||
.n_limits = ARRAY_SIZE(hwsim_if_limits) - 1,
|
||||
.max_interfaces = 2048,
|
||||
.num_different_channels = 1,
|
||||
},
|
||||
{
|
||||
.limits = hwsim_if_dfs_limits,
|
||||
.n_limits = ARRAY_SIZE(hwsim_if_dfs_limits),
|
||||
.max_interfaces = 8,
|
||||
.num_different_channels = 1,
|
||||
.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||
BIT(NL80211_CHAN_WIDTH_20) |
|
||||
BIT(NL80211_CHAN_WIDTH_40) |
|
||||
BIT(NL80211_CHAN_WIDTH_80) |
|
||||
BIT(NL80211_CHAN_WIDTH_160),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
|
||||
|
@ -475,18 +478,12 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
|
|||
.n_limits = ARRAY_SIZE(hwsim_if_limits),
|
||||
.max_interfaces = 2048,
|
||||
.num_different_channels = 1,
|
||||
},
|
||||
{
|
||||
.limits = hwsim_if_dfs_limits,
|
||||
.n_limits = ARRAY_SIZE(hwsim_if_dfs_limits),
|
||||
.max_interfaces = 8,
|
||||
.num_different_channels = 1,
|
||||
.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||
BIT(NL80211_CHAN_WIDTH_20) |
|
||||
BIT(NL80211_CHAN_WIDTH_40) |
|
||||
BIT(NL80211_CHAN_WIDTH_80) |
|
||||
BIT(NL80211_CHAN_WIDTH_160),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static spinlock_t hwsim_radio_lock;
|
||||
|
@ -552,6 +549,8 @@ struct mac80211_hwsim_data {
|
|||
|
||||
/* group shared by radios created in the same netns */
|
||||
int netgroup;
|
||||
/* wmediumd portid responsible for netgroup of this radio */
|
||||
u32 wmediumd;
|
||||
|
||||
int power_level;
|
||||
|
||||
|
@ -983,6 +982,29 @@ static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data,
|
|||
return true;
|
||||
}
|
||||
|
||||
static int hwsim_unicast_netgroup(struct mac80211_hwsim_data *data,
|
||||
struct sk_buff *skb, int portid)
|
||||
{
|
||||
struct net *net;
|
||||
bool found = false;
|
||||
int res = -ENOENT;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_net_rcu(net) {
|
||||
if (data->netgroup == hwsim_net_get_netgroup(net)) {
|
||||
res = genlmsg_unicast(net, skb, portid);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!found)
|
||||
nlmsg_free(skb);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
|
||||
struct sk_buff *my_skb,
|
||||
int dst_portid)
|
||||
|
@ -1062,7 +1084,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
|
|||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(skb, msg_head);
|
||||
if (genlmsg_unicast(&init_net, skb, dst_portid))
|
||||
if (hwsim_unicast_netgroup(data, skb, dst_portid))
|
||||
goto err_free_txskb;
|
||||
|
||||
/* Enqueue the packet */
|
||||
|
@ -1355,7 +1377,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
|||
mac80211_hwsim_monitor_rx(hw, skb, channel);
|
||||
|
||||
/* wmediumd mode check */
|
||||
_portid = ACCESS_ONCE(wmediumd_portid);
|
||||
_portid = ACCESS_ONCE(data->wmediumd);
|
||||
|
||||
if (_portid)
|
||||
return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
|
||||
|
@ -1451,7 +1473,8 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
|||
struct sk_buff *skb,
|
||||
struct ieee80211_channel *chan)
|
||||
{
|
||||
u32 _pid = ACCESS_ONCE(wmediumd_portid);
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
u32 _pid = ACCESS_ONCE(data->wmediumd);
|
||||
|
||||
if (ieee80211_hw_check(hw, SUPPORTS_RC_TABLE)) {
|
||||
struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
|
||||
|
@ -1918,8 +1941,12 @@ static void hw_scan_work(struct work_struct *work)
|
|||
|
||||
mutex_lock(&hwsim->mutex);
|
||||
if (hwsim->scan_chan_idx >= req->n_channels) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
|
||||
wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n");
|
||||
ieee80211_scan_completed(hwsim->hw, false);
|
||||
ieee80211_scan_completed(hwsim->hw, &info);
|
||||
hwsim->hw_scan_request = NULL;
|
||||
hwsim->hw_scan_vif = NULL;
|
||||
hwsim->tmp_chan = NULL;
|
||||
|
@ -2004,13 +2031,16 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw,
|
|||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mac80211_hwsim_data *hwsim = hw->priv;
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n");
|
||||
|
||||
cancel_delayed_work_sync(&hwsim->hw_scan);
|
||||
|
||||
mutex_lock(&hwsim->mutex);
|
||||
ieee80211_scan_completed(hwsim->hw, true);
|
||||
ieee80211_scan_completed(hwsim->hw, &info);
|
||||
hwsim->tmp_chan = NULL;
|
||||
hwsim->hw_scan_request = NULL;
|
||||
hwsim->hw_scan_vif = NULL;
|
||||
|
@ -2448,13 +2478,14 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
|||
hw->wiphy->max_scan_ssids = 255;
|
||||
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
|
||||
hw->wiphy->max_remain_on_channel_duration = 1000;
|
||||
/* For channels > 1 DFS is not allowed */
|
||||
hw->wiphy->n_iface_combinations = 1;
|
||||
hw->wiphy->iface_combinations = &data->if_combination;
|
||||
if (param->p2p_device)
|
||||
data->if_combination = hwsim_if_comb_p2p_dev[0];
|
||||
else
|
||||
data->if_combination = hwsim_if_comb[0];
|
||||
hw->wiphy->n_iface_combinations = 1;
|
||||
/* For channels > 1 DFS is not allowed */
|
||||
data->if_combination.radar_detect_widths = 0;
|
||||
data->if_combination.num_different_channels = data->channels;
|
||||
} else if (param->p2p_device) {
|
||||
hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev;
|
||||
|
@ -2796,6 +2827,20 @@ static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr)
|
|||
return data;
|
||||
}
|
||||
|
||||
static void hwsim_register_wmediumd(struct net *net, u32 portid)
|
||||
{
|
||||
struct mac80211_hwsim_data *data;
|
||||
|
||||
hwsim_net_set_wmediumd(net, portid);
|
||||
|
||||
spin_lock_bh(&hwsim_radio_lock);
|
||||
list_for_each_entry(data, &hwsim_radios, list) {
|
||||
if (data->netgroup == hwsim_net_get_netgroup(net))
|
||||
data->wmediumd = portid;
|
||||
}
|
||||
spin_unlock_bh(&hwsim_radio_lock);
|
||||
}
|
||||
|
||||
static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
|
||||
struct genl_info *info)
|
||||
{
|
||||
|
@ -2811,9 +2856,6 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
|
|||
int i;
|
||||
bool found = false;
|
||||
|
||||
if (info->snd_portid != wmediumd_portid)
|
||||
return -EINVAL;
|
||||
|
||||
if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
|
||||
!info->attrs[HWSIM_ATTR_FLAGS] ||
|
||||
!info->attrs[HWSIM_ATTR_COOKIE] ||
|
||||
|
@ -2829,6 +2871,12 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
|
|||
if (!data2)
|
||||
goto out;
|
||||
|
||||
if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup)
|
||||
goto out;
|
||||
|
||||
if (info->snd_portid != data2->wmediumd)
|
||||
goto out;
|
||||
|
||||
/* look for the skb matching the cookie passed back from user */
|
||||
skb_queue_walk_safe(&data2->pending, skb, tmp) {
|
||||
u64 skb_cookie;
|
||||
|
@ -2892,9 +2940,6 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
|||
void *frame_data;
|
||||
struct sk_buff *skb = NULL;
|
||||
|
||||
if (info->snd_portid != wmediumd_portid)
|
||||
return -EINVAL;
|
||||
|
||||
if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
|
||||
!info->attrs[HWSIM_ATTR_FRAME] ||
|
||||
!info->attrs[HWSIM_ATTR_RX_RATE] ||
|
||||
|
@ -2920,6 +2965,12 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
|||
if (!data2)
|
||||
goto out;
|
||||
|
||||
if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup)
|
||||
goto out;
|
||||
|
||||
if (info->snd_portid != data2->wmediumd)
|
||||
goto out;
|
||||
|
||||
/* check if radio is configured properly */
|
||||
|
||||
if (data2->idle || !data2->started)
|
||||
|
@ -2966,6 +3017,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
|||
static int hwsim_register_received_nl(struct sk_buff *skb_2,
|
||||
struct genl_info *info)
|
||||
{
|
||||
struct net *net = genl_info_net(info);
|
||||
struct mac80211_hwsim_data *data;
|
||||
int chans = 1;
|
||||
|
||||
|
@ -2982,10 +3034,10 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2,
|
|||
if (chans > 1)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (wmediumd_portid)
|
||||
if (hwsim_net_get_wmediumd(net))
|
||||
return -EBUSY;
|
||||
|
||||
wmediumd_portid = info->snd_portid;
|
||||
hwsim_register_wmediumd(net, info->snd_portid);
|
||||
|
||||
printk(KERN_DEBUG "mac80211_hwsim: received a REGISTER, "
|
||||
"switching to wmediumd mode with pid %d\n", info->snd_portid);
|
||||
|
@ -3152,7 +3204,7 @@ static const struct genl_ops hwsim_ops[] = {
|
|||
.cmd = HWSIM_CMD_REGISTER,
|
||||
.policy = hwsim_genl_policy,
|
||||
.doit = hwsim_register_received_nl,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
},
|
||||
{
|
||||
.cmd = HWSIM_CMD_FRAME,
|
||||
|
@ -3218,10 +3270,10 @@ static int mac80211_hwsim_netlink_notify(struct notifier_block *nb,
|
|||
|
||||
remove_user_radios(notify->portid);
|
||||
|
||||
if (notify->portid == wmediumd_portid) {
|
||||
if (notify->portid == hwsim_net_get_wmediumd(notify->net)) {
|
||||
printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink"
|
||||
" socket, switching to perfect channel medium\n");
|
||||
wmediumd_portid = 0;
|
||||
hwsim_register_wmediumd(notify->net, 0);
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
|
||||
|
|
|
@ -796,10 +796,15 @@ void lbs_scan_done(struct lbs_private *priv)
|
|||
{
|
||||
WARN_ON(!priv->scan_req);
|
||||
|
||||
if (priv->internal_scan)
|
||||
if (priv->internal_scan) {
|
||||
kfree(priv->scan_req);
|
||||
else
|
||||
cfg80211_scan_done(priv->scan_req, false);
|
||||
} else {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
|
||||
cfg80211_scan_done(priv->scan_req, &info);
|
||||
}
|
||||
|
||||
priv->scan_req = NULL;
|
||||
}
|
||||
|
|
|
@ -1057,8 +1057,12 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
|
|||
if (!priv)
|
||||
continue;
|
||||
if (priv->scan_request) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
cfg80211_scan_done(priv->scan_request, &info);
|
||||
priv->scan_request = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -1112,8 +1116,12 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
|
|||
if (!priv)
|
||||
continue;
|
||||
if (priv->scan_request) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
mwifiex_dbg(adapter, WARN, "info: aborting scan\n");
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
cfg80211_scan_done(priv->scan_request, &info);
|
||||
priv->scan_request = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -697,9 +697,13 @@ mwifiex_close(struct net_device *dev)
|
|||
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||
|
||||
if (priv->scan_request) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"aborting scan on ndo_stop\n");
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
cfg80211_scan_done(priv->scan_request, &info);
|
||||
priv->scan_request = NULL;
|
||||
priv->scan_aborting = true;
|
||||
}
|
||||
|
|
|
@ -1956,9 +1956,13 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
|
|||
mwifiex_complete_scan(priv);
|
||||
|
||||
if (priv->scan_request) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
|
||||
mwifiex_dbg(adapter, INFO,
|
||||
"info: notifying scan done\n");
|
||||
cfg80211_scan_done(priv->scan_request, 0);
|
||||
cfg80211_scan_done(priv->scan_request, &info);
|
||||
priv->scan_request = NULL;
|
||||
} else {
|
||||
priv->scan_aborting = false;
|
||||
|
@ -1977,9 +1981,13 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
|
|||
|
||||
if (!adapter->active_scan_triggered) {
|
||||
if (priv->scan_request) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
mwifiex_dbg(adapter, INFO,
|
||||
"info: aborting scan\n");
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
cfg80211_scan_done(priv->scan_request, &info);
|
||||
priv->scan_request = NULL;
|
||||
} else {
|
||||
priv->scan_aborting = false;
|
||||
|
|
|
@ -2134,6 +2134,7 @@ static void rndis_get_scan_results(struct work_struct *work)
|
|||
struct rndis_wlan_private *priv =
|
||||
container_of(work, struct rndis_wlan_private, scan_work.work);
|
||||
struct usbnet *usbdev = priv->usbdev;
|
||||
struct cfg80211_scan_info info = {};
|
||||
int ret;
|
||||
|
||||
netdev_dbg(usbdev->net, "get_scan_results\n");
|
||||
|
@ -2143,7 +2144,8 @@ static void rndis_get_scan_results(struct work_struct *work)
|
|||
|
||||
ret = rndis_check_bssid_list(usbdev, NULL, NULL);
|
||||
|
||||
cfg80211_scan_done(priv->scan_request, ret < 0);
|
||||
info.aborted = ret < 0;
|
||||
cfg80211_scan_done(priv->scan_request, &info);
|
||||
|
||||
priv->scan_request = NULL;
|
||||
}
|
||||
|
@ -3574,7 +3576,11 @@ static int rndis_wlan_stop(struct usbnet *usbdev)
|
|||
flush_workqueue(priv->workqueue);
|
||||
|
||||
if (priv->scan_request) {
|
||||
cfg80211_scan_done(priv->scan_request, true);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
cfg80211_scan_done(priv->scan_request, &info);
|
||||
priv->scan_request = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -167,6 +167,10 @@ void cw1200_scan_work(struct work_struct *work)
|
|||
}
|
||||
|
||||
if (!priv->scan.req || (priv->scan.curr == priv->scan.end)) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = priv->scan.status ? 1 : 0,
|
||||
};
|
||||
|
||||
if (priv->scan.output_power != priv->output_power)
|
||||
wsm_set_output_power(priv, priv->output_power * 10);
|
||||
if (priv->join_status == CW1200_JOIN_STATUS_STA &&
|
||||
|
@ -188,7 +192,7 @@ void cw1200_scan_work(struct work_struct *work)
|
|||
cw1200_scan_restart_delayed(priv);
|
||||
wsm_unlock_tx(priv);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
ieee80211_scan_completed(priv->hw, priv->scan.status ? 1 : 0);
|
||||
ieee80211_scan_completed(priv->hw, &info);
|
||||
up(&priv->scan.lock);
|
||||
return;
|
||||
} else {
|
||||
|
|
|
@ -36,7 +36,11 @@ static int wl1251_event_scan_complete(struct wl1251 *wl,
|
|||
mbox->scheduled_scan_channels);
|
||||
|
||||
if (wl->scanning) {
|
||||
ieee80211_scan_completed(wl->hw, false);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
|
||||
ieee80211_scan_completed(wl->hw, &info);
|
||||
wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
|
||||
wl->scanning = false;
|
||||
if (wl->hw->conf.flags & IEEE80211_CONF_IDLE)
|
||||
|
|
|
@ -448,7 +448,11 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
|
|||
WARN_ON(wl->state != WL1251_STATE_ON);
|
||||
|
||||
if (wl->scanning) {
|
||||
ieee80211_scan_completed(wl->hw, true);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
ieee80211_scan_completed(wl->hw, &info);
|
||||
wl->scanning = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2615,6 +2615,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
|||
|
||||
if (wl->scan.state != WL1271_SCAN_STATE_IDLE &&
|
||||
wl->scan_wlvif == wlvif) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
|
||||
/*
|
||||
* Rearm the tx watchdog just before idling scan. This
|
||||
* prevents just-finished scans from triggering the watchdog
|
||||
|
@ -2625,7 +2629,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
|||
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
|
||||
wl->scan_wlvif = NULL;
|
||||
wl->scan.req = NULL;
|
||||
ieee80211_scan_completed(wl->hw, true);
|
||||
ieee80211_scan_completed(wl->hw, &info);
|
||||
}
|
||||
|
||||
if (wl->sched_vif == wlvif)
|
||||
|
@ -3649,6 +3653,9 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = true,
|
||||
};
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan");
|
||||
|
@ -3681,7 +3688,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
|
|||
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
|
||||
wl->scan_wlvif = NULL;
|
||||
wl->scan.req = NULL;
|
||||
ieee80211_scan_completed(wl->hw, true);
|
||||
ieee80211_scan_completed(wl->hw, &info);
|
||||
|
||||
out_sleep:
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
|
|
@ -36,6 +36,9 @@ void wl1271_scan_complete_work(struct work_struct *work)
|
|||
struct delayed_work *dwork;
|
||||
struct wl1271 *wl;
|
||||
struct wl12xx_vif *wlvif;
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
int ret;
|
||||
|
||||
dwork = to_delayed_work(work);
|
||||
|
@ -82,7 +85,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
|
|||
|
||||
wlcore_cmd_regdomain_config_locked(wl);
|
||||
|
||||
ieee80211_scan_completed(wl->hw, false);
|
||||
ieee80211_scan_completed(wl->hw, &info);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
|
|
@ -1256,10 +1256,15 @@ void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
|
|||
DBG_8723A("%s with scan req\n", __func__);
|
||||
|
||||
if (pwdev_priv->scan_request->wiphy !=
|
||||
pwdev_priv->rtw_wdev->wiphy)
|
||||
pwdev_priv->rtw_wdev->wiphy) {
|
||||
DBG_8723A("error wiphy compare\n");
|
||||
else
|
||||
cfg80211_scan_done(pwdev_priv->scan_request, aborted);
|
||||
} else {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = aborted,
|
||||
};
|
||||
|
||||
cfg80211_scan_done(pwdev_priv->scan_request, &info);
|
||||
}
|
||||
|
||||
pwdev_priv->scan_request = NULL;
|
||||
} else {
|
||||
|
|
|
@ -454,7 +454,11 @@ static void CfgScanResult(enum scan_event scan_event,
|
|||
mutex_lock(&priv->scan_req_lock);
|
||||
|
||||
if (priv->pstrScanReq) {
|
||||
cfg80211_scan_done(priv->pstrScanReq, false);
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
|
||||
cfg80211_scan_done(priv->pstrScanReq, &info);
|
||||
priv->u32RcvdChCount = 0;
|
||||
priv->bCfgScanning = false;
|
||||
priv->pstrScanReq = NULL;
|
||||
|
@ -464,10 +468,14 @@ static void CfgScanResult(enum scan_event scan_event,
|
|||
mutex_lock(&priv->scan_req_lock);
|
||||
|
||||
if (priv->pstrScanReq) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = false,
|
||||
};
|
||||
|
||||
update_scan_time();
|
||||
refresh_scan(priv, 1, false);
|
||||
|
||||
cfg80211_scan_done(priv->pstrScanReq, false);
|
||||
cfg80211_scan_done(priv->pstrScanReq, &info);
|
||||
priv->bCfgScanning = false;
|
||||
priv->pstrScanReq = NULL;
|
||||
}
|
||||
|
|
|
@ -338,6 +338,8 @@ static int prism2_scan(struct wiphy *wiphy,
|
|||
struct p80211msg_dot11req_scan msg1;
|
||||
struct p80211msg_dot11req_scan_results msg2;
|
||||
struct cfg80211_bss *bss;
|
||||
struct cfg80211_scan_info info = {};
|
||||
|
||||
int result;
|
||||
int err = 0;
|
||||
int numbss = 0;
|
||||
|
@ -440,7 +442,8 @@ static int prism2_scan(struct wiphy *wiphy,
|
|||
err = prism2_result2err(msg2.resultcode.data);
|
||||
|
||||
exit:
|
||||
cfg80211_scan_done(request, err ? 1 : 0);
|
||||
info.aborted = !!(err);
|
||||
cfg80211_scan_done(request, &info);
|
||||
priv->scan_request = NULL;
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
|
@ -2464,7 +2465,7 @@ static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
|
|||
*/
|
||||
static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb)
|
||||
{
|
||||
if (skb->len < 25)
|
||||
if (skb->len < IEEE80211_MIN_ACTION_SIZE)
|
||||
return false;
|
||||
return _ieee80211_is_robust_mgmt_frame((void *)skb->data);
|
||||
}
|
||||
|
@ -2486,6 +2487,35 @@ static inline bool ieee80211_is_public_action(struct ieee80211_hdr *hdr,
|
|||
return mgmt->u.action.category == WLAN_CATEGORY_PUBLIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* _ieee80211_is_group_privacy_action - check if frame is a group addressed
|
||||
* privacy action frame
|
||||
* @hdr: the frame
|
||||
*/
|
||||
static inline bool _ieee80211_is_group_privacy_action(struct ieee80211_hdr *hdr)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt = (void *)hdr;
|
||||
|
||||
if (!ieee80211_is_action(hdr->frame_control) ||
|
||||
!is_multicast_ether_addr(hdr->addr1))
|
||||
return false;
|
||||
|
||||
return mgmt->u.action.category == WLAN_CATEGORY_MESH_ACTION ||
|
||||
mgmt->u.action.category == WLAN_CATEGORY_MULTIHOP_ACTION;
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee80211_is_group_privacy_action - check if frame is a group addressed
|
||||
* privacy action frame
|
||||
* @skb: the skb containing the frame, length will be checked
|
||||
*/
|
||||
static inline bool ieee80211_is_group_privacy_action(struct sk_buff *skb)
|
||||
{
|
||||
if (skb->len < IEEE80211_MIN_ACTION_SIZE)
|
||||
return false;
|
||||
return _ieee80211_is_group_privacy_action((void *)skb->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee80211_tu_to_usec - convert time units (TU) to microseconds
|
||||
* @tu: the TUs
|
||||
|
|
|
@ -330,6 +330,9 @@ struct ieee80211_supported_band {
|
|||
* in a separate chapter.
|
||||
*/
|
||||
|
||||
#define VHT_MUMIMO_GROUPS_DATA_LEN (WLAN_MEMBERSHIP_LEN +\
|
||||
WLAN_USER_POSITION_LEN)
|
||||
|
||||
/**
|
||||
* struct vif_params - describes virtual interface parameters
|
||||
* @use_4addr: use 4-address frames
|
||||
|
@ -339,10 +342,13 @@ struct ieee80211_supported_band {
|
|||
* This feature is only fully supported by drivers that enable the
|
||||
* %NL80211_FEATURE_MAC_ON_CREATE flag. Others may support creating
|
||||
** only p2p devices with specified MAC.
|
||||
* @vht_mumimo_groups: MU-MIMO groupID. used for monitoring only
|
||||
* packets belonging to that MU-MIMO groupID.
|
||||
*/
|
||||
struct vif_params {
|
||||
int use_4addr;
|
||||
u8 macaddr[ETH_ALEN];
|
||||
u8 vht_mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -774,6 +780,7 @@ enum station_parameters_apply_mask {
|
|||
* (bitmask of BIT(NL80211_STA_FLAG_...))
|
||||
* @listen_interval: listen interval or -1 for no change
|
||||
* @aid: AID or zero for no change
|
||||
* @peer_aid: mesh peer AID or zero for no change
|
||||
* @plink_action: plink action to take
|
||||
* @plink_state: set the peer link state for a station
|
||||
* @ht_capa: HT capabilities of station
|
||||
|
@ -805,6 +812,7 @@ struct station_parameters {
|
|||
u32 sta_modify_mask;
|
||||
int listen_interval;
|
||||
u16 aid;
|
||||
u16 peer_aid;
|
||||
u8 supported_rates_len;
|
||||
u8 plink_action;
|
||||
u8 plink_state;
|
||||
|
@ -1417,6 +1425,21 @@ struct cfg80211_ssid {
|
|||
u8 ssid_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_scan_info - information about completed scan
|
||||
* @scan_start_tsf: scan start time in terms of the TSF of the BSS that the
|
||||
* wireless device that requested the scan is connected to. If this
|
||||
* information is not available, this field is left zero.
|
||||
* @tsf_bssid: the BSSID according to which %scan_start_tsf is set.
|
||||
* @aborted: set to true if the scan was aborted for any reason,
|
||||
* userspace will be notified of that
|
||||
*/
|
||||
struct cfg80211_scan_info {
|
||||
u64 scan_start_tsf;
|
||||
u8 tsf_bssid[ETH_ALEN] __aligned(2);
|
||||
bool aborted;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_scan_request - scan request description
|
||||
*
|
||||
|
@ -1427,12 +1450,17 @@ struct cfg80211_ssid {
|
|||
* @scan_width: channel width for scanning
|
||||
* @ie: optional information element(s) to add into Probe Request or %NULL
|
||||
* @ie_len: length of ie in octets
|
||||
* @duration: how long to listen on each channel, in TUs. If
|
||||
* %duration_mandatory is not set, this is the maximum dwell time and
|
||||
* the actual dwell time may be shorter.
|
||||
* @duration_mandatory: if set, the scan duration must be as specified by the
|
||||
* %duration field.
|
||||
* @flags: bit field of flags controlling operation
|
||||
* @rates: bitmap of rates to advertise for each band
|
||||
* @wiphy: the wiphy this was for
|
||||
* @scan_start: time (in jiffies) when the scan started
|
||||
* @wdev: the wireless device to scan for
|
||||
* @aborted: (internal) scan request was notified as aborted
|
||||
* @info: (internal) information about completed scan
|
||||
* @notified: (internal) scan request was notified as done or aborted
|
||||
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
|
||||
* @mac_addr: MAC address used with randomisation
|
||||
|
@ -1448,6 +1476,8 @@ struct cfg80211_scan_request {
|
|||
enum nl80211_bss_scan_width scan_width;
|
||||
const u8 *ie;
|
||||
size_t ie_len;
|
||||
u16 duration;
|
||||
bool duration_mandatory;
|
||||
u32 flags;
|
||||
|
||||
u32 rates[NUM_NL80211_BANDS];
|
||||
|
@ -1461,7 +1491,8 @@ struct cfg80211_scan_request {
|
|||
/* internal */
|
||||
struct wiphy *wiphy;
|
||||
unsigned long scan_start;
|
||||
bool aborted, notified;
|
||||
struct cfg80211_scan_info info;
|
||||
bool notified;
|
||||
bool no_cck;
|
||||
|
||||
/* keep last */
|
||||
|
@ -1594,12 +1625,19 @@ enum cfg80211_signal_type {
|
|||
* buffered on the device) and be accurate to about 10ms.
|
||||
* If the frame isn't buffered, just passing the return value of
|
||||
* ktime_get_boot_ns() is likely appropriate.
|
||||
* @parent_tsf: the time at the start of reception of the first octet of the
|
||||
* timestamp field of the frame. The time is the TSF of the BSS specified
|
||||
* by %parent_bssid.
|
||||
* @parent_bssid: the BSS according to which %parent_tsf is set. This is set to
|
||||
* the BSS that requested the scan in which the beacon/probe was received.
|
||||
*/
|
||||
struct cfg80211_inform_bss {
|
||||
struct ieee80211_channel *chan;
|
||||
enum nl80211_bss_scan_width scan_width;
|
||||
s32 signal;
|
||||
u64 boottime_ns;
|
||||
u64 parent_tsf;
|
||||
u8 parent_bssid[ETH_ALEN] __aligned(2);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -4061,10 +4099,10 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator);
|
|||
* cfg80211_scan_done - notify that scan finished
|
||||
*
|
||||
* @request: the corresponding scan request
|
||||
* @aborted: set to true if the scan was aborted for any reason,
|
||||
* userspace will be notified of that
|
||||
* @info: information about the completed scan
|
||||
*/
|
||||
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted);
|
||||
void cfg80211_scan_done(struct cfg80211_scan_request *request,
|
||||
struct cfg80211_scan_info *info);
|
||||
|
||||
/**
|
||||
* cfg80211_sched_scan_results - notify that new scan results are available
|
||||
|
|
|
@ -4697,9 +4697,10 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw);
|
|||
* any context, including hardirq context.
|
||||
*
|
||||
* @hw: the hardware that finished the scan
|
||||
* @aborted: set to true if scan was aborted
|
||||
* @info: information about the completed scan
|
||||
*/
|
||||
void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted);
|
||||
void ieee80211_scan_completed(struct ieee80211_hw *hw,
|
||||
struct cfg80211_scan_info *info);
|
||||
|
||||
/**
|
||||
* ieee80211_sched_scan_results - got results from scheduled scan
|
||||
|
|
|
@ -1829,6 +1829,44 @@ enum nl80211_commands {
|
|||
* %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per
|
||||
* interface type.
|
||||
*
|
||||
* @NL80211_ATTR_MU_MIMO_GROUP_DATA: array of 24 bytes that defines a MU-MIMO
|
||||
* groupID for monitor mode.
|
||||
* The first 8 bytes are a mask that defines the membership in each
|
||||
* group (there are 64 groups, group 0 and 63 are reserved),
|
||||
* each bit represents a group and set to 1 for being a member in
|
||||
* that group and 0 for not being a member.
|
||||
* The remaining 16 bytes define the position in each group: 2 bits for
|
||||
* each group.
|
||||
* (smaller group numbers represented on most significant bits and bigger
|
||||
* group numbers on least significant bits.)
|
||||
* This attribute is used only if all interfaces are in monitor mode.
|
||||
* Set this attribute in order to monitor packets using the given MU-MIMO
|
||||
* groupID data.
|
||||
* to turn off that feature set all the bits of the groupID to zero.
|
||||
* @NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR: mac address for the sniffer to follow
|
||||
* when using MU-MIMO air sniffer.
|
||||
* to turn that feature off set an invalid mac address
|
||||
* (e.g. FF:FF:FF:FF:FF:FF)
|
||||
*
|
||||
* @NL80211_ATTR_SCAN_START_TIME_TSF: The time at which the scan was actually
|
||||
* started (u64). The time is the TSF of the BSS the interface that
|
||||
* requested the scan is connected to (if available, otherwise this
|
||||
* attribute must not be included).
|
||||
* @NL80211_ATTR_SCAN_START_TIME_TSF_BSSID: The BSS according to which
|
||||
* %NL80211_ATTR_SCAN_START_TIME_TSF is set.
|
||||
* @NL80211_ATTR_MEASUREMENT_DURATION: measurement duration in TUs (u16). If
|
||||
* %NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY is not set, this is the
|
||||
* maximum measurement duration allowed. This attribute is used with
|
||||
* measurement requests. It can also be used with %NL80211_CMD_TRIGGER_SCAN
|
||||
* if the scan is used for beacon report radio measurement.
|
||||
* @NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY: flag attribute that indicates
|
||||
* that the duration specified with %NL80211_ATTR_MEASUREMENT_DURATION is
|
||||
* mandatory. If this flag is not set, the duration is the maximum duration
|
||||
* and the actual measurement duration may be shorter.
|
||||
*
|
||||
* @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is
|
||||
* used to pull the stored data for mesh peer in power save state.
|
||||
*
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
|
@ -2213,6 +2251,16 @@ enum nl80211_attrs {
|
|||
|
||||
NL80211_ATTR_IFTYPE_EXT_CAPA,
|
||||
|
||||
NL80211_ATTR_MU_MIMO_GROUP_DATA,
|
||||
NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR,
|
||||
|
||||
NL80211_ATTR_SCAN_START_TIME_TSF,
|
||||
NL80211_ATTR_SCAN_START_TIME_TSF_BSSID,
|
||||
NL80211_ATTR_MEASUREMENT_DURATION,
|
||||
NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY,
|
||||
|
||||
NL80211_ATTR_MESH_PEER_AID,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
@ -3474,6 +3522,12 @@ enum nl80211_bss_scan_width {
|
|||
* was last updated by a received frame. The value is expected to be
|
||||
* accurate to about 10ms. (u64, nanoseconds)
|
||||
* @NL80211_BSS_PAD: attribute used for padding for 64-bit alignment
|
||||
* @NL80211_BSS_PARENT_TSF: the time at the start of reception of the first
|
||||
* octet of the timestamp field of the last beacon/probe received for
|
||||
* this BSS. The time is the TSF of the BSS specified by
|
||||
* @NL80211_BSS_PARENT_BSSID. (u64).
|
||||
* @NL80211_BSS_PARENT_BSSID: the BSS according to which @NL80211_BSS_PARENT_TSF
|
||||
* is set.
|
||||
* @__NL80211_BSS_AFTER_LAST: internal
|
||||
* @NL80211_BSS_MAX: highest BSS attribute
|
||||
*/
|
||||
|
@ -3495,6 +3549,8 @@ enum nl80211_bss {
|
|||
NL80211_BSS_PRESP_DATA,
|
||||
NL80211_BSS_LAST_SEEN_BOOTTIME,
|
||||
NL80211_BSS_PAD,
|
||||
NL80211_BSS_PARENT_TSF,
|
||||
NL80211_BSS_PARENT_BSSID,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_BSS_AFTER_LAST,
|
||||
|
@ -4479,6 +4535,22 @@ enum nl80211_feature_flags {
|
|||
* %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set
|
||||
* the ASSOC_REQ_USE_RRM flag in the association request even if
|
||||
* NL80211_FEATURE_QUIET is not advertized.
|
||||
* @NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER: This device supports MU-MIMO air
|
||||
* sniffer which means that it can be configured to hear packets from
|
||||
* certain groups which can be configured by the
|
||||
* %NL80211_ATTR_MU_MIMO_GROUP_DATA attribute,
|
||||
* or can be configured to follow a station by configuring the
|
||||
* %NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR attribute.
|
||||
* @NL80211_EXT_FEATURE_SCAN_START_TIME: This driver includes the actual
|
||||
* time the scan started in scan results event. The time is the TSF of
|
||||
* the BSS that the interface that requested the scan is connected to
|
||||
* (if available).
|
||||
* @NL80211_EXT_FEATURE_BSS_PARENT_TSF: Per BSS, this driver reports the
|
||||
* time the last beacon/probe was received. The time is the TSF of the
|
||||
* BSS that the interface that requested the scan is connected to
|
||||
* (if available).
|
||||
* @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of
|
||||
* channel dwell time.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
|
@ -4486,6 +4558,10 @@ enum nl80211_feature_flags {
|
|||
enum nl80211_ext_feature_index {
|
||||
NL80211_EXT_FEATURE_VHT_IBSS,
|
||||
NL80211_EXT_FEATURE_RRM,
|
||||
NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER,
|
||||
NL80211_EXT_FEATURE_SCAN_START_TIME,
|
||||
NL80211_EXT_FEATURE_BSS_PARENT_TSF,
|
||||
NL80211_EXT_FEATURE_SET_SCAN_DWELL,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
|
|
|
@ -306,6 +306,24 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
|
|||
mutex_lock(&sta->ampdu_mlme.mtx);
|
||||
|
||||
if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
|
||||
tid_agg_rx = rcu_dereference_protected(
|
||||
sta->ampdu_mlme.tid_rx[tid],
|
||||
lockdep_is_held(&sta->ampdu_mlme.mtx));
|
||||
|
||||
if (tid_agg_rx->dialog_token == dialog_token) {
|
||||
ht_dbg_ratelimited(sta->sdata,
|
||||
"updated AddBA Req from %pM on tid %u\n",
|
||||
sta->sta.addr, tid);
|
||||
/* We have no API to update the timeout value in the
|
||||
* driver so reject the timeout update.
|
||||
*/
|
||||
status = WLAN_STATUS_REQUEST_DECLINED;
|
||||
ieee80211_send_addba_resp(sta->sdata, sta->sta.addr,
|
||||
tid, dialog_token, status,
|
||||
1, buf_size, timeout);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ht_dbg_ratelimited(sta->sdata,
|
||||
"unexpected AddBA Req from %pM on tid %u\n",
|
||||
sta->sta.addr, tid);
|
||||
|
|
|
@ -997,6 +997,7 @@ static void sta_apply_mesh_params(struct ieee80211_local *local,
|
|||
if (sta->mesh->plink_state != NL80211_PLINK_ESTAB)
|
||||
changed = mesh_plink_inc_estab_count(sdata);
|
||||
sta->mesh->plink_state = params->plink_state;
|
||||
sta->mesh->aid = params->peer_aid;
|
||||
|
||||
ieee80211_mps_sta_status_update(sta);
|
||||
changed |= ieee80211_mps_set_sta_local_pm(sta,
|
||||
|
|
|
@ -1250,6 +1250,7 @@ struct ieee80211_local {
|
|||
int scan_channel_idx;
|
||||
int scan_ies_len;
|
||||
int hw_scan_ies_bufsize;
|
||||
struct cfg80211_scan_info scan_info;
|
||||
|
||||
struct work_struct sched_scan_stopped_work;
|
||||
struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
|
||||
|
|
|
@ -148,25 +148,7 @@ u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
|
|||
void mesh_sta_cleanup(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
u32 changed = 0;
|
||||
|
||||
/*
|
||||
* maybe userspace handles peer allocation and peering, but in either
|
||||
* case the beacon is still generated by the kernel and we might need
|
||||
* an update.
|
||||
*/
|
||||
if (sdata->u.mesh.user_mpm &&
|
||||
sta->mesh->plink_state == NL80211_PLINK_ESTAB)
|
||||
changed |= mesh_plink_dec_estab_count(sdata);
|
||||
changed |= mesh_accept_plinks_update(sdata);
|
||||
if (!sdata->u.mesh.user_mpm) {
|
||||
changed |= mesh_plink_deactivate(sta);
|
||||
del_timer_sync(&sta->mesh->plink_timer);
|
||||
}
|
||||
|
||||
/* make sure no readers can access nexthop sta from here on */
|
||||
mesh_path_flush_by_nexthop(sta);
|
||||
synchronize_net();
|
||||
u32 changed = mesh_plink_deactivate(sta);
|
||||
|
||||
if (changed)
|
||||
ieee80211_mbss_info_change_notify(sdata, changed);
|
||||
|
|
|
@ -370,13 +370,21 @@ u32 mesh_plink_deactivate(struct sta_info *sta)
|
|||
|
||||
spin_lock_bh(&sta->mesh->plink_lock);
|
||||
changed = __mesh_plink_deactivate(sta);
|
||||
|
||||
if (!sdata->u.mesh.user_mpm) {
|
||||
sta->mesh->reason = WLAN_REASON_MESH_PEER_CANCELED;
|
||||
mesh_plink_frame_tx(sdata, sta, WLAN_SP_MESH_PEERING_CLOSE,
|
||||
sta->sta.addr, sta->mesh->llid, sta->mesh->plid,
|
||||
sta->mesh->reason);
|
||||
sta->sta.addr, sta->mesh->llid,
|
||||
sta->mesh->plid, sta->mesh->reason);
|
||||
}
|
||||
spin_unlock_bh(&sta->mesh->plink_lock);
|
||||
if (!sdata->u.mesh.user_mpm)
|
||||
del_timer_sync(&sta->mesh->plink_timer);
|
||||
mesh_path_flush_by_nexthop(sta);
|
||||
|
||||
/* make sure no readers can access nexthop sta from here on */
|
||||
synchronize_net();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
|
|
@ -1624,8 +1624,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|||
if (mmie_keyidx < NUM_DEFAULT_KEYS ||
|
||||
mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
|
||||
return RX_DROP_MONITOR; /* unexpected BIP keyidx */
|
||||
if (rx->sta)
|
||||
if (rx->sta) {
|
||||
if (ieee80211_is_group_privacy_action(skb) &&
|
||||
test_sta_flag(rx->sta, WLAN_STA_MFP))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]);
|
||||
}
|
||||
if (!rx->key)
|
||||
rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
|
||||
} else if (!ieee80211_has_protected(fc)) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright 2016 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -70,6 +71,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
|||
.boottime_ns = rx_status->boottime_ns,
|
||||
};
|
||||
bool signal_valid;
|
||||
struct ieee80211_sub_if_data *scan_sdata;
|
||||
|
||||
if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
|
||||
bss_meta.signal = rx_status->signal * 100;
|
||||
|
@ -83,6 +85,20 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
|||
bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
|
||||
|
||||
bss_meta.chan = channel;
|
||||
|
||||
rcu_read_lock();
|
||||
scan_sdata = rcu_dereference(local->scan_sdata);
|
||||
if (scan_sdata && scan_sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
scan_sdata->vif.bss_conf.assoc &&
|
||||
ieee80211_have_rx_timestamp(rx_status)) {
|
||||
bss_meta.parent_tsf =
|
||||
ieee80211_calculate_rx_timestamp(local, rx_status,
|
||||
len + FCS_LEN, 24);
|
||||
ether_addr_copy(bss_meta.parent_bssid,
|
||||
scan_sdata->vif.bss_conf.bssid);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
|
||||
mgmt, len, GFP_ATOMIC);
|
||||
if (!cbss)
|
||||
|
@ -345,6 +361,12 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
|||
|
||||
if (rc == 0)
|
||||
return;
|
||||
|
||||
/* HW scan failed and is going to be reported as aborted,
|
||||
* so clear old scan info.
|
||||
*/
|
||||
memset(&local->scan_info, 0, sizeof(local->scan_info));
|
||||
aborted = true;
|
||||
}
|
||||
|
||||
kfree(local->hw_scan_req);
|
||||
|
@ -353,8 +375,10 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
|||
scan_req = rcu_dereference_protected(local->scan_req,
|
||||
lockdep_is_held(&local->mtx));
|
||||
|
||||
if (scan_req != local->int_scan_req)
|
||||
cfg80211_scan_done(scan_req, aborted);
|
||||
if (scan_req != local->int_scan_req) {
|
||||
local->scan_info.aborted = aborted;
|
||||
cfg80211_scan_done(scan_req, &local->scan_info);
|
||||
}
|
||||
RCU_INIT_POINTER(local->scan_req, NULL);
|
||||
|
||||
scan_sdata = rcu_dereference_protected(local->scan_sdata,
|
||||
|
@ -391,15 +415,19 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
|||
ieee80211_start_next_roc(local);
|
||||
}
|
||||
|
||||
void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
||||
void ieee80211_scan_completed(struct ieee80211_hw *hw,
|
||||
struct cfg80211_scan_info *info)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
|
||||
trace_api_scan_completed(local, aborted);
|
||||
trace_api_scan_completed(local, info);
|
||||
|
||||
set_bit(SCAN_COMPLETED, &local->scanning);
|
||||
if (aborted)
|
||||
if (info->aborted)
|
||||
set_bit(SCAN_ABORTED, &local->scanning);
|
||||
|
||||
memcpy(&local->scan_info, info, sizeof(*info));
|
||||
|
||||
ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_scan_completed);
|
||||
|
@ -566,6 +594,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
|||
local->hw_scan_req->req.ie = ies;
|
||||
local->hw_scan_req->req.flags = req->flags;
|
||||
eth_broadcast_addr(local->hw_scan_req->req.bssid);
|
||||
local->hw_scan_req->req.duration = req->duration;
|
||||
local->hw_scan_req->req.duration_mandatory =
|
||||
req->duration_mandatory;
|
||||
|
||||
local->hw_scan_band = 0;
|
||||
|
||||
|
@ -1073,6 +1104,7 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
|
|||
*/
|
||||
cancel_delayed_work(&local->scan_work);
|
||||
/* and clean up */
|
||||
memset(&local->scan_info, 0, sizeof(local->scan_info));
|
||||
__ieee80211_scan_completed(&local->hw, true);
|
||||
out:
|
||||
mutex_unlock(&local->mtx);
|
||||
|
|
|
@ -129,42 +129,31 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
if (wide_bw_chansw_ie) {
|
||||
new_vht_chandef.chan = new_chan;
|
||||
new_vht_chandef.center_freq1 =
|
||||
ieee80211_channel_to_frequency(
|
||||
struct ieee80211_vht_operation vht_oper = {
|
||||
.chan_width =
|
||||
wide_bw_chansw_ie->new_channel_width,
|
||||
.center_freq_seg1_idx =
|
||||
wide_bw_chansw_ie->new_center_freq_seg0,
|
||||
new_band);
|
||||
|
||||
switch (wide_bw_chansw_ie->new_channel_width) {
|
||||
default:
|
||||
/* hmmm, ignore VHT and use HT if present */
|
||||
case IEEE80211_VHT_CHANWIDTH_USE_HT:
|
||||
new_vht_chandef.chan = NULL;
|
||||
break;
|
||||
case IEEE80211_VHT_CHANWIDTH_80MHZ:
|
||||
new_vht_chandef.width = NL80211_CHAN_WIDTH_80;
|
||||
break;
|
||||
case IEEE80211_VHT_CHANWIDTH_160MHZ:
|
||||
new_vht_chandef.width = NL80211_CHAN_WIDTH_160;
|
||||
break;
|
||||
case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
|
||||
/* field is otherwise reserved */
|
||||
new_vht_chandef.center_freq2 =
|
||||
ieee80211_channel_to_frequency(
|
||||
.center_freq_seg2_idx =
|
||||
wide_bw_chansw_ie->new_center_freq_seg1,
|
||||
new_band);
|
||||
new_vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
|
||||
break;
|
||||
}
|
||||
/* .basic_mcs_set doesn't matter */
|
||||
};
|
||||
|
||||
/* default, for the case of IEEE80211_VHT_CHANWIDTH_USE_HT,
|
||||
* to the previously parsed chandef
|
||||
*/
|
||||
new_vht_chandef = csa_ie->chandef;
|
||||
|
||||
/* ignore if parsing fails */
|
||||
if (!ieee80211_chandef_vht_oper(&vht_oper, &new_vht_chandef))
|
||||
new_vht_chandef.chan = NULL;
|
||||
|
||||
if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ &&
|
||||
new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80)
|
||||
ieee80211_chandef_downgrade(&new_vht_chandef);
|
||||
if (sta_flags & IEEE80211_STA_DISABLE_160MHZ &&
|
||||
new_vht_chandef.width == NL80211_CHAN_WIDTH_160)
|
||||
ieee80211_chandef_downgrade(&new_vht_chandef);
|
||||
if (sta_flags & IEEE80211_STA_DISABLE_40MHZ &&
|
||||
new_vht_chandef.width > NL80211_CHAN_WIDTH_20)
|
||||
ieee80211_chandef_downgrade(&new_vht_chandef);
|
||||
}
|
||||
|
||||
/* if VHT data is there validate & use it */
|
||||
|
|
|
@ -1747,6 +1747,7 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata,
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
call_drv:
|
||||
drv_tdls_recv_channel_switch(sdata->local, sdata, ¶ms);
|
||||
|
||||
|
|
|
@ -593,6 +593,9 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
|
|||
else if (tx->sta &&
|
||||
(key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
|
||||
tx->key = key;
|
||||
else if (ieee80211_is_group_privacy_action(tx->skb) &&
|
||||
(key = rcu_dereference(tx->sdata->default_multicast_key)))
|
||||
tx->key = key;
|
||||
else if (ieee80211_is_mgmt(hdr->frame_control) &&
|
||||
is_multicast_ether_addr(hdr->addr1) &&
|
||||
ieee80211_is_robust_mgmt_frame(tx->skb) &&
|
||||
|
@ -625,7 +628,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
|
|||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
if (!ieee80211_is_data_present(hdr->frame_control) &&
|
||||
!ieee80211_use_mfp(hdr->frame_control, tx->sta,
|
||||
tx->skb))
|
||||
tx->skb) &&
|
||||
!ieee80211_is_group_privacy_action(tx->skb))
|
||||
tx->key = NULL;
|
||||
else
|
||||
skip_hw = (tx->key->conf.flags &
|
||||
|
@ -1445,7 +1449,9 @@ int ieee80211_txq_setup_flows(struct ieee80211_local *local)
|
|||
local->cvars = kcalloc(fq->flows_cnt, sizeof(local->cvars[0]),
|
||||
GFP_KERNEL);
|
||||
if (!local->cvars) {
|
||||
spin_lock_bh(&fq->lock);
|
||||
fq_reset(fq, fq_skb_free_func);
|
||||
spin_unlock_bh(&fq->lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -1465,7 +1471,9 @@ void ieee80211_txq_teardown_flows(struct ieee80211_local *local)
|
|||
kfree(local->cvars);
|
||||
local->cvars = NULL;
|
||||
|
||||
spin_lock_bh(&fq->lock);
|
||||
fq_reset(fq, fq_skb_free_func);
|
||||
spin_unlock_bh(&fq->lock);
|
||||
}
|
||||
|
||||
struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
|
||||
|
|
|
@ -220,7 +220,7 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
|
|||
|
||||
if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
|
||||
if (WARN_ON(!rdev->scan_req->notified))
|
||||
rdev->scan_req->aborted = true;
|
||||
rdev->scan_req->info.aborted = true;
|
||||
___cfg80211_scan_done(rdev, false);
|
||||
}
|
||||
}
|
||||
|
@ -1087,7 +1087,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
cfg80211_update_iface_num(rdev, wdev->iftype, -1);
|
||||
if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
|
||||
if (WARN_ON(!rdev->scan_req->notified))
|
||||
rdev->scan_req->aborted = true;
|
||||
rdev->scan_req->info.aborted = true;
|
||||
___cfg80211_scan_done(rdev, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -141,6 +141,18 @@ struct cfg80211_internal_bss {
|
|||
unsigned long refcount;
|
||||
atomic_t hold;
|
||||
|
||||
/* time at the start of the reception of the first octet of the
|
||||
* timestamp field of the last beacon/probe received for this BSS.
|
||||
* The time is the TSF of the BSS specified by %parent_bssid.
|
||||
*/
|
||||
u64 parent_tsf;
|
||||
|
||||
/* the BSS according to which %parent_tsf is set. This is set to
|
||||
* the BSS that the interface that requested the scan was connected to
|
||||
* when the beacon/probe was received.
|
||||
*/
|
||||
u8 parent_bssid[ETH_ALEN] __aligned(2);
|
||||
|
||||
/* must be last because of priv member */
|
||||
struct cfg80211_bss pub;
|
||||
};
|
||||
|
|
|
@ -405,6 +405,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|||
[NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
|
||||
[NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
|
||||
.len = VHT_MUMIMO_GROUPS_DATA_LEN
|
||||
},
|
||||
[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
@ -2695,6 +2699,38 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
|||
change = true;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) {
|
||||
const u8 *mumimo_groups;
|
||||
u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
|
||||
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mumimo_groups =
|
||||
nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
|
||||
|
||||
/* bits 0 and 63 are reserved and must be zero */
|
||||
if ((mumimo_groups[0] & BIT(7)) ||
|
||||
(mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(0)))
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(params.vht_mumimo_groups, mumimo_groups,
|
||||
VHT_MUMIMO_GROUPS_DATA_LEN);
|
||||
change = true;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) {
|
||||
u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
|
||||
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
nla_memcpy(params.macaddr,
|
||||
info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR],
|
||||
ETH_ALEN);
|
||||
change = true;
|
||||
}
|
||||
|
||||
if (flags && (*flags & MONITOR_FLAG_ACTIVE) &&
|
||||
!(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -4410,6 +4446,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
|||
nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
|
||||
if (params.plink_state >= NUM_NL80211_PLINK_STATES)
|
||||
return -EINVAL;
|
||||
if (info->attrs[NL80211_ATTR_MESH_PEER_AID]) {
|
||||
params.peer_aid = nla_get_u16(
|
||||
info->attrs[NL80211_ATTR_MESH_PEER_AID]);
|
||||
if (params.peer_aid > IEEE80211_MAX_AID)
|
||||
return -EINVAL;
|
||||
}
|
||||
params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
|
||||
}
|
||||
|
||||
|
@ -5287,6 +5329,51 @@ static const struct nla_policy
|
|||
[NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
static int nl80211_check_bool(const struct nlattr *nla, u8 min, u8 max, bool *out)
|
||||
{
|
||||
u8 val = nla_get_u8(nla);
|
||||
if (val < min || val > max)
|
||||
return -EINVAL;
|
||||
*out = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_check_u8(const struct nlattr *nla, u8 min, u8 max, u8 *out)
|
||||
{
|
||||
u8 val = nla_get_u8(nla);
|
||||
if (val < min || val > max)
|
||||
return -EINVAL;
|
||||
*out = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_check_u16(const struct nlattr *nla, u16 min, u16 max, u16 *out)
|
||||
{
|
||||
u16 val = nla_get_u16(nla);
|
||||
if (val < min || val > max)
|
||||
return -EINVAL;
|
||||
*out = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_check_u32(const struct nlattr *nla, u32 min, u32 max, u32 *out)
|
||||
{
|
||||
u32 val = nla_get_u32(nla);
|
||||
if (val < min || val > max)
|
||||
return -EINVAL;
|
||||
*out = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_check_s32(const struct nlattr *nla, s32 min, s32 max, s32 *out)
|
||||
{
|
||||
s32 val = nla_get_s32(nla);
|
||||
if (val < min || val > max)
|
||||
return -EINVAL;
|
||||
*out = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_parse_mesh_config(struct genl_info *info,
|
||||
struct mesh_config *cfg,
|
||||
u32 *mask_out)
|
||||
|
@ -5297,9 +5384,8 @@ static int nl80211_parse_mesh_config(struct genl_info *info,
|
|||
#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \
|
||||
do { \
|
||||
if (tb[attr]) { \
|
||||
if (fn(tb[attr]) < min || fn(tb[attr]) > max) \
|
||||
if (fn(tb[attr], min, max, &cfg->param)) \
|
||||
return -EINVAL; \
|
||||
cfg->param = fn(tb[attr]); \
|
||||
mask |= (1 << (attr - 1)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -5318,99 +5404,99 @@ do { \
|
|||
/* Fill in the params struct */
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255,
|
||||
mask, NL80211_MESHCONF_RETRY_TIMEOUT,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255,
|
||||
mask, NL80211_MESHCONF_CONFIRM_TIMEOUT,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255,
|
||||
mask, NL80211_MESHCONF_HOLDING_TIMEOUT,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255,
|
||||
mask, NL80211_MESHCONF_MAX_PEER_LINKS,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16,
|
||||
mask, NL80211_MESHCONF_MAX_RETRIES,
|
||||
nla_get_u8);
|
||||
nl80211_check_u8);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255,
|
||||
mask, NL80211_MESHCONF_TTL, nla_get_u8);
|
||||
mask, NL80211_MESHCONF_TTL, nl80211_check_u8);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255,
|
||||
mask, NL80211_MESHCONF_ELEMENT_TTL,
|
||||
nla_get_u8);
|
||||
nl80211_check_u8);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1,
|
||||
mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
|
||||
nla_get_u8);
|
||||
nl80211_check_bool);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
|
||||
1, 255, mask,
|
||||
NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
|
||||
nla_get_u32);
|
||||
nl80211_check_u32);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255,
|
||||
mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
|
||||
nla_get_u8);
|
||||
nl80211_check_u8);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535,
|
||||
mask, NL80211_MESHCONF_PATH_REFRESH_TIME,
|
||||
nla_get_u32);
|
||||
nl80211_check_u32);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535,
|
||||
mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
|
||||
1, 65535, mask,
|
||||
NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
|
||||
nla_get_u32);
|
||||
nl80211_check_u32);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
|
||||
1, 65535, mask,
|
||||
NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval,
|
||||
1, 65535, mask,
|
||||
NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
|
||||
dot11MeshHWMPnetDiameterTraversalTime,
|
||||
1, 65535, mask,
|
||||
NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4,
|
||||
mask, NL80211_MESHCONF_HWMP_ROOTMODE,
|
||||
nla_get_u8);
|
||||
nl80211_check_u8);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535,
|
||||
mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
|
||||
dot11MeshGateAnnouncementProtocol, 0, 1,
|
||||
mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
|
||||
nla_get_u8);
|
||||
nl80211_check_bool);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,
|
||||
mask, NL80211_MESHCONF_FORWARDING,
|
||||
nla_get_u8);
|
||||
nl80211_check_bool);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
|
||||
mask, NL80211_MESHCONF_RSSI_THRESHOLD,
|
||||
nla_get_s32);
|
||||
nl80211_check_s32);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16,
|
||||
mask, NL80211_MESHCONF_HT_OPMODE,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
|
||||
1, 65535, mask,
|
||||
NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
|
||||
nla_get_u32);
|
||||
nl80211_check_u32);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, 1, 65535,
|
||||
mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
|
||||
dot11MeshHWMPconfirmationInterval,
|
||||
1, 65535, mask,
|
||||
NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
|
||||
nla_get_u16);
|
||||
nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode,
|
||||
NL80211_MESH_POWER_ACTIVE,
|
||||
NL80211_MESH_POWER_MAX,
|
||||
mask, NL80211_MESHCONF_POWER_MODE,
|
||||
nla_get_u32);
|
||||
nl80211_check_u32);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,
|
||||
0, 65535, mask,
|
||||
NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
|
||||
NL80211_MESHCONF_AWAKE_WINDOW, nl80211_check_u16);
|
||||
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff,
|
||||
mask, NL80211_MESHCONF_PLINK_TIMEOUT,
|
||||
nla_get_u32);
|
||||
nl80211_check_u32);
|
||||
if (mask_out)
|
||||
*mask_out = mask;
|
||||
|
||||
|
@ -6143,6 +6229,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
|
||||
if (!wiphy_ext_feature_isset(wiphy,
|
||||
NL80211_EXT_FEATURE_SET_SCAN_DWELL)) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
request->duration =
|
||||
nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
|
||||
request->duration_mandatory =
|
||||
nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]);
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
|
||||
request->flags = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_SCAN_FLAGS]);
|
||||
|
@ -6976,6 +7075,13 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
|
|||
jiffies_to_msecs(jiffies - intbss->ts)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (intbss->parent_tsf &&
|
||||
(nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
|
||||
intbss->parent_tsf, NL80211_BSS_PAD) ||
|
||||
nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
|
||||
intbss->parent_bssid)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (intbss->ts_boottime &&
|
||||
nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
|
||||
intbss->ts_boottime, NL80211_BSS_PAD))
|
||||
|
@ -11749,6 +11855,13 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
|
|||
nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (req->info.scan_start_tsf &&
|
||||
(nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
|
||||
req->info.scan_start_tsf, NL80211_BSS_PAD) ||
|
||||
nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
|
||||
req->info.tsf_bssid)))
|
||||
goto nla_put_failure;
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -ENOBUFS;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright 2016 Intel Deutschland GmbH
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -194,7 +195,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
|
|||
if (wdev->netdev)
|
||||
cfg80211_sme_scan_done(wdev->netdev);
|
||||
|
||||
if (!request->aborted &&
|
||||
if (!request->info.aborted &&
|
||||
request->flags & NL80211_SCAN_FLAG_FLUSH) {
|
||||
/* flush entries from previous scans */
|
||||
spin_lock_bh(&rdev->bss_lock);
|
||||
|
@ -202,10 +203,10 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
|
|||
spin_unlock_bh(&rdev->bss_lock);
|
||||
}
|
||||
|
||||
msg = nl80211_build_scan_msg(rdev, wdev, request->aborted);
|
||||
msg = nl80211_build_scan_msg(rdev, wdev, request->info.aborted);
|
||||
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (wdev->netdev && !request->aborted) {
|
||||
if (wdev->netdev && !request->info.aborted) {
|
||||
memset(&wrqu, 0, sizeof(wrqu));
|
||||
|
||||
wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL);
|
||||
|
@ -236,12 +237,13 @@ void __cfg80211_scan_done(struct work_struct *wk)
|
|||
rtnl_unlock();
|
||||
}
|
||||
|
||||
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
|
||||
void cfg80211_scan_done(struct cfg80211_scan_request *request,
|
||||
struct cfg80211_scan_info *info)
|
||||
{
|
||||
trace_cfg80211_scan_done(request, aborted);
|
||||
trace_cfg80211_scan_done(request, info);
|
||||
WARN_ON(request != wiphy_to_rdev(request->wiphy)->scan_req);
|
||||
|
||||
request->aborted = aborted;
|
||||
request->info = *info;
|
||||
request->notified = true;
|
||||
queue_work(cfg80211_wq, &wiphy_to_rdev(request->wiphy)->scan_done_wk);
|
||||
}
|
||||
|
@ -843,6 +845,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
|
|||
found->pub.capability = tmp->pub.capability;
|
||||
found->ts = tmp->ts;
|
||||
found->ts_boottime = tmp->ts_boottime;
|
||||
found->parent_tsf = tmp->parent_tsf;
|
||||
ether_addr_copy(found->parent_bssid, tmp->parent_bssid);
|
||||
} else {
|
||||
struct cfg80211_internal_bss *new;
|
||||
struct cfg80211_internal_bss *hidden;
|
||||
|
@ -1086,6 +1090,8 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
|
|||
tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
|
||||
tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
|
||||
tmp.ts_boottime = data->boottime_ns;
|
||||
tmp.parent_tsf = data->parent_tsf;
|
||||
ether_addr_copy(tmp.parent_bssid, data->parent_bssid);
|
||||
|
||||
signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
|
||||
wiphy->max_adj_channel_rssi_comp;
|
||||
|
|
|
@ -2642,8 +2642,9 @@ TRACE_EVENT(cfg80211_tdls_oper_request,
|
|||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_scan_done,
|
||||
TP_PROTO(struct cfg80211_scan_request *request, bool aborted),
|
||||
TP_ARGS(request, aborted),
|
||||
TP_PROTO(struct cfg80211_scan_request *request,
|
||||
struct cfg80211_scan_info *info),
|
||||
TP_ARGS(request, info),
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, n_channels)
|
||||
__dynamic_array(u8, ie, request ? request->ie_len : 0)
|
||||
|
@ -2652,6 +2653,8 @@ TRACE_EVENT(cfg80211_scan_done,
|
|||
MAC_ENTRY(wiphy_mac)
|
||||
__field(bool, no_cck)
|
||||
__field(bool, aborted)
|
||||
__field(u64, scan_start_tsf)
|
||||
MAC_ENTRY(tsf_bssid)
|
||||
),
|
||||
TP_fast_assign(
|
||||
if (request) {
|
||||
|
@ -2666,9 +2669,16 @@ TRACE_EVENT(cfg80211_scan_done,
|
|||
request->wiphy->perm_addr);
|
||||
__entry->no_cck = request->no_cck;
|
||||
}
|
||||
__entry->aborted = aborted;
|
||||
if (info) {
|
||||
__entry->aborted = info->aborted;
|
||||
__entry->scan_start_tsf = info->scan_start_tsf;
|
||||
MAC_ASSIGN(tsf_bssid, info->tsf_bssid);
|
||||
}
|
||||
),
|
||||
TP_printk("aborted: %s", BOOL_TO_STR(__entry->aborted))
|
||||
TP_printk("aborted: %s, scan start (TSF): %llu, tsf_bssid: " MAC_PR_FMT,
|
||||
BOOL_TO_STR(__entry->aborted),
|
||||
(unsigned long long)__entry->scan_start_tsf,
|
||||
MAC_PR_ARG(tsf_bssid))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_results,
|
||||
|
@ -2721,6 +2731,8 @@ TRACE_EVENT(cfg80211_inform_bss_frame,
|
|||
__dynamic_array(u8, mgmt, len)
|
||||
__field(s32, signal)
|
||||
__field(u64, ts_boottime)
|
||||
__field(u64, parent_tsf)
|
||||
MAC_ENTRY(parent_bssid)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
|
@ -2730,10 +2742,15 @@ TRACE_EVENT(cfg80211_inform_bss_frame,
|
|||
memcpy(__get_dynamic_array(mgmt), mgmt, len);
|
||||
__entry->signal = data->signal;
|
||||
__entry->ts_boottime = data->boottime_ns;
|
||||
__entry->parent_tsf = data->parent_tsf;
|
||||
MAC_ASSIGN(parent_bssid, data->parent_bssid);
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "(scan_width: %d) signal: %d, tsb:%llu",
|
||||
WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width,
|
||||
__entry->signal, (unsigned long long)__entry->ts_boottime)
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT
|
||||
"(scan_width: %d) signal: %d, tsb:%llu, detect_tsf:%llu, tsf_bssid: "
|
||||
MAC_PR_FMT, WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width,
|
||||
__entry->signal, (unsigned long long)__entry->ts_boottime,
|
||||
(unsigned long long)__entry->parent_tsf,
|
||||
MAC_PR_ARG(parent_bssid))
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(cfg80211_bss_evt,
|
||||
|
|
Loading…
Reference in New Issue