Linux wireless drivers development
 help / color / mirror / Atom feed
* RE: PROBLEM: brcm80211 unable to survive suspend/resume cycle
From: Arend Van Spriel @ 2011-01-12  9:26 UTC (permalink / raw)
  To: Jon Masters, Brett Rudley
  Cc: devel, Linux Kernel Mailing List, linux-wireless@vger.kernel.org
In-Reply-To: <1293028287.6319.171.camel@constitution.bos.jonmasters.org>

Hi Jon,

Brett delegated this problem to me and I have resolved it in the driver. I will post it to the staging-2.6 repository in coming days when stomach flu subsides. Keep your eyes on the devel archives.

Gr. AvS

|-----Original Message-----
|From: devel-bounces@linuxdriverproject.org [mailto:devel-
|bounces@linuxdriverproject.org] On Behalf Of Jon Masters
|Sent: Wednesday, December 22, 2010 3:31 PM
|To: Brett Rudley
|Cc: devel; Linux Kernel Mailing List
|Subject: RE: PROBLEM: brcm80211 unable to survive suspend/resume cycle
|
|On Mon, 2010-11-15 at 23:04 -0500, Jon Masters wrote:
|> On Tue, 2010-11-09 at 10:02 -0800, Brett Rudley wrote:
|> > Hey Jon, thanks for the heads up.  I can repro and am looking into
|it.
|>
|> Did you get chance to poke much yet?
|
|Any word on this?
|
|Jon.
|
|
|_______________________________________________
|devel mailing list
|devel@linuxdriverproject.org
|http://driverdev.linuxdriverproject.org/mailman/listinfo/devel



^ permalink raw reply

* [PATCH] wl12xx: change debug_level module param sysfs permissions
From: Guy Eilam @ 2011-01-12  9:33 UTC (permalink / raw)
  To: linux-wireless; +Cc: coelho

changed the visibility of the debug_level module parameter
in the filesystem to be readable and writable to the root user.
It is now accessible under /sys/module/wl12xx/parameters

removed the debug_level debugfs file that was created under
/sys/kernel/debug/...

Signed-off-by: Guy Eilam <guy@wizery.com>
---
 drivers/net/wireless/wl12xx/debugfs.c |    5 -----
 drivers/net/wireless/wl12xx/main.c    |    4 ++--
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index 36e7ec1..dc3ca00 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -402,11 +402,6 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
 
 	DEBUGFS_ADD(gpio_power, rootdir);
 
-	entry = debugfs_create_x32("debug_level", 0600, rootdir,
-				   &wl12xx_debug_level);
-	if (!entry || IS_ERR(entry))
-		goto err;
-
 	return 0;
 
 err:
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 45a9d2f..03dcd8f 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2893,9 +2893,9 @@ int wl1271_free_hw(struct wl1271 *wl)
 }
 EXPORT_SYMBOL_GPL(wl1271_free_hw);
 
-u32 wl12xx_debug_level;
+u32 wl12xx_debug_level = DEBUG_NONE;
 EXPORT_SYMBOL_GPL(wl12xx_debug_level);
-module_param_named(debug_level, wl12xx_debug_level, uint, DEBUG_NONE);
+module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(debug_level, "wl12xx debugging level");
 
 MODULE_LICENSE("GPL");
-- 
1.7.1


^ permalink raw reply related

* Re: packet injection not working on rt2800usb, ath9k
From: Jouni Malinen @ 2011-01-12 10:06 UTC (permalink / raw)
  To: Andy Pyles; +Cc: linux-wireless
In-Reply-To: <AANLkTin0NYnoki8wD-Q4o33KyNhu8jJwr=LBJx-FCnNF@mail.gmail.com>

On Tue, Jan 11, 2011 at 03:49:06PM -0500, Andy Pyles wrote:
> Thanks for the tip! After some debugging, it turns out that my
> radiotap header is not getting parsed correctly
> in ./net/mac80211/tx.c:__ieee80211_parse_tx_radiotap()
> 
> Would you mind sending me the radiotap header you are using?

http://w1.fi/gitweb/gitweb.cgi?p=hostap.git;a=blob_plain;f=wlantest/inject.c;hb=HEAD

-- 
Jouni Malinen                                            PGP id EFC895FA

^ permalink raw reply

* Re: Mesh join/leave
From: Steve Brown @ 2011-01-12 10:28 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1294823034.3639.15.camel@jlt3.sipsolutions.net>

On Wed, 2011-01-12 at 10:03 +0100, Johannes Berg wrote:
> On Tue, 2011-01-11 at 16:20 -0500, Steve Brown wrote:
> > In testing this, the command "iw mesh0 mesh leave" doesn't stop
> > beaconing. Beaconing continues with a null mesh id.
> > 
> > Is this the intended behavior?
> 
> No, it's not -- what driver are you using?
> 
> johannes
> 
ath9k with adapter AR9160 802.11abgn Wireless PCI Adapter (168c:2082)

Steve




^ permalink raw reply

* Re: Mesh join/leave
From: Johannes Berg @ 2011-01-12 10:44 UTC (permalink / raw)
  To: sbrown; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1294828087.16447.2.camel@mythtv.ewol.com>

On Wed, 2011-01-12 at 05:28 -0500, Steve Brown wrote:
> On Wed, 2011-01-12 at 10:03 +0100, Johannes Berg wrote:
> > On Tue, 2011-01-11 at 16:20 -0500, Steve Brown wrote:
> > > In testing this, the command "iw mesh0 mesh leave" doesn't stop
> > > beaconing. Beaconing continues with a null mesh id.
> > > 
> > > Is this the intended behavior?
> > 
> > No, it's not -- what driver are you using?
> > 
> > johannes
> > 
> ath9k with adapter AR9160 802.11abgn Wireless PCI Adapter (168c:2082)

No idea then, it looks like ath9k correctly handles
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); so
you should look at what's happening around there.

johannes


^ permalink raw reply

* Re: Mesh join/leave
From: Steve Brown @ 2011-01-12 10:43 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1294823034.3639.15.camel@jlt3.sipsolutions.net>

On Wed, 2011-01-12 at 10:03 +0100, Johannes Berg wrote:
> On Tue, 2011-01-11 at 16:20 -0500, Steve Brown wrote:
> > In testing this, the command "iw mesh0 mesh leave" doesn't stop
> > beaconing. Beaconing continues with a null mesh id.
> > 
> > Is this the intended behavior?
> 
> No, it's not -- what driver are you using?
> 
> johannes
> 
The ath5k driver behaves differently. On "leave" it stops beaconing and
on "join", starts back up.

Steve



^ permalink raw reply

* Re: Mesh join/leave
From: Johannes Berg @ 2011-01-12 10:46 UTC (permalink / raw)
  To: sbrown; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1294828087.16447.2.camel@mythtv.ewol.com>

On Wed, 2011-01-12 at 05:28 -0500, Steve Brown wrote:
> On Wed, 2011-01-12 at 10:03 +0100, Johannes Berg wrote:
> > On Tue, 2011-01-11 at 16:20 -0500, Steve Brown wrote:
> > > In testing this, the command "iw mesh0 mesh leave" doesn't stop
> > > beaconing. Beaconing continues with a null mesh id.
> > > 
> > > Is this the intended behavior?
> > 
> > No, it's not -- what driver are you using?

Of course maybe mac80211 should be doings omething like this too:

johannes

--- wireless-testing.orig/net/mac80211/tx.c	2011-01-12 11:44:52.000000000 +0100
+++ wireless-testing/net/mac80211/tx.c	2011-01-12 11:45:52.000000000 +0100
@@ -2299,6 +2299,11 @@ struct sk_buff *ieee80211_beacon_get_tim
 		struct ieee80211_mgmt *mgmt;
 		u8 *pos;
 
+#ifdef CONFIG_MAC80211_MESH
+		if (!sdata->u.mesh.mesh_id_len)
+			goto out;
+#endif
+
 		/* headroom, head length, tail length and maximum TIM length */
 		skb = dev_alloc_skb(local->tx_headroom + 400 +
 				sdata->u.mesh.vendor_ie_len);



^ permalink raw reply

* Re: Mesh join/leave
From: Steve Brown @ 2011-01-12 11:09 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1294829180.3639.19.camel@jlt3.sipsolutions.net>

On Wed, 2011-01-12 at 11:46 +0100, Johannes Berg wrote:
> On Wed, 2011-01-12 at 05:28 -0500, Steve Brown wrote:
> > On Wed, 2011-01-12 at 10:03 +0100, Johannes Berg wrote:
> > > On Tue, 2011-01-11 at 16:20 -0500, Steve Brown wrote:
> > > > In testing this, the command "iw mesh0 mesh leave" doesn't stop
> > > > beaconing. Beaconing continues with a null mesh id.
> > > > 
> > > > Is this the intended behavior?
> > > 
> > > No, it's not -- what driver are you using?
> 
> Of course maybe mac80211 should be doings omething like this too:
> 
> johannes
> 
> --- wireless-testing.orig/net/mac80211/tx.c	2011-01-12 11:44:52.000000000 +0100
> +++ wireless-testing/net/mac80211/tx.c	2011-01-12 11:45:52.000000000 +0100
> @@ -2299,6 +2299,11 @@ struct sk_buff *ieee80211_beacon_get_tim
>  		struct ieee80211_mgmt *mgmt;
>  		u8 *pos;
>  
> +#ifdef CONFIG_MAC80211_MESH
> +		if (!sdata->u.mesh.mesh_id_len)
> +			goto out;
> +#endif
> +
>  		/* headroom, head length, tail length and maximum TIM length */
>  		skb = dev_alloc_skb(local->tx_headroom + 400 +
>  				sdata->u.mesh.vendor_ie_len);
> 
> 
With the patch, leave/join stop and restart beaconing.

Thanks,
Steve



^ permalink raw reply

* Re: Mesh join/leave
From: Johannes Berg @ 2011-01-12 11:12 UTC (permalink / raw)
  To: sbrown; +Cc: linux-wireless@vger.kernel.org, Jouni Malinen
In-Reply-To: <1294830560.2333.2.camel@mythtv.ewol.com>

On Wed, 2011-01-12 at 06:09 -0500, Steve Brown wrote:

> > Of course maybe mac80211 should be doings omething like this too:
> > 
> > johannes
> > 
> > --- wireless-testing.orig/net/mac80211/tx.c	2011-01-12 11:44:52.000000000 +0100
> > +++ wireless-testing/net/mac80211/tx.c	2011-01-12 11:45:52.000000000 +0100
> > @@ -2299,6 +2299,11 @@ struct sk_buff *ieee80211_beacon_get_tim
> >  		struct ieee80211_mgmt *mgmt;
> >  		u8 *pos;
> >  
> > +#ifdef CONFIG_MAC80211_MESH
> > +		if (!sdata->u.mesh.mesh_id_len)
> > +			goto out;
> > +#endif
> > +
> >  		/* headroom, head length, tail length and maximum TIM length */
> >  		skb = dev_alloc_skb(local->tx_headroom + 400 +
> >  				sdata->u.mesh.vendor_ie_len);
> > 
> > 
> With the patch, leave/join stop and restart beaconing.

Yeah but evidently ath9k isn't cleanly stopping beaconing, it's still
attempting to beacon but doesn't get a beacon from mac80211 so can't
send one.

johannes


^ permalink raw reply

* [RFC 0/2] fix aggregation buffer size limits
From: Johannes Berg @ 2011-01-12 12:13 UTC (permalink / raw)
  To: linux-wireless

Luca and I found that we do not correctly handle
peers that want a limit (other than 64) on the
number of subframes in an aggregate. Here's a
completely untested attempt at fixing this.

Comments welcome.

johannes


^ permalink raw reply

* [RFC 2/2] iwlwifi: use maximum aggregation size
From: Johannes Berg @ 2011-01-12 12:13 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20110112121322.702618109@sipsolutions.net>

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

Use the values from the peer to set up the ucode
for the right maximum number of subframes in an
aggregate. Since the ucode only tracks this per
station, use the minimum across all aggregation
sessions with this peer.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c |    5 +++-
 drivers/net/wireless/iwlwifi/iwl-agn.c    |   32 +++++++++++++++++++++++++-----
 drivers/net/wireless/iwlwifi/iwl-dev.h    |    1 
 3 files changed, 32 insertions(+), 6 deletions(-)

--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-agn-rs.c	2011-01-12 13:08:22.000000000 +0100
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-agn-rs.c	2011-01-12 13:10:58.000000000 +0100
@@ -2889,6 +2889,8 @@ static void rs_fill_link_cmd(struct iwl_
 	u8 ant_toggle_cnt = 0;
 	u8 use_ht_possible = 1;
 	u8 valid_tx_ant = 0;
+	struct iwl_station_priv *sta_priv =
+		container_of(lq_sta, struct iwl_station_priv, lq_sta);
 	struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq;
 
 	/* Override starting rate (index 0) if needed for debug purposes */
@@ -3007,7 +3009,8 @@ static void rs_fill_link_cmd(struct iwl_
 		repeat_rate--;
 	}
 
-	lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+	lq_cmd->agg_params.agg_frame_cnt_limit =
+		sta_priv->max_agg_bufsize ?: LINK_QUAL_AGG_FRAME_LIMIT_DEF;
 	lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
 
 	lq_cmd->agg_params.agg_time_limit =
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-agn.c	2011-01-12 13:03:34.000000000 +0100
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-agn.c	2011-01-12 13:11:50.000000000 +0100
@@ -3421,6 +3421,7 @@ int iwlagn_mac_ampdu_action(struct ieee8
 {
 	struct iwl_priv *priv = hw->priv;
 	int ret = -EINVAL;
+	struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
 
 	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
 		     sta->addr, tid);
@@ -3475,11 +3476,28 @@ int iwlagn_mac_ampdu_action(struct ieee8
 		}
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		/*
+		 * If the limit is 0, then it wasn't initialised yet,
+		 * use the default. We can do that since we take the
+		 * minimum below, and we don't want to go above our
+		 * default due to hardware restrictions.
+		 */
+		if (sta_priv->max_agg_bufsize == 0)
+			sta_priv->max_agg_bufsize =
+				LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+
+		/*
+		 * Even though in theory the peer could have different
+		 * aggregation reorder buffer sizes for different sessions,
+		 * our ucode doesn't allow for that and has a global limit
+		 * for each station. Therefore, use the minimum of all the
+		 * aggregation sessions and our default value.
+		 */
+		sta_priv->max_agg_bufsize =
+			min(sta_priv->max_agg_bufsize, buf_size);
+
 		if (priv->cfg->ht_params &&
 		    priv->cfg->ht_params->use_rts_for_aggregation) {
-			struct iwl_station_priv *sta_priv =
-				(void *) sta->drv_priv;
-
 			/*
 			 * switch to RTS/CTS if it is the prefer protection
 			 * method for HT traffic
@@ -3487,9 +3505,13 @@ int iwlagn_mac_ampdu_action(struct ieee8
 
 			sta_priv->lq_sta.lq.general_params.flags |=
 				LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
-			iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
-					&sta_priv->lq_sta.lq, CMD_ASYNC, false);
 		}
+
+		sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
+			sta_priv->max_agg_bufsize;
+
+		iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
+				&sta_priv->lq_sta.lq, CMD_ASYNC, false);
 		ret = 0;
 		break;
 	}
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-dev.h	2011-01-12 13:03:12.000000000 +0100
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-dev.h	2011-01-12 13:03:31.000000000 +0100
@@ -509,6 +509,7 @@ struct iwl_station_priv {
 	atomic_t pending_frames;
 	bool client;
 	bool asleep;
+	u8 max_agg_bufsize;
 };
 
 /**



^ permalink raw reply

* [RFC 1/2] mac80211: track receivers aggregation reorder buffer size
From: Johannes Berg @ 2011-01-12 12:13 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20110112121322.702618109@sipsolutions.net>

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

The aggregation code currently doesn't implement the
buffer size negotiation. It will always request a max
buffer size (which is fine, if a little pointless, as
the mac80211 code doesn't know and might just use 0
instead), but if the peer requests a smaller size it
isn't possible to honour this request.

In order to fix this, look at the buffer size in the
addBA response frame, keep track of it and pass it to
the driver in the ampdu_action callback when called
with the IEEE80211_AMPDU_TX_OPERATIONAL action. That
way the driver can limit the number of subframes in
aggregates appropriately.

Note that this doesn't fix any drivers apart from the
addition of the new argument -- they all need to be
updated separately to use this variable!

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/ath/ar9170/main.c        |    3 ++-
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |    2 +-
 drivers/net/wireless/ath/ath9k/main.c         |    2 +-
 drivers/net/wireless/ath/carl9170/main.c      |    2 +-
 drivers/net/wireless/iwlwifi/iwl-agn.c        |    3 ++-
 drivers/net/wireless/iwlwifi/iwl-agn.h        |    3 ++-
 drivers/net/wireless/mac80211_hwsim.c         |    3 ++-
 drivers/net/wireless/mwl8k.c                  |    3 ++-
 drivers/net/wireless/rt2x00/rt2800lib.c       |    3 ++-
 drivers/net/wireless/rt2x00/rt2800lib.h       |    3 ++-
 drivers/net/wireless/rtlwifi/core.c           |    3 ++-
 include/net/mac80211.h                        |    7 ++++++-
 net/mac80211/agg-rx.c                         |    4 ++--
 net/mac80211/agg-tx.c                         |   20 +++++++++++++++++---
 net/mac80211/driver-ops.h                     |    6 +++---
 net/mac80211/driver-trace.h                   |   11 +++++++----
 net/mac80211/sta_info.h                       |    2 ++
 17 files changed, 56 insertions(+), 24 deletions(-)

--- wireless-testing.orig/include/net/mac80211.h	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/include/net/mac80211.h	2011-01-12 13:02:36.000000000 +0100
@@ -1723,6 +1723,10 @@ enum ieee80211_ampdu_mlme_action {
  * 	ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
  * 	is the first frame we expect to perform the action on. Notice
  * 	that TX/RX_STOP can pass NULL for this parameter.
+ *	The @buf_size parameter is only valid when the action is set to
+ *	%IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder
+ *	buffer size (number of subframes) for this session -- aggregates
+ *	containing more subframes than this may not be transmitted to the peer.
  *	Returns a negative error code on failure.
  *	The callback can sleep.
  *
@@ -1825,7 +1829,8 @@ struct ieee80211_ops {
 	int (*ampdu_action)(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size);
 	int (*get_survey)(struct ieee80211_hw *hw, int idx,
 		struct survey_info *survey);
 	void (*rfkill_poll)(struct ieee80211_hw *hw);
--- wireless-testing.orig/net/mac80211/agg-tx.c	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/net/mac80211/agg-tx.c	2011-01-12 13:02:36.000000000 +0100
@@ -190,7 +190,7 @@ int ___ieee80211_stop_tx_ba_session(stru
 
 	ret = drv_ampdu_action(local, sta->sdata,
 			       IEEE80211_AMPDU_TX_STOP,
-			       &sta->sta, tid, NULL);
+			       &sta->sta, tid, NULL, 0);
 
 	/* HW shall not deny going back to legacy */
 	if (WARN_ON(ret)) {
@@ -311,7 +311,7 @@ void ieee80211_tx_ba_session_handle_star
 	start_seq_num = sta->tid_seq[tid] >> 4;
 
 	ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
-			       &sta->sta, tid, &start_seq_num);
+			       &sta->sta, tid, &start_seq_num, 0);
 	if (ret) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "BA request denied - HW unavailable for"
@@ -487,7 +487,8 @@ static void ieee80211_agg_tx_operational
 
 	drv_ampdu_action(local, sta->sdata,
 			 IEEE80211_AMPDU_TX_OPERATIONAL,
-			 &sta->sta, tid, NULL);
+			 &sta->sta, tid, NULL,
+			 sta->ampdu_mlme.tid_tx[tid]->buf_size);
 
 	/*
 	 * synchronize with TX path, while splicing the TX path
@@ -742,9 +743,11 @@ void ieee80211_process_addba_resp(struct
 {
 	struct tid_ampdu_tx *tid_tx;
 	u16 capab, tid;
+	u8 buf_size;
 
 	capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
 	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
+	buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
 
 	mutex_lock(&sta->ampdu_mlme.mtx);
 
@@ -767,12 +770,23 @@ void ieee80211_process_addba_resp(struct
 
 	if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
 			== WLAN_STATUS_SUCCESS) {
+		/*
+		 * IEEE 802.11-2007 7.3.1.14:
+		 * In an ADDBA Response frame, when the Status Code field
+		 * is set to 0, the Buffer Size subfield is set to a value
+		 * of at least 1.
+		 */
+		if (!buf_size)
+			goto out;
+
 		if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED,
 				     &tid_tx->state)) {
 			/* ignore duplicate response */
 			goto out;
 		}
 
+		tid_tx->buf_size = buf_size;
+
 		if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))
 			ieee80211_agg_tx_operational(local, sta, tid);
 
--- wireless-testing.orig/net/mac80211/sta_info.h	2011-01-12 13:02:28.000000000 +0100
+++ wireless-testing/net/mac80211/sta_info.h	2011-01-12 13:02:36.000000000 +0100
@@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags {
  * @state: session state (see above)
  * @stop_initiator: initiator of a session stop
  * @tx_stop: TX DelBA frame when stopping
+ * @buf_size: reorder buffer size at receiver
  *
  * This structure's lifetime is managed by RCU, assignments to
  * the array holding it must hold the aggregation mutex.
@@ -101,6 +102,7 @@ struct tid_ampdu_tx {
 	u8 dialog_token;
 	u8 stop_initiator;
 	bool tx_stop;
+	u8 buf_size;
 };
 
 /**
--- wireless-testing.orig/net/mac80211/agg-rx.c	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/net/mac80211/agg-rx.c	2011-01-12 13:02:36.000000000 +0100
@@ -76,7 +76,7 @@ void ___ieee80211_stop_rx_ba_session(str
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
 	if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP,
-			     &sta->sta, tid, NULL))
+			     &sta->sta, tid, NULL, 0))
 		printk(KERN_DEBUG "HW problem - can not stop rx "
 				"aggregation for tid %d\n", tid);
 
@@ -294,7 +294,7 @@ void ieee80211_process_addba_request(str
 	}
 
 	ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
-			       &sta->sta, tid, &start_seq_num);
+			       &sta->sta, tid, &start_seq_num, 0);
 #ifdef CONFIG_MAC80211_HT_DEBUG
 	printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
--- wireless-testing.orig/net/mac80211/driver-ops.h	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/net/mac80211/driver-ops.h	2011-01-12 13:02:36.000000000 +0100
@@ -382,17 +382,17 @@ static inline int drv_ampdu_action(struc
 				   struct ieee80211_sub_if_data *sdata,
 				   enum ieee80211_ampdu_mlme_action action,
 				   struct ieee80211_sta *sta, u16 tid,
-				   u16 *ssn)
+				   u16 *ssn, u8 buf_size)
 {
 	int ret = -EOPNOTSUPP;
 
 	might_sleep();
 
-	trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn);
+	trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size);
 
 	if (local->ops->ampdu_action)
 		ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
-					       sta, tid, ssn);
+					       sta, tid, ssn, buf_size);
 
 	trace_drv_return_int(local, ret);
 
--- wireless-testing.orig/net/mac80211/driver-trace.h	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/net/mac80211/driver-trace.h	2011-01-12 13:02:36.000000000 +0100
@@ -784,9 +784,9 @@ TRACE_EVENT(drv_ampdu_action,
 		 struct ieee80211_sub_if_data *sdata,
 		 enum ieee80211_ampdu_mlme_action action,
 		 struct ieee80211_sta *sta, u16 tid,
-		 u16 *ssn),
+		 u16 *ssn, u8 buf_size),
 
-	TP_ARGS(local, sdata, action, sta, tid, ssn),
+	TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
@@ -794,6 +794,7 @@ TRACE_EVENT(drv_ampdu_action,
 		__field(u32, action)
 		__field(u16, tid)
 		__field(u16, ssn)
+		__field(u8, buf_size)
 		VIF_ENTRY
 	),
 
@@ -804,11 +805,13 @@ TRACE_EVENT(drv_ampdu_action,
 		__entry->action = action;
 		__entry->tid = tid;
 		__entry->ssn = ssn ? *ssn : 0;
+		__entry->buf_size = buf_size;
 	),
 
 	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d",
-		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid
+		LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d",
+		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action,
+		__entry->tid, __entry->buf_size
 	)
 );
 
--- wireless-testing.orig/drivers/net/wireless/ath/ar9170/main.c	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/drivers/net/wireless/ath/ar9170/main.c	2011-01-12 13:02:36.000000000 +0100
@@ -1945,7 +1945,8 @@ static int ar9170_conf_tx(struct ieee802
 static int ar9170_ampdu_action(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
 			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size)
 {
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
--- wireless-testing.orig/drivers/net/wireless/ath/ath9k/htc_drv_main.c	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/drivers/net/wireless/ath/ath9k/htc_drv_main.c	2011-01-12 13:02:36.000000000 +0100
@@ -1548,7 +1548,7 @@ static int ath9k_htc_ampdu_action(struct
 				  struct ieee80211_vif *vif,
 				  enum ieee80211_ampdu_mlme_action action,
 				  struct ieee80211_sta *sta,
-				  u16 tid, u16 *ssn)
+				  u16 tid, u16 *ssn, u8 buf_size)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath9k_htc_sta *ista;
--- wireless-testing.orig/drivers/net/wireless/ath/ath9k/main.c	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/drivers/net/wireless/ath/ath9k/main.c	2011-01-12 13:02:36.000000000 +0100
@@ -2018,7 +2018,7 @@ static int ath9k_ampdu_action(struct iee
 			      struct ieee80211_vif *vif,
 			      enum ieee80211_ampdu_mlme_action action,
 			      struct ieee80211_sta *sta,
-			      u16 tid, u16 *ssn)
+			      u16 tid, u16 *ssn, u8 buf_size)
 {
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
--- wireless-testing.orig/drivers/net/wireless/ath/carl9170/main.c	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/drivers/net/wireless/ath/carl9170/main.c	2011-01-12 13:02:36.000000000 +0100
@@ -1279,7 +1279,7 @@ static int carl9170_op_ampdu_action(stru
 				    struct ieee80211_vif *vif,
 				    enum ieee80211_ampdu_mlme_action action,
 				    struct ieee80211_sta *sta,
-				    u16 tid, u16 *ssn)
+				    u16 tid, u16 *ssn, u8 buf_size)
 {
 	struct ar9170 *ar = hw->priv;
 	struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-agn.c	2011-01-12 13:02:35.000000000 +0100
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-agn.c	2011-01-12 13:02:36.000000000 +0100
@@ -3416,7 +3416,8 @@ int iwlagn_mac_set_key(struct ieee80211_
 int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size)
 {
 	struct iwl_priv *priv = hw->priv;
 	int ret = -EINVAL;
--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-agn.h	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-agn.h	2011-01-12 13:02:36.000000000 +0100
@@ -363,7 +363,8 @@ void iwlagn_mac_update_tkip_key(struct i
 int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size);
 int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
 		       struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta);
--- wireless-testing.orig/drivers/net/wireless/mac80211_hwsim.c	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/drivers/net/wireless/mac80211_hwsim.c	2011-01-12 13:02:36.000000000 +0100
@@ -943,7 +943,8 @@ static int mac80211_hwsim_testmode_cmd(s
 static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
 				       enum ieee80211_ampdu_mlme_action action,
-				       struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+				       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+				       u8 buf_size)
 {
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
--- wireless-testing.orig/drivers/net/wireless/mwl8k.c	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/drivers/net/wireless/mwl8k.c	2011-01-12 13:02:36.000000000 +0100
@@ -3932,7 +3932,8 @@ static int mwl8k_get_survey(struct ieee8
 static int
 mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		   enum ieee80211_ampdu_mlme_action action,
-		   struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+		   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+		   u8 buf_size)
 {
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
--- wireless-testing.orig/drivers/net/wireless/rt2x00/rt2800lib.c	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/drivers/net/wireless/rt2x00/rt2800lib.c	2011-01-12 13:02:36.000000000 +0100
@@ -3530,7 +3530,8 @@ EXPORT_SYMBOL_GPL(rt2800_get_tsf);
 
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			u8 buf_size)
 {
 	int ret = 0;
 
--- wireless-testing.orig/drivers/net/wireless/rt2x00/rt2800lib.h	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/drivers/net/wireless/rt2x00/rt2800lib.h	2011-01-12 13:02:36.000000000 +0100
@@ -198,7 +198,8 @@ int rt2800_conf_tx(struct ieee80211_hw *
 u64 rt2800_get_tsf(struct ieee80211_hw *hw);
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			u8 buf_size);
 int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
 		      struct survey_info *survey);
 
--- wireless-testing.orig/drivers/net/wireless/rtlwifi/core.c	2011-01-12 13:02:27.000000000 +0100
+++ wireless-testing/drivers/net/wireless/rtlwifi/core.c	2011-01-12 13:02:36.000000000 +0100
@@ -748,7 +748,8 @@ static void rtl_op_sta_notify(struct iee
 static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
 			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 * ssn)
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 



^ permalink raw reply

* [RFC 0/2] advertise aggregate size limit
From: Johannes Berg @ 2011-01-12 12:31 UTC (permalink / raw)
  To: linux-wireless

This can help optimise peers reorder buffer sizes.

johannes


^ permalink raw reply

* [RFC 1/2] mac80211: allow advertising correct maximum aggregate size
From: Johannes Berg @ 2011-01-12 12:31 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20110112123100.615900267@sipsolutions.net>

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

Currently, mac80211 always advertises that it may send
up to 64 subframes in an aggregate. This is fine, since
it's the max, but might as well be set to zero instead
since it doesn't have any information.

However, drivers might have that information, so allow
them to set a variable giving it, which will then be
used. The default of zero will be fine since to the
peer that means we don't know and it will just use its
own limit for the buffer size.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h |    5 +++++
 net/mac80211/agg-tx.c  |    3 ++-
 2 files changed, 7 insertions(+), 1 deletion(-)

--- wireless-testing.orig/include/net/mac80211.h	2011-01-12 13:25:40.000000000 +0100
+++ wireless-testing/include/net/mac80211.h	2011-01-12 13:26:56.000000000 +0100
@@ -1147,6 +1147,10 @@ enum ieee80211_hw_flags {
  * @napi_weight: weight used for NAPI polling.  You must specify an
  *	appropriate value here if a napi_poll operation is provided
  *	by your driver.
+ *
+ * @max_tx_aggregation_subframes: maximum number of subframes in an
+ *	aggregate an HT driver will transmit, used by the peer as a
+ *	hint to size its reorder buffer.
  */
 struct ieee80211_hw {
 	struct ieee80211_conf conf;
@@ -1165,6 +1169,7 @@ struct ieee80211_hw {
 	u8 max_rates;
 	u8 max_report_rates;
 	u8 max_rate_tries;
+	u8 max_tx_aggregation_subframes;
 };
 
 /**
--- wireless-testing.orig/net/mac80211/agg-tx.c	2011-01-12 13:27:01.000000000 +0100
+++ wireless-testing/net/mac80211/agg-tx.c	2011-01-12 13:27:20.000000000 +0100
@@ -342,7 +342,8 @@ void ieee80211_tx_ba_session_handle_star
 	/* send AddBA request */
 	ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
 				     tid_tx->dialog_token, start_seq_num,
-				     0x40, tid_tx->timeout);
+				     local->hw.max_tx_aggregation_subframes,
+				     tid_tx->timeout);
 }
 
 int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,



^ permalink raw reply

* [RFC 2/2] iwlwifi: advertise max aggregate size
From: Johannes Berg @ 2011-01-12 12:31 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20110112123100.615900267@sipsolutions.net>

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

Allow peers to size their reorder buffer more
accurately by advertising that we'll never send
aggregates longer than the default (31).

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c |    2 ++
 1 file changed, 2 insertions(+)

--- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-agn.c	2011-01-12 13:28:18.000000000 +0100
+++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-agn.c	2011-01-12 13:28:41.000000000 +0100
@@ -3191,6 +3191,8 @@ static int iwl_mac_setup_register(struct
 		    IEEE80211_HW_SPECTRUM_MGMT |
 		    IEEE80211_HW_REPORTS_TX_ACK_STATUS;
 
+	hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+
 	if (!priv->cfg->base_params->broken_powersave)
 		hw->flags |= IEEE80211_HW_SUPPORTS_PS |
 			     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;



^ permalink raw reply

* [PATCH] mac80211: fix lockdep warning
From: Johannes Berg @ 2011-01-12 12:40 UTC (permalink / raw)
  To: John Linville
  Cc: linux-wireless@vger.kernel.org, Miles Lane, Sujith, Larry Finger

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

Since the introduction of the fixes for the
reorder timer, mac80211 will cause lockdep
warnings because lockdep confuses
local->skb_queue and local->rx_skb_queue
and treats their lock as the same.

However, their locks are different, and are
valid in different contexts (the former is
used in IRQ context, the latter in BH only)
and the only thing to be done is mark the
former as a different lock class so that
lockdep can tell the difference.

Reported-by: Larry Finger <Larry.Finger@lwfinger.net>
Reported-by: Sujith <m.sujith@gmail.com>
Reported-by: Miles Lane <miles.lane@gmail.com>
Tested-by: Sujith <m.sujith@gmail.com>
Tested-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/main.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

--- wireless-testing.orig/net/mac80211/main.c	2011-01-12 09:58:07.000000000 +0100
+++ wireless-testing/net/mac80211/main.c	2011-01-12 10:02:03.000000000 +0100
@@ -39,6 +39,8 @@ module_param(ieee80211_disable_40mhz_24g
 MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz,
 		 "Disable 40MHz support in the 2.4GHz band");
 
+static struct lock_class_key ieee80211_rx_skb_queue_class;
+
 void ieee80211_configure_filter(struct ieee80211_local *local)
 {
 	u64 mc;
@@ -569,7 +571,15 @@ struct ieee80211_hw *ieee80211_alloc_hw(
 	spin_lock_init(&local->filter_lock);
 	spin_lock_init(&local->queue_stop_reason_lock);
 
-	skb_queue_head_init(&local->rx_skb_queue);
+	/*
+	 * The rx_skb_queue is only accessed from tasklets,
+	 * but other SKB queues are used from within IRQ
+	 * context. Therefore, this one needs a different
+	 * locking class so our direct, non-irq-safe use of
+	 * the queue's lock doesn't throw lockdep warnings.
+	 */
+	skb_queue_head_init_class(&local->rx_skb_queue,
+				  &ieee80211_rx_skb_queue_class);
 
 	INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
 



^ permalink raw reply

* [PATCH 2/2] wl12xx: add hw configuration for max supported AMDPU size
From: coelho @ 2011-01-12 12:40 UTC (permalink / raw)
  To: linux-wireless; +Cc: juuso.oikarinen
In-Reply-To: <1294836052-16828-1-git-send-email-coelho@ti.com>

From: Luciano Coelho <coelho@ti.com>

The wl12xx chips do the AMDPU aggregation work in the firmware, but it
supports a maximum of 8 frames per block.  Configure the mac80211 hw
structure accordingly.

Signed-off-by: Luciano Coelho <coelho@ti.com>
---
 drivers/net/wireless/wl12xx/main.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 67732ea..463d6bf 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -3178,6 +3178,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
 
 	wl->hw->sta_data_size = sizeof(struct wl1271_station);
 
+	wl->hw->max_rx_aggregation_subframes = 8;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(wl1271_init_ieee80211);
-- 
1.7.1


^ permalink raw reply related

* [PATCH 1/2] mac80211: add hw configuration for max ampdu buffer size
From: coelho @ 2011-01-12 12:40 UTC (permalink / raw)
  To: linux-wireless; +Cc: juuso.oikarinen

From: Luciano Coelho <coelho@ti.com>

Some devices don't support the maximum AMDPU buffer size of 64, so we
need to add an option to configure this in the hardware configuration.
This value will be used in the ADDBA response instead of the value
suggested in the request, if the latter is greater than the max
supported.

Signed-off-by: Luciano Coelho <coelho@ti.com>
---
 include/net/mac80211.h |    4 ++++
 net/mac80211/agg-rx.c  |    3 +++
 net/mac80211/main.c    |    1 +
 3 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5b3fd5a..1341d82 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1143,6 +1143,9 @@ enum ieee80211_hw_flags {
  * @napi_weight: weight used for NAPI polling.  You must specify an
  *	appropriate value here if a napi_poll operation is provided
  *	by your driver.
+ * @max_rx_aggregation_subframes: maximum buffer size (number of
+ *	sub-frames) to be used for A-MPDU block ack receiver
+ *	aggregation.
  */
 struct ieee80211_hw {
 	struct ieee80211_conf conf;
@@ -1161,6 +1164,7 @@ struct ieee80211_hw {
 	u8 max_rates;
 	u8 max_report_rates;
 	u8 max_rate_tries;
+	u8 max_rx_aggregation_subframes;
 };
 
 /**
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index f138b19..002db5e 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -239,6 +239,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 		buf_size = buf_size << sband->ht_cap.ampdu_factor;
 	}
 
+	/* make sure the size doesn't exceed the maximum supported by the hw */
+	if (buf_size > local->hw.max_rx_aggregation_subframes)
+		buf_size = local->hw.max_rx_aggregation_subframes;
 
 	/* examine state machine */
 	mutex_lock(&sta->ampdu_mlme.mtx);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 485d36b..1c507c6 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -552,6 +552,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 	local->hw.queues = 1;
 	local->hw.max_rates = 1;
 	local->hw.max_report_rates = 0;
+	local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
 	local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
 	local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
 	local->user_power_level = -1;
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCH 1/2] mac80211: add hw configuration for max ampdu buffer size
From: Luciano Coelho @ 2011-01-12 12:43 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: juuso.oikarinen@nokia.com
In-Reply-To: <1294836052-16828-1-git-send-email-coelho@ti.com>

On Wed, 2011-01-12 at 13:40 +0100, Coelho, Luciano wrote:
> From: Luciano Coelho <coelho@ti.com>
> 
> Some devices don't support the maximum AMDPU buffer size of 64, so we
> need to add an option to configure this in the hardware configuration.
> This value will be used in the ADDBA response instead of the value
> suggested in the request, if the latter is greater than the max
> supported.
> 
> Signed-off-by: Luciano Coelho <coelho@ti.com>
> ---

This has not been tested, so it should probably have been sent as RFC.
Juuso is testing it at the moment (I think ;).


-- 
Cheers,
Luca.


^ permalink raw reply

* Re: [PATCH 1/2] mac80211: add hw configuration for max ampdu buffer size
From: Johannes Berg @ 2011-01-12 12:46 UTC (permalink / raw)
  To: coelho; +Cc: linux-wireless, juuso.oikarinen
In-Reply-To: <1294836052-16828-1-git-send-email-coelho@ti.com>

On Wed, 2011-01-12 at 14:40 +0200, coelho@ti.com wrote:
> From: Luciano Coelho <coelho@ti.com>
> 
> Some devices don't support the maximum AMDPU buffer size of 64, so we
> need to add an option to configure this in the hardware configuration.
> This value will be used in the ADDBA response instead of the value
> suggested in the request, if the latter is greater than the max
> supported.
> 
> Signed-off-by: Luciano Coelho <coelho@ti.com>
> ---
>  include/net/mac80211.h |    4 ++++
>  net/mac80211/agg-rx.c  |    3 +++
>  net/mac80211/main.c    |    1 +
>  3 files changed, 8 insertions(+), 0 deletions(-)
> 
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index 5b3fd5a..1341d82 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -1143,6 +1143,9 @@ enum ieee80211_hw_flags {
>   * @napi_weight: weight used for NAPI polling.  You must specify an
>   *	appropriate value here if a napi_poll operation is provided
>   *	by your driver.
> + * @max_rx_aggregation_subframes: maximum buffer size (number of
> + *	sub-frames) to be used for A-MPDU block ack receiver
> + *	aggregation.

... "This is only relevant if the device has restrictions on the number
of subframes, if it relies on mac80211 to do reordering it shouldn't be
set." maybe?

johannes


^ permalink raw reply

* [PATCH] mac80211: use maximum number of a-msdu frames as default in BA RX
From: coelho @ 2011-01-12 12:51 UTC (permalink / raw)
  To: linux-wireless; +Cc: Luciano Coelho, stable, Johannes Berg

From: Luciano Coelho <coelho@ti.com>

When the buffer size is set to zero in the block ack parameter set
field, we should use the maximum supported number of subframes.  The
existing code was bogus and was doing some unnecessary calculations
that lead to wrong values.

Thanks Johannes for helping me figure this one out.

Cc: stable@kernel.org
Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
 net/mac80211/agg-rx.c |    9 ++-------
 1 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 002db5e..ed3ee93 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -231,13 +231,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 		goto end_no_lock;
 	}
 	/* determine default buffer size */
-	if (buf_size == 0) {
-		struct ieee80211_supported_band *sband;
-
-		sband = local->hw.wiphy->bands[conf->channel->band];
-		buf_size = IEEE80211_MIN_AMPDU_BUF;
-		buf_size = buf_size << sband->ht_cap.ampdu_factor;
-	}
+	if (buf_size == 0)
+		buf_size = IEEE80211_MAX_AMPDU_BUF;
 
 	/* make sure the size doesn't exceed the maximum supported by the hw */
 	if (buf_size > local->hw.max_rx_aggregation_subframes)
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCH] mac80211: use maximum number of a-msdu frames as default in BA RX
From: Johannes Berg @ 2011-01-12 12:54 UTC (permalink / raw)
  To: coelho; +Cc: linux-wireless, stable
In-Reply-To: <1294836681-21712-1-git-send-email-coelho@ti.com>

On Wed, 2011-01-12 at 14:51 +0200, coelho@ti.com wrote:
> From: Luciano Coelho <coelho@ti.com>
> 
> When the buffer size is set to zero in the block ack parameter set
> field, we should use the maximum supported number of subframes.  The
> existing code was bogus and was doing some unnecessary calculations
> that lead to wrong values.
> 
> Thanks Johannes for helping me figure this one out.
> 
> Cc: stable@kernel.org
> Cc: Johannes Berg <johannes@sipsolutions.net>

Reviewed-by: Johannes Berg <johannes@sipsolutions.net>

It'd be easier for stable if you reordered with the other patch, I
think, but I guess it's easy enough to fix up.

Also some older stable versions might have this code in a different
file, but I'm not sure how to handle that.

johannes

> Signed-off-by: Luciano Coelho <coelho@ti.com>
> ---
>  net/mac80211/agg-rx.c |    9 ++-------
>  1 files changed, 2 insertions(+), 7 deletions(-)
> 
> diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
> index 002db5e..ed3ee93 100644
> --- a/net/mac80211/agg-rx.c
> +++ b/net/mac80211/agg-rx.c
> @@ -231,13 +231,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
>  		goto end_no_lock;
>  	}
>  	/* determine default buffer size */
> -	if (buf_size == 0) {
> -		struct ieee80211_supported_band *sband;
> -
> -		sband = local->hw.wiphy->bands[conf->channel->band];
> -		buf_size = IEEE80211_MIN_AMPDU_BUF;
> -		buf_size = buf_size << sband->ht_cap.ampdu_factor;
> -	}
> +	if (buf_size == 0)
> +		buf_size = IEEE80211_MAX_AMPDU_BUF;
>  
>  	/* make sure the size doesn't exceed the maximum supported by the hw */
>  	if (buf_size > local->hw.max_rx_aggregation_subframes)



^ permalink raw reply

* Re: [PATCH 1/2] mac80211: add hw configuration for max ampdu buffer size
From: Juuso Oikarinen @ 2011-01-12 12:57 UTC (permalink / raw)
  To: ext coelho@ti.com; +Cc: linux-wireless
In-Reply-To: <1294836052-16828-1-git-send-email-coelho@ti.com>

On Wed, 2011-01-12 at 14:40 +0200, ext coelho@ti.com wrote:
> From: Luciano Coelho <coelho@ti.com>
> 
> Some devices don't support the maximum AMDPU buffer size of 64, so we
> need to add an option to configure this in the hardware configuration.
> This value will be used in the ADDBA response instead of the value
> suggested in the request, if the latter is greater than the max
> supported.
> 
> Signed-off-by: Luciano Coelho <coelho@ti.com>
> ---

Tested-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>

-Juuso


^ permalink raw reply

* [RFC 1/2] mac80211: track receivers aggregation reorder buffer size
From: Sujith @ 2011-01-12 13:01 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <20110112121417.852157387@sipsolutions.net>

Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
> 
> The aggregation code currently doesn't implement the
> buffer size negotiation. It will always request a max
> buffer size (which is fine, if a little pointless, as
> the mac80211 code doesn't know and might just use 0
> instead), but if the peer requests a smaller size it
> isn't possible to honour this request.
> 
> In order to fix this, look at the buffer size in the
> addBA response frame, keep track of it and pass it to
> the driver in the ampdu_action callback when called
> with the IEEE80211_AMPDU_TX_OPERATIONAL action. That
> way the driver can limit the number of subframes in
> aggregates appropriately.
> 
> Note that this doesn't fix any drivers apart from the
> addition of the new argument -- they all need to be
> updated separately to use this variable!

At least for ath9k_htc, the fix is pretty simple, something like the patch below.
I tested this with a peer advertising a non-default subframe count
(using max_tx_aggregation_subframes) and it seems to work. Now all that is needed
is to fix the FW to actually _use_ this value. :)

diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 1ce506f..94a4b14 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -210,6 +210,7 @@ struct ath9k_htc_vif {
 
 #define ATH9K_HTC_MAX_STA 8
 #define ATH9K_HTC_MAX_TID 8
+#define ATH9K_HTC_MAX_SUBFRAME 20
 
 enum tid_aggr_state {
 	AGGR_STOP = 0,
@@ -433,7 +434,7 @@ void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id,
 void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
 			enum htc_endpoint_id ep_id, bool txok);
 
-int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv);
+int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, u8 buf_size);
 void ath9k_htc_station_work(struct work_struct *work);
 void ath9k_htc_aggr_work(struct work_struct *work);
 void ath9k_ani_work(struct work_struct *work);;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index f4d576b..3a3f982 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -304,7 +304,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
 	/*
 	 * Set chainmask etc. on the target.
 	 */
-	ret = ath9k_htc_update_cap_target(priv);
+	ret = ath9k_htc_update_cap_target(priv, ATH9K_HTC_MAX_SUBFRAME);
 	if (ret)
 		ath_dbg(common, ATH_DBG_CONFIG,
 			"Failed to update capability in target\n");
@@ -430,7 +430,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
 	return 0;
 }
 
-int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv)
+int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, u8 buf_size)
 {
 	struct ath9k_htc_cap_target tcap;
 	int ret;
@@ -442,7 +442,7 @@ int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv)
 	tcap.flags = 0x240c40;
 	tcap.flags_ext = 0x80601000;
 	tcap.ampdu_limit = 0xffff0000;
-	tcap.ampdu_subframes = 20;
+	tcap.ampdu_subframes = min((u8)ATH9K_HTC_MAX_SUBFRAME, buf_size);
 	tcap.tx_chainmask_legacy = priv->ah->caps.tx_chainmask;
 	tcap.protmode = 1;
 	tcap.tx_chainmask = priv->ah->caps.tx_chainmask;
@@ -1130,7 +1130,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 	if (ret)
 		goto out;
 
-	ret = ath9k_htc_update_cap_target(priv);
+	ret = ath9k_htc_update_cap_target(priv, ATH9K_HTC_MAX_SUBFRAME);
 	if (ret)
 		ath_dbg(common, ATH_DBG_CONFIG,
 			"Failed to update capability in target\n");
@@ -1548,7 +1548,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
 				  enum ieee80211_ampdu_mlme_action action,
 				  struct ieee80211_sta *sta,
-				  u16 tid, u16 *ssn)
+				  u16 tid, u16 *ssn, u8 buf_size)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath9k_htc_sta *ista;
@@ -1570,6 +1570,12 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
 		ista = (struct ath9k_htc_sta *) sta->drv_priv;
+		if (buf_size < ATH9K_HTC_MAX_SUBFRAME) {
+			ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG,
+				"Choosing subframe count %d for station %pM\n",
+				buf_size, sta->addr);
+			ath9k_htc_update_cap_target(priv, buf_size);
+		}
 		spin_lock_bh(&priv->tx_lock);
 		ista->tid_state[tid] = AGGR_OPERATIONAL;
 		spin_unlock_bh(&priv->tx_lock);

^ permalink raw reply related

* Re: [PATCH] mac80211: use maximum number of a-msdu frames as default in BA RX
From: Luciano Coelho @ 2011-01-12 13:03 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org, stable@kernel.org
In-Reply-To: <1294836844.3639.26.camel@jlt3.sipsolutions.net>

On Wed, 2011-01-12 at 13:54 +0100, Johannes Berg wrote:
> On Wed, 2011-01-12 at 14:51 +0200, coelho@ti.com wrote:
> > From: Luciano Coelho <coelho@ti.com>
> > 
> > When the buffer size is set to zero in the block ack parameter set
> > field, we should use the maximum supported number of subframes.  The
> > existing code was bogus and was doing some unnecessary calculations
> > that lead to wrong values.
> > 
> > Thanks Johannes for helping me figure this one out.
> > 
> > Cc: stable@kernel.org
> > Cc: Johannes Berg <johannes@sipsolutions.net>
> 
> Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
> 
> It'd be easier for stable if you reordered with the other patch, I
> think, but I guess it's easy enough to fix up.

Will do.


> Also some older stable versions might have this code in a different
> file, but I'm not sure how to handle that.

Dunno how to handle that either... If I need to do something, someone
please just let me know. ;)

-- 
Cheers,
Luca.


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox