Commit 1d76250b authored by Avraham Stern's avatar Avraham Stern Committed by Johannes Berg

nl80211: support beacon report scanning

Beacon report radio measurement requires reporting observed BSSs
on the channels specified in the beacon request. If the measurement
mode is set to passive or active, it requires actually performing a
scan (passive or active, accordingly), and reporting the time that
the scan was started and the time each beacon/probe was received
(both in terms of TSF of the BSS of the requesting AP). If the
request mode is table, this information is optional.
In addition, the radio measurement request specifies the channel
dwell time for the measurement.

In order to use scan for beacon report when the mode is active or
passive, add a parameter to scan request that specifies the
channel dwell time, and add scan start time and beacon received time
to scan results information.

Supporting beacon report is required for Multi Band Operation (MBO).
Signed-off-by: default avatarAssaf Krauss <assaf.krauss@intel.com>
Signed-off-by: default avatarDavid Spinadel <david.spinadel@intel.com>
Signed-off-by: default avatarAvraham Stern <avraham.stern@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent f1724b02
...@@ -859,7 +859,11 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, ...@@ -859,7 +859,11 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
struct ath6kl *ar = vif->ar; struct ath6kl *ar = vif->ar;
if (vif->scan_req) { 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; vif->scan_req = NULL;
} }
...@@ -1069,6 +1073,9 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, ...@@ -1069,6 +1073,9 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted) void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
{ {
struct ath6kl *ar = vif->ar; struct ath6kl *ar = vif->ar;
struct cfg80211_scan_info info = {
.aborted = aborted,
};
int i; int i;
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__, 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) ...@@ -1089,7 +1096,7 @@ void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
} }
out: out:
cfg80211_scan_done(vif->scan_req, aborted); cfg80211_scan_done(vif->scan_req, &info);
vif->scan_req = NULL; vif->scan_req = NULL;
} }
...@@ -3614,7 +3621,11 @@ void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready) ...@@ -3614,7 +3621,11 @@ void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready)
} }
if (vif->scan_req) { 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; vif->scan_req = NULL;
} }
......
...@@ -1369,7 +1369,11 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy, ...@@ -1369,7 +1369,11 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
mutex_lock(&wil->mutex); mutex_lock(&wil->mutex);
started = wil_p2p_stop_discovery(wil); started = wil_p2p_stop_discovery(wil);
if (started && wil->scan_request) { 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->scan_request = NULL;
wil->radio_wdev = wil->wdev; wil->radio_wdev = wil->wdev;
} }
......
...@@ -850,10 +850,14 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) ...@@ -850,10 +850,14 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
mutex_unlock(&wil->wmi_mutex); mutex_unlock(&wil->wmi_mutex);
if (wil->scan_request) { if (wil->scan_request) {
struct cfg80211_scan_info info = {
.aborted = true,
};
wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
wil->scan_request); wil->scan_request);
del_timer_sync(&wil->scan_timer); del_timer_sync(&wil->scan_timer);
cfg80211_scan_done(wil->scan_request, true); cfg80211_scan_done(wil->scan_request, &info);
wil->scan_request = NULL; wil->scan_request = NULL;
} }
...@@ -1049,10 +1053,14 @@ int __wil_down(struct wil6210_priv *wil) ...@@ -1049,10 +1053,14 @@ int __wil_down(struct wil6210_priv *wil)
(void)wil_p2p_stop_discovery(wil); (void)wil_p2p_stop_discovery(wil);
if (wil->scan_request) { if (wil->scan_request) {
struct cfg80211_scan_info info = {
.aborted = true,
};
wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
wil->scan_request); wil->scan_request);
del_timer_sync(&wil->scan_timer); del_timer_sync(&wil->scan_timer);
cfg80211_scan_done(wil->scan_request, true); cfg80211_scan_done(wil->scan_request, &info);
wil->scan_request = NULL; wil->scan_request = NULL;
} }
......
...@@ -252,8 +252,12 @@ void wil_p2p_search_expired(struct work_struct *work) ...@@ -252,8 +252,12 @@ void wil_p2p_search_expired(struct work_struct *work)
mutex_unlock(&wil->mutex); mutex_unlock(&wil->mutex);
if (started) { if (started) {
struct cfg80211_scan_info info = {
.aborted = false,
};
mutex_lock(&wil->p2p_wdev_mutex); 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->scan_request = NULL;
wil->radio_wdev = wil->wdev; wil->radio_wdev = wil->wdev;
mutex_unlock(&wil->p2p_wdev_mutex); mutex_unlock(&wil->p2p_wdev_mutex);
......
...@@ -426,15 +426,17 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, ...@@ -426,15 +426,17 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
{ {
if (wil->scan_request) { if (wil->scan_request) {
struct wmi_scan_complete_event *data = d; 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_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n", 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); del_timer_sync(&wil->scan_timer);
mutex_lock(&wil->p2p_wdev_mutex); 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; wil->radio_wdev = wil->wdev;
mutex_unlock(&wil->p2p_wdev_mutex); mutex_unlock(&wil->p2p_wdev_mutex);
wil->scan_request = NULL; wil->scan_request = NULL;
......
...@@ -775,9 +775,13 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, ...@@ -775,9 +775,13 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
if (!aborted) if (!aborted)
cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
} else if (scan_request) { } else if (scan_request) {
struct cfg80211_scan_info info = {
.aborted = aborted,
};
brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n", brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
aborted ? "Aborted" : "Done"); 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)) if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n"); brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");
......
...@@ -237,7 +237,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv, ...@@ -237,7 +237,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv,
scan_abort: scan_abort:
if (priv->scan_request) { 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; priv->scan_request = NULL;
} }
} }
...@@ -245,7 +249,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv, ...@@ -245,7 +249,11 @@ void orinoco_add_hostscan_results(struct orinoco_private *priv,
void orinoco_scan_done(struct orinoco_private *priv, bool abort) void orinoco_scan_done(struct orinoco_private *priv, bool abort)
{ {
if (priv->scan_request) { 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; priv->scan_request = NULL;
} }
} }
...@@ -796,10 +796,15 @@ void lbs_scan_done(struct lbs_private *priv) ...@@ -796,10 +796,15 @@ void lbs_scan_done(struct lbs_private *priv)
{ {
WARN_ON(!priv->scan_req); WARN_ON(!priv->scan_req);
if (priv->internal_scan) if (priv->internal_scan) {
kfree(priv->scan_req); kfree(priv->scan_req);
else } else {
cfg80211_scan_done(priv->scan_req, false); struct cfg80211_scan_info info = {
.aborted = false,
};
cfg80211_scan_done(priv->scan_req, &info);
}
priv->scan_req = NULL; priv->scan_req = NULL;
} }
......
...@@ -1057,8 +1057,12 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) ...@@ -1057,8 +1057,12 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
if (!priv) if (!priv)
continue; continue;
if (priv->scan_request) { if (priv->scan_request) {
struct cfg80211_scan_info info = {
.aborted = true,
};
mwifiex_dbg(adapter, WARN, "info: aborting scan\n"); 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; priv->scan_request = NULL;
} }
} }
...@@ -1112,8 +1116,12 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) ...@@ -1112,8 +1116,12 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
if (!priv) if (!priv)
continue; continue;
if (priv->scan_request) { if (priv->scan_request) {
struct cfg80211_scan_info info = {
.aborted = true,
};
mwifiex_dbg(adapter, WARN, "info: aborting scan\n"); 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; priv->scan_request = NULL;
} }
} }
......
...@@ -697,9 +697,13 @@ mwifiex_close(struct net_device *dev) ...@@ -697,9 +697,13 @@ mwifiex_close(struct net_device *dev)
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
if (priv->scan_request) { if (priv->scan_request) {
struct cfg80211_scan_info info = {
.aborted = true,
};
mwifiex_dbg(priv->adapter, INFO, mwifiex_dbg(priv->adapter, INFO,
"aborting scan on ndo_stop\n"); "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_request = NULL;
priv->scan_aborting = true; priv->scan_aborting = true;
} }
......
...@@ -1956,9 +1956,13 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv) ...@@ -1956,9 +1956,13 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
mwifiex_complete_scan(priv); mwifiex_complete_scan(priv);
if (priv->scan_request) { if (priv->scan_request) {
struct cfg80211_scan_info info = {
.aborted = false,
};
mwifiex_dbg(adapter, INFO, mwifiex_dbg(adapter, INFO,
"info: notifying scan done\n"); "info: notifying scan done\n");
cfg80211_scan_done(priv->scan_request, 0); cfg80211_scan_done(priv->scan_request, &info);
priv->scan_request = NULL; priv->scan_request = NULL;
} else { } else {
priv->scan_aborting = false; priv->scan_aborting = false;
...@@ -1977,9 +1981,13 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv) ...@@ -1977,9 +1981,13 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
if (!adapter->active_scan_triggered) { if (!adapter->active_scan_triggered) {
if (priv->scan_request) { if (priv->scan_request) {
struct cfg80211_scan_info info = {
.aborted = true,
};
mwifiex_dbg(adapter, INFO, mwifiex_dbg(adapter, INFO,
"info: aborting scan\n"); "info: aborting scan\n");
cfg80211_scan_done(priv->scan_request, 1); cfg80211_scan_done(priv->scan_request, &info);
priv->scan_request = NULL; priv->scan_request = NULL;
} else { } else {
priv->scan_aborting = false; priv->scan_aborting = false;
......
...@@ -2134,6 +2134,7 @@ static void rndis_get_scan_results(struct work_struct *work) ...@@ -2134,6 +2134,7 @@ static void rndis_get_scan_results(struct work_struct *work)
struct rndis_wlan_private *priv = struct rndis_wlan_private *priv =
container_of(work, struct rndis_wlan_private, scan_work.work); container_of(work, struct rndis_wlan_private, scan_work.work);
struct usbnet *usbdev = priv->usbdev; struct usbnet *usbdev = priv->usbdev;
struct cfg80211_scan_info info = {};
int ret; int ret;
netdev_dbg(usbdev->net, "get_scan_results\n"); netdev_dbg(usbdev->net, "get_scan_results\n");
...@@ -2143,7 +2144,8 @@ static void rndis_get_scan_results(struct work_struct *work) ...@@ -2143,7 +2144,8 @@ static void rndis_get_scan_results(struct work_struct *work)
ret = rndis_check_bssid_list(usbdev, NULL, NULL); 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; priv->scan_request = NULL;
} }
...@@ -3574,7 +3576,11 @@ static int rndis_wlan_stop(struct usbnet *usbdev) ...@@ -3574,7 +3576,11 @@ static int rndis_wlan_stop(struct usbnet *usbdev)
flush_workqueue(priv->workqueue); flush_workqueue(priv->workqueue);
if (priv->scan_request) { 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; priv->scan_request = NULL;
} }
......
...@@ -1256,10 +1256,15 @@ void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv, ...@@ -1256,10 +1256,15 @@ void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
DBG_8723A("%s with scan req\n", __func__); DBG_8723A("%s with scan req\n", __func__);
if (pwdev_priv->scan_request->wiphy != if (pwdev_priv->scan_request->wiphy !=
pwdev_priv->rtw_wdev->wiphy) pwdev_priv->rtw_wdev->wiphy) {
DBG_8723A("error wiphy compare\n"); DBG_8723A("error wiphy compare\n");
else } else {
cfg80211_scan_done(pwdev_priv->scan_request, aborted); struct cfg80211_scan_info info = {
.aborted = aborted,
};
cfg80211_scan_done(pwdev_priv->scan_request, &info);
}
pwdev_priv->scan_request = NULL; pwdev_priv->scan_request = NULL;
} else { } else {
......
...@@ -454,7 +454,11 @@ static void CfgScanResult(enum scan_event scan_event, ...@@ -454,7 +454,11 @@ static void CfgScanResult(enum scan_event scan_event,
mutex_lock(&priv->scan_req_lock); mutex_lock(&priv->scan_req_lock);
if (priv->pstrScanReq) { 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->u32RcvdChCount = 0;
priv->bCfgScanning = false; priv->bCfgScanning = false;
priv->pstrScanReq = NULL; priv->pstrScanReq = NULL;
...@@ -464,10 +468,14 @@ static void CfgScanResult(enum scan_event scan_event, ...@@ -464,10 +468,14 @@ static void CfgScanResult(enum scan_event scan_event,
mutex_lock(&priv->scan_req_lock); mutex_lock(&priv->scan_req_lock);
if (priv->pstrScanReq) { if (priv->pstrScanReq) {
struct cfg80211_scan_info info = {
.aborted = false,
};
update_scan_time(); update_scan_time();
refresh_scan(priv, 1, false); refresh_scan(priv, 1, false);
cfg80211_scan_done(priv->pstrScanReq, false); cfg80211_scan_done(priv->pstrScanReq, &info);
priv->bCfgScanning = false; priv->bCfgScanning = false;
priv->pstrScanReq = NULL; priv->pstrScanReq = NULL;
} }
......
...@@ -338,6 +338,8 @@ static int prism2_scan(struct wiphy *wiphy, ...@@ -338,6 +338,8 @@ static int prism2_scan(struct wiphy *wiphy,
struct p80211msg_dot11req_scan msg1; struct p80211msg_dot11req_scan msg1;
struct p80211msg_dot11req_scan_results msg2; struct p80211msg_dot11req_scan_results msg2;
struct cfg80211_bss *bss; struct cfg80211_bss *bss;
struct cfg80211_scan_info info = {};
int result; int result;
int err = 0; int err = 0;
int numbss = 0; int numbss = 0;
...@@ -440,7 +442,8 @@ static int prism2_scan(struct wiphy *wiphy, ...@@ -440,7 +442,8 @@ static int prism2_scan(struct wiphy *wiphy,
err = prism2_result2err(msg2.resultcode.data); err = prism2_result2err(msg2.resultcode.data);
exit: exit:
cfg80211_scan_done(request, err ? 1 : 0); info.aborted = !!(err);
cfg80211_scan_done(request, &info);
priv->scan_request = NULL; priv->scan_request = NULL;
return err; return err;
} }
......
...@@ -1423,6 +1423,21 @@ struct cfg80211_ssid { ...@@ -1423,6 +1423,21 @@ struct cfg80211_ssid {
u8 ssid_len; 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 * struct cfg80211_scan_request - scan request description
* *
...@@ -1433,12 +1448,17 @@ struct cfg80211_ssid { ...@@ -1433,12 +1448,17 @@ struct cfg80211_ssid {
* @scan_width: channel width for scanning * @scan_width: channel width for scanning
* @ie: optional information element(s) to add into Probe Request or %NULL * @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets * @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 * @flags: bit field of flags controlling operation
* @rates: bitmap of rates to advertise for each band * @rates: bitmap of rates to advertise for each band
* @wiphy: the wiphy this was for * @wiphy: the wiphy this was for
* @scan_start: time (in jiffies) when the scan started * @scan_start: time (in jiffies) when the scan started
* @wdev: the wireless device to scan for * @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 * @notified: (internal) scan request was notified as done or aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band * @no_cck: used to send probe requests at non CCK rate in 2GHz band
* @mac_addr: MAC address used with randomisation * @mac_addr: MAC address used with randomisation
...@@ -1454,6 +1474,8 @@ struct cfg80211_scan_request { ...@@ -1454,6 +1474,8 @@ struct cfg80211_scan_request {
enum nl80211_bss_scan_width scan_width; enum nl80211_bss_scan_width scan_width;
const u8 *ie; const u8 *ie;
size_t ie_len; size_t ie_len;
u16 duration;
bool duration_mandatory;
u32 flags; u32 flags;
u32 rates[NUM_NL80211_BANDS]; u32 rates[NUM_NL80211_BANDS];
...@@ -1467,7 +1489,8 @@ struct cfg80211_scan_request { ...@@ -1467,7 +1489,8 @@ struct cfg80211_scan_request {
/* internal */ /* internal */
struct wiphy *wiphy; struct wiphy *wiphy;
unsigned long scan_start; unsigned long scan_start;
bool aborted, notified; struct cfg80211_scan_info info;
bool notified;
bool no_cck; bool no_cck;
/* keep last */ /* keep last */
...@@ -1600,12 +1623,19 @@ enum cfg80211_signal_type { ...@@ -1600,12 +1623,19 @@ enum cfg80211_signal_type {
* buffered on the device) and be accurate to about 10ms. * buffered on the device) and be accurate to about 10ms.
* If the frame isn't buffered, just passing the return value of * If the frame isn't buffered, just passing the return value of
* ktime_get_boot_ns() is likely appropriate. * 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 cfg80211_inform_bss {
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
enum nl80211_bss_scan_width scan_width; enum nl80211_bss_scan_width scan_width;
s32 signal; s32 signal;
u64 boottime_ns; u64 boottime_ns;
u64 parent_tsf;
u8 parent_bssid[ETH_ALEN] __aligned(2);
}; };
/** /**
...@@ -4067,10 +4097,10 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator); ...@@ -4067,10 +4097,10 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator);
* cfg80211_scan_done - notify that scan finished