Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: cross compile backports with LTIB
From: Jonathan Bagg @ 2013-08-01 19:12 UTC (permalink / raw)
  To: backports; +Cc: Solomon Peachy, linux-wireless
In-Reply-To: <20130801174749.GC10904@shaftnet.org>

On 13-08-01 01:47 PM, Solomon Peachy wrote:
> On Thu, Aug 01, 2013 at 12:37:33PM -0400, Jonathan Bagg wrote:
>> I've been cross compiling compat-wireless and now I'm trying
>> backports.  It looks like conf.c and zconf.tab.c are being compiled
>> as arm and then the build process is trying to run conf on my x86
>> host.  Results using the below make parameters I was using for
>> compat-wireless......
Learned some things....Problem was LTIB (ltib = Freescale tool) 
environment.  Outside of LTIB, backports cross compiles fine.  To get 
backports happy in LTIB need to use UNSPOOF/SPOOF_PATH to switch between 
host and cross environment....

%Build
export PATH=$UNSPOOF_PATH

make defconfig-cw1200 make prefix=%{_prefix} 
CROSS_COMPILE=${TOOLCHAIN_PATH}/bin/${TOOLCHAIN_PREFIX} ARCH=$LINTARCH 
KLIB=${TOP}/rootfs/lib/modules/%{kversion} KLIB_BUILD=${TOP}/rpm/BUILD/linux

export PATH=$SPOOF_PATH

make prefix=%{_prefix} 
CROSS_COMPILE=${TOOLCHAIN_PATH}/bin/${TOOLCHAIN_PREFIX} ARCH=$LINTARCH 
KLIB=${TOP}/rootfs/lib/modules/%{kversion} KLIB_BUILD=${TOP}/rpm/BUILD/linux

Jon

> Howdy.  :)
>
> (btw, I'm CC'ing the backports mailing list, which is a better place to
>   ask these sorts of questions)
>
> I found that the backports cross-compile process worked much the same
> way as building compat-wireless.  This is what I'm doing currently in my
> build script:  (This is using a backports package generated last night
> using the backports git HEAD code with the cw1200 driver integrated)
>
>   set -a
>   CROSS_COMPILE=${CROSS_COMPILE}
>   ARCH=${TARGET_CPU}
>   KLIB_BUILD=${DEV_PATH}/${LINUX_DIR}
>   KLIB=${TARGET_ROOT_ON_HOST}
>   set +a
>   make oldconfig  # menuconfig worked here too
>   make
>   make install
>
> That said, the 'make install' target isn't currently sane for
> cross-builds due to the bacport_firmware_install script not respecting
> prefixes.  I just commented that script (and a few others like initrd
> updates) out of the Makefiles, and I had a successful build/install.
>
>   - Solomon


-- 
Jonathan Bagg
Software Developer
NAD Electronics | Lenbrook Industries Limited
633 Granite Court, Pickering, Ontario, Canada L1W 3K1 | 905-831-0799 ext 4478 | http://www.nadelectronics.com


^ permalink raw reply

* Re: cross compile backports?
From: Luis R. Rodriguez @ 2013-08-01 19:03 UTC (permalink / raw)
  To: Solomon Peachy; +Cc: Jonathan Bagg, linux-wireless, backports@vger.kernel.org
In-Reply-To: <20130801174749.GC10904@shaftnet.org>

On Thu, Aug 1, 2013 at 10:47 AM, Solomon Peachy <pizza@shaftnet.org> wrote:
> On Thu, Aug 01, 2013 at 12:37:33PM -0400, Jonathan Bagg wrote:
>> I've been cross compiling compat-wireless and now I'm trying
>> backports.  It looks like conf.c and zconf.tab.c are being compiled
>> as arm and then the build process is trying to run conf on my x86
>> host.  Results using the below make parameters I was using for
>> compat-wireless......
>
> Howdy.  :)
>
> (btw, I'm CC'ing the backports mailing list, which is a better place to
>  ask these sorts of questions)
>
> I found that the backports cross-compile process worked much the same
> way as building compat-wireless.  This is what I'm doing currently in my
> build script:  (This is using a backports package generated last night
> using the backports git HEAD code with the cw1200 driver integrated)
>
>  set -a
>  CROSS_COMPILE=${CROSS_COMPILE}
>  ARCH=${TARGET_CPU}
>  KLIB_BUILD=${DEV_PATH}/${LINUX_DIR}
>  KLIB=${TARGET_ROOT_ON_HOST}
>  set +a
>  make oldconfig  # menuconfig worked here too
>  make
>  make install
>
> That said, the 'make install' target isn't currently sane for
> cross-builds due to the bacport_firmware_install script not respecting
> prefixes.  I just commented that script (and a few others like initrd
> updates) out of the Makefiles, and I had a successful build/install.

Thanks, now:

https://backports.wiki.kernel.org/index.php/Documentation#Cross_compiling

Patches welcome to help improve the cross compile install target.

  Luis

^ permalink raw reply

* Re: cross compile backports?
From: Solomon Peachy @ 2013-08-01 17:47 UTC (permalink / raw)
  To: Jonathan Bagg; +Cc: linux-wireless, backports
In-Reply-To: <51FA8ECD.7070401@lenbrook.com>

[-- Attachment #1: Type: text/plain, Size: 1449 bytes --]

On Thu, Aug 01, 2013 at 12:37:33PM -0400, Jonathan Bagg wrote:
> I've been cross compiling compat-wireless and now I'm trying
> backports.  It looks like conf.c and zconf.tab.c are being compiled
> as arm and then the build process is trying to run conf on my x86
> host.  Results using the below make parameters I was using for
> compat-wireless......

Howdy.  :)

(btw, I'm CC'ing the backports mailing list, which is a better place to 
 ask these sorts of questions)

I found that the backports cross-compile process worked much the same 
way as building compat-wireless.  This is what I'm doing currently in my 
build script:  (This is using a backports package generated last night 
using the backports git HEAD code with the cw1200 driver integrated)

 set -a
 CROSS_COMPILE=${CROSS_COMPILE} 
 ARCH=${TARGET_CPU}
 KLIB_BUILD=${DEV_PATH}/${LINUX_DIR}
 KLIB=${TARGET_ROOT_ON_HOST}
 set +a
 make oldconfig  # menuconfig worked here too
 make
 make install

That said, the 'make install' target isn't currently sane for 
cross-builds due to the bacport_firmware_install script not respecting 
prefixes.  I just commented that script (and a few others like initrd 
updates) out of the Makefiles, and I had a successful build/install.

 - Solomon
-- 
Solomon Peachy        		       pizza at shaftnet dot org
Delray Beach, FL                          ^^ (email/xmpp) ^^
Quidquid latine dictum sit, altum viditur.

[-- Attachment #2: Type: application/pgp-signature, Size: 190 bytes --]

^ permalink raw reply

* Re: [PATCH 0/8] include/net: next set of extern removals
From: Joe Perches @ 2013-08-01 17:05 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David Howells, netdev, linux-hams, linux-wireless, linux-kernel,
	linux-afs
In-Reply-To: <1375375486.10515.170.camel@edumazet-glaptop>

On Thu, 2013-08-01 at 09:44 -0700, Eric Dumazet wrote:
> 'extern' in include files are an easy way to have a grep friendly
> marker, and otherwise are harmless.
> 
> _You_ believe they are useless, other people think otherwise.

I believe I wrote superfluous.

> I learned C 30 years ago, and using 'extern' is quite natural for me.

I think I've got a few years headstart on you.
All that means is we're both relatively old...

cheers, Joe


^ permalink raw reply

* cross compile backports?
From: Jonathan Bagg @ 2013-08-01 16:37 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <1375370826-1387-1-git-send-email-sujith@msujith.org>

Hello,

I've been cross compiling compat-wireless and now I'm trying backports.  
It looks like conf.c and zconf.tab.c are being compiled as arm and then 
the build process is trying to run conf on my x86 host.  Results using 
the below make parameters I was using for compat-wireless......

Generating local configuration database from kernel ... done.
gcc -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 
-fomit-frame-pointer   -c -o conf.o conf.c
gcc -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 
-fomit-frame-pointer   -c -o zconf.tab.o zconf.tab.c
gcc   conf.o zconf.tab.o   -o conf
./kconf/conf: ./kconf/conf: cannot execute binary file

There must be a way to build conf as x86 and the actual drivers as arm 
without butchering the makefile? I've been cross compiling 
compat-wireless with....

make    prefix=%{_prefix}
CROSS_COMPILE=/opt/freescale/usr/local/gcc-4.6.2-glibc-2.13-linaro-multilib-2011.12/fsl-linaro-toolchain/bin/arm-none-linux-gnueabi- 
\
     ARCH=arm \
     KLIB=/media/hdd1/ltibs/n100/rootfs/lib/modules/%{kversion} \
     KLIB_BUILD=/media/hdd1/ltibs/n100/rpm/BUILD/linux

Jon

^ permalink raw reply

* Re: [PATCH 0/8] include/net: next set of extern removals
From: Eric Dumazet @ 2013-08-01 16:44 UTC (permalink / raw)
  To: Joe Perches
  Cc: David Howells, netdev, linux-hams, linux-wireless, linux-kernel,
	linux-afs
In-Reply-To: <1375374560.2034.52.camel@joe-AO722>

On Thu, 2013-08-01 at 09:29 -0700, Joe Perches wrote:
> On Thu, 2013-08-01 at 13:04 +0100, David Howells wrote:
> > Joe Perches <joe@perches.com> wrote:
> > > Standardize on no extern use on function prototypes
> > Can we please standardise on _having_ externs on function prototypes?
> 
> Why?
> 
> What value is there in using extern for function prototypes?
> 
> Your argument for "picking out at a glance"
> https://lkml.org/lkml/2013/8/1/237
> really doesn't make sense to me.
> 
> Basically, anything with parentheses that's not a #define
> is an extern.
> 
> Exceptions exist for extern function pointers, but those
> are fairly unusual anyway.  Outside of netfilter,
> extern function pointers are only used about a dozen times
> total in the kernel tree.
> 
> So, please provide some examples supporting your view.

My main concern about these changes is they are a huge pain for us
doing bug tracking, rebases and backports. "git blame" and friends will
show lot of noise.

'extern' in include files are an easy way to have a grep friendly
marker, and otherwise are harmless.

_You_ believe they are useless, other people think otherwise.

I really don't see any value doing all these changes on existing code,
apart from adding noise to netdev and adding more work for us.

Using rules for new code is fine, but changing 10 years old code is
really not worth the pain.

I learned C 30 years ago, and using 'extern' is quite natural for me.

It's crazy the time we have to spend on these issues, while we have so
many bugs to fix in the kernel.




^ permalink raw reply

* Re: [PATCH 0/8] include/net: next set of extern removals
From: Joe Perches @ 2013-08-01 16:29 UTC (permalink / raw)
  To: David Howells; +Cc: netdev, linux-hams, linux-wireless, linux-kernel, linux-afs
In-Reply-To: <24958.1375358650@warthog.procyon.org.uk>

On Thu, 2013-08-01 at 13:04 +0100, David Howells wrote:
> Joe Perches <joe@perches.com> wrote:
> > Standardize on no extern use on function prototypes
> Can we please standardise on _having_ externs on function prototypes?

Why?

What value is there in using extern for function prototypes?

Your argument for "picking out at a glance"
https://lkml.org/lkml/2013/8/1/237
really doesn't make sense to me.

Basically, anything with parentheses that's not a #define
is an extern.

Exceptions exist for extern function pointers, but those
are fairly unusual anyway.  Outside of netfilter,
extern function pointers are only used about a dozen times
total in the kernel tree.

So, please provide some examples supporting your view.



^ permalink raw reply

* [[PATCHv2]rt2800usb: ampdu len] rt2800usb: update aggregation len
From: Sylvain ROGER RIEUNIER @ 2013-08-01 15:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: users, Sylvain Roger Rieunier

From: Sylvain Roger Rieunier <sylvain.roger.rieunier@gmail.com>

I tried to read periodically TX_AGG_CNT registers on the rt2800usb driver.
I'had made USB synchronous and asynchronous read. But it's only reduces the
bandwidth.
Does anyone have an idea?


Signed-off-by: Sylvain ROGER RIEUNIER <sylvain.roger.rieunier@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c   |   69 ++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2800usb.c   |   92 +++++++++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2x00.h      |   28 +++++++++
 drivers/net/wireless/rt2x00/rt2x00debug.c |   66 +++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2x00dev.c   |    2 +
 drivers/net/wireless/rt2x00/rt2x00usb.c   |    2 +
 6 files changed, 259 insertions(+)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index dedc3d4..0db45fb 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1813,6 +1813,75 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 }
 EXPORT_SYMBOL_GPL(rt2800_config_ant);
 
+void rt2800_update_aggr_stats(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+	u32 all;
+	int i;
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT, &reg);
+	rt2x00dev->aggr_stats.no_aggr =
+		rt2x00_get_field32(reg,TX_AGG_CNT_NON_AGG_TX_COUNT);
+	rt2x00dev->aggr_stats.all_aggr =
+		rt2x00_get_field32(reg,TX_AGG_CNT_AGG_TX_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT0, &reg);
+	rt2x00dev->aggr_stats.ampduCount[0] =
+		rt2x00_get_field32(reg,TX_AGG_CNT0_AGG_SIZE_1_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[1] =
+		rt2x00_get_field32(reg,TX_AGG_CNT0_AGG_SIZE_2_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT1, &reg);
+	rt2x00dev->aggr_stats.ampduCount[2] =
+		rt2x00_get_field32(reg,TX_AGG_CNT1_AGG_SIZE_3_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[3] =
+		rt2x00_get_field32(reg,TX_AGG_CNT1_AGG_SIZE_4_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT2, &reg);
+	rt2x00dev->aggr_stats.ampduCount[4] =
+		rt2x00_get_field32(reg,TX_AGG_CNT2_AGG_SIZE_5_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[5] =
+		rt2x00_get_field32(reg,TX_AGG_CNT2_AGG_SIZE_6_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT3, &reg);
+	rt2x00dev->aggr_stats.ampduCount[6] =
+		rt2x00_get_field32(reg,TX_AGG_CNT3_AGG_SIZE_7_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[7] =
+		rt2x00_get_field32(reg,TX_AGG_CNT3_AGG_SIZE_8_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT4, &reg);
+	rt2x00dev->aggr_stats.ampduCount[8] =
+		rt2x00_get_field32(reg,TX_AGG_CNT4_AGG_SIZE_9_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[9] =
+		rt2x00_get_field32(reg,TX_AGG_CNT4_AGG_SIZE_10_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT5, &reg);
+	rt2x00dev->aggr_stats.ampduCount[10] =
+		rt2x00_get_field32(reg,TX_AGG_CNT5_AGG_SIZE_11_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[11] =
+		rt2x00_get_field32(reg,TX_AGG_CNT5_AGG_SIZE_12_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT6, &reg);
+	rt2x00dev->aggr_stats.ampduCount[12] =
+		rt2x00_get_field32(reg,TX_AGG_CNT6_AGG_SIZE_13_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[13] =
+		rt2x00_get_field32(reg,TX_AGG_CNT6_AGG_SIZE_14_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT7, &reg);
+	rt2x00dev->aggr_stats.ampduCount[14] =
+		rt2x00_get_field32(reg,TX_AGG_CNT7_AGG_SIZE_15_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[15] =
+		rt2x00_get_field32(reg,TX_AGG_CNT7_AGG_SIZE_16_COUNT);
+
+	all = rt2x00dev->aggr_stats.no_aggr +
+		rt2x00dev->aggr_stats.all_aggr;
+
+	for( i = 0; i < 16 ; i++)
+		rt2x00dev->aggr_stats.ampduRatio[i] =
+			((rt2x00dev->aggr_stats.ampduCount[i] * 100) / all);
+}
+EXPORT_SYMBOL_GPL(rt2800_update_aggr_stats);
+
 static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
 				   struct rt2x00lib_conf *libconf)
 {
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index fc9efdf..6ca9cdb 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -225,6 +225,79 @@ static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer)
 	return HRTIMER_NORESTART;
 }
 
+
+
+static bool rt2800usb_tx_agg_cnt_read_completed(struct rt2x00_dev *rt2x00dev,
+					   int urb_status, u32 reg)
+{
+
+	if (urb_status) {
+		WARNING(rt2x00dev, "TX status read failed %d\n", urb_status);
+		return false;
+	}
+
+	if(rt2x00dev->aggr_stats.cnt == 0) {
+		rt2x00dev->aggr_stats.no_aggr =
+			rt2x00_get_field32(reg,TX_AGG_CNT_NON_AGG_TX_COUNT);
+		rt2x00dev->aggr_stats.all_aggr =
+			rt2x00_get_field32(reg,TX_AGG_CNT_AGG_TX_COUNT);
+	} else {
+		unsigned int tmp = (rt2x00dev->aggr_stats.cnt - 1)*2;
+
+		rt2x00dev->aggr_stats.ampduCount[tmp] =
+		rt2x00_get_field32(reg,TX_AGG_CNT0_AGG_SIZE_1_COUNT);
+		rt2x00dev->aggr_stats.ampduCount[tmp+1] =
+		rt2x00_get_field32(reg,TX_AGG_CNT0_AGG_SIZE_2_COUNT);
+	}
+
+	if(rt2x00dev->aggr_stats.cnt == 9) {
+		rt2x00dev->aggr_stats.cnt = 0;
+		clear_bit(TX_AGG_TIMER, &rt2x00dev->aggr_stats.flags);
+	} else {
+		rt2x00dev->aggr_stats.cnt++;
+		/* Read next TX_AGG_CNT register after 1 ms */
+		hrtimer_start(&rt2x00dev->txaggcnt_timer,
+			      ktime_set(0, 1000000), HRTIMER_MODE_REL);
+	}
+
+	 return true;
+}
+
+static enum hrtimer_restart rt2800usb_tx_agg_cnt_timeout(struct hrtimer *timer)
+{
+	struct rt2x00_dev *rt2x00dev =
+	    container_of(timer, struct rt2x00_dev, txaggcnt_timer);
+	unsigned int offset;
+
+	offset = TX_AGG_CNT + rt2x00dev->aggr_stats.cnt*4;
+	rt2x00usb_register_read_async(rt2x00dev,offset,
+				      rt2800usb_tx_agg_cnt_read_completed);
+
+	return HRTIMER_NORESTART;
+}
+
+static void rt2800usb_async_read_tx_agg_cnt(struct rt2x00_dev *rt2x00dev)
+{
+
+	if (test_and_set_bit(TX_AGG_TIMER, &rt2x00dev->aggr_stats.flags))
+		return;
+
+	/* Read TX_AGG_CNT register after 1 ms */
+	hrtimer_start(&rt2x00dev->txaggcnt_timer, ktime_set(0, 1000000),
+		      HRTIMER_MODE_REL);
+}
+
+static void rt2800usb_timer_txagg(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+
+	if (!test_bit(TX_AGG_TIMER, &rt2x00dev->aggr_stats.flags))
+		rt2800usb_async_read_tx_agg_cnt(rt2x00dev);
+
+	rt2x00dev->txagg_timer.expires += 5000;
+	add_timer(&rt2x00dev->txagg_timer);
+}
+
 /*
  * Firmware functions
  */
@@ -750,6 +823,7 @@ static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
 static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
 	int retval;
+	unsigned long j = jiffies;
 
 	retval = rt2800_probe_hw(rt2x00dev);
 	if (retval)
@@ -765,6 +839,24 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	 */
 	PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);
 
+	/*
+	 * Set txaggcnt timer function. for usb async read
+	 */
+	rt2x00dev->txaggcnt_timer.function = rt2800usb_tx_agg_cnt_timeout;
+
+	/*
+	 * Set txagg timer function. periodic read
+	 */
+	clear_bit(TX_AGG_TIMER, &rt2x00dev->aggr_stats.flags);
+	rt2x00dev->aggr_stats.cnt = 0;
+	init_timer(&rt2x00dev->txagg_timer);
+	rt2x00dev->txagg_timer.function = rt2800usb_timer_txagg;
+	rt2x00dev->txagg_timer.data = (unsigned long)rt2x00dev;
+
+	j = jiffies;
+	rt2x00dev->txagg_timer.expires = j + 5000;
+	add_timer(&rt2x00dev->txagg_timer);
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index fe4c572..b6ae9f3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -637,6 +637,7 @@ struct rt2x00lib_ops {
 			struct ieee80211_sta *sta);
 	int (*sta_remove) (struct rt2x00_dev *rt2x00dev,
 			   int wcid);
+	void (*update_aggr_stats) (struct rt2x00_dev *rt2x00dev);
 };
 
 /*
@@ -733,6 +734,24 @@ enum {
 	NUM_IF_COMB,
 };
 
+#define RT2X00_AGGR_CNT_MAX 16
+
+/*
+ * rt2x00 aggregation state flags
+ */
+enum rt2x00_agg_state_flags {
+	TX_AGG_TIMER,
+};
+struct rt2x00_aggr_stats {
+	unsigned long flags;
+	unsigned int cnt;
+	u32 all_aggr;
+	u32 no_aggr;
+	u32 ampduCount[RT2X00_AGGR_CNT_MAX];
+	u32 ampduRatio[RT2X00_AGGR_CNT_MAX];
+};
+
+
 /*
  * rt2x00 device structure.
  */
@@ -764,6 +783,8 @@ struct rt2x00_dev {
 	enum ieee80211_band curr_band;
 	int curr_freq;
 
+	struct rt2x00_aggr_stats aggr_stats;
+
 	/*
 	 * If enabled, the debugfs interface structures
 	 * required for deregistration of debugfs.
@@ -984,6 +1005,13 @@ struct rt2x00_dev {
 	struct hrtimer txstatus_timer;
 
 	/*
+	 * Timer to ensure tx aggregation counter reports are read (rt2800usb).
+	 */
+	struct hrtimer txaggcnt_timer;
+
+	struct timer_list txagg_timer;
+
+	/*
 	 * Tasklet for processing tx status reports (rt2800pci).
 	 */
 	struct tasklet_struct txstatus_tasklet;
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index fe7a7f6..c41d5a8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -75,6 +75,7 @@ struct rt2x00debug_intf {
 	 *     - frame dump file
 	 *     - queue stats file
 	 *     - crypto stats file
+	 *     - aggr stats file
 	 */
 	struct dentry *driver_folder;
 	struct dentry *driver_entry;
@@ -96,6 +97,7 @@ struct rt2x00debug_intf {
 	struct dentry *queue_frame_dump_entry;
 	struct dentry *queue_stats_entry;
 	struct dentry *crypto_stats_entry;
+	struct dentry *aggr_stats_entry;
 
 	/*
 	 * The frame dump file only allows a single reader,
@@ -589,6 +591,63 @@ static const struct file_operations rt2x00debug_fop_cap_flags = {
 	.llseek		= default_llseek,
 };
 
+
+static ssize_t rt2x00debug_read_aggr_stats(struct file *file,
+					  char __user *buf,
+					  size_t length,
+					  loff_t *offset)
+{
+	struct rt2x00debug_intf *intf =	file->private_data;
+	struct rt2x00_dev *rt2x00dev = intf->rt2x00dev;
+	size_t size;
+	char *data;
+	char *temp;
+	int i;
+
+	if (*offset)
+		return 0;
+
+	data = kzalloc(17 * MAX_LINE_LENGTH, GFP_KERNEL);
+	if (!data)
+		return 0;
+
+	temp = data;
+	temp += sprintf(temp, "all aggr(%u) no agg(%u) \n",
+		       rt2x00dev->aggr_stats.all_aggr,
+		       rt2x00dev->aggr_stats.no_aggr);
+
+	for (i = 0; i < 15 ; i++) {
+		temp += sprintf(temp, "%u AMPDU cnt(%u), ratio(%u)\n", (i+1),
+		       rt2x00dev->aggr_stats.ampduCount[i],
+		       rt2x00dev->aggr_stats.ampduRatio[i]);
+	}
+
+	temp += sprintf(temp, "16 or up AMPDU cnt(%u), ratio(%u)\n",
+			rt2x00dev->aggr_stats.ampduCount[i],
+			rt2x00dev->aggr_stats.ampduRatio[i]);
+
+	size = strlen(data);
+	size = min(size, length);
+
+	if (copy_to_user(buf, data, size)) {
+		kfree(data);
+		return -EFAULT;
+	}
+
+	kfree(data);
+
+	*offset += size;
+	return size;
+}
+
+static const struct file_operations rt2x00debug_fop_aggr_stats = {
+	.owner		= THIS_MODULE,
+	.read		= rt2x00debug_read_aggr_stats,
+	.open		= rt2x00debug_file_open,
+	.release	= rt2x00debug_file_release,
+	.llseek		= default_llseek,
+};
+
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
 						     struct rt2x00debug_intf
 						     *intf,
@@ -694,6 +753,12 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 	if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
 		goto exit;
 
+	intf->aggr_stats_entry = debugfs_create_file("aggr_stats", S_IRUSR,
+					      intf->driver_folder, intf,
+					      &rt2x00debug_fop_aggr_stats);
+	if (IS_ERR(intf->aggr_stats_entry) || !intf->aggr_stats_entry)
+		goto exit;
+
 	intf->register_folder =
 	    debugfs_create_dir("register", intf->driver_folder);
 	if (IS_ERR(intf->register_folder) || !intf->register_folder)
@@ -794,6 +859,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 	debugfs_remove(intf->chipset_entry);
 	debugfs_remove(intf->driver_entry);
 	debugfs_remove(intf->driver_folder);
+	debugfs_remove(intf->aggr_stats_entry);
 	kfree(intf->chipset_blob.data);
 	kfree(intf->driver_blob.data);
 	kfree(intf);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index b16521e..935e8b1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1403,7 +1403,9 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
 	cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
 	cancel_work_sync(&rt2x00dev->sleep_work);
 	if (rt2x00_is_usb(rt2x00dev)) {
+		hrtimer_cancel(&rt2x00dev->txaggcnt_timer);
 		hrtimer_cancel(&rt2x00dev->txstatus_timer);
+		del_timer(&rt2x00dev->txagg_timer);
 		cancel_work_sync(&rt2x00dev->rxdone_work);
 		cancel_work_sync(&rt2x00dev->txdone_work);
 	}
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 8828987..0529f69 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -813,6 +813,8 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
 	INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
 	hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
 		     HRTIMER_MODE_REL);
+	hrtimer_init(&rt2x00dev->txaggcnt_timer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
 
 	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	if (retval)
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH v2 8/8] ath9k: Add statistics for antenna diversity
From: Sujith Manoharan @ 2013-08-01 15:27 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless
In-Reply-To: <1375338204-2021-8-git-send-email-sujith@msujith.org>

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/antenna.c | 18 ++++---
 drivers/net/wireless/ath/ath9k/debug.c   | 85 ++++++++++++++++++++++++++------
 drivers/net/wireless/ath/ath9k/debug.h   | 20 +++++---
 3 files changed, 95 insertions(+), 28 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c
index 42f3b87..391d557 100644
--- a/drivers/net/wireless/ath/ath9k/antenna.c
+++ b/drivers/net/wireless/ath/ath9k/antenna.c
@@ -734,15 +734,18 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
 		antcomb->main_total_rssi += main_rssi;
 		antcomb->alt_total_rssi  += alt_rssi;
 
-		if (main_ant_conf == rx_ant_conf) {
+		if (main_ant_conf == rx_ant_conf)
 			antcomb->main_recv_cnt++;
-			ANT_STAT_INC(ANT_MAIN, recv_cnt);
-			ANT_LNA_INC(ANT_MAIN, rx_ant_conf);
-		} else {
+		else
 			antcomb->alt_recv_cnt++;
-			ANT_STAT_INC(ANT_ALT, recv_cnt);
-			ANT_LNA_INC(ANT_ALT, rx_ant_conf);
-		}
+	}
+
+	if (main_ant_conf == rx_ant_conf) {
+		ANT_STAT_INC(ANT_MAIN, recv_cnt);
+		ANT_LNA_INC(ANT_MAIN, rx_ant_conf);
+	} else {
+		ANT_STAT_INC(ANT_ALT, recv_cnt);
+		ANT_LNA_INC(ANT_ALT, rx_ant_conf);
 	}
 
 	/* Short scan check */
@@ -821,6 +824,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
 div_comb_done:
 	ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio);
 	ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf);
+	ath9k_debug_stat_ant(sc, &div_ant_conf, main_rssi_avg, alt_rssi_avg);
 
 	antcomb->scan_start_time = jiffies;
 	antcomb->total_pkt_count = 0;
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 56cbe5d..a43bd8c 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -321,6 +321,20 @@ static const struct file_operations fops_bt_ant_diversity = {
 	.llseek = default_llseek,
 };
 
+void ath9k_debug_stat_ant(struct ath_softc *sc,
+			  struct ath_hw_antcomb_conf *div_ant_conf,
+			  int main_rssi_avg, int alt_rssi_avg)
+{
+	struct ath_antenna_stats *as_main = &sc->debug.stats.ant_stats[ANT_MAIN];
+	struct ath_antenna_stats *as_alt = &sc->debug.stats.ant_stats[ANT_ALT];
+
+	as_main->lna_attempt_cnt[div_ant_conf->main_lna_conf]++;
+	as_alt->lna_attempt_cnt[div_ant_conf->alt_lna_conf]++;
+
+	as_main->rssi_avg = main_rssi_avg;
+	as_alt->rssi_avg = alt_rssi_avg;
+}
+
 static ssize_t read_file_antenna_diversity(struct file *file,
 					   char __user *user_buf,
 					   size_t count, loff_t *ppos)
@@ -330,9 +344,14 @@ static ssize_t read_file_antenna_diversity(struct file *file,
 	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	struct ath_antenna_stats *as_main = &sc->debug.stats.ant_stats[ANT_MAIN];
 	struct ath_antenna_stats *as_alt = &sc->debug.stats.ant_stats[ANT_ALT];
+	struct ath_hw_antcomb_conf div_ant_conf;
 	unsigned int len = 0, size = 1024;
 	ssize_t retval = 0;
 	char *buf;
+	char *lna_conf_str[4] = {"LNA1_MINUS_LNA2",
+				 "LNA2",
+				 "LNA1",
+				 "LNA1_PLUS_LNA2"};
 
 	buf = kzalloc(size, GFP_KERNEL);
 	if (buf == NULL)
@@ -344,28 +363,66 @@ static ssize_t read_file_antenna_diversity(struct file *file,
 		goto exit;
 	}
 
+	ath9k_ps_wakeup(sc);
+	ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
+	len += snprintf(buf + len, size - len, "Current MAIN config : %s\n",
+			lna_conf_str[div_ant_conf.main_lna_conf]);
+	len += snprintf(buf + len, size - len, "Current ALT config  : %s\n",
+			lna_conf_str[div_ant_conf.alt_lna_conf]);
+	len += snprintf(buf + len, size - len, "Average MAIN RSSI   : %d\n",
+			as_main->rssi_avg);
+	len += snprintf(buf + len, size - len, "Average ALT RSSI    : %d\n\n",
+			as_alt->rssi_avg);
+	ath9k_ps_restore(sc);
+
+	len += snprintf(buf + len, size - len, "Packet Receive Cnt:\n");
+	len += snprintf(buf + len, size - len, "-------------------\n");
+
 	len += snprintf(buf + len, size - len, "%30s%15s\n",
 			"MAIN", "ALT");
-	len += snprintf(buf + len, size - len, "%-15s%15d%15d\n",
-			"RECV CNT",
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"TOTAL COUNT",
 			as_main->recv_cnt,
 			as_alt->recv_cnt);
-	len += snprintf(buf + len, size - len, "%-15s%15d%15d\n",
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA1",
+			as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1],
+			as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA2",
+			as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2],
+			as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA1 + LNA2",
+			as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
+			as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+			"LNA1 - LNA2",
+			as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
+			as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
+
+	len += snprintf(buf + len, size - len, "\nLNA Config Attempts:\n");
+	len += snprintf(buf + len, size - len, "--------------------\n");
+
+	len += snprintf(buf + len, size - len, "%30s%15s\n",
+			"MAIN", "ALT");
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
 			"LNA1",
-			as_main->lna_config_cnt[ATH_ANT_DIV_COMB_LNA1],
-			as_alt->lna_config_cnt[ATH_ANT_DIV_COMB_LNA1]);
-	len += snprintf(buf + len, size - len, "%-15s%15d%15d\n",
+			as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1],
+			as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
 			"LNA2",
-			as_main->lna_config_cnt[ATH_ANT_DIV_COMB_LNA2],
-			as_alt->lna_config_cnt[ATH_ANT_DIV_COMB_LNA2]);
-	len += snprintf(buf + len, size - len, "%-15s%15d%15d\n",
+			as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2],
+			as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
 			"LNA1 + LNA2",
-			as_main->lna_config_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
-			as_alt->lna_config_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
-	len += snprintf(buf + len, size - len, "%-15s%15d%15d\n",
+			as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
+			as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
+	len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
 			"LNA1 - LNA2",
-			as_main->lna_config_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
-			as_alt->lna_config_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
+			as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
+			as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
+
 exit:
 	if (len > size)
 		len = size;
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index a879e45..01c5c6a 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -29,7 +29,7 @@ struct fft_sample_tlv;
 #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
 #define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++
 #define ANT_STAT_INC(i, c) sc->debug.stats.ant_stats[i].c++
-#define ANT_LNA_INC(i, c) sc->debug.stats.ant_stats[i].lna_config_cnt[c]++;
+#define ANT_LNA_INC(i, c) sc->debug.stats.ant_stats[i].lna_recv_cnt[c]++;
 #else
 #define TX_STAT_INC(q, c) do { } while (0)
 #define RESET_STAT_INC(sc, type) do { } while (0)
@@ -252,7 +252,9 @@ struct ath_rx_stats {
 
 struct ath_antenna_stats {
 	u32 recv_cnt;
-	u32 lna_config_cnt[4];
+	u32 rssi_avg;
+	u32 lna_recv_cnt[4];
+	u32 lna_attempt_cnt[4];
 };
 
 struct ath_stats {
@@ -294,10 +296,11 @@ void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
 			      struct ieee80211_sta *sta,
 			      struct dentry *dir);
-
 void ath_debug_send_fft_sample(struct ath_softc *sc,
 			       struct fft_sample_tlv *fft_sample);
-
+void ath9k_debug_stat_ant(struct ath_softc *sc,
+			  struct ath_hw_antcomb_conf *div_ant_conf,
+			  int main_rssi_avg, int alt_rssi_avg);
 #else
 
 #define RX_STAT_INC(c) /* NOP */
@@ -310,12 +313,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
 static inline void ath9k_deinit_debug(struct ath_softc *sc)
 {
 }
-
 static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
 					    enum ath9k_int status)
 {
 }
-
 static inline void ath_debug_stat_tx(struct ath_softc *sc,
 				     struct ath_buf *bf,
 				     struct ath_tx_status *ts,
@@ -323,11 +324,16 @@ static inline void ath_debug_stat_tx(struct ath_softc *sc,
 				     unsigned int flags)
 {
 }
-
 static inline void ath_debug_stat_rx(struct ath_softc *sc,
 				     struct ath_rx_status *rs)
 {
 }
+static inline void ath9k_debug_stat_ant(struct ath_softc *sc,
+					struct ath_hw_antcomb_conf *div_ant_conf,
+					int main_rssi_avg, int alt_rssi_avg)
+{
+
+}
 
 #endif /* CONFIG_ATH9K_DEBUGFS */
 
-- 
1.8.3.4


^ permalink raw reply related

* Re: [PATCHv5 0/4] add master channel switch announcement support
From: Johannes Berg @ 2013-08-01 15:01 UTC (permalink / raw)
  To: Simon Wunderlich; +Cc: linux-wireless, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1373551749-5107-1-git-send-email-siwu@hrz.tu-chemnitz.de>

On Thu, 2013-07-11 at 16:09 +0200, Simon Wunderlich wrote:
> This is the 5th edition of the CSA support patch series. This patchset adds
> generic channel switch support for AP. This is required for DFS operation
> (e.g. Wi-Fi Alliance requires this for 802.11h certification). This will also
> be required for IBSS-DFS later.

Applied 1-3 with some changes (merging 2/3 and small fixes)

johannes


^ permalink raw reply

* [[PATCHv2]rt2800usb: ampdu len] rt2800usb: update aggregation len
From: Sylvain ROGER RIEUNIER @ 2013-08-01 14:42 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, users, Sylvain Roger Rieunier

From: Sylvain Roger Rieunier <sylvain.roger.rieunier@gmail.com>

I tried to read periodically TX_AGG_CNT registers on the rt2800usb driver.
I'had made USB synchronous and asynchronous read. But it's only reduces the
bandwidth.
Does anyone have an idea?


Signed-off-by: Sylvain ROGER RIEUNIER <sylvain.roger.rieunier@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c   |   69 ++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2800usb.c   |   92 +++++++++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2x00.h      |   28 +++++++++
 drivers/net/wireless/rt2x00/rt2x00debug.c |   66 +++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2x00dev.c   |    2 +
 drivers/net/wireless/rt2x00/rt2x00usb.c   |    2 +
 6 files changed, 259 insertions(+)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index dedc3d4..0db45fb 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1813,6 +1813,75 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 }
 EXPORT_SYMBOL_GPL(rt2800_config_ant);
 
+void rt2800_update_aggr_stats(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+	u32 all;
+	int i;
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT, &reg);
+	rt2x00dev->aggr_stats.no_aggr =
+		rt2x00_get_field32(reg,TX_AGG_CNT_NON_AGG_TX_COUNT);
+	rt2x00dev->aggr_stats.all_aggr =
+		rt2x00_get_field32(reg,TX_AGG_CNT_AGG_TX_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT0, &reg);
+	rt2x00dev->aggr_stats.ampduCount[0] =
+		rt2x00_get_field32(reg,TX_AGG_CNT0_AGG_SIZE_1_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[1] =
+		rt2x00_get_field32(reg,TX_AGG_CNT0_AGG_SIZE_2_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT1, &reg);
+	rt2x00dev->aggr_stats.ampduCount[2] =
+		rt2x00_get_field32(reg,TX_AGG_CNT1_AGG_SIZE_3_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[3] =
+		rt2x00_get_field32(reg,TX_AGG_CNT1_AGG_SIZE_4_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT2, &reg);
+	rt2x00dev->aggr_stats.ampduCount[4] =
+		rt2x00_get_field32(reg,TX_AGG_CNT2_AGG_SIZE_5_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[5] =
+		rt2x00_get_field32(reg,TX_AGG_CNT2_AGG_SIZE_6_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT3, &reg);
+	rt2x00dev->aggr_stats.ampduCount[6] =
+		rt2x00_get_field32(reg,TX_AGG_CNT3_AGG_SIZE_7_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[7] =
+		rt2x00_get_field32(reg,TX_AGG_CNT3_AGG_SIZE_8_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT4, &reg);
+	rt2x00dev->aggr_stats.ampduCount[8] =
+		rt2x00_get_field32(reg,TX_AGG_CNT4_AGG_SIZE_9_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[9] =
+		rt2x00_get_field32(reg,TX_AGG_CNT4_AGG_SIZE_10_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT5, &reg);
+	rt2x00dev->aggr_stats.ampduCount[10] =
+		rt2x00_get_field32(reg,TX_AGG_CNT5_AGG_SIZE_11_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[11] =
+		rt2x00_get_field32(reg,TX_AGG_CNT5_AGG_SIZE_12_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT6, &reg);
+	rt2x00dev->aggr_stats.ampduCount[12] =
+		rt2x00_get_field32(reg,TX_AGG_CNT6_AGG_SIZE_13_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[13] =
+		rt2x00_get_field32(reg,TX_AGG_CNT6_AGG_SIZE_14_COUNT);
+
+	rt2800_register_read(rt2x00dev,TX_AGG_CNT7, &reg);
+	rt2x00dev->aggr_stats.ampduCount[14] =
+		rt2x00_get_field32(reg,TX_AGG_CNT7_AGG_SIZE_15_COUNT);
+	rt2x00dev->aggr_stats.ampduCount[15] =
+		rt2x00_get_field32(reg,TX_AGG_CNT7_AGG_SIZE_16_COUNT);
+
+	all = rt2x00dev->aggr_stats.no_aggr +
+		rt2x00dev->aggr_stats.all_aggr;
+
+	for( i = 0; i < 16 ; i++)
+		rt2x00dev->aggr_stats.ampduRatio[i] =
+			((rt2x00dev->aggr_stats.ampduCount[i] * 100) / all);
+}
+EXPORT_SYMBOL_GPL(rt2800_update_aggr_stats);
+
 static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
 				   struct rt2x00lib_conf *libconf)
 {
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index fc9efdf..6ca9cdb 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -225,6 +225,79 @@ static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer)
 	return HRTIMER_NORESTART;
 }
 
+
+
+static bool rt2800usb_tx_agg_cnt_read_completed(struct rt2x00_dev *rt2x00dev,
+					   int urb_status, u32 reg)
+{
+
+	if (urb_status) {
+		WARNING(rt2x00dev, "TX status read failed %d\n", urb_status);
+		return false;
+	}
+
+	if(rt2x00dev->aggr_stats.cnt == 0) {
+		rt2x00dev->aggr_stats.no_aggr =
+			rt2x00_get_field32(reg,TX_AGG_CNT_NON_AGG_TX_COUNT);
+		rt2x00dev->aggr_stats.all_aggr =
+			rt2x00_get_field32(reg,TX_AGG_CNT_AGG_TX_COUNT);
+	} else {
+		unsigned int tmp = (rt2x00dev->aggr_stats.cnt - 1)*2;
+
+		rt2x00dev->aggr_stats.ampduCount[tmp] =
+		rt2x00_get_field32(reg,TX_AGG_CNT0_AGG_SIZE_1_COUNT);
+		rt2x00dev->aggr_stats.ampduCount[tmp+1] =
+		rt2x00_get_field32(reg,TX_AGG_CNT0_AGG_SIZE_2_COUNT);
+	}
+
+	if(rt2x00dev->aggr_stats.cnt == 9) {
+		rt2x00dev->aggr_stats.cnt = 0;
+		clear_bit(TX_AGG_TIMER, &rt2x00dev->aggr_stats.flags);
+	} else {
+		rt2x00dev->aggr_stats.cnt++;
+		/* Read next TX_AGG_CNT register after 1 ms */
+		hrtimer_start(&rt2x00dev->txaggcnt_timer,
+			      ktime_set(0, 1000000), HRTIMER_MODE_REL);
+	}
+
+	 return true;
+}
+
+static enum hrtimer_restart rt2800usb_tx_agg_cnt_timeout(struct hrtimer *timer)
+{
+	struct rt2x00_dev *rt2x00dev =
+	    container_of(timer, struct rt2x00_dev, txaggcnt_timer);
+	unsigned int offset;
+
+	offset = TX_AGG_CNT + rt2x00dev->aggr_stats.cnt*4;
+	rt2x00usb_register_read_async(rt2x00dev,offset,
+				      rt2800usb_tx_agg_cnt_read_completed);
+
+	return HRTIMER_NORESTART;
+}
+
+static void rt2800usb_async_read_tx_agg_cnt(struct rt2x00_dev *rt2x00dev)
+{
+
+	if (test_and_set_bit(TX_AGG_TIMER, &rt2x00dev->aggr_stats.flags))
+		return;
+
+	/* Read TX_AGG_CNT register after 1 ms */
+	hrtimer_start(&rt2x00dev->txaggcnt_timer, ktime_set(0, 1000000),
+		      HRTIMER_MODE_REL);
+}
+
+static void rt2800usb_timer_txagg(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+
+	if (!test_bit(TX_AGG_TIMER, &rt2x00dev->aggr_stats.flags))
+		rt2800usb_async_read_tx_agg_cnt(rt2x00dev);
+
+	rt2x00dev->txagg_timer.expires += 5000;
+	add_timer(&rt2x00dev->txagg_timer);
+}
+
 /*
  * Firmware functions
  */
@@ -750,6 +823,7 @@ static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
 static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
 	int retval;
+	unsigned long j = jiffies;
 
 	retval = rt2800_probe_hw(rt2x00dev);
 	if (retval)
@@ -765,6 +839,24 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	 */
 	PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);
 
+	/*
+	 * Set txaggcnt timer function. for usb async read
+	 */
+	rt2x00dev->txaggcnt_timer.function = rt2800usb_tx_agg_cnt_timeout;
+
+	/*
+	 * Set txagg timer function. periodic read
+	 */
+	clear_bit(TX_AGG_TIMER, &rt2x00dev->aggr_stats.flags);
+	rt2x00dev->aggr_stats.cnt = 0;
+	init_timer(&rt2x00dev->txagg_timer);
+	rt2x00dev->txagg_timer.function = rt2800usb_timer_txagg;
+	rt2x00dev->txagg_timer.data = (unsigned long)rt2x00dev;
+
+	j = jiffies;
+	rt2x00dev->txagg_timer.expires = j + 5000;
+	add_timer(&rt2x00dev->txagg_timer);
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index fe4c572..b6ae9f3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -637,6 +637,7 @@ struct rt2x00lib_ops {
 			struct ieee80211_sta *sta);
 	int (*sta_remove) (struct rt2x00_dev *rt2x00dev,
 			   int wcid);
+	void (*update_aggr_stats) (struct rt2x00_dev *rt2x00dev);
 };
 
 /*
@@ -733,6 +734,24 @@ enum {
 	NUM_IF_COMB,
 };
 
+#define RT2X00_AGGR_CNT_MAX 16
+
+/*
+ * rt2x00 aggregation state flags
+ */
+enum rt2x00_agg_state_flags {
+	TX_AGG_TIMER,
+};
+struct rt2x00_aggr_stats {
+	unsigned long flags;
+	unsigned int cnt;
+	u32 all_aggr;
+	u32 no_aggr;
+	u32 ampduCount[RT2X00_AGGR_CNT_MAX];
+	u32 ampduRatio[RT2X00_AGGR_CNT_MAX];
+};
+
+
 /*
  * rt2x00 device structure.
  */
@@ -764,6 +783,8 @@ struct rt2x00_dev {
 	enum ieee80211_band curr_band;
 	int curr_freq;
 
+	struct rt2x00_aggr_stats aggr_stats;
+
 	/*
 	 * If enabled, the debugfs interface structures
 	 * required for deregistration of debugfs.
@@ -984,6 +1005,13 @@ struct rt2x00_dev {
 	struct hrtimer txstatus_timer;
 
 	/*
+	 * Timer to ensure tx aggregation counter reports are read (rt2800usb).
+	 */
+	struct hrtimer txaggcnt_timer;
+
+	struct timer_list txagg_timer;
+
+	/*
 	 * Tasklet for processing tx status reports (rt2800pci).
 	 */
 	struct tasklet_struct txstatus_tasklet;
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index fe7a7f6..c41d5a8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -75,6 +75,7 @@ struct rt2x00debug_intf {
 	 *     - frame dump file
 	 *     - queue stats file
 	 *     - crypto stats file
+	 *     - aggr stats file
 	 */
 	struct dentry *driver_folder;
 	struct dentry *driver_entry;
@@ -96,6 +97,7 @@ struct rt2x00debug_intf {
 	struct dentry *queue_frame_dump_entry;
 	struct dentry *queue_stats_entry;
 	struct dentry *crypto_stats_entry;
+	struct dentry *aggr_stats_entry;
 
 	/*
 	 * The frame dump file only allows a single reader,
@@ -589,6 +591,63 @@ static const struct file_operations rt2x00debug_fop_cap_flags = {
 	.llseek		= default_llseek,
 };
 
+
+static ssize_t rt2x00debug_read_aggr_stats(struct file *file,
+					  char __user *buf,
+					  size_t length,
+					  loff_t *offset)
+{
+	struct rt2x00debug_intf *intf =	file->private_data;
+	struct rt2x00_dev *rt2x00dev = intf->rt2x00dev;
+	size_t size;
+	char *data;
+	char *temp;
+	int i;
+
+	if (*offset)
+		return 0;
+
+	data = kzalloc(17 * MAX_LINE_LENGTH, GFP_KERNEL);
+	if (!data)
+		return 0;
+
+	temp = data;
+	temp += sprintf(temp, "all aggr(%u) no agg(%u) \n",
+		       rt2x00dev->aggr_stats.all_aggr,
+		       rt2x00dev->aggr_stats.no_aggr);
+
+	for (i = 0; i < 15 ; i++) {
+		temp += sprintf(temp, "%u AMPDU cnt(%u), ratio(%u)\n", (i+1),
+		       rt2x00dev->aggr_stats.ampduCount[i],
+		       rt2x00dev->aggr_stats.ampduRatio[i]);
+	}
+
+	temp += sprintf(temp, "16 or up AMPDU cnt(%u), ratio(%u)\n",
+			rt2x00dev->aggr_stats.ampduCount[i],
+			rt2x00dev->aggr_stats.ampduRatio[i]);
+
+	size = strlen(data);
+	size = min(size, length);
+
+	if (copy_to_user(buf, data, size)) {
+		kfree(data);
+		return -EFAULT;
+	}
+
+	kfree(data);
+
+	*offset += size;
+	return size;
+}
+
+static const struct file_operations rt2x00debug_fop_aggr_stats = {
+	.owner		= THIS_MODULE,
+	.read		= rt2x00debug_read_aggr_stats,
+	.open		= rt2x00debug_file_open,
+	.release	= rt2x00debug_file_release,
+	.llseek		= default_llseek,
+};
+
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
 						     struct rt2x00debug_intf
 						     *intf,
@@ -694,6 +753,12 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 	if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
 		goto exit;
 
+	intf->aggr_stats_entry = debugfs_create_file("aggr_stats", S_IRUSR,
+					      intf->driver_folder, intf,
+					      &rt2x00debug_fop_aggr_stats);
+	if (IS_ERR(intf->aggr_stats_entry) || !intf->aggr_stats_entry)
+		goto exit;
+
 	intf->register_folder =
 	    debugfs_create_dir("register", intf->driver_folder);
 	if (IS_ERR(intf->register_folder) || !intf->register_folder)
@@ -794,6 +859,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 	debugfs_remove(intf->chipset_entry);
 	debugfs_remove(intf->driver_entry);
 	debugfs_remove(intf->driver_folder);
+	debugfs_remove(intf->aggr_stats_entry);
 	kfree(intf->chipset_blob.data);
 	kfree(intf->driver_blob.data);
 	kfree(intf);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index b16521e..935e8b1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1403,7 +1403,9 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
 	cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
 	cancel_work_sync(&rt2x00dev->sleep_work);
 	if (rt2x00_is_usb(rt2x00dev)) {
+		hrtimer_cancel(&rt2x00dev->txaggcnt_timer);
 		hrtimer_cancel(&rt2x00dev->txstatus_timer);
+		del_timer(&rt2x00dev->txagg_timer);
 		cancel_work_sync(&rt2x00dev->rxdone_work);
 		cancel_work_sync(&rt2x00dev->txdone_work);
 	}
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 8828987..0529f69 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -813,6 +813,8 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
 	INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
 	hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
 		     HRTIMER_MODE_REL);
+	hrtimer_init(&rt2x00dev->txaggcnt_timer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
 
 	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	if (retval)
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCH] mac80211: add debugfs for driver-buffered TID bitmap
From: Johannes Berg @ 2013-08-01 13:08 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <1374496504-17705-1-git-send-email-johannes@sipsolutions.net>

On Mon, 2013-07-22 at 14:35 +0200, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
> 
> Add a per-station debugfs file indicating the TIDs (as
> a bitmap) that the driver has data buffered on.

Applied.

johannes


^ permalink raw reply

* [PATCH] wireless: make TU conversion macros available
From: Johannes Berg @ 2013-08-01 13:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

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

A few places in the code (mac80211 and iwlmvm) use the same
TU_TO_JIFFIES() macro and could use TU_TO_EXP_TIME() that
mac80211 has. Make these available to everyone and use them.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlwifi/mvm/time-event.c | 7 ++-----
 include/linux/ieee80211.h                     | 4 ++++
 net/mac80211/ieee80211_i.h                    | 3 ---
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index ad9bbca..9f10036 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -73,7 +73,6 @@
 #include "iwl-prph.h"
 
 /* A TimeUnit is 1024 microsecond */
-#define TU_TO_JIFFIES(_tu)	(usecs_to_jiffies((_tu) * 1024))
 #define MSEC_TO_TU(_msec)	(_msec*1000/1024)
 
 /*
@@ -191,8 +190,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
 		iwl_mvm_te_clear_data(mvm, te_data);
 	} else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) {
 		te_data->running = true;
-		te_data->end_jiffies = jiffies +
-			TU_TO_JIFFIES(te_data->duration);
+		te_data->end_jiffies = TU_TO_EXP_TIME(te_data->duration);
 
 		if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {
 			set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
@@ -329,8 +327,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
 	lockdep_assert_held(&mvm->mutex);
 
 	if (te_data->running &&
-	    time_after(te_data->end_jiffies,
-		       jiffies + TU_TO_JIFFIES(min_duration))) {
+	    time_after(te_data->end_jiffies, TU_TO_EXP_TIME(min_duration))) {
 		IWL_DEBUG_TE(mvm, "We have enough time in the current TE: %u\n",
 			     jiffies_to_msecs(te_data->end_jiffies - jiffies));
 		return;
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index b3ce299..23a8877 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2288,4 +2288,8 @@ static inline bool ieee80211_check_tim(const struct ieee80211_tim_ie *tim,
 	return !!(tim->virtual_map[index] & mask);
 }
 
+/* convert time units */
+#define TU_TO_JIFFIES(x)	(usecs_to_jiffies((x) * 1024))
+#define TU_TO_EXP_TIME(x)	(jiffies + TU_TO_JIFFIES(x))
+
 #endif /* LINUX_IEEE80211_H */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d779383..49a8d98 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -53,9 +53,6 @@ struct ieee80211_local;
  * increased memory use (about 2 kB of RAM per entry). */
 #define IEEE80211_FRAGMENT_MAX 4
 
-#define TU_TO_JIFFIES(x)	(usecs_to_jiffies((x) * 1024))
-#define TU_TO_EXP_TIME(x)	(jiffies + TU_TO_JIFFIES(x))
-
 /* power level hasn't been configured (or set to automatic) */
 #define IEEE80211_UNSET_POWER_LEVEL	INT_MIN
 
-- 
1.8.0


^ permalink raw reply related

* Re: [PATCH 0/8] include/net: next set of extern removals
From: David Howells @ 2013-08-01 12:04 UTC (permalink / raw)
  To: Joe Perches
  Cc: dhowells, netdev, linux-hams, linux-wireless, linux-kernel,
	linux-afs
In-Reply-To: <cover.1375316912.git.joe@perches.com>

Joe Perches <joe@perches.com> wrote:

> Standardize on no extern use on function prototypes

Ugh.  Can we please standardise on _having_ externs on function prototypes?

David

^ permalink raw reply

* [PATCH 3.11] iwl4965: reset firmware after rfkill off
From: Stanislaw Gruszka @ 2013-08-01 10:07 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Stanislaw Gruszka

Using rfkill switch can make firmware unstable, what cause various
Microcode errors and kernel warnings. Reseting firmware just after
rfkill off (radio on) helped with that.

Resolve:
https://bugzilla.redhat.com/show_bug.cgi?id=977053

Reported-and-tested-by: Justin Pearce <whitefox@guardianfox.net>
Cc: stable@vger.kernel.org
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/iwlegacy/4965-mac.c | 10 +++++-----
 drivers/net/wireless/iwlegacy/common.c   |  1 +
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index f0b7794..f2ed62e 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -4460,12 +4460,12 @@ il4965_irq_tasklet(struct il_priv *il)
 		 * is killed. Hence update the killswitch state here. The
 		 * rfkill handler will care about restarting if needed.
 		 */
-		if (!test_bit(S_ALIVE, &il->status)) {
-			if (hw_rf_kill)
-				set_bit(S_RFKILL, &il->status);
-			else
-				clear_bit(S_RFKILL, &il->status);
+		if (hw_rf_kill) {
+			set_bit(S_RFKILL, &il->status);
+		} else {
+			clear_bit(S_RFKILL, &il->status);
 			wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
+			il_force_reset(il, true);
 		}
 
 		handled |= CSR_INT_BIT_RF_KILL;
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index 3195aad..b03e22e 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -4660,6 +4660,7 @@ il_force_reset(struct il_priv *il, bool external)
 
 	return 0;
 }
+EXPORT_SYMBOL(il_force_reset);
 
 int
 il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH 3.11] iwl4965: set power mode early
From: Stanislaw Gruszka @ 2013-08-01 10:07 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Stanislaw Gruszka

If device was put into a sleep and system was restarted or module
reloaded, we have to wake device up before sending other commands.
Otherwise it will fail to start with Microcode error.

Cc: stable@vger.kernel.org
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/iwlegacy/4965-mac.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index b9b2bb5..f0b7794 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -5334,6 +5334,9 @@ il4965_alive_start(struct il_priv *il)
 
 	il->active_rate = RATES_MASK;
 
+	il_power_update_mode(il, true);
+	D_INFO("Updated power mode\n");
+
 	if (il_is_associated(il)) {
 		struct il_rxon_cmd *active_rxon =
 		    (struct il_rxon_cmd *)&il->active;
@@ -5364,9 +5367,6 @@ il4965_alive_start(struct il_priv *il)
 	D_INFO("ALIVE processing complete.\n");
 	wake_up(&il->wait_command_queue);
 
-	il_power_update_mode(il, true);
-	D_INFO("Updated power mode\n");
-
 	return;
 
 restart:
-- 
1.7.11.7


^ permalink raw reply related

* Re: [RFC 1/3] nl/cfg80211: add chan_time for scan request
From: Michal Kazior @ 2013-08-01  9:14 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, ath10k
In-Reply-To: <1375342845.8608.8.camel@jlt4.sipsolutions.net>

On 1 August 2013 09:40, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Mon, 2013-07-29 at 10:39 +0200, Michal Kazior wrote:
>
>> + * @NL80211_ATTR_SCAN_CHAN_TIME: Specifies how many msec should a driver spend
>> + *   on each channel during scanning. This is optional and the default is
>> + *   leave the decision up to the driver. This setting may, but preferrably
>
> typo: preferably :)
>
>> + *   shouldn't, be ignored by driver.
>
> This seems a bit iffy - you don't differentiate between active/passive
> scans?

Is there a reason this should be differentiated?


> Also maybe there should be a bit saying "I support scan timing" or even
> the min/max times?

Sounds good. I can add it.


> This also interferes a bit with some other scan optimisations that could
> be done at a low firmware level, so I think we should be careful and
> actually say that this is really more intended for measurement use cases
> and not for normal scans?
>
> Or maybe we should have a separate measurement command with similar
> semantics? This all doesn't seem very clear to me yet :)

Motivation behind this patchset is to simplify ACS implementation and
depend on scan. This also allows easier fallback from survey-based ACS
to BSS-based one.

Other use cases are a side-effect so perhaps clarifying the intent in
the docs is enough.


Pozdrawiam / Best regards,
Michał Kazior.

^ permalink raw reply

* [PATCH] ath10k: add SoC power save option to PCI features map
From: Bartosz Markowski @ 2013-08-01  9:09 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Bartosz Markowski

Unify the PCI options location.

By default the SoC PS option is disabled to boost the
performance and due to poor stability on early HW revisions.
In future we can remove the module parameter and turn on/off
the PS for given hardware.

This change also makes the pci module parameter for SoC PS static.

Signed-off-by: Bartosz Markowski <bartosz.markowski@tieto.com>
---
 drivers/net/wireless/ath/ath10k/pci.c |   24 ++++++++++++++----------
 drivers/net/wireless/ath/ath10k/pci.h |   11 +++++++----
 2 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index c71b488..287098e 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -32,7 +32,7 @@
 #include "ce.h"
 #include "pci.h"
 
-unsigned int ath10k_target_ps;
+static unsigned int ath10k_target_ps;
 module_param(ath10k_target_ps, uint, 0644);
 MODULE_PARM_DESC(ath10k_target_ps, "Enable ath10k Target (SoC) PS option");
 
@@ -1740,6 +1740,7 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
 
 static int ath10k_pci_hif_power_up(struct ath10k *ar)
 {
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	int ret;
 
 	/*
@@ -1758,13 +1759,8 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
 	if (ret)
 		goto err;
 
-	if (ath10k_target_ps) {
-		ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n");
-	} else {
-		/* Force AWAKE forever */
-		ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save disabled\n");
-		ath10k_do_pci_wake(ar);
-	}
+	if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
+		ath10k_do_pci_wake(ar); /* Force AWAKE forever */
 
 	ret = ath10k_pci_ce_init(ar);
 	if (ret)
@@ -1785,7 +1781,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
 err_ce:
 	ath10k_pci_ce_deinit(ar);
 err_ps:
-	if (!ath10k_target_ps)
+	if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
 		ath10k_do_pci_sleep(ar);
 err:
 	return ret;
@@ -1793,8 +1789,10 @@ err:
 
 static void ath10k_pci_hif_power_down(struct ath10k *ar)
 {
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
 	ath10k_pci_ce_deinit(ar);
-	if (!ath10k_target_ps)
+	if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
 		ath10k_do_pci_sleep(ar);
 }
 
@@ -2239,6 +2237,9 @@ static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci)
 		case ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND:
 			ath10k_dbg(ATH10K_DBG_PCI, "QCA988X_1.0 workaround enabled\n");
 			break;
+		case ATH10K_PCI_FEATURE_SOC_POWER_SAVE:
+			ath10k_dbg(ATH10K_DBG_PCI, "QCA98XX SoC power save enabled\n");
+			break;
 		}
 	}
 }
@@ -2274,6 +2275,9 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 		goto err_ar_pci;
 	}
 
+	if (ath10k_target_ps)
+		set_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features);
+
 	ath10k_pci_dump_features(ar_pci);
 
 	ar = ath10k_core_create(ar_pci, ar_pci->dev, &ath10k_pci_hif_ops);
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index d3a2e6c..871bb33 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -153,6 +153,7 @@ struct service_to_pipe {
 enum ath10k_pci_features {
 	ATH10K_PCI_FEATURE_MSI_X		= 0,
 	ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND	= 1,
+	ATH10K_PCI_FEATURE_SOC_POWER_SAVE	= 2,
 
 	/* keep last */
 	ATH10K_PCI_FEATURE_COUNT
@@ -335,20 +336,22 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
 	return ioread32(ar_pci->mem + offset);
 }
 
-extern unsigned int ath10k_target_ps;
-
 void ath10k_do_pci_wake(struct ath10k *ar);
 void ath10k_do_pci_sleep(struct ath10k *ar);
 
 static inline void ath10k_pci_wake(struct ath10k *ar)
 {
-	if (ath10k_target_ps)
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+	if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
 		ath10k_do_pci_wake(ar);
 }
 
 static inline void ath10k_pci_sleep(struct ath10k *ar)
 {
-	if (ath10k_target_ps)
+	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+	if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
 		ath10k_do_pci_sleep(ar);
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH v2] mac80211: report some VHT radiotap infos for tx status
From: Johannes Berg @ 2013-08-01  8:07 UTC (permalink / raw)
  To: Karl Beldan; +Cc: linux-wireless, Karl Beldan
In-Reply-To: <20130801075649.GA30476@magnum.frso.rivierawaves.com>

On Thu, 2013-08-01 at 09:56 +0200, Karl Beldan wrote:
> On Thu, Aug 01, 2013 at 09:35:54AM +0200, Johannes Berg wrote:
> > On Sat, 2013-07-27 at 11:47 +0200, Karl Beldan wrote:
> > 
> > > +		/* required alignment from rthdr */
> > > +		pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
> > 
> > This is bad, it potentially leaks a byte of kernel data, please
> > explicitly clear the padding, like
> > 
> > if ((pos - (u8 *)rthdr) & 1)
> >   *pos++ = 0;
> > 
> I don't see what's wrong.
> The whole radiotap space is already zeroed, as for the 'leaks' I don't
> see how it could leak either.

Oh, I didn't see that, I'll apply the patch then.

johannes


^ permalink raw reply

* Re: [PATCH] ieee80211: add definition for 802.11ac information elements
From: Johannes Berg @ 2013-08-01  8:06 UTC (permalink / raw)
  To: Fred Zhou; +Cc: linux-wireless
In-Reply-To: <1375337788-6822-1-git-send-email-fred.zy@gmail.com>

On Thu, 2013-08-01 at 14:16 +0800, Fred Zhou wrote:
> Added element IDs for Extended BSS Load, VHT TX Power Envelope, AID, and Quiet Channel

Applied, but please reword the commit log in active voice next time and
break to less than 72 columns.

johannes


^ permalink raw reply

* Re: [PATCH v2] mac80211: report some VHT radiotap infos for tx status
From: Karl Beldan @ 2013-08-01  7:56 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Karl Beldan
In-Reply-To: <1375342554.8608.4.camel@jlt4.sipsolutions.net>

On Thu, Aug 01, 2013 at 09:35:54AM +0200, Johannes Berg wrote:
> On Sat, 2013-07-27 at 11:47 +0200, Karl Beldan wrote:
> 
> > +		/* required alignment from rthdr */
> > +		pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
> 
> This is bad, it potentially leaks a byte of kernel data, please
> explicitly clear the padding, like
> 
> if ((pos - (u8 *)rthdr) & 1)
>   *pos++ = 0;
> 
I don't see what's wrong.
The whole radiotap space is already zeroed, as for the 'leaks' I don't
see how it could leak either.
Though, if you prefer, I can replace
	pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
with:
	if ((pos - (u8 *)rthdr) & 1)
		pos++;

-- 
Karl

^ permalink raw reply

* Re: [PATCH] mac80211: allow lowest basic rate for unicast management frame in mesh
From: Johannes Berg @ 2013-08-01  7:44 UTC (permalink / raw)
  To: Chun-Yeow Yeoh; +Cc: linux-wireless, linville, devel
In-Reply-To: <1375148892-18121-1-git-send-email-yeohchunyeow@cozybit.com>

On Mon, 2013-07-29 at 18:48 -0700, Chun-Yeow Yeoh wrote:
> Allow lowest basic rate to be used for unicast management frame in
> mesh. Otherwise, the lowest supported rate is used for unicast
> management frame, such as 1Mbps for 2.4GHz and 6Mbps for 5GHz. Rename
> the rc_send_low_broadcast to re_send_low_basicrate since now it is
> also applied to unicast management frame in mesh.
> 
> Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@cozybit.com>
> ---
>  net/mac80211/rate.c |   11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
> index ba63ac8..8038d47 100644
> --- a/net/mac80211/rate.c
> +++ b/net/mac80211/rate.c
> @@ -210,7 +210,7 @@ static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc)
>  		!ieee80211_is_data(fc);
>  }
>  
> -static void rc_send_low_broadcast(s8 *idx, u32 basic_rates,
> +static void rc_send_low_basicrate(s8 *idx, u32 basic_rates,
>  				  struct ieee80211_supported_band *sband)
>  {
>  	u8 i;
> @@ -269,6 +269,7 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
>  {
>  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
>  	struct ieee80211_supported_band *sband = txrc->sband;
> +	struct sta_info *sta_mesh = container_of(sta, struct sta_info, sta);

That doesn't seem like a good idea - IMHO you shouldn't use container_of
on NULL even if it still works in the end.

Also it might be a good idea to use more regular names: struct
ieee80211_sta *pubsta, struct sta_info *sta.


> @@ -281,10 +282,16 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
>  				return true;
>  			}
>  
> -			rc_send_low_broadcast(&info->control.rates[0].idx,
> +			rc_send_low_basicrate(&info->control.rates[0].idx,
>  					      txrc->bss_conf->basic_rates,
>  					      sband);
>  		}
> +
> +		if (sta && ieee80211_vif_is_mesh(&sta_mesh->sdata->vif))
> +			rc_send_low_basicrate(&info->control.rates[0].idx,
> +					      txrc->bss_conf->basic_rates,
> +					      sband);

I don't get this - that just duplicates the code above, no chance to
refactor it a bit instead of duplicating the call?

johannes


^ permalink raw reply

* Re: [RFC 1/3] nl/cfg80211: add chan_time for scan request
From: Johannes Berg @ 2013-08-01  7:40 UTC (permalink / raw)
  To: Michal Kazior; +Cc: linux-wireless, ath10k
In-Reply-To: <1375087158-22077-2-git-send-email-michal.kazior@tieto.com>

On Mon, 2013-07-29 at 10:39 +0200, Michal Kazior wrote:

> + * @NL80211_ATTR_SCAN_CHAN_TIME: Specifies how many msec should a driver spend
> + *	on each channel during scanning. This is optional and the default is
> + *	leave the decision up to the driver. This setting may, but preferrably

typo: preferably :)

> + *	shouldn't, be ignored by driver.

This seems a bit iffy - you don't differentiate between active/passive
scans?

Also maybe there should be a bit saying "I support scan timing" or even
the min/max times?

This also interferes a bit with some other scan optimisations that could
be done at a low firmware level, so I think we should be careful and
actually say that this is really more intended for measurement use cases
and not for normal scans?

Or maybe we should have a separate measurement command with similar
semantics? This all doesn't seem very clear to me yet :)

johannes


^ permalink raw reply

* Re: [RFC 0/3] introduce chan_time parameter to scan request
From: Johannes Berg @ 2013-08-01  7:36 UTC (permalink / raw)
  To: Michal Kazior; +Cc: linux-wireless, ath10k
In-Reply-To: <1375087158-22077-1-git-send-email-michal.kazior@tieto.com>

On Mon, 2013-07-29 at 10:39 +0200, Michal Kazior wrote:

> I'm wondering if it would be okay to set swscan
> probe delay to 0 if chan_time is non-zero? Or does
> probe delay need to be non-zero? Or maybe it
> should also be configurable via a parameter?

probe delay needs to be non-zero for NAV adjustment.

johannes


^ permalink raw reply

* Re: [PATCH v2] mac80211: report some VHT radiotap infos for tx status
From: Johannes Berg @ 2013-08-01  7:35 UTC (permalink / raw)
  To: Karl Beldan; +Cc: linux-wireless, Karl Beldan
In-Reply-To: <1374918424-1305-1-git-send-email-karl.beldan@gmail.com>

On Sat, 2013-07-27 at 11:47 +0200, Karl Beldan wrote:

> +		/* required alignment from rthdr */
> +		pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);

This is bad, it potentially leaks a byte of kernel data, please
explicitly clear the padding, like

if ((pos - (u8 *)rthdr) & 1)
  *pos++ = 0;

or so.

johannes


^ 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