All of lore.kernel.org
 help / color / mirror / Atom feed
From: Johannes Berg <johannes@sipsolutions.net>
To: linux-wireless@vger.kernel.org
Subject: [RFC 2/2] mac80211: implement off-channel TX using hw r-o-c offload
Date: Thu, 16 Dec 2010 15:15:20 +0100	[thread overview]
Message-ID: <20101216141633.369507239@sipsolutions.net> (raw)
In-Reply-To: 20101216141518.879668720@sipsolutions.net

From: Johannes Berg <johannes.berg@intel.com>

When the driver has remain-on-channel offload,
implement off-channel transmission using that
primitive.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c         |   59 +++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/ieee80211_i.h |    2 +
 net/mac80211/offchannel.c  |   30 +++++++++++++++-------
 3 files changed, 81 insertions(+), 10 deletions(-)

--- wireless-testing.orig/net/mac80211/cfg.c	2010-12-16 08:04:15.000000000 +0100
+++ wireless-testing/net/mac80211/cfg.c	2010-12-16 14:45:18.000000000 +0100
@@ -1610,6 +1610,7 @@ static int ieee80211_remain_on_channel(s
 		ret = ieee80211_remain_on_channel_hw(local, dev,
 						     chan, channel_type,
 						     duration, cookie);
+		local->hw_roc_for_tx = false;
 		mutex_unlock(&local->mtx);
 
 		return ret;
@@ -1749,6 +1750,49 @@ static int ieee80211_mgmt_tx(struct wiph
 
 	*cookie = (unsigned long) skb;
 
+	if (is_offchan && local->ops->remain_on_channel) {
+		unsigned int duration;
+		int ret;
+
+		mutex_lock(&local->mtx);
+		/*
+		 * If the duration is zero, then the driver
+		 * wouldn't actually do anything. Set it to
+		 * 100 for now.
+		 *
+		 * TODO: cancel the off-channel operation
+		 *       when we get the SKB's TX status and
+		 *       the wait time was zero before.
+		 */
+		duration = 100;
+		if (wait)
+			duration = wait;
+		ret = ieee80211_remain_on_channel_hw(local, dev, chan,
+						     channel_type,
+						     duration, cookie);
+		if (ret) {
+			kfree_skb(skb);
+			mutex_unlock(&local->mtx);
+			return ret;
+		}
+
+		local->hw_roc_for_tx = true;
+		local->hw_roc_duration = wait;
+
+		/*
+		 * queue up frame for transmission after
+		 * ieee80211_ready_on_channel call
+		 */
+
+		/* modify cookie to prevent API mismatches */
+		*cookie ^= 2;
+		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN;
+		local->hw_roc_skb = skb;
+		mutex_unlock(&local->mtx);
+
+		return 0;
+	}
+
 	/*
 	 * Can transmit right away if the channel was the
 	 * right one and there's no wait involved... If a
@@ -1789,6 +1833,21 @@ static int ieee80211_mgmt_tx_cancel_wait
 	int ret = -ENOENT;
 
 	mutex_lock(&local->mtx);
+
+	if (local->ops->cancel_remain_on_channel) {
+		cookie ^= 2;
+		ret = ieee80211_cancel_remain_on_channel_hw(local, cookie);
+
+		if (ret == 0) {
+			kfree_skb(local->hw_roc_skb);
+			local->hw_roc_skb = NULL;
+		}
+
+		mutex_unlock(&local->mtx);
+
+		return ret;
+	}
+
 	list_for_each_entry(wk, &local->work_list, list) {
 		if (wk->sdata != sdata)
 			continue;
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2010-12-16 08:04:15.000000000 +0100
+++ wireless-testing/net/mac80211/ieee80211_i.h	2010-12-16 14:39:27.000000000 +0100
@@ -940,10 +940,12 @@ struct ieee80211_local {
 
 	struct ieee80211_channel *hw_roc_channel;
 	struct net_device *hw_roc_dev;
+	struct sk_buff *hw_roc_skb;
 	struct work_struct hw_roc_start, hw_roc_done;
 	enum nl80211_channel_type hw_roc_channel_type;
 	unsigned int hw_roc_duration;
 	u32 hw_roc_cookie;
+	bool hw_roc_for_tx;
 
 	/* dummy netdev for use w/ NAPI */
 	struct net_device napi_dev;
--- wireless-testing.orig/net/mac80211/offchannel.c	2010-12-16 08:04:15.000000000 +0100
+++ wireless-testing/net/mac80211/offchannel.c	2010-12-16 14:41:08.000000000 +0100
@@ -196,6 +196,7 @@ static void ieee80211_hw_roc_start(struc
 {
 	struct ieee80211_local *local =
 		container_of(work, struct ieee80211_local, hw_roc_start);
+	struct ieee80211_sub_if_data *sdata;
 
 	mutex_lock(&local->mtx);
 
@@ -206,11 +207,19 @@ static void ieee80211_hw_roc_start(struc
 
 	ieee80211_recalc_idle(local);
 
-	cfg80211_ready_on_channel(local->hw_roc_dev, local->hw_roc_cookie,
-				  local->hw_roc_channel,
-				  local->hw_roc_channel_type,
-				  local->hw_roc_duration,
-				  GFP_KERNEL);
+	if (local->hw_roc_skb) {
+		sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev);
+		ieee80211_tx_skb(sdata, local->hw_roc_skb);
+		local->hw_roc_skb = NULL;
+	} else {
+		cfg80211_ready_on_channel(local->hw_roc_dev,
+					  local->hw_roc_cookie,
+					  local->hw_roc_channel,
+					  local->hw_roc_channel_type,
+					  local->hw_roc_duration,
+					  GFP_KERNEL);
+	}
+
 	mutex_unlock(&local->mtx);
 }
 
@@ -236,11 +245,12 @@ static void ieee80211_hw_roc_done(struct
 		return;
 	}
 
-	cfg80211_remain_on_channel_expired(local->hw_roc_dev,
-					   local->hw_roc_cookie,
-					   local->hw_roc_channel,
-					   local->hw_roc_channel_type,
-					   GFP_KERNEL);
+	if (!local->hw_roc_for_tx)
+		cfg80211_remain_on_channel_expired(local->hw_roc_dev,
+						   local->hw_roc_cookie,
+						   local->hw_roc_channel,
+						   local->hw_roc_channel_type,
+						   GFP_KERNEL);
 
 	local->hw_roc_channel = NULL;
 	local->hw_roc_cookie = 0;



  parent reply	other threads:[~2010-12-16 14:17 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-16 14:15 [RFC 0/2] remain-on-channel HW offload Johannes Berg
2010-12-16 14:15 ` [RFC 1/2] mac80211: implement hardware offload for remain-on-channel Johannes Berg
2010-12-16 14:15 ` Johannes Berg [this message]
     [not found] ` <14A60364A8914B6FA548CF6DCEDDBD06@ChuckPC>
2010-12-16 14:40   ` [RFC 0/2] remain-on-channel HW offload Johannes Berg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101216141633.369507239@sipsolutions.net \
    --to=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.