diff mbox

[RFC,06/15] mac80211: add support for HW periodic scan

Message ID 1288612336-2830-7-git-send-email-luciano.coelho@nokia.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Luciano Coelho Nov. 1, 2010, 11:52 a.m. UTC
None
diff mbox

Patch

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 9fdf982..4ea2149 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1759,6 +1759,10 @@  struct ieee80211_ops {
 				u32 iv32, u16 *phase1key);
 	int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct cfg80211_scan_request *req);
+	int (*periodic_start)(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif);
+	int (*periodic_stop)(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif);
 	void (*sw_scan_start)(struct ieee80211_hw *hw);
 	void (*sw_scan_complete)(struct ieee80211_hw *hw);
 	int (*get_stats)(struct ieee80211_hw *hw,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 18bd0e5..ff29840 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1223,6 +1223,30 @@  static int ieee80211_scan(struct wiphy *wiphy,
 	return ieee80211_request_scan(sdata, req);
 }
 
+static int ieee80211_periodic_start(struct wiphy *wiphy,
+				    struct net_device *dev,
+				    struct cfg80211_periodic_request *req)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if(!sdata->local->ops->periodic_start)
+		return -EOPNOTSUPP;
+
+	return ieee80211_request_periodic_start(sdata, req);
+}
+
+static int ieee80211_periodic_stop(struct wiphy *wiphy,
+				   struct net_device *dev,
+				   struct cfg80211_periodic_request *req)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if(!sdata->local->ops->periodic_stop)
+		return -EOPNOTSUPP;
+
+	return ieee80211_request_periodic_stop(sdata);
+}
+
 static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
 			  struct cfg80211_auth_request *req)
 {
@@ -1654,6 +1678,8 @@  struct cfg80211_ops mac80211_config_ops = {
 	.suspend = ieee80211_suspend,
 	.resume = ieee80211_resume,
 	.scan = ieee80211_scan,
+	.periodic_start= ieee80211_periodic_start,
+	.periodic_stop= ieee80211_periodic_stop,
 	.auth = ieee80211_auth,
 	.assoc = ieee80211_assoc,
 	.deauth = ieee80211_deauth,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 1698382..c425e1c 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -191,6 +191,32 @@  static inline int drv_hw_scan(struct ieee80211_local *local,
 	return ret;
 }
 
+static inline int drv_periodic_start(struct ieee80211_local *local,
+				     struct ieee80211_sub_if_data *sdata)
+{
+	int ret;
+
+	might_sleep();
+
+	trace_drv_periodic_start(local, sdata);
+	ret = local->ops->periodic_start(&local->hw, &sdata->vif);
+	trace_drv_return_int(local, ret);
+	return ret;
+}
+
+static inline int drv_periodic_stop(struct ieee80211_local *local,
+				    struct ieee80211_sub_if_data *sdata)
+{
+	int ret;
+
+	might_sleep();
+
+	trace_drv_periodic_stop(local, sdata);
+	ret = local->ops->periodic_stop(&local->hw, &sdata->vif);
+	trace_drv_return_int(local, ret);
+	return ret;
+}
+
 static inline void drv_sw_scan_start(struct ieee80211_local *local)
 {
 	might_sleep();
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 6831fb1..a09c17d 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -439,6 +439,50 @@  TRACE_EVENT(drv_hw_scan,
 	)
 );
 
+TRACE_EVENT(drv_periodic_start,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata),
+
+	TP_ARGS(local, sdata),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		VIF_ENTRY
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		VIF_ASSIGN;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT VIF_PR_FMT,
+		LOCAL_PR_ARG,VIF_PR_ARG
+	)
+);
+
+TRACE_EVENT(drv_periodic_stop,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata),
+
+	TP_ARGS(local, sdata),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		VIF_ENTRY
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		VIF_ASSIGN;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT VIF_PR_FMT,
+		LOCAL_PR_ARG,VIF_PR_ARG
+	)
+);
+
 TRACE_EVENT(drv_sw_scan_start,
 	TP_PROTO(struct ieee80211_local *local),
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b80c386..305bd57 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -812,6 +812,7 @@  struct ieee80211_local {
 	struct cfg80211_ssid scan_ssid;
 	struct cfg80211_scan_request *int_scan_req;
 	struct cfg80211_scan_request *scan_req, *hw_scan_req;
+	struct cfg80211_periodic_request *periodic_req;
 	struct ieee80211_channel *scan_channel;
 	enum ieee80211_band hw_scan_band;
 	int scan_channel_idx;
@@ -1115,6 +1116,11 @@  ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
 void ieee80211_rx_bss_put(struct ieee80211_local *local,
 			  struct ieee80211_bss *bss);
 
+/* periodic scan handling */
+int ieee80211_request_periodic_start(struct ieee80211_sub_if_data *sdata,
+				     struct cfg80211_periodic_request *req);
+int ieee80211_request_periodic_stop(struct ieee80211_sub_if_data *sdata);
+
 /* off-channel helpers */
 void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local);
 void ieee80211_offchannel_stop_station(struct ieee80211_local *local);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 592acfb..fa73abe 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -823,3 +823,57 @@  void ieee80211_scan_cancel(struct ieee80211_local *local)
 	if (finish)
 		__ieee80211_scan_completed_finish(&local->hw, false);
 }
+
+int ieee80211_request_periodic_start(struct ieee80211_sub_if_data *sdata,
+				     struct cfg80211_periodic_request *req)
+{
+	struct ieee80211_local *local = sdata->local;
+	int ret;
+
+	mutex_lock(&sdata->local->mtx);
+
+	/* FIXME: check if hw scanning or associated and return -EBUSY */
+
+	if (local->periodic_req) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (!local->ops->periodic_start) {
+		ret = -ENOTSUPP;
+		goto out;
+	}
+
+	local->periodic_req = req;
+
+	ret = drv_periodic_start(local, sdata);
+	if (ret)
+		local->periodic_req = NULL;
+out:
+	mutex_unlock(&sdata->local->mtx);
+
+	return ret;
+}
+
+int ieee80211_request_periodic_stop(struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_local *local = sdata->local;
+	int ret = 0;
+
+	mutex_lock(&sdata->local->mtx);
+
+	if (!local->ops->periodic_stop) {
+		ret = -ENOTSUPP;
+		goto out;
+	}
+
+	if (local->periodic_req) {
+		ret = drv_periodic_stop(local, sdata);
+		local->periodic_req = NULL;
+	}
+
+out:
+	mutex_unlock(&sdata->local->mtx);
+
+	return ret;
+}