[ath5k-devel] [PATCH 01/13] ath5k: Switch from read-and-clear to write-to-clear method when handling PISR/SISR registers

2011-11-20 Thread Nick Kossifidis
Since card has 12 tx queues and we want to keep track of the interrupts
per queue we can't fit all these interrupt bits on a single register.
So we have 5 registers, the primary interrupt status register (PISR) and
the 4 secondary interupt status registers (SISRs).

In order to be able to read them all at once (atomic operation) Atheros
introduced the Read-And-Clear registers to make things easier. So when
reading RAC_PISR register, hw does a read on PISR and all SISRs, returns
the value of PISR, copies all SISR values to their shadow copies (RAC_SISRx)
and clears PISR and SISRs. This saves us from reading PISR/SISRs in a sequence.

So far we 've used this approach and MadWiFi/Windows driver etc also used it
for years.

It turns out this operation is not atomic after all (at least not on all cards)
That means it's possible to loose some interrupts because they came after the
copy step and hw cleared them on the clean step !

That's probably the reason we got missed beacons, got stuck queues etc and
couldn't figure out what was going on.

With this patch we switch from RaC operation to an alternative method (that
makes more sense IMHO anyway, I just chose to be on the safe side so far).
Instead of reading RAC registers, we read the normal PISR/SISR registers and
clear any bits we got by writing them back on the register. This will clear only
the bits we got on our read step and leave any new bits unaffected (at least
that's what docs say). So if any new interrupts come up we won't miss it.

I've tested this with an AR5213 and an AR2425 and it seems O.K.

Many thanks to Adrian Chadd for debuging this !

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
---
 drivers/net/wireless/ath/ath5k/ath5k.h |8 +-
 drivers/net/wireless/ath/ath5k/base.c  |2 +-
 drivers/net/wireless/ath/ath5k/dma.c   |  206 +++-
 drivers/net/wireless/ath/ath5k/reg.h   |9 +-
 4 files changed, 134 insertions(+), 91 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h 
b/drivers/net/wireless/ath/ath5k/ath5k.h
index fecbcd9..0f42a57 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1187,7 +1187,13 @@ struct ath5k_hw {
u32 ah_txq_imr_cbrurn;
u32 ah_txq_imr_qtrig;
u32 ah_txq_imr_nofrm;
-   u32 ah_txq_isr;
+
+   u32 ah_txq_isr_txok_all;
+   u32 ah_txq_isr_txurn;
+   u32 ah_txq_isr_qcborn;
+   u32 ah_txq_isr_qcburn;
+   u32 ah_txq_isr_qtrig;
+
u32 *ah_rf_banks;
size_t  ah_rf_banks_size;
size_t  ah_rf_regs_count;
diff --git a/drivers/net/wireless/ath/ath5k/base.c 
b/drivers/net/wireless/ath/ath5k/base.c
index b346d04..c18d310 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1689,7 +1689,7 @@ ath5k_tasklet_tx(unsigned long data)
struct ath5k_hw *ah = (void *)data;
 
for (i = 0; i  AR5K_NUM_TX_QUEUES; i++)
-   if (ah-txqs[i].setup  (ah-ah_txq_isr  BIT(i)))
+   if (ah-txqs[i].setup  (ah-ah_txq_isr_txok_all  BIT(i)))
ath5k_tx_processq(ah, ah-txqs[i]);
 
ah-tx_pending = false;
diff --git a/drivers/net/wireless/ath/ath5k/dma.c 
b/drivers/net/wireless/ath/ath5k/dma.c
index 2481f9c..3a14475 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -450,7 +450,6 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int 
queue, u32 phys_addr)
  *
  * XXX: Link this with tx DMA size ?
  * XXX: Use it to save interrupts ?
- * TODO: Needs testing, i think it's related to bmiss...
  */
 int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
 {
@@ -523,62 +522,122 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
  * being mapped on some standard non hw-specific positions
  * (check out ath5k_int).
  *
- * NOTE: We use read-and-clear register, so after this function is called ISR
- * is zeroed.
+ * NOTE: We do write-to-clear, so the active PISR/SISR bits at the time this
+ * function gets called are cleared on return.
  */
 int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
 {
-   u32 data;
+   u32 data = 0;
 
/*
-* Read interrupt status from the Interrupt Status register
-* on 5210
+* Read interrupt status from Primary Interrupt
+* Register.
+*
+* Note: PISR/SISR Not available on 5210
 */
if (ah-ah_version == AR5K_AR5210) {
-   data = ath5k_hw_reg_read(ah, AR5K_ISR);
-   if (unlikely(data == AR5K_INT_NOCARD)) {
-   *interrupt_mask = data;
+   u32 isr = 0;
+   isr = ath5k_hw_reg_read(ah, AR5K_ISR);
+   if 

[ath5k-devel] [PATCH 05/13] ath5k: Calibration re-work

2011-11-20 Thread Nick Kossifidis
Noise floor calibration does not interfere with traffic and should run more
often as part of our short calibration. The full calibration is not the
noise floor calibration but the AGC + Gain_F (on RF5111 and RF5112) calibration
and should run less often because it does interfere with traffic.

So

Short calibration - I/Q  NF Calibration
Long calibration - Short + AGC + Gain_F

This patch was for some time on my pub/ dir on www.kernel.org and has been 
tested
by a few people and me. I think it's O.K. to go in.

I also changed ah_calibration to ah_iq_cal_needed to make more sense.

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
---
 drivers/net/wireless/ath/ath5k/ath5k.h |   12 ++--
 drivers/net/wireless/ath/ath5k/base.c  |  102 +++-
 drivers/net/wireless/ath/ath5k/phy.c   |   81 +++--
 3 files changed, 140 insertions(+), 55 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h 
b/drivers/net/wireless/ath/ath5k/ath5k.h
index b8abdbc..5f9362d 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -187,10 +187,9 @@
 #define AR5K_TUNE_MAX_TXPOWER  63
 #define AR5K_TUNE_DEFAULT_TXPOWER  25
 #define AR5K_TUNE_TPC_TXPOWER  false
-#define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL1   /* 10 sec */
+#define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL6   /* 60 sec */
+#defineATH5K_TUNE_CALIBRATION_INTERVAL_SHORT   1   /* 10 sec */
 #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI1000/* 1 sec */
-#define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 6   /* 60 sec */
-
 #define ATH5K_TX_COMPLETE_POLL_INT 3000/* 3 sec */
 
 #define AR5K_INIT_CARR_SENSE_EN1
@@ -896,7 +895,8 @@ enum ath5k_int {
 enum ath5k_calibration_mask {
AR5K_CALIBRATION_FULL = 0x01,
AR5K_CALIBRATION_SHORT = 0x02,
-   AR5K_CALIBRATION_ANI = 0x04,
+   AR5K_CALIBRATION_NF = 0x04,
+   AR5K_CALIBRATION_ANI = 0x08,
 };
 
 /*
@@ -1145,7 +1145,7 @@ struct ath5k_hw {
enum ath5k_int  ah_imr;
 
struct ieee80211_channel *ah_current_channel;
-   boolah_calibration;
+   boolah_iq_cal_needed;
boolah_single_chip;
 
enum ath5k_version  ah_version;
@@ -1235,8 +1235,8 @@ struct ath5k_hw {
 
/* Calibration timestamp */
unsigned long   ah_cal_next_full;
+   unsigned long   ah_cal_next_short;
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 47194a4..120bba0 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2112,15 +2112,28 @@ static void
 ath5k_intr_calibration_poll(struct ath5k_hw *ah)
 {
if (time_is_before_eq_jiffies(ah-ah_cal_next_ani) 
-   !(ah-ah_cal_mask  AR5K_CALIBRATION_FULL)) {
-   /* run ANI only when full calibration is not active */
+  !(ah-ah_cal_mask  AR5K_CALIBRATION_FULL) 
+  !(ah-ah_cal_mask  AR5K_CALIBRATION_SHORT)) {
+
+   /* Run ANI only when calibration is not active */
+
ah-ah_cal_next_ani = jiffies +
msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI);
tasklet_schedule(ah-ani_tasklet);
 
-   } else if (time_is_before_eq_jiffies(ah-ah_cal_next_full)) {
-   ah-ah_cal_next_full = jiffies +
-   msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL);
+   } else if (time_is_before_eq_jiffies(ah-ah_cal_next_short) 
+   !(ah-ah_cal_mask  AR5K_CALIBRATION_FULL) 
+   !(ah-ah_cal_mask  AR5K_CALIBRATION_SHORT)) {
+
+   /* Run calibration only when another calibration
+* is not running.
+*
+* Note: This is for both full/short calibration,
+* if it's time for a full one, tasklet will deal
+* with it. */
+
+   ah-ah_cal_next_short = jiffies +
+   msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_SHORT);
tasklet_schedule(ah-calib);
}
/* we could use SWI to generate enough interrupts to meet our
@@ -2290,37 +2303,53 @@ ath5k_tasklet_calibrate(unsigned long data)
 {
struct ath5k_hw *ah = (void *)data;
 
-   /* Only full calibration for now */
-   ah-ah_cal_mask |= AR5K_CALIBRATION_FULL;
+   /* Should we run a full calibration ? */
+   if (time_is_before_eq_jiffies(ah-ah_cal_next_full)) {
+
+   ah-ah_cal_next_full = jiffies +
+   msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL);
+   ah-ah_cal_mask |= AR5K_CALIBRATION_FULL;
+

[ath5k-devel] [PATCH 02/13] ath5k: Maintain PISR snapshot

2011-11-20 Thread Nick Kossifidis
Since we dont read a snapshot of the interrupt
registers it might be possible to get a new interrupt
while reading them. In this case we should make sure
that we clear all SISR bits we get from PISR.

Tested on an AR2425

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
---
 drivers/net/wireless/ath/ath5k/dma.c |   49 -
 drivers/net/wireless/ath/ath5k/reg.h |   12 +++-
 2 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/dma.c 
b/drivers/net/wireless/ath/ath5k/dma.c
index 3a14475..6a7b907 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -578,16 +578,59 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int 
*interrupt_mask)
return -ENODEV;
}
 
+   /* Sanity checks:
+* Since we read these registers sequentialy
+* we might get a new interrupt while reading
+* e.g. SISR0 that we didn't catch when reading
+* PISR. So since we are going to handle it on
+* this run of get_isr, we need to clear it
+* from PISR also (PISR contains the logical OR of
+* various interrupt bits from SISRs -see reg.h).
+*
+* NOTE: We could check if PISR is inconsistent
+* with SISRs but it 'll take more time for no
+* reason. If e.g. a TXOK bit is set on SISR0
+* it 'll also get set on PISR by hw anyway. */
+
sisr0 = ath5k_hw_reg_read(ah, AR5K_SISR0);
+   if (sisr0  AR5K_SISR0_QCU_TXOK)
+   pisr |= AR5K_ISR_TXOK;
+   if (sisr0  AR5K_SISR0_QCU_TXDESC)
+   pisr |= AR5K_ISR_TXDESC;
+
sisr1 = ath5k_hw_reg_read(ah, AR5K_SISR1);
+   if (sisr1  AR5K_SISR1_QCU_TXERR)
+   pisr |= AR5K_ISR_TXERR;
+   if (sisr1  AR5K_SISR1_QCU_TXEOL)
+   pisr |= AR5K_ISR_TXEOL;
+
sisr2 = ath5k_hw_reg_read(ah, AR5K_SISR2);
+   if (sisr2  AR5K_SISR2_QCU_TXURN)
+   pisr |= AR5K_ISR_TXURN;
+   if (sisr2  (AR5K_SISR2_MCABT | AR5K_SISR2_SSERR
+   | AR5K_SISR2_DPERR))
+   pisr |= AR5K_ISR_HIUERR;
+   if (sisr2  (AR5K_SISR2_TIM | AR5K_SISR2_CAB_END
+   | AR5K_SISR2_DTIM_SYNC | AR5K_SISR2_BCN_TIMEOUT
+   | AR5K_SISR2_CAB_TIMEOUT | AR5K_SISR2_DTIM))
+   pisr |= AR5K_ISR_BCNMISC;
+   /* XXX: How about TSFOOR ? Docs say nothing about
+* it being bart of BCNMISC, it doesn't make sense ! */
+
sisr3 = ath5k_hw_reg_read(ah, AR5K_SISR3);
-   sisr4 = ath5k_hw_reg_read(ah, AR5K_SISR4);
+   if (sisr3  AR5K_SISR3_QCBRORN)
+   pisr |= AR5K_ISR_QCBRORN;
+   if (sisr3  AR5K_SISR3_QCBRURN)
+   pisr |= AR5K_ISR_QCBRURN;
 
+   sisr4 = ath5k_hw_reg_read(ah, AR5K_SISR4);
+   if (sisr4  AR5K_SISR4_QTRIG)
+   pisr |= AR5K_ISR_QTRIG;
 
/*
 * Write to clear them...
-* Note: This means that each bit we write back
+*
+* NOTE: This means that each bit we write back
 * to the registers will get cleared, leaving the
 * rest unaffected. So this won't affect new interrupts
 * we didn't catch while reading/processing, we 'll get
@@ -634,9 +677,11 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int 
*interrupt_mask)
AR5K_SISR2_QCU_TXURN);
 
/* Misc Beacon related interrupts */
+   /* This one is for 5211 */
if (pisr  AR5K_ISR_TIM)
*interrupt_mask |= AR5K_INT_TIM;
 
+   /* For 5212+ */
if (pisr  AR5K_ISR_BCNMISC) {
if (sisr2  AR5K_SISR2_TIM)
*interrupt_mask |= AR5K_INT_TIM;
diff --git a/drivers/net/wireless/ath/ath5k/reg.h 
b/drivers/net/wireless/ath/ath5k/reg.h
index 688d509..99bbfb4 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -280,6 +280,10 @@
  * 5211/5212 we have one primary and 4 secondary registers.
  * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212.
  * Most of these bits are common for all chipsets.
+ *
+ * NOTE: On 5211+ TXOK, TXDESC, TXERR, TXEOL and TXURN contain
+ * the logical OR from per-queue interrupt bits found on SISR registers
+ * (see below).
  */
 #define AR5K_ISR   0x001c  /* Register Address 
[5210] */
 #define AR5K_PISR  0x0080  /* Register Address 
[5211+] */
@@ -292,7 +296,10 @@
 #define 

[ath5k-devel] [PATCH 13/13] ath5k: Optimize ath5k_cw_validate

2011-11-20 Thread Nick Kossifidis
Optimize ath5k_cw_validate by using the classic (X  (X - 1)) == 0
check to see if a number is power of 2.

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
---
 drivers/net/wireless/ath/ath5k/qcu.c |   10 ++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/qcu.c 
b/drivers/net/wireless/ath/ath5k/qcu.c
index e50e64d..cdbaad7 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -111,6 +111,16 @@ ath5k_cw_validate(u16 cw_req)
u32 cw = 1;
cw_req = min(cw_req, (u16)1023);
 
+   /* Check if cw_req + 1 a power of 2 */
+   if (!((cw_req + 1)  cw_req))
+   return cw_req;
+
+   /* Check if cw_req is a power of 2 */
+   if (!(cw_req  (cw_req - 1)))
+   return cw_req - 1;
+
+   /* If none of the above is correct
+* find the closest power of 2 */
while (cw  cw_req)
cw = (cw  1) | 1;
 
-- 
1.7.8.rc1

___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


[ath5k-devel] [PATCH 09/13] ath5k: Add a module parameter to disable hw rf kill switch

2011-11-20 Thread Nick Kossifidis
Add a module parameter to disable hw rf kill switch (GPIO interrupt) because
in some cases when the card doesn't come with the laptop, EEPROM configuration
doesn't match laptop's configuration and rf kill interrupt always fires up and
disables hw. I thought of moving this to debugfs and make it per-card but
this way it's easier for users and distros to handle.

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
Tested-by: Pavel Roskin pro...@.gnu.org
---
 drivers/net/wireless/ath/ath5k/base.c |   11 +--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/base.c 
b/drivers/net/wireless/ath/ath5k/base.c
index 587c6fb..b901721 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -80,6 +80,11 @@ static int modparam_fastchanswitch;
 module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO);
 MODULE_PARM_DESC(fastchanswitch, Enable fast channel switching for 
AR2413/AR5413 radios.);
 
+static int ath5k_modparam_no_hw_rfkill_switch;
+module_param_named(no_hw_rfkill_switch, ath5k_modparam_no_hw_rfkill_switch,
+   bool, S_IRUGO);
+MODULE_PARM_DESC(no_hw_rfkill_switch, Ignore the GPIO RFKill switch state);
+
 
 /* Module info */
 MODULE_AUTHOR(Jiri Slaby);
@@ -2634,7 +2639,8 @@ int ath5k_start(struct ieee80211_hw *hw)
if (ret)
goto done;
 
-   ath5k_rfkill_hw_start(ah);
+   if (!ath5k_modparam_no_hw_rfkill_switch)
+   ath5k_rfkill_hw_start(ah);
 
/*
 * Reset the key cache since some parts do not reset the
@@ -2719,7 +2725,8 @@ void ath5k_stop(struct ieee80211_hw *hw)
 
cancel_delayed_work_sync(ah-tx_complete_work);
 
-   ath5k_rfkill_hw_stop(ah);
+   if (!ath5k_modparam_no_hw_rfkill_switch)
+   ath5k_rfkill_hw_stop(ah);
 }
 
 /*
-- 
1.7.8.rc1

___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


[ath5k-devel] [PATCH 12/13] ath5k: Renumber hw queue ids

2011-11-20 Thread Nick Kossifidis
According to documentation higher DCUs have higher priority and should
be used for beacons and CAB traffic. More specifically DCU 9 should be
used for beacons and DCU 8 for CAB traffic, I assumed DCU 7 should be
OK for UAPSD traffic.

Note that DCU 8 and 9 are special because they can only be mapped to a single
QCU each but since we use a 1:1 mapping between QCUs and DCUs anyway we don't
have to change much.

P.S. I also did a few related cleanups on qcu.c and ath5k.h

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
---
 drivers/net/wireless/ath/ath5k/ath5k.h |   10 --
 drivers/net/wireless/ath/ath5k/qcu.c   |   14 +++---
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h 
b/drivers/net/wireless/ath/ath5k/ath5k.h
index 304cc92..892aaa1 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -571,20 +571,18 @@ enum ath5k_tx_queue_subtype {
  * @AR5K_TX_QUEUE_ID_CAB: Content after beacon queue
  * @AR5K_TX_QUEUE_ID_BEACON: Beacon queue
  * @AR5K_TX_QUEUE_ID_UAPSD: Urgent Automatic Power Save Delivery,
- * @AR5K_TX_QUEUE_ID_XR_DATA: XR Data queue
  *
  * Each number represents a hw queue. If hw does not support hw queues
- * (eg 5210) all data goes in one queue. These match
- * mac80211 definitions.
+ * (eg 5210) all data goes in one queue.
  */
 enum ath5k_tx_queue_id {
AR5K_TX_QUEUE_ID_NOQCU_DATA = 0,
AR5K_TX_QUEUE_ID_NOQCU_BEACON   = 1,
AR5K_TX_QUEUE_ID_DATA_MIN   = 0,
AR5K_TX_QUEUE_ID_DATA_MAX   = 3,
-   AR5K_TX_QUEUE_ID_CAB= 6,
-   AR5K_TX_QUEUE_ID_BEACON = 7,
-   AR5K_TX_QUEUE_ID_UAPSD  = 8,
+   AR5K_TX_QUEUE_ID_UAPSD  = 7,
+   AR5K_TX_QUEUE_ID_CAB= 8,
+   AR5K_TX_QUEUE_ID_BEACON = 9,
 };
 
 /*
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c 
b/drivers/net/wireless/ath/ath5k/qcu.c
index 31924c3..e50e64d 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -54,7 +54,7 @@ Queue Control Unit, DCF Control Unit Functions
 /**
  * ath5k_hw_num_tx_pending() - Get number of pending frames for a  given queue
  * @ah: The struct ath5k_hw
- * @queue: The hw queue number
+ * @queue: One of enum ath5k_tx_queue_id
  */
 u32
 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
@@ -85,7 +85,7 @@ ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int 
queue)
 /**
  * ath5k_hw_release_tx_queue() - Set a transmit queue inactive
  * @ah: The struct ath5k_hw
- * @queue: The hw queue number
+ * @queue: One of enum ath5k_tx_queue_id
  */
 void
 ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
@@ -120,7 +120,7 @@ ath5k_cw_validate(u16 cw_req)
 /**
  * ath5k_hw_get_tx_queueprops() - Get properties for a transmit queue
  * @ah: The struct ath5k_hw
- * @queue: The hw queue number
+ * @queue: One of enum ath5k_tx_queue_id
  * @queue_info: The struct ath5k_txq_info to fill
  */
 int
@@ -134,7 +134,7 @@ ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
 /**
  * ath5k_hw_set_tx_queueprops() - Set properties for a transmit queue
  * @ah: The struct ath5k_hw
- * @queue: The hw queue number
+ * @queue: One of enum ath5k_tx_queue_id
  * @qinfo: The struct ath5k_txq_info to use
  *
  * Returns 0 on success or -EIO if queue is inactive
@@ -267,7 +267,7 @@ ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum 
ath5k_tx_queue queue_type,
 /**
  * ath5k_hw_set_tx_retry_limits() - Set tx retry limits on DCU
  * @ah: The struct ath5k_hw
- * @queue: The hw queue number
+ * @queue: One of enum ath5k_tx_queue_id
  *
  * This function is used when initializing a queue, to set
  * retry limits based on ah-ah_retry_* and the chipset used.
@@ -310,9 +310,9 @@ ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
 /**
  * ath5k_hw_reset_tx_queue() - Initialize a single hw queue
  * @ah: The struct ath5k_hw
- * @queue: The hw queue number
+ * @queue: One of enum ath5k_tx_queue_id
  *
- * Set DFS properties for the given transmit queue on DCU
+ * Set DCF properties for the given transmit queue on DCU
  * and configures all queue-specific parameters.
  */
 int
-- 
1.7.8.rc1

___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


[ath5k-devel] [PATCH 06/13] ath5k: Use usleep_range where possible

2011-11-20 Thread Nick Kossifidis
Use usleep_range where possible to reduce busy waits

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
---
 drivers/net/wireless/ath/ath5k/attach.c |2 +-
 drivers/net/wireless/ath/ath5k/pci.c|2 +-
 drivers/net/wireless/ath/ath5k/phy.c|   22 +++---
 drivers/net/wireless/ath/ath5k/reset.c  |   14 +++---
 4 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/attach.c 
b/drivers/net/wireless/ath/ath5k/attach.c
index 91627dd..49fdc93 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -298,7 +298,7 @@ int ath5k_hw_init(struct ath5k_hw *ah)
 
/* Reset SERDES to load new settings */
ath5k_hw_reg_write(ah, 0x, AR5K_PCIE_SERDES_RESET);
-   mdelay(1);
+   usleep_range(1000, 1500);
}
 
/* Get misc capabilities */
diff --git a/drivers/net/wireless/ath/ath5k/pci.c 
b/drivers/net/wireless/ath/ath5k/pci.c
index c1dff2c..7fdae9b 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -97,7 +97,7 @@ ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, 
u16 *data)
0x);
return true;
}
-   udelay(15);
+   usleep_range(15, 20);
}
 
return false;
diff --git a/drivers/net/wireless/ath/ath5k/phy.c 
b/drivers/net/wireless/ath/ath5k/phy.c
index addf775..25fc268 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -58,7 +58,7 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum 
ieee80211_band band)
return 0;
}
 
-   mdelay(2);
+   usleep_range(2000, 2500);
 
/* ...wait until PHY is ready and read the selected radio revision */
ath5k_hw_reg_write(ah, 0x1c16, AR5K_PHY(0x34));
@@ -308,9 +308,9 @@ static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah,
delay = delay  2;
/* XXX: /2 on turbo ? Let's be safe
 * for now */
-   udelay(100 + delay);
+   usleep_range(100 + delay, 100 + (2 * delay));
} else {
-   mdelay(1);
+   usleep_range(1000, 1500);
}
 }
 
@@ -1083,7 +1083,7 @@ static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah,
data = ath5k_hw_rf5110_chan2athchan(channel);
ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER);
ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0);
-   mdelay(1);
+   usleep_range(1000, 1500);
 
return 0;
 }
@@ -1454,7 +1454,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
ath5k_hw_reg_write(ah, beacon  ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
 
-   mdelay(2);
+   usleep_range(2000, 2500);
 
/*
 * Set the channel (with AGC turned off)
@@ -1467,7 +1467,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
 * Activate PHY and wait
 */
ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
-   mdelay(1);
+   usleep_range(1000, 1500);
 
AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
 
@@ -1504,7 +1504,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG);
AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
 
-   mdelay(1);
+   usleep_range(1000, 1500);
 
/*
 * Enable calibration and wait until completion
@@ -3396,7 +3396,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct 
ieee80211_channel *channel,
if (ret)
return ret;
 
-   mdelay(1);
+   usleep_range(1000, 1500);
 
/*
 * Write RF buffer
@@ -3417,10 +3417,10 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct 
ieee80211_channel *channel,
}
 
} else if (ah-ah_version == AR5K_AR5210) {
-   mdelay(1);
+   usleep_range(1000, 1500);
/* Disable phy and wait */
ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
-   mdelay(1);
+   usleep_range(1000, 1500);
}
 
/* Set channel on PHY */
@@ -3446,7 +3446,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct 
ieee80211_channel *channel,
for (i = 0; i = 20; i++) {
if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST)  0x10))
break;
-   udelay(200);
+   usleep_range(200, 250);
}
ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
 
diff --git a/drivers/net/wireless/ath/ath5k/reset.c 
b/drivers/net/wireless/ath/ath5k/reset.c
index 2abac25..de28be4 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ 

[ath5k-devel] [PATCH 04/13] ath5k: Cleanups v1

2011-11-20 Thread Nick Kossifidis
No functional changes, just a few comments/documentation/cleanup

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
---
 drivers/net/wireless/ath/ath5k/base.c |  112 -
 drivers/net/wireless/ath/ath5k/dma.c  |   17 -
 2 files changed, 96 insertions(+), 33 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/base.c 
b/drivers/net/wireless/ath/ath5k/base.c
index c18d310..47194a4 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2149,69 +2149,110 @@ ath5k_intr(int irq, void *dev_id)
enum ath5k_int status;
unsigned int counter = 1000;
 
+
+   /*
+* If hw is not ready (or detached) and we get an
+* interrupt, or if we have no interrupts pending
+* (that means it's not for us) skip it.
+*
+* NOTE: Group 0/1 PCI interface registers are not
+* supported on WiSOCs, so we can't check for pending
+* interrupts (ISR belongs to another register group
+* so we are ok).
+*/
if (unlikely(test_bit(ATH_STAT_INVALID, ah-status) ||
-   ((ath5k_get_bus_type(ah) != ATH_AHB) 
-   !ath5k_hw_is_intr_pending(ah
+   ((ath5k_get_bus_type(ah) != ATH_AHB) 
+   !ath5k_hw_is_intr_pending(ah
return IRQ_NONE;
 
+   /** Main loop **/
do {
-   ath5k_hw_get_isr(ah, status);  /* NB: clears IRQ too */
+   ath5k_hw_get_isr(ah, status);  /* NB: clears IRQ too */
+
ATH5K_DBG(ah, ATH5K_DEBUG_INTR, status 0x%x/0x%x\n,
status, ah-imask);
+
+   /*
+* Fatal hw error - Log and reset
+*
+* Fatal errors are unrecoverable so we have to
+* reset the card. These errors include bus and
+* dma errors.
+*/
if (unlikely(status  AR5K_INT_FATAL)) {
-   /*
-* Fatal errors are unrecoverable.
-* Typically these are caused by DMA errors.
-*/
+
ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
  fatal int, resetting\n);
ieee80211_queue_work(ah-hw, ah-reset_work);
+
+   /*
+* RX Overrun - Count and reset if needed
+*
+* Receive buffers are full. Either the bus is busy or
+* the CPU is not fast enough to process all received
+* frames.
+*/
} else if (unlikely(status  AR5K_INT_RXORN)) {
+
/*
-* Receive buffers are full. Either the bus is busy or
-* the CPU is not fast enough to process all received
-* frames.
 * Older chipsets need a reset to come out of this
 * condition, but we treat it as RX for newer chips.
-* We don't know exactly which versions need a reset -
+* We don't know exactly which versions need a reset
 * this guess is copied from the HAL.
 */
ah-stats.rxorn_intr++;
+
if (ah-ah_mac_srev  AR5K_SREV_AR5212) {
ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
  rx overrun, resetting\n);
ieee80211_queue_work(ah-hw, ah-reset_work);
} else
ath5k_schedule_rx(ah);
+
} else {
+
+   /* Software Beacon Alert - Schedule beacon tasklet */
if (status  AR5K_INT_SWBA)
tasklet_hi_schedule(ah-beacontq);
 
-   if (status  AR5K_INT_RXEOL) {
-   /*
-   * NB: the hardware should re-read the link when
-   * RXE bit is written, but it doesn't work at
-   * least on older hardware revs.
-   */
+   /*
+* No more RX descriptors - Just count
+*
+* NB: the hardware should re-read the link when
+* RXE bit is written, but it doesn't work at
+* least on older hardware revs.
+*/
+   if (status  AR5K_INT_RXEOL)
ah-stats.rxeol_intr++;
-   }
-   if (status  AR5K_INT_TXURN) {
-   /* bump tx trigger level */
+
+
+   /* TX Underrun - 

[ath5k-devel] [PATCH 10/13] ath5k: MRR support and 2GHz radio override belong in ah_capabilities

2011-11-20 Thread Nick Kossifidis
MRR support and 2GHz radio override belong in ah_capabilities and we
should use them (e.g. so far  we used to set mrr descriptor without
checking if MRR support is enabled + we checked for MRR support 2
times, one by trying to set up an MRR descriptor and another one based
on MAC version).

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
---
 drivers/net/wireless/ath/ath5k/ahb.c|4 ++-
 drivers/net/wireless/ath/ath5k/ath5k.h  |   12 
 drivers/net/wireless/ath/ath5k/attach.c |5 ---
 drivers/net/wireless/ath/ath5k/base.c   |   47 ---
 drivers/net/wireless/ath/ath5k/caps.c   |   27 +
 5 files changed, 47 insertions(+), 48 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ahb.c 
b/drivers/net/wireless/ath/ath5k/ahb.c
index e5be7e70..ee7ea57 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -166,7 +166,9 @@ static int ath_ahb_probe(struct platform_device *pdev)
if (to_platform_device(ah-dev)-id == 0 
(bcfg-config-flags  (BD_WLAN0 | BD_WLAN1)) ==
 (BD_WLAN1 | BD_WLAN0))
-   __set_bit(ATH_STAT_2G_DISABLED, ah-status);
+   ah-ah_capabilities.cap_needs_2GHz_ovr = true;
+   else
+   ah-ah_capabilities.cap_needs_2GHz_ovr = false;
}
 
ret = ath5k_init_ah(ah, ath_ahb_bus_ops);
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h 
b/drivers/net/wireless/ath/ath5k/ath5k.h
index 743938c..304cc92 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1159,6 +1159,8 @@ struct ath5k_capabilities {
} cap_queues;
 
bool cap_has_phyerr_counters;
+   bool cap_has_mrr_support;
+   bool cap_needs_2GHz_ovr;
 };
 
 /* size of noise floor history (keep it a power of two) */
@@ -1274,13 +1276,11 @@ struct ath5k_hw {
dma_addr_t  desc_daddr; /* DMA (physical) address */
size_t  desc_len;   /* size of TX/RX descriptors */
 
-   DECLARE_BITMAP(status, 6);
+   DECLARE_BITMAP(status, 4);
 #define ATH_STAT_INVALID   0   /* disable hardware accesses */
-#define ATH_STAT_MRRETRY   1   /* multi-rate retry support */
-#define ATH_STAT_PROMISC   2
-#define ATH_STAT_LEDSOFT   3   /* enable LED gpio status */
-#define ATH_STAT_STARTED   4   /* opened  irqs enabled */
-#define ATH_STAT_2G_DISABLED   5   /* multiband radio without 2G */
+#define ATH_STAT_PROMISC   1
+#define ATH_STAT_LEDSOFT   2   /* enable LED gpio status */
+#define ATH_STAT_STARTED   3   /* opened  irqs enabled */
 
unsigned intfilter_flags;   /* HW flags, AR5K_RX_FILTER_* */
struct ieee80211_channel *curchan;  /* current h/w channel */
diff --git a/drivers/net/wireless/ath/ath5k/attach.c 
b/drivers/net/wireless/ath/ath5k/attach.c
index b69e057..d7114c7 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -306,11 +306,6 @@ int ath5k_hw_init(struct ath5k_hw *ah)
goto err;
}
 
-   if (test_bit(ATH_STAT_2G_DISABLED, ah-status)) {
-   __clear_bit(AR5K_MODE_11B, ah-ah_capabilities.cap_mode);
-   __clear_bit(AR5K_MODE_11G, ah-ah_capabilities.cap_mode);
-   }
-
/* Crypto settings */
common-keymax = (ah-ah_version == AR5K_AR5210 ?
  AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
diff --git a/drivers/net/wireless/ath/ath5k/base.c 
b/drivers/net/wireless/ath/ath5k/base.c
index b901721..ef0ffcd 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -725,21 +725,24 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf 
*bf,
if (ret)
goto err_unmap;
 
-   memset(mrr_rate, 0, sizeof(mrr_rate));
-   memset(mrr_tries, 0, sizeof(mrr_tries));
-   for (i = 0; i  3; i++) {
-   rate = ieee80211_get_alt_retry_rate(ah-hw, info, i);
-   if (!rate)
-   break;
+   /* Set up MRR descriptor */
+   if (ah-ah_capabilities.cap_has_mrr_support) {
+   memset(mrr_rate, 0, sizeof(mrr_rate));
+   memset(mrr_tries, 0, sizeof(mrr_tries));
+   for (i = 0; i  3; i++) {
+   rate = ieee80211_get_alt_retry_rate(ah-hw, info, i);
+   if (!rate)
+   break;
 
-   mrr_rate[i] = rate-hw_value;
-   mrr_tries[i] = info-control.rates[i + 1].count;
-   }
+   mrr_rate[i] = rate-hw_value;
+   mrr_tries[i] = info-control.rates[i + 1].count;
+   }
 
-   ath5k_hw_setup_mrr_tx_desc(ah, ds,
-   mrr_rate[0], mrr_tries[0],
-  

[ath5k-devel] [PATCH 11/13] ath5k: ath5k_ani_period_restart only touches struct ath5k_ani_state

2011-11-20 Thread Nick Kossifidis
No need to take ath5k_hw as an argument.

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
---
 drivers/net/wireless/ath/ath5k/ani.c |7 +++
 1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ani.c 
b/drivers/net/wireless/ath/ath5k/ani.c
index 2dfcf1a..bf67416 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -440,13 +440,12 @@ ath5k_ani_save_and_clear_phy_errors(struct ath5k_hw *ah,
 
 /**
  * ath5k_ani_period_restart() - Restart ANI period
- * @ah: The struct ath5k_hw
  * @as: The struct ath5k_ani_state
  *
  * Just reset counters, so they are clear for the next ani period.
  */
 static void
-ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as)
+ath5k_ani_period_restart(struct ath5k_ani_state *as)
 {
/* keep last values for debugging */
as-last_ofdm_errors = as-ofdm_errors;
@@ -502,7 +501,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
/* too many PHY errors - we have to raise immunity */
bool ofdm_flag = as-ofdm_errors  ofdm_high ? true : false;
ath5k_ani_raise_immunity(ah, as, ofdm_flag);
-   ath5k_ani_period_restart(ah, as);
+   ath5k_ani_period_restart(as);
 
} else if (as-listen_time  5 * ATH5K_ANI_LISTEN_PERIOD) {
/* If more than 5 (TODO: why 5?) periods have passed and we got
@@ -514,7 +513,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
if (as-ofdm_errors = ofdm_low  as-cck_errors = cck_low)
ath5k_ani_lower_immunity(ah, as);
 
-   ath5k_ani_period_restart(ah, as);
+   ath5k_ani_period_restart(as);
}
 }
 
-- 
1.7.8.rc1

___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


[ath5k-devel] [PATCH 03/13] ath5k: Add TXNOFRM to INT_TX_ALL

2011-11-20 Thread Nick Kossifidis
Add TXNOFRM to INT_TX_ALL since it's a TX interrupt too.

Signed-off-by: Nick Kossifidis mickfl...@gmail.com

---
 drivers/net/wireless/ath/ath5k/ath5k.h |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h 
b/drivers/net/wireless/ath/ath5k/ath5k.h
index 0f42a57..b8abdbc 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -856,6 +856,7 @@ enum ath5k_int {
AR5K_INT_TX_ALL = AR5K_INT_TXOK
| AR5K_INT_TXDESC
| AR5K_INT_TXERR
+   | AR5K_INT_TXNOFRM
| AR5K_INT_TXEOL
| AR5K_INT_TXURN,
 
-- 
1.7.8.rc1

___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


[ath5k-devel] [PATCH 00/13] ath5k: A few updates + cleanups + kerneldoc

2011-11-20 Thread Nick Kossifidis
This series of patches includes some stability fixes related to interrupt
handling, an updated version of a calibration-related patch I posted some
time ago but never submited here and a new module parameter to disable
GPIO based rfkill switch (we had a few bug reports on that recently).

It also adds kernel doc on all ath5k_hw_* functions and structs (needs
some more work but it should be fine, I reviewed the output, spell-ckecked
it etc) and a few minor fixes and optimizations.

Nick Kossifidis (13):
  ath5k: Switch from read-and-clear to write-to-clear method when handling
  PISR/SISR registers.
  ath5k: Maintain PISR snapshot
  ath5k: Add TXNOFRM to INT_TX_ALL
  ath5k: Cleanups v1
  ath5k: Calibration re-work
  ath5k: Use usleep_range where possible
  ath5k: Cleanups v2 + add kerneldoc on all hw functions
  ath5k: We always do full calibration on AR5210
  ath5k: Add a module parameter to disable hw rf kill switch
  ath5k: MRR support and 2GHz radio override belong in ah_capabilities
  ath5k: ath5k_ani_period_restart only touches struct ath5k_ani_state
  ath5k: Renumber hw queue ids
  ath5k: Optimize ath5k_cw_validate

 drivers/net/wireless/ath/ath5k/ahb.c  |4 +-
 drivers/net/wireless/ath/ath5k/ani.c  |   91 ++--
 drivers/net/wireless/ath/ath5k/ani.h  |   32 +-
 drivers/net/wireless/ath/ath5k/ath5k.h|  566 +--
 drivers/net/wireless/ath/ath5k/attach.c   |   16 +-
 drivers/net/wireless/ath/ath5k/base.c |  277 +++---
 drivers/net/wireless/ath/ath5k/caps.c |   27 +-
 drivers/net/wireless/ath/ath5k/desc.c |  217 ++--
 drivers/net/wireless/ath/ath5k/desc.h |  124 +++--
 drivers/net/wireless/ath/ath5k/dma.c  |  380 -
 drivers/net/wireless/ath/ath5k/gpio.c |   81 +++-
 drivers/net/wireless/ath/ath5k/initvals.c |   75 ++-
 drivers/net/wireless/ath/ath5k/pci.c  |2 +-
 drivers/net/wireless/ath/ath5k/pcu.c  |  222 +---
 drivers/net/wireless/ath/ath5k/phy.c  |  852 +++--
 drivers/net/wireless/ath/ath5k/qcu.c  |  136 --
 drivers/net/wireless/ath/ath5k/reg.h  |   21 +-
 drivers/net/wireless/ath/ath5k/reset.c|  230 ++--
 drivers/net/wireless/ath/ath5k/rfbuffer.h |   59 ++-
 drivers/net/wireless/ath/ath5k/rfgain.h   |   22 +-
 20 files changed, 2457 insertions(+), 977 deletions(-)

-- 
1.7.8.rc1

___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


[ath5k-devel] [PATCH 08/13] ath5k: We always do full calibration on AR5210

2011-11-20 Thread Nick Kossifidis
There is no short calibration on AR5210, make sure we treat it always
as full calibration.

Signed-off-by: Nick Kossifidis mickfl...@gmail.com
---
 drivers/net/wireless/ath/ath5k/phy.c |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/phy.c 
b/drivers/net/wireless/ath/ath5k/phy.c
index 3bb42a4..1a166d7 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1674,6 +1674,9 @@ ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
u32 phy_sig, phy_agc, phy_sat, beacon;
int ret;
 
+   if (!(ah-ah_cal_mask  AR5K_CALIBRATION_FULL))
+   return 0;
+
/*
 * Disable beacons and RX/TX queues, wait
 */
-- 
1.7.8.rc1

___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


Re: [ath5k-devel] [PATCH 06/13] ath5k: Use usleep_range where possible

2011-11-20 Thread Felix Fietkau
On 2011-11-20 8:56 AM, Nick Kossifidis wrote:
 Use usleep_range where possible to reduce busy waits
 
 Signed-off-by: Nick Kossifidis mickfl...@gmail.com
 ---
  drivers/net/wireless/ath/ath5k/attach.c |2 +-
  drivers/net/wireless/ath/ath5k/pci.c|2 +-
  drivers/net/wireless/ath/ath5k/phy.c|   22 +++---
  drivers/net/wireless/ath/ath5k/reset.c  |   14 +++---
  4 files changed, 20 insertions(+), 20 deletions(-)
 
 @@ -1454,7 +1454,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw 
 *ah,
   beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
   ath5k_hw_reg_write(ah, beacon  ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
  
 - mdelay(2);
 + usleep_range(2000, 2500);
  
   /*
* Set the channel (with AGC turned off)
 @@ -1467,7 +1467,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw 
 *ah,
* Activate PHY and wait
*/
   ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
 - mdelay(1);
 + usleep_range(1000, 1500);
  
   AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
  
Are you sure this is safe? This looks like it's being called from
tasklet context, and I think usleep_range is not allowed there.

- Felix
___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


Re: [ath5k-devel] [PATCH 06/13] ath5k: Use usleep_range where possible

2011-11-20 Thread Nick Kossifidis
2011/11/20 Felix Fietkau n...@openwrt.org:
 On 2011-11-20 8:56 AM, Nick Kossifidis wrote:
 Use usleep_range where possible to reduce busy waits

 Signed-off-by: Nick Kossifidis mickfl...@gmail.com
 ---
  drivers/net/wireless/ath/ath5k/attach.c |    2 +-
  drivers/net/wireless/ath/ath5k/pci.c    |    2 +-
  drivers/net/wireless/ath/ath5k/phy.c    |   22 +++---
  drivers/net/wireless/ath/ath5k/reset.c  |   14 +++---
  4 files changed, 20 insertions(+), 20 deletions(-)

 @@ -1454,7 +1454,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw 
 *ah,
       beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
       ath5k_hw_reg_write(ah, beacon  ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);

 -     mdelay(2);
 +     usleep_range(2000, 2500);

       /*
        * Set the channel (with AGC turned off)
 @@ -1467,7 +1467,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw 
 *ah,
        * Activate PHY and wait
        */
       ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
 -     mdelay(1);
 +     usleep_range(1000, 1500);

       AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);

 Are you sure this is safe? This looks like it's being called from
 tasklet context, and I think usleep_range is not allowed there.

 - Felix


Reset runs in process context. Calls to reset are done directly from
non-interrupt context (e.g. during init) or through a work queue, not
a tasklet. They are also locked using a mutex lock, not a spinlock so
we should be fine.

I did a few tests to be on the safe side and run this on a multi-core
system with an AR2425 with no problems/deadlocks or anything.



-- 
GPG ID: 0xEE878588
As you read this post global entropy rises. Have Fun ;-)
Nick
___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


Re: [ath5k-devel] [PATCH 13/13] ath5k: Optimize ath5k_cw_validate

2011-11-20 Thread Bob Copeland
On Sun, Nov 20, 2011 at 09:56:28AM +0200, Nick Kossifidis wrote:
 + /* Check if cw_req + 1 a power of 2 */
 + if (!((cw_req + 1)  cw_req))
 + return cw_req;
 +
 + /* Check if cw_req is a power of 2 */
 + if (!(cw_req  (cw_req - 1)))
 + return cw_req - 1;

There's is_power_of_two() in log2.h .. but this whole thing could also
be something like roundup_pow_of_two(cw) maybe?

-- 
Bob Copeland %% www.bobcopeland.com

___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


Re: [ath5k-devel] [PATCH 06/13] ath5k: Use usleep_range where possible

2011-11-20 Thread Jiri Slaby
On 11/20/2011 04:43 PM, Nick Kossifidis wrote:
 2011/11/20 Felix Fietkau n...@openwrt.org:
 On 2011-11-20 8:56 AM, Nick Kossifidis wrote:
 Use usleep_range where possible to reduce busy waits

 Signed-off-by: Nick Kossifidis mickfl...@gmail.com
 ---
  drivers/net/wireless/ath/ath5k/attach.c |2 +-
  drivers/net/wireless/ath/ath5k/pci.c|2 +-
  drivers/net/wireless/ath/ath5k/phy.c|   22 +++---
  drivers/net/wireless/ath/ath5k/reset.c  |   14 +++---
  4 files changed, 20 insertions(+), 20 deletions(-)

 @@ -1454,7 +1454,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw 
 *ah,
   beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
   ath5k_hw_reg_write(ah, beacon  ~AR5K_BEACON_ENABLE, 
 AR5K_BEACON_5210);

 - mdelay(2);
 + usleep_range(2000, 2500);

   /*
* Set the channel (with AGC turned off)
 @@ -1467,7 +1467,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw 
 *ah,
* Activate PHY and wait
*/
   ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
 - mdelay(1);
 + usleep_range(1000, 1500);

   AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);

 Are you sure this is safe? This looks like it's being called from
 tasklet context, and I think usleep_range is not allowed there.

 - Felix

 
 Reset runs in process context. Calls to reset are done directly from
 non-interrupt context (e.g. during init) or through a work queue, not
 a tasklet. They are also locked using a mutex lock, not a spinlock so
 we should be fine.

But those two are not reset, but calibrate. And calibration is performed
in a tasklet.

thanks,
-- 
js
___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


Re: [ath5k-devel] [PATCH 13/13] ath5k: Optimize ath5k_cw_validate

2011-11-20 Thread Nick Kossifidis
2011/11/20 Bob Copeland m...@bobcopeland.com:
 On Sun, Nov 20, 2011 at 09:56:28AM +0200, Nick Kossifidis wrote:
 +     /* Check if cw_req + 1 a power of 2 */
 +     if (!((cw_req + 1)  cw_req))
 +             return cw_req;
 +
 +     /* Check if cw_req is a power of 2 */
 +     if (!(cw_req  (cw_req - 1)))
 +             return cw_req - 1;

 There's is_power_of_two() in log2.h .. but this whole thing could also
 be something like roundup_pow_of_two(cw) maybe?


Nice catch ! I didn't knew about log2.h, seems interesting :-)

roundup_pow_of_two(n) - 1 should take away that while loop but in most
cases we 'll get a correct cw value so is_power_of_two(cw_req + 1)
would take care of that faster.

I'll post an update



-- 
GPG ID: 0xEE878588
As you read this post global entropy rises. Have Fun ;-)
Nick
___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


Re: [ath5k-devel] [PATCH 06/13] ath5k: Use usleep_range where possible

2011-11-20 Thread Nick Kossifidis
2011/11/20 Jiri Slaby jirisl...@gmail.com:
 On 11/20/2011 04:43 PM, Nick Kossifidis wrote:
 2011/11/20 Felix Fietkau n...@openwrt.org:
 On 2011-11-20 8:56 AM, Nick Kossifidis wrote:
 Use usleep_range where possible to reduce busy waits

 Signed-off-by: Nick Kossifidis mickfl...@gmail.com
 ---
  drivers/net/wireless/ath/ath5k/attach.c |    2 +-
  drivers/net/wireless/ath/ath5k/pci.c    |    2 +-
  drivers/net/wireless/ath/ath5k/phy.c    |   22 +++---
  drivers/net/wireless/ath/ath5k/reset.c  |   14 +++---
  4 files changed, 20 insertions(+), 20 deletions(-)

 @@ -1454,7 +1454,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw 
 *ah,
       beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
       ath5k_hw_reg_write(ah, beacon  ~AR5K_BEACON_ENABLE, 
 AR5K_BEACON_5210);

 -     mdelay(2);
 +     usleep_range(2000, 2500);

       /*
        * Set the channel (with AGC turned off)
 @@ -1467,7 +1467,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw 
 *ah,
        * Activate PHY and wait
        */
       ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
 -     mdelay(1);
 +     usleep_range(1000, 1500);

       AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);

 Are you sure this is safe? This looks like it's being called from
 tasklet context, and I think usleep_range is not allowed there.

 - Felix


 Reset runs in process context. Calls to reset are done directly from
 non-interrupt context (e.g. during init) or through a work queue, not
 a tasklet. They are also locked using a mutex lock, not a spinlock so
 we should be fine.

 But those two are not reset, but calibrate. And calibration is performed
 in a tasklet.

 thanks,
 --
 js


Just noticed I missed that part on 05, there is no need to run
calibration through a tasklet, will post an update on 05...


-- 
GPG ID: 0xEE878588
As you read this post global entropy rises. Have Fun ;-)
Nick
___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


Re: [ath5k-devel] [PATCH 02/13] ath5k: Maintain PISR snapshot

2011-11-20 Thread Nick Kossifidis
2011/11/21 Adrian Chadd adr...@freebsd.org:
 .. replying to this after having not slept for  24 hours, thanks to
 being in transit between the US and Western Australia..

Ouch ! I've done that a lot lately, without traveling :P

 On 20 November 2011 15:56, Nick Kossifidis mickfl...@gmail.com wrote:
 Since we dont read a snapshot of the interrupt
 registers it might be possible to get a new interrupt
 while reading them. In this case we should make sure
 that we clear all SISR bits we get from PISR.

 Just to be clear, you _shouldn't_ clear the secondary status mask bit
 in the primary status register when you write back 1's to the primary
 ISR.
 Clear the bits that you read in the secondary status registers. If you
 clear the relevant bit in the primary status register then you may
 also skip perfectly valid interrupts.

 You don't need to check the secondary registers and the primary ISR
 bits for consistency. Just read what I did in freebsd-head :
 src/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c . it works fine.


 Adrian


ACK, thanks for the update ! It's just that docs say nothing about
when and how PISR gets updated so i tried to manually update it.

-- 
GPG ID: 0xEE878588
As you read this post global entropy rises. Have Fun ;-)
Nick
___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


[ath5k-devel] A weird hw crypto bug...

2011-11-20 Thread Nick Kossifidis
Some time ago we had a few reports of AR2413 cards being unable to
encrypt packets of specific lengths.

From https://bugs.launchpad.net/ubuntu/+source/linux/+bug/568090, user
Musaraigne did some further investigation/debuging on this:

The cause of the high and unpredictable latencies is that packets are
dropped depending on their size. According to my tests, packet sizes
of the form
  size = 128*k + 81 + m
or
  size = 128*k + 105 + m
for any k=2 and 0=m=7

are dropped randomly in 90-95% of the cases. Conversely, all other
packet sizes work fine.

You can see for yourself if this is true on your system:
  ping -M do -s 596 www.google.com
should result in 90% packet loss (because 624 = 128*4 + 105 + 7; the
28 byte difference comes from network headers added by ping)
while
  ping -M do -s 597 www.google.com
should result in negligible packet loss.

So far I couldn't reproduce this bug with my AR2413 and now after e
few user reports I'm almost sure that it's only present on cards
created by Askey. I verified it again recently based on a bug report
from an OpenSUSE user here...

https://bugzilla.novell.com/show_bug.cgi?id=731576

What seems weird is that some users reported that MadWiFi worked fine
on these cards (I have no idea what happens on their windows driver,
maybe they disable hw crypto) ! Since for hw crypto we use code from
the common ath module (and I think this is the same with HAL) I don't
see how that can happen.

Anyway my question is how to handle this:

a) Just disable hw crypto for all AR2413 cards made by Askey
b) If we handle such card do some padding based on Musaraigne's findings

I'd like to go with b but I don't know how to do it correctly without
corrupting anything. Any ideas ?


-- 
GPG ID: 0xEE878588
As you read this post global entropy rises. Have Fun ;-)
Nick
___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


Re: [ath5k-devel] A weird hw crypto bug...

2011-11-20 Thread Adrian Chadd
On 21 November 2011 12:08, Nick Kossifidis mickfl...@gmail.com wrote:
 Some time ago we had a few reports of AR2413 cards being unable to
 encrypt packets of specific lengths.

 From https://bugs.launchpad.net/ubuntu/+source/linux/+bug/568090, user
 Musaraigne did some further investigation/debuging on this:

 The cause of the high and unpredictable latencies is that packets are
 dropped depending on their size. According to my tests, packet sizes
 of the form
  size = 128*k + 81 + m
 or
  size = 128*k + 105 + m
 for any k=2 and 0=m=7

 are dropped randomly in 90-95% of the cases. Conversely, all other
 packet sizes work fine.

That seems a bit odd. Erm, how do they fail?

* Does the hardware just plain fail at encrypting the frame?
* Does the hardware just plain fail to _TX_ the frame of that size?
(ie, if you disable crypto and take padding into account, does it
fail?)
* What about other encryption types? AES? TKIP? WEP? None? :-)
* This is a PCIe NIC, right? Are there some kind of weird bus bugs
that you're seeing with this particular NIC and this particular bus
glue?

Since Madwifi works, I wonder if FreeBSD also works. If so, there's
only a few places I'd bet you'll find weird stuff:

* how the bus is setup during attach (eg overriding PCI values);
* which crypto key slots are allocated;
* are you still doing split keys on that hardware? or are they
combined like the ar5416+ chips are?
* are you perhaps doing multi-descriptor TX frames and you've not set
the encryption bits correctly? IIRC, the enctype field needs to match
on all descriptors of a frame (eg, if your packet is a chain rather
than a single skb, you need to make sure you're copying the descriptor
fields right.)
* what about the frame and header length fields? and encryption
padding? are they all setup the same with madwifi versus ath5k?

I bet a bit of methodical poking is going to reveal this bug. I find
it rather annoying that ath5k/ath9k have lots of encryption issues but
I've not had any reports of encryption on FreeBSD failing (save where
the AP is totally lying about which keyidx a frame is encrypted with.)
It's possible that you're seeing these errors because more people are
using ath5k then FreeBSD, but still:

* does freebsd-9 (wifi) work on the same hardware?

Nick, can you find out if someone can send us one of these weird NICs?
I'll throw it into my pile-o-old-stuff-to-test and do some regression
testing with it.


Adrian
___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel


Re: [ath5k-devel] A weird hw crypto bug...

2011-11-20 Thread Nick Kossifidis
2011/11/21 Adrian Chadd adr...@freebsd.org:
 On 21 November 2011 12:08, Nick Kossifidis mickfl...@gmail.com wrote:
 Some time ago we had a few reports of AR2413 cards being unable to
 encrypt packets of specific lengths.

 From https://bugs.launchpad.net/ubuntu/+source/linux/+bug/568090, user
 Musaraigne did some further investigation/debuging on this:

 The cause of the high and unpredictable latencies is that packets are
 dropped depending on their size. According to my tests, packet sizes
 of the form
  size = 128*k + 81 + m
 or
  size = 128*k + 105 + m
 for any k=2 and 0=m=7

 are dropped randomly in 90-95% of the cases. Conversely, all other
 packet sizes work fine.

 That seems a bit odd. Erm, how do they fail?

 * Does the hardware just plain fail at encrypting the frame?
 * Does the hardware just plain fail to _TX_ the frame of that size?
 (ie, if you disable crypto and take padding into account, does it
 fail?)
 * What about other encryption types? AES? TKIP? WEP? None? :-)
 * This is a PCIe NIC, right? Are there some kind of weird bus bugs
 that you're seeing with this particular NIC and this particular bus
 glue?

This is about specific AR2413 cards made by Askey, AR2413 cards in
general work fine, I have one myself. Problem is when hw encryption is
enabled (not sure about WEP, I think I've seen a report on WEP also)
when packets of specific lengths are dropped. They work O.K. without
encryption or with sw encryption. I haven't seen any report with dumps
etc so I don't know if packers are corrupted or never transmitted etc,
it's just weird that it happens only on specific AR2413 cards, not any
AR2413 card (that means in general we handle hw encryption correctly
as it works fine on most cards, in fact right now I think that's the
only active bug we have on encryption). The way I see it it's a hw
issue found on these implementations that we don't handle. Btw AR2413
is plain pci card, only AR5424/2424/2425 are pci-e from ar5k series
(it's also AR5418 but it's handled by ath9k).

 Since Madwifi works, I wonder if FreeBSD also works. If so, there's
 only a few places I'd bet you'll find weird stuff:

 * how the bus is setup during attach (eg overriding PCI values);
 * which crypto key slots are allocated;
 * are you still doing split keys on that hardware? or are they
 combined like the ar5416+ chips are?

When we had crypto code inside ath5k we did what the old HAL did (via
rev. engineering), now we use the common code from the ath module, so
we do whatever ath9k does (and I think MadWiFi too). Again hw crypto
works fine, even on AR2413 cards, it's this vendor that has done
something weird that results tx failures on hw encryption. Plus I
don't know what version of MadWiFi they used or if they used hw crypto
on MadWiFi at all.

 * are you perhaps doing multi-descriptor TX frames and you've not set
 the encryption bits correctly? IIRC, the enctype field needs to match
 on all descriptors of a frame (eg, if your packet is a chain rather
 than a single skb, you need to make sure you're copying the descriptor
 fields right.)

No fast frames here or multi-descriptor stuff.

 * what about the frame and header length fields? and encryption
 padding? are they all setup the same with madwifi versus ath5k?

That would show up as most of the things you mention above on any card
since it's common code, or even on a specific chip version/revision.
Here we have this issue with a specific implementation and everything
works fine on other implementations with the same chip.

 I bet a bit of methodical poking is going to reveal this bug. I find
 it rather annoying that ath5k/ath9k have lots of encryption issues but
 I've not had any reports of encryption on FreeBSD failing (save where
 the AP is totally lying about which keyidx a frame is encrypted with.)
 It's possible that you're seeing these errors because more people are
 using ath5k then FreeBSD, but still:

 * does freebsd-9 (wifi) work on the same hardware?

No idea :-(

 Nick, can you find out if someone can send us one of these weird NICs?
 I'll throw it into my pile-o-old-stuff-to-test and do some regression
 testing with it.


Haven't found so far but I think it's clearly a hw issue (I've done
some testing on my AR2413 and it seems fine) and since we know what
packet lengths fail maybe we can create a workaround with padding etc.



-- 
GPG ID: 0xEE878588
As you read this post global entropy rises. Have Fun ;-)
Nick
___
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel