On 17-11-2016 12:39, Arend van Spriel wrote: > The driver can indicate gscan results are available or gscan operation > has stopped. > > Reviewed-by: Hante Meuleman <hante.meule...@broadcom.com> > Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesbe...@broadcom.com> > Reviewed-by: Franky Lin <franky....@broadcom.com> > Signed-off-by: Arend van Spriel <arend.vanspr...@broadcom.com> > --- > include/net/cfg80211.h | 28 ++++++++++++++++++++ > include/uapi/linux/nl80211.h | 2 ++ > net/wireless/core.c | 2 ++ > net/wireless/core.h | 2 ++ > net/wireless/nl80211.c | 19 ++++++++++++++ > net/wireless/nl80211.h | 2 ++ > net/wireless/scan.c | 61 > ++++++++++++++++++++++++++++++++++++++++++++ > net/wireless/trace.h | 10 ++++++++ > 8 files changed, 126 insertions(+) > > diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h > index b4b0536..d85a439 100644 > --- a/include/net/cfg80211.h > +++ b/include/net/cfg80211.h > @@ -4570,6 +4570,34 @@ void cfg80211_scan_done(struct cfg80211_scan_request > *request, > void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy); > > /** > + * cfg80211_gscan_results - notify that new scan results are available > + * > + * @wiphy: the wiphy which got GScan results > + */ > +void cfg80211_gscan_results(struct wiphy *wiphy); > + > +/** > + * cfg80211_gscan_stopped - notify that the GScan has stopped > + * > + * @wiphy: the wiphy on which the GScan stopped. > + * > + * The driver can call this function to inform cfg80211 that the > + * GScan had to be stopped, for whatever reason. > + */ > +void cfg80211_gscan_stopped(struct wiphy *wiphy); > + > +/** > + * cfg80211_gscan_stopped_rtnl - notify that the GScan has stopped > + * > + * @wiphy: the wiphy on which the GScan stopped. > + * > + * The driver can call this function to inform cfg80211 that the > + * GScan had to be stopped, for whatever reason. > + * This function should be called with rtnl locked. > + */ > +void cfg80211_gscan_stopped_rtnl(struct wiphy *wiphy); > + > +/** > * cfg80211_inform_bss_frame_data - inform cfg80211 of a received BSS frame > * @wiphy: the wiphy reporting the BSS > * @data: the BSS metadata > diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h > index 8071dae..c4c9005 100644 > --- a/include/uapi/linux/nl80211.h > +++ b/include/uapi/linux/nl80211.h > @@ -896,6 +896,7 @@ > * > * @NL80211_CMD_START_GSCAN: start GScan. > * @NL80211_CMD_STOP_GSCAN: request to stop current GScan. > + * @NL80211_CMD_GSCAN_RESULTS: indicates that there GScan results available. > * @NL80211_CMD_GSCAN_STOPPED: indicates that the currently running GScan > * has stopped. This event is generated upon @NL80211_CMD_STOP_GSCAN and > * the driver may issue this event at any time when a GScan is running. > @@ -1101,6 +1102,7 @@ enum nl80211_commands { > > NL80211_CMD_START_GSCAN, > NL80211_CMD_STOP_GSCAN, > + NL80211_CMD_GSCAN_RESULTS, > NL80211_CMD_GSCAN_STOPPED, > > /* add new commands above here */ > diff --git a/net/wireless/core.c b/net/wireless/core.c > index 760a2fb..69eea4c 100644 > --- a/net/wireless/core.c > +++ b/net/wireless/core.c > @@ -453,6 +453,7 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops > *ops, int sizeof_priv, > INIT_LIST_HEAD(&rdev->bss_list); > INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); > INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results); > + INIT_WORK(&rdev->gscan_results_wk, __cfg80211_gscan_results); > INIT_LIST_HEAD(&rdev->mlme_unreg); > spin_lock_init(&rdev->mlme_unreg_lock); > INIT_WORK(&rdev->mlme_unreg_wk, cfg80211_mlme_unreg_wk); > @@ -935,6 +936,7 @@ void wiphy_unregister(struct wiphy *wiphy) > cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); > flush_work(&rdev->destroy_work); > flush_work(&rdev->sched_scan_stop_wk); > + flush_work(&rdev->gscan_stop_wk); > flush_work(&rdev->mlme_unreg_wk); > > #ifdef CONFIG_PM > diff --git a/net/wireless/core.h b/net/wireless/core.h > index b0f2519..1d56ef4 100644 > --- a/net/wireless/core.h > +++ b/net/wireless/core.h > @@ -78,6 +78,7 @@ struct cfg80211_registered_device { > unsigned long suspend_at; > struct work_struct scan_done_wk; > struct work_struct sched_scan_results_wk; > + struct work_struct gscan_results_wk; > > struct genl_info *cur_cmd_info; > > @@ -423,6 +424,7 @@ void ___cfg80211_scan_done(struct > cfg80211_registered_device *rdev, > void __cfg80211_sched_scan_results(struct work_struct *wk); > int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, > bool driver_initiated); > +void __cfg80211_gscan_results(struct work_struct *wk); > int __cfg80211_stop_gscan(struct cfg80211_registered_device *rdev, > bool driver_initiated); > void cfg80211_upload_connect_keys(struct wireless_dev *wdev); > diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c > index 5b22310..f0099ee 100644 > --- a/net/wireless/nl80211.c > +++ b/net/wireless/nl80211.c > @@ -13304,6 +13304,25 @@ void nl80211_send_sched_scan_results(struct > cfg80211_registered_device *rdev, > NL80211_MCGRP_SCAN, GFP_KERNEL); > } > > +void nl80211_send_gscan_results(struct cfg80211_registered_device *rdev, > + struct net_device *netdev) > +{ > + struct sk_buff *msg; > + > + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); > + if (!msg) > + return; > + > + if (nl80211_send_scan_event_msg(msg, rdev, netdev, 0, 0, 0, > + NL80211_CMD_GSCAN_RESULTS) < 0) { > + nlmsg_free(msg); > + return; > + } > + > + genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, > + NL80211_MCGRP_SCAN, GFP_KERNEL); > +} > + > void nl80211_send_scan_event(struct cfg80211_registered_device *rdev, > struct net_device *netdev, u32 cmd) > { > diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h > index fb304ce9..4eec856 100644 > --- a/net/wireless/nl80211.h > +++ b/net/wireless/nl80211.h > @@ -20,6 +20,8 @@ void nl80211_send_scan_event(struct > cfg80211_registered_device *rdev, > struct net_device *netdev, u32 cmd); > void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, > struct net_device *netdev); > +void nl80211_send_gscan_results(struct cfg80211_registered_device *rdev, > + struct net_device *netdev); > void nl80211_common_reg_change_event(enum nl80211_commands cmd_id, > struct regulatory_request *request); > > diff --git a/net/wireless/scan.c b/net/wireless/scan.c > index 327b23c..f34d5d4 100644 > --- a/net/wireless/scan.c > +++ b/net/wireless/scan.c > @@ -287,6 +287,47 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy) > } > EXPORT_SYMBOL(cfg80211_sched_scan_results); > > +void __cfg80211_gscan_results(struct work_struct *wk) > +{ > + struct cfg80211_registered_device *rdev; > + struct cfg80211_gscan_request *request; > + > + rdev = container_of(wk, struct cfg80211_registered_device, > + gscan_results_wk); > + > + rtnl_lock(); > + > + request = rtnl_dereference(rdev->gscan_req); > + > + /* we don't have sched_scan_req anymore if the scan is stopping */ > + if (request) { > +#if 0 > + /* TODO: how to deal with flush */ > + if (request->flags & NL80211_SCAN_FLAG_FLUSH) { > + /* flush entries from previous scans */ > + spin_lock_bh(&rdev->bss_lock); > + __cfg80211_bss_expire(rdev, request->scan_start); > + spin_unlock_bh(&rdev->bss_lock); > + request->scan_start = jiffies; > + } > +#endif
Yikes. Still subject to discussion, but need it is bss storage with last results is sufficient. > + nl80211_send_gscan_results(rdev, request->dev); > + } > + > + rtnl_unlock(); > +} Regards, Arend