Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [ath5k-devel] [PATCH] [ath5k][leds] Ability to disable leds support. If leds support enabled do not force mac802.11 leds layer selection.
From: Pavel Roskin @ 2010-05-12 15:48 UTC (permalink / raw)
  To: Dmytro Milinevskyy
  Cc: ath5k-devel, Kalle Valo, linux-wireless, GeunSik Lim, Jiri Slaby,
	Greg Kroah-Hartman, John W. Linville, Keng-Yu Lin, netdev,
	Jiri Kosina, Johannes Berg, Shahar Or, linux-kernel,
	Luca Verdesca
In-Reply-To: <4bea1f81.09b6660a.746e.1c12@mx.google.com>

On Wed, 2010-04-07 at 21:58 +0300, Dmytro Milinevskyy wrote:

> Here is the patch to disable ath5k leds support on build stage.
> However if the leds support was enabled do not force selection of 802.11 leds layer.

The idea is good, but the implementation could be improved.

There are too many preprocessor conditionals in your patch.

> +#ifdef CONFIG_ATH5K_LEDS
>  /*
>   * These match net80211 definitions (not used in
>   * mac80211).
> @@ -939,11 +940,7 @@ enum ath5k_power_mode {
>  #define AR5K_LED_AUTH	2 /*IEEE80211_S_AUTH*/
>  #define AR5K_LED_ASSOC	3 /*IEEE80211_S_ASSOC*/
>  #define AR5K_LED_RUN	4 /*IEEE80211_S_RUN*/

It should be OK to leave the constants defined even if they are not
used.

> +#ifdef CONFIG_ATH5K_LEDS
>  /* LED functions */
>  extern int ath5k_init_leds(struct ath5k_softc *sc);
>  extern void ath5k_led_enable(struct ath5k_softc *sc);
>  extern void ath5k_led_off(struct ath5k_softc *sc);
>  extern void ath5k_unregister_leds(struct ath5k_softc *sc);
> +#endif

You could add inline functions for the case when CONFIG_ATH5K_LEDS is
not defined.  That would avoid may conditionals in the code.

>  /* GPIO Functions */
> +#ifdef CONFIG_ATH5K_LEDS
>  extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
> +#endif

The same comment applies.

Also, there is nothing wrong with having an external declaration that is
not used in some particular configuration.

> +#ifdef CONFIG_ATH5K_LEDS
>  	/* turn on HW LEDs */
>  	ath5k_hw_set_ledstate(ah, AR5K_LED_INIT);
> +#endif

This is avoidable by having an inline ath5k_hw_set_ledstate() that does
nothing.

> +#ifdef CONFIG_ATH5K_LEDS
>  	struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev));
>  	struct ath5k_softc *sc = hw->priv;
>  
>  	ath5k_led_off(sc);
> +#endif

Even this is avoidable if ath5k_led_off() does nothing.  gcc should be
smart enough to optimize out unneeded function calls.

> +#ifdef CONFIG_ATH5K_LEDS
>  /*
>   * State for LED triggers
>   */
>  struct ath5k_led
>  {
> +#ifdef CONFIG_LEDS_CLASS

I'm not sure this complexity is needed.  Are you going to support LEDs
if CONFIG_LEDS_CLASS is disabled?

> +#ifdef CONFIG_ATH5K_LEDS
>  	unsigned int		led_pin,	/* GPIO pin for driving LED */
>  				led_on;		/* pin setting for LED on */
> +#endif
>  
>  	struct tasklet_struct	restq;		/* reset tasklet */
>  
> @@ -164,7 +172,9 @@ struct ath5k_softc {
>  	spinlock_t		rxbuflock;
>  	u32			*rxlink;	/* link ptr in last RX desc */
>  	struct tasklet_struct	rxtq;		/* rx intr tasklet */
> +#ifdef CONFIG_ATH5K_LEDS
>  	struct ath5k_led	rx_led;		/* rx led */
> +#endif

You may want to group those fields together to make the code more
readable.

> --- a/drivers/net/wireless/ath/ath5k/led.c
> +++ b/drivers/net/wireless/ath/ath5k/led.c

I wonder if you could omit led.c completely in the Makefile.  If there
are some parts of led.c that are needed without CONFIG_ATH5K_LEDS, maybe
they belong elsewhere?

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* Re: kernel BUG in iwl-agn-rs.c:2076, WAS: iwlagn + some accesspoint == hardlock
From: Christian Borntraeger @ 2010-05-12 15:18 UTC (permalink / raw)
  To: reinette chatre
  Cc: John W. Linville, NilsRadtkelkml@think-future.de,
	linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org
In-Reply-To: <1273598493.2370.7891.camel@rchatre-DESK>

Am Dienstag 11 Mai 2010 19:21:33 schrieb reinette chatre:
> > de0f60ea94e132c858caa64a44b2012e1e8580b0
> > 8b9fce77737ae9983f61ec56cd53f52fb738b2c7
> > 
> > reverting both solves my hard lockup. I will try to isolate the "bad" patch
> > but this takes some more days since I wont be in the "hazardous environment"
> > this week.

Drat! Now I got a lockup with these two patches reverted. Dont know if that  was
the same bug.

> Thank you for digging into this. It will be very helpful it you can get
> us a trace of the crash - any chance that netconsole may work?

No success so far.




^ permalink raw reply

* Re: [PATCH 8/9] rt2x00: Reverse calling order of bus write_tx_desc and driver write_tx_desc.
From: Gertjan van Wingerde @ 2010-05-12  9:55 UTC (permalink / raw)
  To: Ivo Van Doorn; +Cc: John W. Linville, linux-wireless, users
In-Reply-To: <AANLkTinMB9AThStTLQ5vkRrKJgDz84n447kFcTwQaQvQ@mail.gmail.com>

On Wed, May 12, 2010 at 9:02 AM, Ivo Van Doorn <ivdoorn@gmail.com> wrote:
> On Tue, May 11, 2010 at 11:51 PM, Gertjan van Wingerde
> <gwingerde@gmail.com> wrote:
>> For rt2800 reverse the calling order of rt2x00pci_write_data and
>> rt2800pci_write_data. Currently rt2800pci_write_data calls rt2x00pci_write_data
>> as there can be only 1 driver callback function specified by the driver.
>> Reverse this calling order by introducing a new driver callback function,
>> called add_tx_datadesc, which is called from the bus-specific write_tx_data
>> functions.
>> Preparation for futher cleanups in the skb data handling of rt2x00.
>>
>> Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
>> ---
>>  drivers/net/wireless/rt2x00/rt2800pci.c |   15 ++++-----------
>>  drivers/net/wireless/rt2x00/rt2x00.h    |    2 ++
>>  drivers/net/wireless/rt2x00/rt2x00pci.c |    6 ++++++
>>  drivers/net/wireless/rt2x00/rt2x00usb.c |    6 ++++++
>>  4 files changed, 18 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
>> index fcca30c..bbd6481 100644
>> --- a/drivers/net/wireless/rt2x00/rt2800pci.c
>> +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
>> @@ -614,18 +614,10 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
>>  /*
>>  * TX descriptor initialization
>>  */
>> -static int rt2800pci_write_tx_data(struct queue_entry* entry,
>> -                                  struct txentry_desc *txdesc)
>> +static void rt2800pci_add_tx_datadesc(struct queue_entry* entry,
>> +                                     struct txentry_desc *txdesc)
>>  {
>> -       int ret;
>> -
>> -       ret = rt2x00pci_write_tx_data(entry, txdesc);
>> -       if (ret)
>> -               return ret;
>> -
>>        rt2800_write_txwi(entry->skb, txdesc);
>> -
>> -       return 0;
>>  }
>>
>>
>> @@ -1080,7 +1072,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
>>        .reset_tuner            = rt2800_reset_tuner,
>>        .link_tuner             = rt2800_link_tuner,
>>        .write_tx_desc          = rt2800pci_write_tx_desc,
>> -       .write_tx_data          = rt2800pci_write_tx_data,
>> +       .write_tx_data          = rt2x00pci_write_tx_data,
>> +       .add_tx_datadesc        = rt2800pci_add_tx_datadesc,
>>        .write_beacon           = rt2800pci_write_beacon,
>>        .kick_tx_queue          = rt2800pci_kick_tx_queue,
>>        .kill_tx_queue          = rt2800pci_kill_tx_queue,
>
> Doesn't the name write_tx_datadesc make more sense?
>

The names are equivalent to me. But if that name makes more sense to
you then I have no problem with changing the name of the callback
function.

---
Gertjan

^ permalink raw reply

* Re: [PATCH 6/9] rt2x00: Push beacon TX descriptor writing to drivers.
From: Gertjan van Wingerde @ 2010-05-12  9:53 UTC (permalink / raw)
  To: Ivo Van Doorn; +Cc: John W. Linville, linux-wireless, users
In-Reply-To: <AANLkTilYgBGsowRMhANjzNzv7IngLb0NZQR5QqSMDYc5@mail.gmail.com>

On Wed, May 12, 2010 at 9:06 AM, Ivo Van Doorn <ivdoorn@gmail.com> wrote:
> On Tue, May 11, 2010 at 11:51 PM, Gertjan van Wingerde
> <gwingerde@gmail.com> wrote:
>> Not all the devices require a TX descriptor to be written (i.e. rt2800
>> device don't require them). Push down the creation of the TX descriptor
>> to the device drivers so that they can decide for themselves whether
>> a TX descriptor is to be created.
>>
>> Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
>> ---
>>  drivers/net/wireless/rt2x00/rt2400pci.c   |   16 ++++++++++------
>>  drivers/net/wireless/rt2x00/rt2500pci.c   |   16 ++++++++++------
>>  drivers/net/wireless/rt2x00/rt2500usb.c   |   11 +++++++++++
>>  drivers/net/wireless/rt2x00/rt2800pci.c   |   17 +++++++++++++++++
>>  drivers/net/wireless/rt2x00/rt2800usb.c   |   17 +++++++++++++++++
>>  drivers/net/wireless/rt2x00/rt2x00debug.c |    1 +
>>  drivers/net/wireless/rt2x00/rt2x00queue.c |   10 +---------
>>  drivers/net/wireless/rt2x00/rt61pci.c     |   11 +++++++++++
>>  drivers/net/wireless/rt2x00/rt73usb.c     |   11 +++++++++++
>>  9 files changed, 89 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
>> index def3fa4..741c531 100644
>> --- a/drivers/net/wireless/rt2x00/rt2400pci.c
>> +++ b/drivers/net/wireless/rt2x00/rt2400pci.c
>> @@ -33,6 +33,7 @@
>>  #include <linux/eeprom_93cx6.h>
>>
>>  #include "rt2x00.h"
>> +#include "rt2x00lib.h"
>>  #include "rt2x00pci.h"
>>  #include "rt2400pci.h"
>
> rt2x00lib.h must not be used in the drivers. It is for the rt2x00lib
> internal files only.

OK. This include is/was necessary for the rt2x00debug_dump_frame call.
So this may be handled with your next issue.

>
>> @@ -1074,9 +1075,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
>>                                   struct txentry_desc *txdesc)
>>  {
>>        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
>> -       struct queue_entry_priv_pci *entry_priv = entry->priv_data;
>> -       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
>> -       u32 word;
>>        u32 reg;
>>
>>        /*
>> @@ -1089,9 +1087,15 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
>>
>>        rt2x00queue_map_txskb(rt2x00dev, entry->skb);
>>
>> -       rt2x00_desc_read(entry_priv->desc, 1, &word);
>> -       rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
>> -       rt2x00_desc_write(entry_priv->desc, 1, word);
>> +       /*
>> +        * Write the TX descriptor for the beacon.
>> +        */
>> +       rt2400pci_write_tx_desc(rt2x00dev, entry->skb, txdesc);
>> +
>> +       /*
>> +        * Dump beacon to userspace through debugfs.
>> +        */
>> +       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
>
> The goal for rt2x00debug was that the logic must be inside rt2x00lib
> as much as possible.
> This can/should be moved into rt2x00lib where write_beacon() is being called.
>

Yes, I wasn't too happy about this part about the patch, but couldn't
find a better solution. The problem is that with the patch the frame
cannot be dumped before the call to write_beacon, as the descriptor
hasn't been set up yet. Also, it cannot be dumped after the call to
write_beacon as most of the write_beacon functions actually free the
skb with the beacon.
So, I ran out of ideas as to how to keep rt2x00debug only inside
rt2x00lib. I'm open for suggestions, though.

---
Gertjan

^ permalink raw reply

* Re: [PATCH 2/9] rt2x00: Fix beacon descriptor writing for rt61pci.
From: Gertjan van Wingerde @ 2010-05-12  9:46 UTC (permalink / raw)
  To: Ivo Van Doorn; +Cc: John W. Linville, linux-wireless, users
In-Reply-To: <AANLkTikOV973PKZYkNyUoaFOXhSPOumhmHwQ7Ei8tvgv@mail.gmail.com>

On Wed, May 12, 2010 at 8:59 AM, Ivo Van Doorn <ivdoorn@gmail.com> wrote:
> On Tue, May 11, 2010 at 11:51 PM, Gertjan van Wingerde
> <gwingerde@gmail.com> wrote:
>> The buffer address descriptor word is not part of the TXINFO structure
>> needed for beacons. The current writing of that word for beacons is
>> therefore an out-of-bounds write.
>> Fix this by only writing the buffer address descriptor word for TX
>> queues.
>>
>> Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
>> ---
>>  drivers/net/wireless/rt2x00/rt61pci.c |   10 +++++-----
>>  1 files changed, 5 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
>> index 2436363..99c2981 100644
>> --- a/drivers/net/wireless/rt2x00/rt61pci.c
>> +++ b/drivers/net/wireless/rt2x00/rt61pci.c
>> @@ -1801,12 +1801,12 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
>>        rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
>>        rt2x00_desc_write(txd, 5, word);
>>
>> -       rt2x00_desc_read(txd, 6, &word);
>> -       rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
>> -                          skbdesc->skb_dma);
>> -       rt2x00_desc_write(txd, 6, word);
>> +       if (txdesc->queue != QID_BEACON) {
>> +               rt2x00_desc_read(txd, 6, &word);
>> +               rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
>> +                                  skbdesc->skb_dma);
>> +               rt2x00_desc_write(txd, 6, word);
>>
>> -       if (skbdesc->desc_len > TXINFO_SIZE) {
>>                rt2x00_desc_read(txd, 11, &word);
>>                rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0,
>>                                   txdesc->length);
>
> Shouldn't the check for TXINFO_SIZE be used rather than explicitly
> checking for the QID?
>

I agree that this is a change that didn't have to be made in this patch.
However, after patch 4 of the series we cannot depend on the
skbdesc->desc_len being set anymore, and we would have to depend on
checking the QID anyway.
Note that in reality these two checks are completely equivalent with
respect to the result.

---
Gertjan.

^ permalink raw reply

* [PATCH 12/12] ath5k: print error message if ANI levels are out of range
From: Bruno Randolf @ 2010-05-12  9:40 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

Since we have sysfs to manually set the ANI levels, we should print errors to
the kernel log if the values are out of bounds.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/ani.c |   11 +++++------
 1 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
index 987e3d3..26dbe65 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -74,8 +74,8 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
 	const s8 fr[] = { -78, -80 };
 #endif
 	if (level < 0 || level >= ARRAY_SIZE(sz)) {
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
-			"level out of range %d", level);
+		ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range",
+			  level);
 		return;
 	}
 
@@ -106,8 +106,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
 
 	if (level < 0 || level >= ARRAY_SIZE(val) ||
 	    level > ah->ah_sc->ani_state.max_spur_level) {
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
-			"level out of range %d", level);
+		ATH5K_ERR(ah->ah_sc, "spur immunity level %d out of range",
+			  level);
 		return;
 	}
 
@@ -130,8 +130,7 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level)
 	const int val[] = { 0, 4, 8 };
 
 	if (level < 0 || level >= ARRAY_SIZE(val)) {
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
-			"level out of range %d", level);
+		ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level);
 		return;
 	}
 


^ permalink raw reply related

* [PATCH 11/12] ath5k: always calculate ANI listen time
From: Bruno Randolf @ 2010-05-12  9:40 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

Calculate 'listen' time also when automatic ANI is off, since this and the
"busy" time is useful information also in manual mode.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/ani.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
index f2311ab..987e3d3 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -481,14 +481,15 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
 	struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
 	int listen, ofdm_high, ofdm_low, cck_high, cck_low;
 
-	if (as->ani_mode != ATH5K_ANI_MODE_AUTO)
-		return;
-
 	/* get listen time since last call and add it to the counter because we
-	 * might not have restarted the "ani period" last time */
+	 * might not have restarted the "ani period" last time.
+	 * always do this to calculate the busy time also in manual mode */
 	listen = ath5k_hw_ani_get_listen_time(ah, as);
 	as->listen_time += listen;
 
+	if (as->ani_mode != ATH5K_ANI_MODE_AUTO)
+		return;
+
 	ath5k_ani_save_and_clear_phy_errors(ah, as);
 
 	ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000;


^ permalink raw reply related

* [PATCH 10/12] ath5k: add sysfs files for ANI parameters
From: Bruno Randolf @ 2010-05-12  9:40 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

/sys/class/ieee80211/phy0/device/ani/ani_mode
/sys/class/ieee80211/phy0/device/ani/noise_immunity_level
/sys/class/ieee80211/phy0/device/ani/spur_level
/sys/class/ieee80211/phy0/device/ani/firstep_level
/sys/class/ieee80211/phy0/device/ani/ofdm_weak_signal_detection
/sys/class/ieee80211/phy0/device/ani/cck_weak_signal_detection
/sys/class/ieee80211/phy0/device/ani/noise_immunity_level_max
/sys/class/ieee80211/phy0/device/ani/spur_level_max
/sys/class/ieee80211/phy0/device/ani/firstep_level_max

sysfs has a lot of symlinks, so you can find the files also in other locations,
like (by PCI ID) /sys/devices/pci0000:00/0000:00:11.0/ani and others.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/Makefile |    1 
 drivers/net/wireless/ath/ath5k/ath5k.h  |    3 +
 drivers/net/wireless/ath/ath5k/base.c   |    3 +
 drivers/net/wireless/ath/ath5k/reset.c  |    1 
 drivers/net/wireless/ath/ath5k/sysfs.c  |  116 +++++++++++++++++++++++++++++++
 5 files changed, 123 insertions(+), 1 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath5k/sysfs.c

diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
index cc09595..2242a14 100644
--- a/drivers/net/wireless/ath/ath5k/Makefile
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -13,5 +13,6 @@ ath5k-y				+= base.o
 ath5k-y				+= led.o
 ath5k-y				+= rfkill.o
 ath5k-y				+= ani.o
+ath5k-y				+= sysfs.o
 ath5k-$(CONFIG_ATH5K_DEBUG)	+= debug.o
 obj-$(CONFIG_ATH5K)		+= ath5k.o
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index d6f9afe..eace74d 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1150,6 +1150,9 @@ struct ath5k_hw {
 int ath5k_hw_attach(struct ath5k_softc *sc);
 void ath5k_hw_detach(struct ath5k_hw *ah);
 
+int ath5k_sysfs_register(struct ath5k_softc *sc);
+void ath5k_sysfs_unregister(struct ath5k_softc *sc);
+
 /* LED functions */
 int ath5k_init_leds(struct ath5k_softc *sc);
 void ath5k_led_enable(struct ath5k_softc *sc);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 3fcf220..053cb36 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -861,6 +861,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 
 	ath5k_init_leds(sc);
 
+	ath5k_sysfs_register(sc);
+
 	return 0;
 err_queues:
 	ath5k_txq_release(sc);
@@ -896,6 +898,7 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 	ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
 	ath5k_unregister_leds(sc);
 
+	ath5k_sysfs_unregister(sc);
 	/*
 	 * NB: can't reclaim these until after ieee80211_ifdetach
 	 * returns because we'll get called back to reclaim node
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 2890a7f..b1d3239 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -851,7 +851,6 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
 			AR5K_PHY_NF_THRESH62,
 			ee->ee_thr_62[ee_mode]);
 
-
 	/* False detect backoff for channels
 	 * that have spur noise. Write the new
 	 * cyclic power RSSI threshold. */
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c
new file mode 100644
index 0000000..90757de
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/sysfs.c
@@ -0,0 +1,116 @@
+#include <linux/device.h>
+#include <linux/pci.h>
+
+#include "base.h"
+#include "ath5k.h"
+#include "reg.h"
+
+#define SIMPLE_SHOW_STORE(name, get, set)				\
+static ssize_t ath5k_attr_show_##name(struct device *dev,		\
+			struct device_attribute *attr,			\
+			char *buf)					\
+{									\
+	struct ath5k_softc *sc = dev_get_drvdata(dev);			\
+	return snprintf(buf, PAGE_SIZE, "%d\n", get); 			\
+}									\
+									\
+static ssize_t ath5k_attr_store_##name(struct device *dev,		\
+			struct device_attribute *attr,			\
+			const char *buf, size_t count)			\
+{									\
+	struct ath5k_softc *sc = dev_get_drvdata(dev);			\
+	int val;							\
+									\
+	val = (int)simple_strtoul(buf, NULL, 10);			\
+	set(sc->ah, val);						\
+	return count;							\
+}									\
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR,				\
+		   ath5k_attr_show_##name, ath5k_attr_store_##name)
+
+#define SIMPLE_SHOW(name, get)						\
+static ssize_t ath5k_attr_show_##name(struct device *dev,		\
+			struct device_attribute *attr,			\
+			char *buf)					\
+{									\
+	struct ath5k_softc *sc = dev_get_drvdata(dev);			\
+	return snprintf(buf, PAGE_SIZE, "%d\n", get); 			\
+}									\
+static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL)
+
+/*** ANI ***/
+
+SIMPLE_SHOW_STORE(ani_mode, sc->ani_state.ani_mode, ath5k_ani_init);
+SIMPLE_SHOW_STORE(noise_immunity_level, sc->ani_state.noise_imm_level,
+			ath5k_ani_set_noise_immunity_level);
+SIMPLE_SHOW_STORE(spur_level, sc->ani_state.spur_level,
+			ath5k_ani_set_spur_immunity_level);
+SIMPLE_SHOW_STORE(firstep_level, sc->ani_state.firstep_level,
+			ath5k_ani_set_firstep_level);
+SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, sc->ani_state.ofdm_weak_sig,
+			ath5k_ani_set_ofdm_weak_signal_detection);
+SIMPLE_SHOW_STORE(cck_weak_signal_detection, sc->ani_state.cck_weak_sig,
+			ath5k_ani_set_cck_weak_signal_detection);
+SIMPLE_SHOW(spur_level_max, sc->ani_state.max_spur_level);
+
+static ssize_t ath5k_attr_show_noise_immunity_level_max(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_NOISE_IMM_LVL);
+}
+static DEVICE_ATTR(noise_immunity_level_max, S_IRUGO,
+		   ath5k_attr_show_noise_immunity_level_max, NULL);
+
+static ssize_t ath5k_attr_show_firstep_level_max(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_FIRSTEP_LVL);
+}
+static DEVICE_ATTR(firstep_level_max, S_IRUGO,
+		   ath5k_attr_show_firstep_level_max, NULL);
+
+static struct attribute *ath5k_sysfs_entries_ani[] = {
+	&dev_attr_ani_mode.attr,
+	&dev_attr_noise_immunity_level.attr,
+	&dev_attr_spur_level.attr,
+	&dev_attr_firstep_level.attr,
+	&dev_attr_ofdm_weak_signal_detection.attr,
+	&dev_attr_cck_weak_signal_detection.attr,
+	&dev_attr_noise_immunity_level_max.attr,
+	&dev_attr_spur_level_max.attr,
+	&dev_attr_firstep_level_max.attr,
+	NULL
+};
+
+static struct attribute_group ath5k_attribute_group_ani = {
+	.name = "ani",
+	.attrs = ath5k_sysfs_entries_ani,
+};
+
+
+/*** register / unregister ***/
+
+int
+ath5k_sysfs_register(struct ath5k_softc *sc)
+{
+	struct device *dev = &sc->pdev->dev;
+	int err;
+
+	err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani);
+	if (err) {
+		ATH5K_ERR(sc, "failed to create sysfs group\n");
+		return err;
+	}
+
+	return 0;
+}
+
+void
+ath5k_sysfs_unregister(struct ath5k_softc *sc)
+{
+	struct device *dev = &sc->pdev->dev;
+
+	sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani);
+}


^ permalink raw reply related

* [PATCH 09/12] ath5k: use ath5k_softc as driver data
From: Bruno Randolf @ 2010-05-12  9:40 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

It's our "private driver data"... It's used more often and hw is the mac80211
part. This makes more sense with the next (sysfs) patch.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/base.c |   15 ++++++---------
 1 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index e3803ba..3fcf220 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -578,7 +578,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
 	spin_lock_init(&sc->block);
 
 	/* Set private data */
-	pci_set_drvdata(pdev, hw);
+	pci_set_drvdata(pdev, sc);
 
 	/* Setup interrupt handler */
 	ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
@@ -694,25 +694,23 @@ err:
 static void __devexit
 ath5k_pci_remove(struct pci_dev *pdev)
 {
-	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_softc *sc = pci_get_drvdata(pdev);
 
 	ath5k_debug_finish_device(sc);
-	ath5k_detach(pdev, hw);
+	ath5k_detach(pdev, sc->hw);
 	ath5k_hw_detach(sc->ah);
 	kfree(sc->ah);
 	free_irq(pdev->irq, sc);
 	pci_iounmap(pdev, sc->iobase);
 	pci_release_region(pdev, 0);
 	pci_disable_device(pdev);
-	ieee80211_free_hw(hw);
+	ieee80211_free_hw(sc->hw);
 }
 
 #ifdef CONFIG_PM
 static int ath5k_pci_suspend(struct device *dev)
 {
-	struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev));
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
 
 	ath5k_led_off(sc);
 	return 0;
@@ -721,8 +719,7 @@ static int ath5k_pci_suspend(struct device *dev)
 static int ath5k_pci_resume(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
-	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_softc *sc = pci_get_drvdata(pdev);
 
 	/*
 	 * Suspend/Resume resets the PCI configuration space, so we have to


^ permalink raw reply related

* [PATCH 08/12] ath5k: clarify logic when to enable spur mitigation filter
From: Bruno Randolf @ 2010-05-12  9:40 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

The old code logically did not make sense and seems to have been confused by
the fact that we could have newer EEPROMs on older hardware. In any case the
spur mitigation filter was set if the srev was >= AR5K_SREV_AR5424.

Spur info is available only from EEPROM versions bigger than 5.3 but but the
EEPOM routines will use static values for older versions, so that should be
o.k.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/reset.c |   15 +++++----------
 1 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 5e23e61..2890a7f 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -1090,22 +1090,17 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 		/* Write OFDM timings on 5212*/
 		if (ah->ah_version == AR5K_AR5212 &&
 			channel->hw_value & CHANNEL_OFDM) {
-			struct ath5k_eeprom_info *ee =
-					&ah->ah_capabilities.cap_eeprom;
 
 			ret = ath5k_hw_write_ofdm_timings(ah, channel);
 			if (ret)
 				return ret;
 
-			/* Note: According to docs we can have a newer
-			 * EEPROM on old hardware, so we need to verify
-			 * that our hardware is new enough to have spur
-			 * mitigation registers (delta phase etc) */
-			if (ah->ah_mac_srev >= AR5K_SREV_AR5424 ||
-			(ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
-			ee->ee_version >= AR5K_EEPROM_VERSION_5_3))
+			/* Spur info is available only from EEPROM versions
+			 * bigger than 5.3 but but the EEPOM routines will use
+			 * static values for older versions */
+			if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
 				ath5k_hw_set_spur_mitigation_filter(ah,
-								channel);
+								    channel);
 		}
 
 		/*Enable/disable 802.11b mode on 5111


^ permalink raw reply related

* [PATCH 07/12] ath5k: remove ATH_TRACE macro
From: Bruno Randolf @ 2010-05-12  9:40 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

Now that we have ftrace, it is not needed any more.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/attach.c |    2 --
 drivers/net/wireless/ath/ath5k/caps.c   |    7 -------
 drivers/net/wireless/ath/ath5k/debug.c  |    1 -
 drivers/net/wireless/ath/ath5k/debug.h  |    8 --------
 drivers/net/wireless/ath/ath5k/desc.c   |    7 -------
 drivers/net/wireless/ath/ath5k/dma.c    |   13 -------------
 drivers/net/wireless/ath/ath5k/eeprom.c |    1 -
 drivers/net/wireless/ath/ath5k/gpio.c   |    7 -------
 drivers/net/wireless/ath/ath5k/pcu.c    |   24 ------------------------
 drivers/net/wireless/ath/ath5k/phy.c    |   13 -------------
 drivers/net/wireless/ath/ath5k/qcu.c    |    9 ---------
 drivers/net/wireless/ath/ath5k/reset.c  |    7 -------
 12 files changed, 0 insertions(+), 99 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index e0c244b..ef2dc1d 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -351,8 +351,6 @@ err_free:
  */
 void ath5k_hw_detach(struct ath5k_hw *ah)
 {
-	ATH5K_TRACE(ah->ah_sc);
-
 	__set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
 
 	if (ah->ah_rf_banks != NULL)
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c
index 74f0071..beae519 100644
--- a/drivers/net/wireless/ath/ath5k/caps.c
+++ b/drivers/net/wireless/ath/ath5k/caps.c
@@ -34,7 +34,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
 {
 	u16 ee_header;
 
-	ATH5K_TRACE(ah->ah_sc);
 	/* Capabilities stored in the EEPROM */
 	ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
 
@@ -123,8 +122,6 @@ int ath5k_hw_get_capability(struct ath5k_hw *ah,
 		enum ath5k_capability_type cap_type,
 		u32 capability, u32 *result)
 {
-	ATH5K_TRACE(ah->ah_sc);
-
 	switch (cap_type) {
 	case AR5K_CAP_NUM_TXQUEUES:
 		if (result) {
@@ -173,8 +170,6 @@ yes:
 int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
 		u16 assoc_id)
 {
-	ATH5K_TRACE(ah->ah_sc);
-
 	if (ah->ah_version == AR5K_AR5210) {
 		AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
 			AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
@@ -186,8 +181,6 @@ int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
 
 int ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
 {
-	ATH5K_TRACE(ah->ah_sc);
-
 	if (ah->ah_version == AR5K_AR5210) {
 		AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
 			AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index c77a6ad..97c5ada 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -307,7 +307,6 @@ static const struct {
 	{ ATH5K_DEBUG_DUMP_RX,	"dumprx",	"print received skb content" },
 	{ ATH5K_DEBUG_DUMP_TX,	"dumptx",	"print transmit skb content" },
 	{ ATH5K_DEBUG_DUMPBANDS, "dumpbands",	"dump bands" },
-	{ ATH5K_DEBUG_TRACE,	"trace",	"trace function calls" },
 	{ ATH5K_DEBUG_ANI,	"ani",		"adaptive noise immunity" },
 	{ ATH5K_DEBUG_ANY,	"all",		"show all debug levels" },
 };
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index c7a0769..606ae94 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -116,18 +116,12 @@ enum ath5k_debug_level {
 	ATH5K_DEBUG_DUMP_RX	= 0x00000100,
 	ATH5K_DEBUG_DUMP_TX	= 0x00000200,
 	ATH5K_DEBUG_DUMPBANDS	= 0x00000400,
-	ATH5K_DEBUG_TRACE	= 0x00001000,
 	ATH5K_DEBUG_ANI		= 0x00002000,
 	ATH5K_DEBUG_ANY		= 0xffffffff
 };
 
 #ifdef CONFIG_ATH5K_DEBUG
 
-#define ATH5K_TRACE(_sc) do { \
-	if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
-		printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \
-	} while (0)
-
 #define ATH5K_DBG(_sc, _m, _fmt, ...) do { \
 	if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \
 		ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
@@ -169,8 +163,6 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
 
 #include <linux/compiler.h>
 
-#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc))
-
 static inline void __attribute__ ((format (printf, 3, 4)))
 ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
 
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c
index 7d7b646..da5dbb6 100644
--- a/drivers/net/wireless/ath/ath5k/desc.c
+++ b/drivers/net/wireless/ath/ath5k/desc.c
@@ -176,7 +176,6 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 	struct ath5k_hw_4w_tx_ctl *tx_ctl;
 	unsigned int frame_len;
 
-	ATH5K_TRACE(ah->ah_sc);
 	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
 
 	/*
@@ -342,8 +341,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
 	struct ath5k_hw_2w_tx_ctl *tx_ctl;
 	struct ath5k_hw_tx_status *tx_status;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
 	tx_status = &desc->ud.ds_tx5210.tx_stat;
 
@@ -396,8 +393,6 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 	struct ath5k_hw_4w_tx_ctl *tx_ctl;
 	struct ath5k_hw_tx_status *tx_status;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
 	tx_status = &desc->ud.ds_tx5212.tx_stat;
 
@@ -490,7 +485,6 @@ static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 {
 	struct ath5k_hw_rx_ctl *rx_ctl;
 
-	ATH5K_TRACE(ah->ah_sc);
 	rx_ctl = &desc->ud.ds_rx.rx_ctl;
 
 	/*
@@ -593,7 +587,6 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
 	struct ath5k_hw_rx_status *rx_status;
 	struct ath5k_hw_rx_error *rx_err;
 
-	ATH5K_TRACE(ah->ah_sc);
 	rx_status = &desc->ud.ds_rx.u.rx_stat;
 
 	/* Overlay on error */
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index 941b511..484f318 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -48,7 +48,6 @@
  */
 void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
 	ath5k_hw_reg_read(ah, AR5K_CR);
 }
@@ -62,7 +61,6 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
 {
 	unsigned int i;
 
-	ATH5K_TRACE(ah->ah_sc);
 	ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
 
 	/*
@@ -96,8 +94,6 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
  */
 void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
 {
-	ATH5K_TRACE(ah->ah_sc);
-
 	ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
 }
 
@@ -125,7 +121,6 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
 {
 	u32 tx_queue;
 
-	ATH5K_TRACE(ah->ah_sc);
 	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 
 	/* Return if queue is declared inactive */
@@ -186,7 +181,6 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
 	unsigned int i = 40;
 	u32 tx_queue, pending;
 
-	ATH5K_TRACE(ah->ah_sc);
 	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 
 	/* Return if queue is declared inactive */
@@ -297,7 +291,6 @@ u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
 {
 	u16 tx_reg;
 
-	ATH5K_TRACE(ah->ah_sc);
 	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 
 	/*
@@ -340,7 +333,6 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
 {
 	u16 tx_reg;
 
-	ATH5K_TRACE(ah->ah_sc);
 	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 
 	/*
@@ -400,8 +392,6 @@ int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
 	u32 trigger_level, imr;
 	int ret = -EIO;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	/*
 	 * Disable interrupts by setting the mask
 	 */
@@ -451,7 +441,6 @@ done:
  */
 bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
 }
 
@@ -475,8 +464,6 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
 {
 	u32 data;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	/*
 	 * Read interrupt status from the Interrupt Status register
 	 * on 5210
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index ed02636..155a82c 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -35,7 +35,6 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
 {
 	u32 status, timeout;
 
-	ATH5K_TRACE(ah->ah_sc);
 	/*
 	 * Initialize EEPROM access
 	 */
diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c
index 64a27e7..bc90503 100644
--- a/drivers/net/wireless/ath/ath5k/gpio.c
+++ b/drivers/net/wireless/ath/ath5k/gpio.c
@@ -34,8 +34,6 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
 	/*5210 has different led mode handling*/
 	u32 led_5210;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	/*Reset led status*/
 	if (ah->ah_version != AR5K_AR5210)
 		AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
@@ -82,7 +80,6 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
  */
 int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	if (gpio >= AR5K_NUM_GPIO)
 		return -EINVAL;
 
@@ -98,7 +95,6 @@ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
  */
 int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	if (gpio >= AR5K_NUM_GPIO)
 		return -EINVAL;
 
@@ -114,7 +110,6 @@ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
  */
 u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	if (gpio >= AR5K_NUM_GPIO)
 		return 0xffffffff;
 
@@ -129,7 +124,6 @@ u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
 int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
 {
 	u32 data;
-	ATH5K_TRACE(ah->ah_sc);
 
 	if (gpio >= AR5K_NUM_GPIO)
 		return -EINVAL;
@@ -153,7 +147,6 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
 {
 	u32 data;
 
-	ATH5K_TRACE(ah->ah_sc);
 	if (gpio >= AR5K_NUM_GPIO)
 		return;
 
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 5212e27..86fdb6d 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -59,8 +59,6 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
 
 	beacon_reg = 0;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	switch (op_mode) {
 	case NL80211_IFTYPE_ADHOC:
 		pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
@@ -173,7 +171,6 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
  */
 static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK))
 			<= timeout)
 		return -EINVAL;
@@ -192,7 +189,6 @@ static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
  */
 static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS))
 			<= timeout)
 		return -EINVAL;
@@ -297,7 +293,6 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
 	u32 low_id, high_id;
 	u32 pcu_reg;
 
-	ATH5K_TRACE(ah->ah_sc);
 	/* Set new station ID */
 	memcpy(common->macaddr, mac, ETH_ALEN);
 
@@ -357,7 +352,6 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah)
 void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
 {
 	struct ath_common *common = ath5k_hw_common(ah);
-	ATH5K_TRACE(ah->ah_sc);
 
 	/* Cache bssid mask so that we can restore it
 	 * on reset */
@@ -382,7 +376,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
  */
 void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
 }
 
@@ -397,7 +390,6 @@ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
  */
 void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
 }
 
@@ -406,8 +398,6 @@ void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
  */
 void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
 {
-	ATH5K_TRACE(ah->ah_sc);
-	/* Set the multicat filter */
 	ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
 	ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
 }
@@ -427,7 +417,6 @@ u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
 {
 	u32 data, filter = 0;
 
-	ATH5K_TRACE(ah->ah_sc);
 	filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
 
 	/*Radar detection for 5212*/
@@ -457,8 +446,6 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
 {
 	u32 data = 0;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	/* Set PHY error filter register on 5212*/
 	if (ah->ah_version == AR5K_AR5212) {
 		if (filter & AR5K_RX_FILTER_RADARERR)
@@ -533,8 +520,6 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
 
 	WARN_ON( i == ATH5K_MAX_TSF_READ );
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	return (((u64)tsf_upper1 << 32) | tsf_lower);
 }
 
@@ -548,8 +533,6 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
  */
 void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64)
 {
-	ATH5K_TRACE(ah->ah_sc);
-
 	ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32);
 	ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32);
 }
@@ -565,8 +548,6 @@ void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
 {
 	u32 val;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF;
 
 	/*
@@ -586,7 +567,6 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
 {
 	u32 timer1, timer2, timer3;
 
-	ATH5K_TRACE(ah->ah_sc);
 	/*
 	 * Set the additional timers by mode
 	 */
@@ -674,7 +654,6 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
 	unsigned int i, type;
 	u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
 
-	ATH5K_TRACE(ah->ah_sc);
 	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
 
 	type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
@@ -749,8 +728,6 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
 	bool is_tkip;
 	const u8 *key_ptr;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	is_tkip = (key->alg == ALG_TKIP);
 
 	/*
@@ -836,7 +813,6 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
 {
 	u32 low_id, high_id;
 
-	ATH5K_TRACE(ah->ah_sc);
 	 /* Invalid entry (key table overflow) */
 	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
 
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 0b24081..f369e7e 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -378,8 +378,6 @@ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
 	u32 data, type;
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	if (ah->ah_rf_banks == NULL ||
 	ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE)
 		return AR5K_RFGAIN_INACTIVE;
@@ -1353,7 +1351,6 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
 	u32 i_pwr, q_pwr;
 	s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
 	int i;
-	ATH5K_TRACE(ah->ah_sc);
 
 	if (!ah->ah_calibration ||
 		ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
@@ -1680,7 +1677,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
 
 int ath5k_hw_phy_disable(struct ath5k_hw *ah)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	/*Just a try M.F.*/
 	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
 
@@ -1696,8 +1692,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
 	u32 srev;
 	u16 ret;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	/*
 	 * Set the radio chip access register
 	 */
@@ -1742,8 +1736,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
 static void /*TODO:Boundary check*/
 ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant)
 {
-	ATH5K_TRACE(ah->ah_sc);
-
 	if (ah->ah_version != AR5K_AR5210)
 		ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA);
 }
@@ -1803,8 +1795,6 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
 
 	def_ant = ah->ah_def_ant;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	switch (channel->hw_value & CHANNEL_MODES) {
 	case CHANNEL_A:
 	case CHANNEL_T:
@@ -2970,7 +2960,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
 	u8 type;
 	int ret;
 
-	ATH5K_TRACE(ah->ah_sc);
 	if (txpower > AR5K_TUNE_MAX_TXPOWER) {
 		ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
 		return -EINVAL;
@@ -3066,8 +3055,6 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
 	struct ieee80211_channel *channel = ah->ah_current_channel;
 	u8 ee_mode;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	switch (channel->hw_value & CHANNEL_MODES) {
 	case CHANNEL_A:
 	case CHANNEL_T:
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index f5831da..4186ff4 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -31,7 +31,6 @@ Queue Control Unit, DFS Control Unit Functions
 int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
 		struct ath5k_txq_info *queue_info)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
 	return 0;
 }
@@ -42,7 +41,6 @@ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
 int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
 				const struct ath5k_txq_info *queue_info)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 
 	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
@@ -69,8 +67,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
 	unsigned int queue;
 	int ret;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	/*
 	 * Get queue by type
 	 */
@@ -149,7 +145,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
 u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
 {
 	u32 pending;
-	ATH5K_TRACE(ah->ah_sc);
 	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 
 	/* Return if queue is declared inactive */
@@ -177,7 +172,6 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
  */
 void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
 {
-	ATH5K_TRACE(ah->ah_sc);
 	if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
 		return;
 
@@ -195,7 +189,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
 	u32 cw_min, cw_max, retry_lg, retry_sh;
 	struct ath5k_txq_info *tq = &ah->ah_txq[queue];
 
-	ATH5K_TRACE(ah->ah_sc);
 	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
 
 	tq = &ah->ah_txq[queue];
@@ -523,8 +516,6 @@ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
 {
 	u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
 		return -EINVAL;
 
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 44bbbf2..5e23e61 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -201,8 +201,6 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
 	int ret;
 	u32 mask = val ? val : ~0U;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	/* Read-and-clear RX Descriptor Pointer*/
 	ath5k_hw_reg_read(ah, AR5K_RXDP);
 
@@ -246,7 +244,6 @@ static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
 	unsigned int i;
 	u32 staid, data;
 
-	ATH5K_TRACE(ah->ah_sc);
 	staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
 
 	switch (mode) {
@@ -393,8 +390,6 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
 	mode = 0;
 	clock = 0;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	/* Wakeup the device */
 	ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
 	if (ret) {
@@ -899,8 +894,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	u8 mode, freq, ee_mode, ant[2];
 	int i, ret;
 
-	ATH5K_TRACE(ah->ah_sc);
-
 	s_ant = 0;
 	ee_mode = 0;
 	staid1_flags = 0;


^ permalink raw reply related

* [PATCH 06/12] ath5k: run NF calibration only every 60 seconds
From: Bruno Randolf @ 2010-05-12  9:40 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

Since NF calibration interferes with TX and RX and also has been the cause of
other problems (when it's run concurrently with ath5k_reset) we want to run it
less often - every 60 seconds for now.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/ath5k.h |    2 ++
 drivers/net/wireless/ath/ath5k/base.c  |   18 +++++++++++-------
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 131e8b3..d6f9afe 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -204,6 +204,7 @@
 #define AR5K_TUNE_TPC_TXPOWER			false
 #define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL    10000   /* 10 sec */
 #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI	1000	/* 1 sec */
+#define ATH5K_TUNE_CALIBRATION_INTERVAL_NF	60000	/* 60 sec */
 
 #define AR5K_INIT_CARR_SENSE_EN			1
 
@@ -1118,6 +1119,7 @@ struct ath5k_hw {
 	/* Calibration timestamp */
 	unsigned long		ah_cal_next_full;
 	unsigned long		ah_cal_next_ani;
+	unsigned long		ah_cal_next_nf;
 
 	/* Calibration mask */
 	u8			ah_cal_mask;
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index b15b9d6..e3803ba 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2801,14 +2801,16 @@ ath5k_tasklet_calibrate(unsigned long data)
 			ieee80211_frequency_to_channel(
 				sc->curchan->center_freq));
 
-	/* TODO: We don't need to run noise floor calibration as often
-	 * as I/Q calibration.*/
-
 	/* Noise floor calibration interrupts rx/tx path while I/Q calibration
-	 * doesn't. Stop queues so that calibration doesn't interfere with tx */
-	ieee80211_stop_queues(sc->hw);
-	ath5k_hw_update_noise_floor(ah);
-	ieee80211_wake_queues(sc->hw);
+	 * doesn't. We stop the queues so that calibration doesn't interfere
+	 * with TX and don't run it as often */
+	if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) {
+		ah->ah_cal_next_nf = jiffies +
+			msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF);
+		ieee80211_stop_queues(sc->hw);
+		ath5k_hw_update_noise_floor(ah);
+		ieee80211_wake_queues(sc->hw);
+	}
 
 	ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;
 }
@@ -2929,6 +2931,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
 
 	ah->ah_cal_next_full = jiffies;
 	ah->ah_cal_next_ani = jiffies;
+	ah->ah_cal_next_nf = jiffies;
+
 	/*
 	 * Change channels and update the h/w rate map if we're switching;
 	 * e.g. 11a to 11b/g.


^ permalink raw reply related

* [PATCH 05/12] ath5k: Stop queues only for NF calibration
From: Bruno Randolf @ 2010-05-12  9:40 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

As far as we know, only NF calibration interferes with RX/TX so we can
leave the queues enabled for the other calibrations.

BTW: Stopping the queues is not enough for avoiding transmissions, since there
might be packets in the queue + beacons are also sent regularly! But i leave it
like this until we have a better solution (stopping TX DMA?).

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/base.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 8bc970f..b15b9d6 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2784,10 +2784,6 @@ ath5k_tasklet_calibrate(unsigned long data)
 	/* Only full calibration for now */
 	ah->ah_cal_mask |= AR5K_CALIBRATION_FULL;
 
-	/* Stop queues so that calibration
-	 * doesn't interfere with tx */
-	ieee80211_stop_queues(sc->hw);
-
 	ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
 		ieee80211_frequency_to_channel(sc->curchan->center_freq),
 		sc->curchan->hw_value);
@@ -2805,8 +2801,13 @@ ath5k_tasklet_calibrate(unsigned long data)
 			ieee80211_frequency_to_channel(
 				sc->curchan->center_freq));
 
+	/* TODO: We don't need to run noise floor calibration as often
+	 * as I/Q calibration.*/
+
+	/* Noise floor calibration interrupts rx/tx path while I/Q calibration
+	 * doesn't. Stop queues so that calibration doesn't interfere with tx */
+	ieee80211_stop_queues(sc->hw);
 	ath5k_hw_update_noise_floor(ah);
-	/* Wake queues */
 	ieee80211_wake_queues(sc->hw);
 
 	ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;


^ permalink raw reply related

* [PATCH 04/12] ath5k: move noise floor calibration into tasklet
From: Bruno Randolf @ 2010-05-12  9:40 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

Seperate noise floor calibration from other PHY calibration and move it to the
tasklet. This is the first step to more separation of different calibrations.

Also move out ath5k_hw_request_rfgain_probe(ah) so we have one clean function
for I/Q calibration on 5111x parts.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/ath5k.h |    1 +
 drivers/net/wireless/ath/ath5k/base.c  |    1 +
 drivers/net/wireless/ath/ath5k/phy.c   |   33 ++++++++++----------------------
 3 files changed, 12 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 2785946..131e8b3 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1270,6 +1270,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
 void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
 int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
 			   struct ieee80211_channel *channel);
+void ath5k_hw_update_noise_floor(struct ath5k_hw *ah);
 /* Spur mitigation */
 bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
 				  struct ieee80211_channel *channel);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 3fc1de4..8bc970f 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2805,6 +2805,7 @@ ath5k_tasklet_calibrate(unsigned long data)
 			ieee80211_frequency_to_channel(
 				sc->curchan->center_freq));
 
+	ath5k_hw_update_noise_floor(ah);
 	/* Wake queues */
 	ieee80211_wake_queues(sc->hw);
 
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 3ce9afb..0b24081 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1167,7 +1167,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)
  * The median of the values in the history is then loaded into the
  * hardware for its own use for RSSI and CCA measurements.
  */
-static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
+void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
 {
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	u32 val;
@@ -1248,7 +1248,6 @@ static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
 /*
  * Perform a PHY calibration on RF5110
  * -Fix BPSK/QAM Constellation (I/Q correction)
- * -Calculate Noise Floor
  */
 static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
 		struct ieee80211_channel *channel)
@@ -1335,8 +1334,6 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
 		return ret;
 	}
 
-	ath5k_hw_update_noise_floor(ah);
-
 	/*
 	 * Re-enable RX/TX and beacons
 	 */
@@ -1348,10 +1345,10 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
 }
 
 /*
- * Perform a PHY calibration on RF5111/5112 and newer chips
+ * Perform I/Q calibration on RF5111/5112 and newer chips
  */
-static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
-		struct ieee80211_channel *channel)
+static int
+ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
 {
 	u32 i_pwr, q_pwr;
 	s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
@@ -1360,10 +1357,9 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
 
 	if (!ah->ah_calibration ||
 		ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
-		goto done;
+		return 0;
 
 	/* Calibration has finished, get the results and re-run */
-
 	/* work around empty results which can apparently happen on 5212 */
 	for (i = 0; i <= 10; i++) {
 		iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
@@ -1384,7 +1380,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
 
 	/* protect against divide by 0 and loss of sign bits */
 	if (i_coffd == 0 || q_coffd < 2)
-		goto done;
+		return -1;
 
 	i_coff = (-iq_corr) / i_coffd;
 	i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */
@@ -1410,17 +1406,6 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
 			AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
 	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
 
-done:
-
-	/* TODO: Separate noise floor calibration from I/Q calibration
-	 * since noise floor calibration interrupts rx path while I/Q
-	 * calibration doesn't. We don't need to run noise floor calibration
-	 * as often as I/Q calibration.*/
-	ath5k_hw_update_noise_floor(ah);
-
-	/* Initiate a gain_F calibration */
-	ath5k_hw_request_rfgain_probe(ah);
-
 	return 0;
 }
 
@@ -1434,8 +1419,10 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
 
 	if (ah->ah_radio == AR5K_RF5110)
 		ret = ath5k_hw_rf5110_calibrate(ah, channel);
-	else
-		ret = ath5k_hw_rf511x_calibrate(ah, channel);
+	else {
+		ret = ath5k_hw_rf511x_iq_calibrate(ah);
+		ath5k_hw_request_rfgain_probe(ah);
+	}
 
 	return ret;
 }


^ permalink raw reply related

* [PATCH 03/12] ath5k: initialize calibration timers
From: Bruno Randolf @ 2010-05-12  9:39 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

Initialize calibration timers on reset, since otherwise they might be in the
future and the calibration tasklet might not be scheduled for a long time.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/base.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 732a2c1..3fc1de4 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2925,6 +2925,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
 
 	ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode);
 
+	ah->ah_cal_next_full = jiffies;
+	ah->ah_cal_next_ani = jiffies;
 	/*
 	 * Change channels and update the h/w rate map if we're switching;
 	 * e.g. 11a to 11b/g.


^ permalink raw reply related

* [PATCH 02/12] ath5k: wake queues on reset
From: Bruno Randolf @ 2010-05-12  9:39 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100512093947.6575.99595.stgit@tt-desk>

We can wake all queues after a chip reset since everything should be set up and
we are ready to transmit. If we don't do that we might end up starting up with
stopped queues, not beeing able to transmit. (This started to happen after
"ath5k: clean up queue manipulation" but since periodic calibration also
stopped and started the queues this effect was hidden most of the time).

This way we can also get rid of the superfluous ath5k_reset_wake() function.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/base.c |   17 +++--------------
 1 files changed, 3 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 9c27623..732a2c1 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -222,7 +222,6 @@ static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
 		struct ath5k_txq *txq);
 static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-static int ath5k_reset_wake(struct ath5k_softc *sc);
 static int ath5k_start(struct ieee80211_hw *hw);
 static void ath5k_stop(struct ieee80211_hw *hw);
 static int ath5k_add_interface(struct ieee80211_hw *hw,
@@ -2769,7 +2768,7 @@ ath5k_tasklet_reset(unsigned long data)
 {
 	struct ath5k_softc *sc = (void *)data;
 
-	ath5k_reset_wake(sc);
+	ath5k_reset(sc, sc->curchan);
 }
 
 /*
@@ -2940,23 +2939,13 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
 	ath5k_beacon_config(sc);
 	/* intrs are enabled by ath5k_beacon_config */
 
+	ieee80211_wake_queues(sc->hw);
+
 	return 0;
 err:
 	return ret;
 }
 
-static int
-ath5k_reset_wake(struct ath5k_softc *sc)
-{
-	int ret;
-
-	ret = ath5k_reset(sc, sc->curchan);
-	if (!ret)
-		ieee80211_wake_queues(sc->hw);
-
-	return ret;
-}
-
 static int ath5k_start(struct ieee80211_hw *hw)
 {
 	return ath5k_init(hw->priv);


^ permalink raw reply related

* [PATCH 01/12] ath5k: add debugfs file for queue debugging
From: Bruno Randolf @ 2010-05-12  9:39 UTC (permalink / raw)
  To: linville; +Cc: ath5k-devel, linux-wireless

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/debug.c |   66 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath5k/debug.h |    1 
 2 files changed, 67 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 6fb5c5f..c77a6ad 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -729,6 +729,66 @@ static const struct file_operations fops_ani = {
 };
 
 
+/* debugfs: queues etc */
+
+static ssize_t read_file_queue(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	char buf[700];
+	unsigned int len = 0;
+
+	struct ath5k_txq *txq;
+	struct ath5k_buf *bf, *bf0;
+	int i, n = 0;
+
+	len += snprintf(buf+len, sizeof(buf)-len,
+			"available txbuffers: %d\n", sc->txbuf_len);
+
+	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
+		txq = &sc->txqs[i];
+
+		len += snprintf(buf+len, sizeof(buf)-len,
+			"%02d: %ssetup\n", i, txq->setup ? "" : "not ");
+
+		if (!txq->setup)
+			continue;
+
+		list_for_each_entry_safe(bf, bf0, &txq->q, list)
+			n++;
+		len += snprintf(buf+len, sizeof(buf)-len, "  len: %d\n", n);
+	}
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_queue(struct file *file,
+				 const char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	char buf[20];
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
+
+	if (strncmp(buf, "start", 5) == 0)
+		ieee80211_wake_queues(sc->hw);
+	else if (strncmp(buf, "stop", 4) == 0)
+		ieee80211_stop_queues(sc->hw);
+
+	return count;
+}
+
+
+static const struct file_operations fops_queue = {
+	.read = read_file_queue,
+	.write = write_file_queue,
+	.open = ath5k_debugfs_open,
+	.owner = THIS_MODULE,
+};
+
+
 /* init */
 
 void
@@ -772,6 +832,11 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
 				S_IWUSR | S_IRUSR,
 				sc->debug.debugfs_phydir, sc,
 				&fops_ani);
+
+	sc->debug.debugfs_queue = debugfs_create_file("queue",
+				S_IWUSR | S_IRUSR,
+				sc->debug.debugfs_phydir, sc,
+				&fops_queue);
 }
 
 void
@@ -790,6 +855,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
 	debugfs_remove(sc->debug.debugfs_antenna);
 	debugfs_remove(sc->debug.debugfs_frameerrors);
 	debugfs_remove(sc->debug.debugfs_ani);
+	debugfs_remove(sc->debug.debugfs_queue);
 	debugfs_remove(sc->debug.debugfs_phydir);
 }
 
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index ddd5b3a..c7a0769 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -77,6 +77,7 @@ struct ath5k_dbg_info {
 	struct dentry		*debugfs_antenna;
 	struct dentry		*debugfs_frameerrors;
 	struct dentry		*debugfs_ani;
+	struct dentry		*debugfs_queue;
 };
 
 /**


^ permalink raw reply related

* Re: [PATCH 1/3] cfg80211: Add nl80211 antenna configuration
From: Johannes Berg @ 2010-05-12  8:29 UTC (permalink / raw)
  To: Bruno Randolf; +Cc: linville, linux-wireless, holgerschurig
In-Reply-To: <20100512082325.26565.46809.stgit@tt-desk>

On Wed, 2010-05-12 at 17:23 +0900, Bruno Randolf wrote:

> +	CMD(get_antenna, GET_ANTENNA);

I'm wondering ... does get_antenna really make sense as a separate
command? Seems like we could just as well report it as part of the wiphy
information dump?

johannes


^ permalink raw reply

* [PATCH 3/3] iw: Add antenna set/get
From: Bruno Randolf @ 2010-05-12  8:27 UTC (permalink / raw)
  To: johannes, linville; +Cc: linux-wireless, holgerschurig
In-Reply-To: <20100512082516.26746.19520.stgit@tt-desk>

Add commands to set and get the antenna configuration. The antenna
configuration is defined as a bitmap of 8 antennas. When multiple antennas are
selected the driver may use diversity. Also the driver may reject antenna
configurations it cannot support.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 Makefile  |    2 +
 antenna.c |   88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 util.c    |    2 +
 3 files changed, 91 insertions(+), 1 deletions(-)
 create mode 100644 antenna.c

diff --git a/Makefile b/Makefile
index d303f45..e526cda 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing
 OBJS = iw.o genl.o event.o info.o phy.o \
 	interface.o ibss.o station.o survey.o util.o \
 	mesh.o mpath.o scan.o reg.o version.o \
-	reason.o status.o connect.o link.o offch.o ps.o cqm.o
+	reason.o status.o connect.o link.o offch.o ps.o cqm.o antenna.o
 OBJS += sections.o
 ALL = iw
 
diff --git a/antenna.c b/antenna.c
new file mode 100644
index 0000000..5869aa6
--- /dev/null
+++ b/antenna.c
@@ -0,0 +1,88 @@
+#include <net/if.h>
+#include <errno.h>
+#include <string.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+#include "nl80211.h"
+#include "iw.h"
+
+SECTION(antenna);
+
+static int set_antenna(struct nl80211_state *state,
+			struct nl_cb *cb,
+			struct nl_msg *msg,
+			int argc, char **argv)
+{
+	char *end;
+	uint8_t tx_ant = 0, rx_ant = 0;
+
+	if (argc == 1)
+		tx_ant = rx_ant = strtoul(argv[0], &end, 10);
+	else if (argc == 4)
+	{
+		while (argc) {
+			if (strcmp(*argv, "tx") == 0 ||
+			    strcmp(*argv, "rx") == 0) {
+				if (strcmp(*argv, "tx") == 0)
+					tx_ant = strtoul(argv[1], &end, 10);
+				else
+					rx_ant = strtoul(argv[1], &end, 10);
+				argv = argv + 2;
+				argc = argc - 2;
+			}
+		}
+	}
+
+	if (*end || !tx_ant || !rx_ant)
+		return 1;
+
+	NLA_PUT_U8(msg, NL80211_ATTR_ANTENNA_TX, tx_ant);
+	NLA_PUT_U8(msg, NL80211_ATTR_ANTENNA_RX, rx_ant);
+	return 0;
+
+ nla_put_failure:
+	return -ENOBUFS;
+}
+
+COMMAND(antenna, set, "<bitmap> | tx <bitmap> rx <bitmap>",
+	NL80211_CMD_SET_ANTENNA, 0, CIB_PHY, set_antenna,
+	"Set a bitmap of allowed antennas to use for TX and RX.\n"
+	"The driver may reject antenna configurations it cannot support.");
+
+
+static int print_antenna_handler(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *attrs[NL80211_ATTR_MAX + 1];
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	uint8_t tx_ant, rx_ant;
+
+	nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (!attrs[NL80211_ATTR_ANTENNA_TX] || !attrs[NL80211_ATTR_ANTENNA_RX])
+		return NL_SKIP;
+
+	tx_ant = nla_get_u8(attrs[NL80211_ATTR_ANTENNA_TX]);
+	rx_ant = nla_get_u8(attrs[NL80211_ATTR_ANTENNA_RX]);
+
+	printf("Antenna configuration: tx %d rx %d\n", tx_ant, rx_ant);
+
+	return NL_SKIP;
+}
+
+static int get_antenna(struct nl80211_state *state,
+			struct nl_cb *cb,
+			struct nl_msg *msg,
+			int argc, char **argv)
+{
+	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_antenna_handler, NULL);
+	return 0;
+}
+
+COMMAND(antenna, get, NULL, NL80211_CMD_GET_ANTENNA, 0, CIB_PHY, get_antenna,
+	"Retrieve antenna configuration.");
diff --git a/util.c b/util.c
index 0c6d978..7d971ac 100644
--- a/util.c
+++ b/util.c
@@ -166,6 +166,8 @@ static const char *commands[NL80211_CMD_MAX + 1] = {
 	[NL80211_CMD_REGISTER_ACTION] = "register_action",
 	[NL80211_CMD_ACTION] = "action",
 	[NL80211_CMD_SET_CHANNEL] = "set_channel",
+	[NL80211_CMD_SET_ANTENNA] = "antenna_set",
+	[NL80211_CMD_GET_ANTENNA] = "antenna_get",
 };
 
 static char cmdbuf[100];


^ permalink raw reply related

* [PATCH 2/3] iw: sync nl80211.h with wireless-testing
From: Bruno Randolf @ 2010-05-12  8:27 UTC (permalink / raw)
  To: johannes, linville; +Cc: linux-wireless, holgerschurig
In-Reply-To: <20100512082516.26746.19520.stgit@tt-desk>

adding antenna settings

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 nl80211.h |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/nl80211.h b/nl80211.h
index b7c77f9..46a2c76 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -341,6 +341,9 @@
  *	of any other interfaces, and other interfaces will again take
  *	precedence when they are used.
  *
+ * @NL80211_CMD_SET_ANTENNA: Set a bitmap of antennas to use.
+ * @NL80211_CMD_GET_ANTENNA: Get antenna configuration from driver.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -441,6 +444,9 @@ enum nl80211_commands {
 
 	NL80211_CMD_SET_CHANNEL,
 
+	NL80211_CMD_SET_ANTENNA,
+	NL80211_CMD_GET_ANTENNA,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -725,6 +731,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations
  *	connected to this BSS.
  *
+ * @NL80211_ATTR_ANTENNA_TX: Bitmap of antennas to use for transmitting.
+ * @NL80211_ATTR_ANTENNA_RX: Bitmap of antennas to use for receiving.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -882,6 +891,9 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_AP_ISOLATE,
 
+	NL80211_ATTR_ANTENNA_TX,
+	NL80211_ATTR_ANTENNA_RX,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,


^ permalink raw reply related

* [PATCH 1/3] iw: add channel command name
From: Bruno Randolf @ 2010-05-12  8:27 UTC (permalink / raw)
  To: johannes, linville; +Cc: linux-wireless, holgerschurig
In-Reply-To: <20100512082516.26746.19520.stgit@tt-desk>

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 util.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/util.c b/util.c
index 42c992d..0c6d978 100644
--- a/util.c
+++ b/util.c
@@ -165,6 +165,7 @@ static const char *commands[NL80211_CMD_MAX + 1] = {
 	[NL80211_CMD_SET_TX_BITRATE_MASK] = "set_tx_bitrate_mask",
 	[NL80211_CMD_REGISTER_ACTION] = "register_action",
 	[NL80211_CMD_ACTION] = "action",
+	[NL80211_CMD_SET_CHANNEL] = "set_channel",
 };
 
 static char cmdbuf[100];


^ permalink raw reply related

* [PATCH 0/3] iw antenna command
From: Bruno Randolf @ 2010-05-12  8:27 UTC (permalink / raw)
  To: johannes, linville; +Cc: linux-wireless, holgerschurig

here the iw part. the option parsing is more flexible now and i added a
possibility to use

  iw phy0 anenna set X

to set both RX and TX antennas

+ one small fix for the channel command name

bruno

---

Bruno Randolf (3):
      iw: add channel command name
      iw: sync nl80211.h with wireless-testing
      iw: Add antenna set/get


 Makefile  |    2 +
 antenna.c |   88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 nl80211.h |   12 ++++++++
 util.c    |    3 ++
 4 files changed, 104 insertions(+), 1 deletions(-)
 create mode 100644 antenna.c

-- 
Signature

^ permalink raw reply

* [PATCH 3/3] ath5k: Add support for antenna configuration
From: Bruno Randolf @ 2010-05-12  8:23 UTC (permalink / raw)
  To: johannes, linville; +Cc: linux-wireless, holgerschurig
In-Reply-To: <20100512082231.26565.16730.stgit@tt-desk>

Support setting the antenna configuration via cfg/mac80211. At the moment only
allow the simple pre-defined configurations we already have (fixed antenna A/B
or diversity), but more advanced settings should be possible later.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 drivers/net/wireless/ath/ath5k/base.c |   34 +++++++++++++++++++++++++++++++++
 1 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 053cb36..9f42af7 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -256,6 +256,8 @@ static void ath5k_sw_scan_start(struct ieee80211_hw *hw);
 static void ath5k_sw_scan_complete(struct ieee80211_hw *hw);
 static void ath5k_set_coverage_class(struct ieee80211_hw *hw,
 		u8 coverage_class);
+static int ath5k_set_antenna(struct ieee80211_hw *hw, u8 tx_ant, u8 rx_ant);
+static int ath5k_get_antenna(struct ieee80211_hw *hw, u8 *tx_ant, u8 *rx_ant);
 
 static const struct ieee80211_ops ath5k_hw_ops = {
 	.tx 		= ath5k_tx,
@@ -277,6 +279,8 @@ static const struct ieee80211_ops ath5k_hw_ops = {
 	.sw_scan_start	= ath5k_sw_scan_start,
 	.sw_scan_complete = ath5k_sw_scan_complete,
 	.set_coverage_class = ath5k_set_coverage_class,
+	.set_antenna	= ath5k_set_antenna,
+	.get_antenna	= ath5k_get_antenna,
 };
 
 /*
@@ -3482,3 +3486,33 @@ static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 	ath5k_hw_set_coverage_class(sc->ah, coverage_class);
 	mutex_unlock(&sc->lock);
 }
+
+static int ath5k_set_antenna(struct ieee80211_hw *hw, u8 tx_ant, u8 rx_ant)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	if (tx_ant == 1 && rx_ant == 1)
+		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
+	else if (tx_ant == 2 && rx_ant == 2)
+		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
+	else if (tx_ant == 3 && rx_ant == 3)
+		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
+	else
+		return -EINVAL;
+	return 0;
+}
+
+static int ath5k_get_antenna(struct ieee80211_hw *hw, u8 *tx_ant, u8 *rx_ant)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	switch (sc->ah->ah_ant_mode) {
+	case AR5K_ANTMODE_FIXED_A:
+		*tx_ant = 1; *rx_ant = 1; break;
+	case AR5K_ANTMODE_FIXED_B:
+		*tx_ant = 2; *rx_ant = 2; break;
+	case AR5K_ANTMODE_DEFAULT:
+		*tx_ant = 3; *rx_ant = 3; break;
+	}
+	return 0;
+}


^ permalink raw reply related

* [PATCH 2/3] mac80211: Add antenna configuration
From: Bruno Randolf @ 2010-05-12  8:23 UTC (permalink / raw)
  To: johannes, linville; +Cc: linux-wireless, holgerschurig
In-Reply-To: <20100512082231.26565.16730.stgit@tt-desk>

Allow antenna configuration by calling driver's function for it.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 include/net/mac80211.h      |    2 ++
 net/mac80211/cfg.c          |   16 ++++++++++++++
 net/mac80211/driver-ops.h   |   23 ++++++++++++++++++++
 net/mac80211/driver-trace.h |   50 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 9448a5b..1a8f97a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1694,6 +1694,8 @@ struct ieee80211_ops {
 	int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
 #endif
 	void (*flush)(struct ieee80211_hw *hw, bool drop);
+	int (*set_antenna)(struct ieee80211_hw *hw, u8 tx_ant, u8 rx_ant);
+	int (*get_antenna)(struct ieee80211_hw *hw, u8 *tx_ant, u8 *rx_ant);
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index c7000a6..efd04bc 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1560,6 +1560,20 @@ static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev,
 				    channel_type, buf, len, cookie);
 }
 
+static int ieee80211_set_antenna(struct wiphy *wiphy, u8 tx_ant, u8 rx_ant)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	return drv_set_antenna(local, tx_ant, rx_ant);
+}
+
+static int ieee80211_get_antenna(struct wiphy *wiphy, u8 *tx_ant, u8 *rx_ant)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	return drv_get_antenna(local, tx_ant, rx_ant);
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -1611,4 +1625,6 @@ struct cfg80211_ops mac80211_config_ops = {
 	.cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
 	.action = ieee80211_action,
 	.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
+	.set_antenna = ieee80211_set_antenna,
+	.get_antenna = ieee80211_get_antenna,
 };
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 997008e..f1b031a 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -373,4 +373,27 @@ static inline void drv_flush(struct ieee80211_local *local, bool drop)
 	if (local->ops->flush)
 		local->ops->flush(&local->hw, drop);
 }
+
+static inline int drv_set_antenna(struct ieee80211_local *local,
+				  u8 tx_ant, u8 rx_ant)
+{
+	int ret = -EOPNOTSUPP;
+	might_sleep();
+	if (local->ops->set_antenna)
+		ret = local->ops->set_antenna(&local->hw, tx_ant, rx_ant);
+	trace_drv_set_antenna(local, tx_ant, rx_ant, ret);
+	return ret;
+}
+
+static inline int drv_get_antenna(struct ieee80211_local *local,
+				  u8 *tx_ant, u8 *rx_ant)
+{
+	int ret = -EOPNOTSUPP;
+	might_sleep();
+	if (local->ops->get_antenna)
+		ret = local->ops->get_antenna(&local->hw, tx_ant, rx_ant);
+	trace_drv_get_antenna(local, *tx_ant, *rx_ant, ret);
+	return ret;
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index ce734b5..466a509 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -774,6 +774,56 @@ TRACE_EVENT(drv_flush,
 	)
 );
 
+TRACE_EVENT(drv_set_antenna,
+	TP_PROTO(struct ieee80211_local *local, u8 tx_ant, u8 rx_ant, int ret),
+
+	TP_ARGS(local, tx_ant, rx_ant, ret),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		__field(u8, tx_ant)
+		__field(u8, rx_ant)
+		__field(int, ret)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		__entry->tx_ant = tx_ant;
+		__entry->rx_ant = rx_ant;
+		__entry->ret = ret;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT " tx_ant:%d rx_ant:%d ret:%d",
+		LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->ret
+	)
+);
+
+TRACE_EVENT(drv_get_antenna,
+	TP_PROTO(struct ieee80211_local *local, u8 tx_ant, u8 rx_ant, int ret),
+
+	TP_ARGS(local, tx_ant, rx_ant, ret),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		__field(u8, tx_ant)
+		__field(u8, rx_ant)
+		__field(int, ret)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		__entry->tx_ant = tx_ant;
+		__entry->rx_ant = rx_ant;
+		__entry->ret = ret;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT " tx_ant:%d rx_ant:%d ret:%d",
+		LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->ret
+	)
+);
+
 /*
  * Tracing for API calls that drivers call.
  */


^ permalink raw reply related

* [PATCH 1/3] cfg80211: Add nl80211 antenna configuration
From: Bruno Randolf @ 2010-05-12  8:23 UTC (permalink / raw)
  To: johannes, linville; +Cc: linux-wireless, holgerschurig
In-Reply-To: <20100512082231.26565.16730.stgit@tt-desk>

Allow setting TX and RX antenna configuration via nl80211/cfg80211.

The antenna configuration is defined as a bitmap of allowed antennas. This
bitmap is 8 bit at the moment, each bit representing one antenna. If multiple
antennas are selected, the driver may use diversity for receive and transmit.
This allows for a simple, yet flexible configuration interface for antennas,
while drivers may reject configurations they cannot support.

Signed-off-by: Bruno Randolf <br1@einfach.org>
---
 include/linux/nl80211.h |   12 +++++
 include/net/cfg80211.h  |    3 +
 net/wireless/nl80211.c  |  116 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 131 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index b7c77f9..46a2c76 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -341,6 +341,9 @@
  *	of any other interfaces, and other interfaces will again take
  *	precedence when they are used.
  *
+ * @NL80211_CMD_SET_ANTENNA: Set a bitmap of antennas to use.
+ * @NL80211_CMD_GET_ANTENNA: Get antenna configuration from driver.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -441,6 +444,9 @@ enum nl80211_commands {
 
 	NL80211_CMD_SET_CHANNEL,
 
+	NL80211_CMD_SET_ANTENNA,
+	NL80211_CMD_GET_ANTENNA,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -725,6 +731,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations
  *	connected to this BSS.
  *
+ * @NL80211_ATTR_ANTENNA_TX: Bitmap of antennas to use for transmitting.
+ * @NL80211_ATTR_ANTENNA_RX: Bitmap of antennas to use for receiving.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -882,6 +891,9 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_AP_ISOLATE,
 
+	NL80211_ATTR_ANTENNA_TX,
+	NL80211_ATTR_ANTENNA_RX,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b44a2e5..8861f40 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1176,6 +1176,9 @@ struct cfg80211_ops {
 	int	(*set_cqm_rssi_config)(struct wiphy *wiphy,
 				       struct net_device *dev,
 				       s32 rssi_thold, u32 rssi_hyst);
+
+	int	(*set_antenna)(struct wiphy *wiphy, u8 tx_ant, u8 rx_ant);
+	int	(*get_antenna)(struct wiphy *wiphy, u8 *tx_ant, u8 *rx_ant);
 };
 
 /*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index aaa1aad..29998e0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -153,6 +153,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
 	[NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
 	[NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
+	[NL80211_ATTR_ANTENNA_TX] = { .type = NLA_U8 },
+	[NL80211_ATTR_ANTENNA_RX] = { .type = NLA_U8 },
 };
 
 /* policy for the attributes */
@@ -590,6 +592,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 		NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
 	}
 	CMD(set_channel, SET_CHANNEL);
+	CMD(set_antenna, SET_ANTENNA);
+	CMD(get_antenna, GET_ANTENNA);
 
 #undef CMD
 
@@ -4963,6 +4967,106 @@ out:
 	return err;
 }
 
+static int nl80211_set_antenna(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev;
+	int res;
+	u8 rx_ant = 0, tx_ant = 0;
+
+	if (!info->attrs[NL80211_ATTR_WIPHY] ||
+	    !info->attrs[NL80211_ATTR_ANTENNA_TX] ||
+	    !info->attrs[NL80211_ATTR_ANTENNA_RX]) {
+		return -EINVAL;
+	}
+
+	tx_ant = nla_get_u8(info->attrs[NL80211_ATTR_ANTENNA_TX]);
+	rx_ant = nla_get_u8(info->attrs[NL80211_ATTR_ANTENNA_RX]);
+
+	rtnl_lock();
+
+	rdev = cfg80211_get_dev_from_info(info);
+	if (IS_ERR(rdev)) {
+		res = -ENODEV;
+		goto unlock_rtnl;
+	}
+
+	if (!rdev->ops->set_antenna) {
+		res = -EOPNOTSUPP;
+		goto unlock_rdev;
+	}
+
+	res = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant);
+
+ unlock_rdev:
+	cfg80211_unlock_rdev(rdev);
+
+ unlock_rtnl:
+	rtnl_unlock();
+	return res;
+}
+
+static int nl80211_get_antenna(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev;
+	struct sk_buff *msg;
+	void *hdr;
+	int res;
+	u8 tx_ant, rx_ant;
+
+	if (!info->attrs[NL80211_ATTR_WIPHY])
+		return -EINVAL;
+
+	rtnl_lock();
+
+	rdev = cfg80211_get_dev_from_info(info);
+	if (IS_ERR(rdev)) {
+		res = -ENODEV;
+		goto unlock_rtnl;
+	}
+
+	if (!rdev->ops->get_antenna) {
+		res = -EOPNOTSUPP;
+		goto unlock_rdev;
+	}
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg) {
+		res = -ENOMEM;
+		goto unlock_rdev;
+	}
+
+	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
+			     NL80211_CMD_GET_ANTENNA);
+	if (!hdr) {
+		res = -ENOMEM;
+		goto free_msg;
+	}
+
+	res = rdev->ops->get_antenna(&rdev->wiphy, &tx_ant, &rx_ant);
+	if (res)
+		goto free_msg;
+
+	NLA_PUT_U8(msg, NL80211_ATTR_ANTENNA_TX, tx_ant);
+	NLA_PUT_U8(msg, NL80211_ATTR_ANTENNA_RX, rx_ant);
+
+	genlmsg_end(msg, hdr);
+	res = genlmsg_reply(msg, info);
+	goto unlock_rdev;
+
+ nla_put_failure:
+	res = -ENOBUFS;
+
+ free_msg:
+	nlmsg_free(msg);
+
+ unlock_rdev:
+	cfg80211_unlock_rdev(rdev);
+
+ unlock_rtnl:
+	rtnl_unlock();
+	return res;
+}
+
 static struct genl_ops nl80211_ops[] = {
 	{
 		.cmd = NL80211_CMD_GET_WIPHY,
@@ -5279,6 +5383,18 @@ static struct genl_ops nl80211_ops[] = {
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
 	},
+	{
+		.cmd = NL80211_CMD_SET_ANTENNA,
+		.doit = nl80211_set_antenna,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = NL80211_CMD_GET_ANTENNA,
+		.doit = nl80211_get_antenna,
+		.policy = nl80211_policy,
+		/* can be retrieved by unprivileged users */
+	},
 };
 
 static struct genl_multicast_group nl80211_mlme_mcgrp = {


^ permalink raw reply related


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