Re: [PATCH 2/2] mac80211: improve minstrel_ht rate sorting by throughput probability

2014-09-08 Thread Felix Fietkau
On 2014-08-22 16:05, Thomas Huehn wrote:
 This patch improves the way minstrel_ht sorts rates according to throughput
 and success probability. 3 FOR-loops across the entire rate and mcs group set
 in function minstrel_ht_update_stats() which where used to determine the
 fastest, second fastest and most robust rate are reduced to 2 FOR-loops.
 
 The sorted list of rates according throughput is extended to the best four
 rates as we need them in upcoming joint rate and power control. The sorting
 is done via the new function minstrel_ht_sort_best_tp_rates(). The annotation
 of those 4 best throughput rates in the debugfs file rc-stats is changes to:
 A,B,C,D, where A is the fastest rate and D the 4th fastest.
 
 Signed-off-by: Thomas Huehn tho...@net.t-labs.tu-berlin.de
 Tested-by: Stefan Venz ikstrea...@gmail.com
 ---
  net/mac80211/rc80211_minstrel_ht.c | 215 
 -
  net/mac80211/rc80211_minstrel_ht.h |  17 +--
  net/mac80211/rc80211_minstrel_ht_debugfs.c |   8 +-
  3 files changed, 128 insertions(+), 112 deletions(-)
 
 diff --git a/net/mac80211/rc80211_minstrel_ht.c 
 b/net/mac80211/rc80211_minstrel_ht.c
 index 85c1e74..7f03c01 100644
 --- a/net/mac80211/rc80211_minstrel_ht.c
 +++ b/net/mac80211/rc80211_minstrel_ht.c
 @@ -228,8 +227,47 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int 
 group, int rate)
   nsecs += minstrel_mcs_groups[group].duration[rate];
  
   /* prob is scaled - see MINSTREL_FRAC above */
 - tp = 100 * ((prob * 1000) / nsecs);
 - mr-cur_tp = MINSTREL_TRUNC(tp);
 + mr-cur_tp = 100 * ((prob * 1000) / nsecs);
 +}
 +
 +/*
 + * Find  sort topmost throughput rates
 + *
 + * If multiple rates provide equal throughput the sorting is based on their
 + * current success probability. Higher success probability is preferred among
 + * MCS groups, CCK rates do not provide aggregation and are therefore at 
 last.
 + */
 +static inline void
You should drop the 'inline'

 +minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, unsigned int 
 index,
 +unsigned int *tp_list)
 +{
 + int j = MAX_THR_RATES;
 + unsigned int cur_group, cur_idx, cur_thr, cur_prob;
 + unsigned int tmp_group, tmp_idx;
 +
 + cur_group = index / MCS_GROUP_RATES;
 + cur_idx = index % MCS_GROUP_RATES;
 + cur_thr = mi-groups[cur_group].rates[cur_idx].cur_tp;
 + cur_prob = mi-groups[cur_group].rates[cur_idx].probability;
 + tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
 + tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
 +
 +
 + while (j  0  (cur_thr  mi-groups[tmp_group].rates[tmp_idx].cur_tp 
 ||
 +(cur_thr == mi-groups[tmp_group].rates[tmp_idx].cur_tp 
 +cur_prob  mi-groups[tmp_group].rates[tmp_idx].probability 
 +cur_group != MINSTREL_CCK_GROUP))) {
Missing one whitespace in indentation in the above two lines
 + j--;
 + tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
 + tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
One tab too many.
I think it would probably make the code more readable if you just do
while (j  0) { ... } and move the other checks inside the block.


 + }
 +
 + if (j  MAX_THR_RATES - 1) {
 + memmove(tp_list[j + 1], tp_list[j], (sizeof(*tp_list) *
 +(MAX_THR_RATES - (j + 1;
 + }
 + if (j  MAX_THR_RATES)
 + tp_list[j] = index;
  }
  
  /*

 @@ -274,24 +312,17 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, 
 struct minstrel_ht_sta *mi)
  
   mi-sample_count++;
  
 + /* (re)Initialize group rate indexes */
 + for(j = 0; j  MAX_THR_RATES; j++){
 + tmp_group_tp_rate[j] = group;
 + }
You can drop the {} here.


 @@ -300,82 +331,72 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, 
 struct minstrel_ht_sta *mi)
  [...]
  
 + /* try to sample all available rates during each interval */
 + mi-sample_count *= 8;
 +
  #ifdef CONFIG_MAC80211_DEBUGFS
   /* use fixed index if set */
   if (mp-fixed_rate_idx != -1) {
 - mi-max_tp_rate = mp-fixed_rate_idx;
 - mi-max_tp_rate2 = mp-fixed_rate_idx;
 + for (i = 0; i  4; i++) {
 + mi-max_tp_rate[i] = mp-fixed_rate_idx;
 + }
You can drop the {}
   mi-max_prob_rate = mp-fixed_rate_idx;
   }
  #endif
  
 + /* Reset update timer */
   mi-stats_update = jiffies;
  }
  
 @@ -735,8 +756,8 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct 
 minstrel_ht_sta *mi)
* if the link is working perfectly.
*/
   sample_dur = minstrel_get_duration(sample_idx);
 - if (sample_dur = minstrel_get_duration(mi-max_tp_rate2) 
 - (mi-max_prob_streams 
 + if (sample_dur = minstrel_get_duration(mi-max_tp_rate[1]) 
 + (minstrel_mcs_groups[mi-max_tp_rate[0] / 

Re: [PATCH v2 0/2] Unify improve Minstrel Minstrel_HT rate control

2014-09-09 Thread Felix Fietkau
On 2014-09-09 23:22, Thomas Huehn wrote:
 This patch series consolidates rate statistic variables between Minstrel and
 Minstrel_HT. It improves the sorting function to find the max throughput rate
 set in Minstrel_HT.
For this series:

Acked-by: Felix Fietkau n...@openwrt.org
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] ath9k_hw: disable hardware ad-hoc flag on ar934x rev 3

2014-09-27 Thread Felix Fietkau
On AR934x rev 3, settin the ad-hoc flag completely messes up hardware
state - beacons get stuck, almost no packets make it out, hardware is
constantly reset.

When leaving out that flag and setting up the hw like in AP mode, TSF
timers won't be automatically synced, but at least the rest works.

AR934x rev 2 and older are not affected by this bug

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/hw.c  | 9 ++---
 drivers/net/wireless/ath/ath9k/reg.h | 4 
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index cf0128e..88654e3 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1189,9 +1189,12 @@ static void ath9k_hw_set_operating_mode(struct ath_hw 
*ah, int opmode)
 
switch (opmode) {
case NL80211_IFTYPE_ADHOC:
-   set |= AR_STA_ID1_ADHOC;
-   REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
-   break;
+   if (!AR_SREV_9340_13(ah)) {
+   set |= AR_STA_ID1_ADHOC;
+   REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+   break;
+   }
+   /* fall through */
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
set |= AR_STA_ID1_STA_AP;
diff --git a/drivers/net/wireless/ath/ath9k/reg.h 
b/drivers/net/wireless/ath/ath9k/reg.h
index a149970..95fdf93 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -903,6 +903,10 @@
 #define AR_SREV_9340(_ah) \
(((_ah)-hw_version.macVersion == AR_SREV_VERSION_9340))
 
+#define AR_SREV_9340_13(_ah) \
+   (AR_SREV_9340((_ah))  \
+((_ah)-hw_version.macRev == AR_SREV_REVISION_9340_13))
+
 #define AR_SREV_9340_13_OR_LATER(_ah) \
(AR_SREV_9340((_ah))  \
 ((_ah)-hw_version.macRev = AR_SREV_REVISION_9340_13))
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] ath9k: use ah-get_mac_revision for all SoC devices if available

2014-09-27 Thread Felix Fietkau
It is needed for AR934x as well

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/hw.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index 3aed729..cf0128e 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -222,31 +222,28 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
 {
u32 val;
 
+   if (ah-get_mac_revision)
+   ah-hw_version.macRev = ah-get_mac_revision();
+
switch (ah-hw_version.devid) {
case AR5416_AR9100_DEVID:
ah-hw_version.macVersion = AR_SREV_VERSION_9100;
break;
case AR9300_DEVID_AR9330:
ah-hw_version.macVersion = AR_SREV_VERSION_9330;
-   if (ah-get_mac_revision) {
-   ah-hw_version.macRev = ah-get_mac_revision();
-   } else {
+   if (!ah-get_mac_revision) {
val = REG_READ(ah, AR_SREV);
ah-hw_version.macRev = MS(val, AR_SREV_REVISION2);
}
return;
case AR9300_DEVID_AR9340:
ah-hw_version.macVersion = AR_SREV_VERSION_9340;
-   val = REG_READ(ah, AR_SREV);
-   ah-hw_version.macRev = MS(val, AR_SREV_REVISION2);
return;
case AR9300_DEVID_QCA955X:
ah-hw_version.macVersion = AR_SREV_VERSION_9550;
return;
case AR9300_DEVID_AR953X:
ah-hw_version.macVersion = AR_SREV_VERSION_9531;
-   if (ah-get_mac_revision)
-   ah-hw_version.macRev = ah-get_mac_revision();
return;
}
 
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/3] ath9k_hw: reduce ANI spur immunity setting on HT40 extension channel

2014-09-29 Thread Felix Fietkau
The cycpwr_thr1 value needs to be lower on the extension channel than on
the control channel, similar to how the register settings are programmed
in the initvals.

Also drop the unnecessary check for HT40 - this register can always be
written. This patch has been reported to improve HT40 stability and
throughput in some environments.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/ar5008_phy.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c 
b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 3b3e910..b72d0be 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -1042,9 +1042,8 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_TIMING5,
  AR_PHY_TIMING5_CYCPWR_THR1, value);
 
-   if (IS_CHAN_HT40(ah-curchan))
-   REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
- AR_PHY_EXT_TIMING5_CYCPWR_THR1, value);
+   REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+ AR_PHY_EXT_TIMING5_CYCPWR_THR1, value - 1);
 
if (level != aniState-spurImmunityLevel) {
ath_dbg(common, ANI,
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/3] ath9k_hw: fix PLL clock initialization for newer SoC

2014-09-29 Thread Felix Fietkau
On AR934x and newer SoC devices, the layout of the AR_RTC_PLL_CONTROL
register changed. This currently breaks at least 5/10 MHz operation.
AR933x uses the old layout.

It might also have been causing other stability issues because of the
different location of the PLL_BYPASS bit which needs to be set during
PLL clock initialization.

This patch also removes more instances of hardcoded register values in
favor of properly computed ones with the PLL_BYPASS bit added.

Reported-by: Lorenzo Bianconi lorenzo.biancon...@gmail.com
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/ar9003_phy.c | 24 +++-
 drivers/net/wireless/ath/ath9k/hw.c |  9 ++---
 drivers/net/wireless/ath/ath9k/reg.h| 11 +++
 3 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c 
b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 542a8d5..697c4ae 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -517,6 +517,23 @@ static void ar9003_hw_spur_mitigate(struct ath_hw *ah,
ar9003_hw_spur_mitigate_ofdm(ah, chan);
 }
 
+static u32 ar9003_hw_compute_pll_control_soc(struct ath_hw *ah,
+struct ath9k_channel *chan)
+{
+   u32 pll;
+
+   pll = SM(0x5, AR_RTC_9300_SOC_PLL_REFDIV);
+
+   if (chan  IS_CHAN_HALF_RATE(chan))
+   pll |= SM(0x1, AR_RTC_9300_SOC_PLL_CLKSEL);
+   else if (chan  IS_CHAN_QUARTER_RATE(chan))
+   pll |= SM(0x2, AR_RTC_9300_SOC_PLL_CLKSEL);
+
+   pll |= SM(0x2c, AR_RTC_9300_SOC_PLL_DIV_INT);
+
+   return pll;
+}
+
 static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah,
 struct ath9k_channel *chan)
 {
@@ -1781,7 +1798,12 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
 
priv_ops-rf_set_freq = ar9003_hw_set_channel;
priv_ops-spur_mitigate_freq = ar9003_hw_spur_mitigate;
-   priv_ops-compute_pll_control = ar9003_hw_compute_pll_control;
+
+   if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah))
+   priv_ops-compute_pll_control = 
ar9003_hw_compute_pll_control_soc;
+   else
+   priv_ops-compute_pll_control = ar9003_hw_compute_pll_control;
+
priv_ops-set_channel_regs = ar9003_hw_set_channel_regs;
priv_ops-init_bb = ar9003_hw_init_bb;
priv_ops-process_ini = ar9003_hw_process_ini;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index 3aed729..f03e283 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -704,6 +704,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
 {
u32 pll;
 
+   pll = ath9k_hw_compute_pll_control(ah, chan);
+
if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
/* program BB PLL ki and kd value, ki=0x4, kd=0x40 */
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
@@ -754,7 +756,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
  AR_CH0_DPLL3_PHASE_SHIFT, 0x1);
 
-   REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+   REG_WRITE(ah, AR_RTC_PLL_CONTROL,
+ pll | AR_RTC_9300_PLL_BYPASS);
udelay(1000);
 
/* program refdiv, nint, frac to RTC register */
@@ -770,7 +773,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
} else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
u32 regval, pll2_divint, pll2_divfrac, refdiv;
 
-   REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+   REG_WRITE(ah, AR_RTC_PLL_CONTROL,
+ pll | AR_RTC_9300_SOC_PLL_BYPASS);
udelay(1000);
 
REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1  16);
@@ -843,7 +847,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
udelay(1000);
}
 
-   pll = ath9k_hw_compute_pll_control(ah, chan);
if (AR_SREV_9565(ah))
pll |= 0x4;
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
diff --git a/drivers/net/wireless/ath/ath9k/reg.h 
b/drivers/net/wireless/ath/ath9k/reg.h
index a149970..3747a8a 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1240,12 +1240,23 @@ enum {
 #define AR_CH0_DPLL3_PHASE_SHIFT_S   23
 #define AR_PHY_CCA_NOM_VAL_2GHZ  -118
 
+#define AR_RTC_9300_SOC_PLL_DIV_INT  0x003f
+#define AR_RTC_9300_SOC_PLL_DIV_INT_S0
+#define AR_RTC_9300_SOC_PLL_DIV_FRAC 0x000fffc0
+#define AR_RTC_9300_SOC_PLL_DIV_FRAC_S   6
+#define AR_RTC_9300_SOC_PLL_REFDIV   0x01f0
+#define AR_RTC_9300_SOC_PLL_REFDIV_S 20
+#define AR_RTC_9300_SOC_PLL_CLKSEL   0x0600
+#define AR_RTC_9300_SOC_PLL_CLKSEL_S 25
+#define

[PATCH 1/3] Revert ath9k_hw: reduce ANI firstep range for older chips

2014-09-29 Thread Felix Fietkau
This reverts commit 09efc56345be4146ab9fc87a55c837ed5d6ea1ab

I've received reports that this change is decreasing throughput in some
rare conditions on an AR9280 based device

Cc: sta...@vger.kernel.org
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/ar5008_phy.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c 
b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 00fb8ba..3b3e910 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -1004,9 +1004,11 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
case ATH9K_ANI_FIRSTEP_LEVEL:{
u32 level = param;
 
-   value = level;
+   value = level * 2;
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
  AR_PHY_FIND_SIG_FIRSTEP, value);
+   REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
+ AR_PHY_FIND_SIG_FIRSTEP_LOW, value);
 
if (level != aniState-firstepLevel) {
ath_dbg(common, ANI,
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] mac80211: minstrel_ht: add basic support for VHT rates = 80MHz@NSS2

2014-09-29 Thread Felix Fietkau
On 2014-09-29 15:58, Karl Beldan wrote:
 You mean having a common hardcoded value for both ?
Yes. And at the same time also getting rid of #if tests for it.

 After 4441e8e9 the minstrel rate indexes have to be u8-s and having this
 common param  2 would require something like:
 
 {{{
 diff --git a/net/mac80211/rc80211_minstrel_ht.c 
 b/net/mac80211/rc80211_minstrel_ht.c
 index 41522c7..c3d9136 100644
 --- a/net/mac80211/rc80211_minstrel_ht.c
 +++ b/net/mac80211/rc80211_minstrel_ht.c
 @@ -346,8 +364,8 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int 
 group, int rate)
   * MCS groups, CCK rates do not provide aggregation and are therefore at 
 last.
   */
  static void
 -minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u8 index,
 -  u8 *tp_list)
 +minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index,
 +  u16 *tp_list)
  {
 int cur_group, cur_idx, cur_thr, cur_prob;
 int tmp_group, tmp_idx, tmp_thr, tmp_prob;
 @@ -384,7 +402,7 @@ minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta 
 *mi, u8 index,
   * Find and set the topmost probability rate per sta and per group
   */
  static void
 -minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u8 index)
 +minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
  {
 struct minstrel_mcs_group_data *mg;
 struct minstrel_rate_stats *mr;
 @@ -427,8 +445,8 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta 
 *mi, u8 index)
   */
  static void
  minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
 -u8 tmp_mcs_tp_rate[MAX_THR_RATES],
 -u8 tmp_cck_tp_rate[MAX_THR_RATES])
 +u16 tmp_mcs_tp_rate[MAX_THR_RATES],
 +u16 tmp_cck_tp_rate[MAX_THR_RATES])
  {
 unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp;
 int i;
 @@ -492,8 +510,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct 
 minstrel_ht_sta *mi)
 struct minstrel_mcs_group_data *mg;
 struct minstrel_rate_stats *mr;
 int group, i, j;
 -   u8 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES];
 -   u8 tmp_cck_tp_rate[MAX_THR_RATES], index;
 +   u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES];
 +   u16 tmp_cck_tp_rate[MAX_THR_RATES], index;
 
 if (mi-ampdu_packets  0) {
 mi-avg_ampdu_len = minstrel_ewma(mi-avg_ampdu_len,
 diff --git a/net/mac80211/rc80211_minstrel_ht.h 
 b/net/mac80211/rc80211_minstrel_ht.h
 index 7856062..354e076 100644
 --- a/net/mac80211/rc80211_minstrel_ht.h
 +++ b/net/mac80211/rc80211_minstrel_ht.h
 @@ -57,8 +57,8 @@ struct minstrel_mcs_group_data {
 u16 supported;
 
 /* sorted rate set within a MCS group*/
 -   u8 max_group_tp_rate[MAX_THR_RATES];
 -   u8 max_group_prob_rate;
 +   u16 max_group_tp_rate[MAX_THR_RATES];
 +   u16 max_group_prob_rate;
 
 /* MCS rate statistics */
 struct minstrel_rate_stats rates[MCS_GROUP_RATES];
 @@ -75,8 +75,8 @@ struct minstrel_ht_sta {
 unsigned int avg_ampdu_len;
 
 /* overall sorted rate set */
 -   u8 max_tp_rate[MAX_THR_RATES];
 -   u8 max_prob_rate;
 +   u16 max_tp_rate[MAX_THR_RATES];
 +   u16 max_prob_rate;
 
 /* time of last status update */
 unsigned long stats_update;
 }}}
 
 With this I could not advertise the patch overhead-less when not setting
 MAC80211_RC_MINSTREL_VHT, too invasive for a simple step to feel the
 limits of the present implementation and a way to test vht tx path.
 
 But maybe that's not what you had in mind for MINSTREL_*_MAX_STREAMS ?
I think the overhead of this is insignificant enough to justify getting
rid of some #if spaghetti. It should probably be posted as a separate
patch though, to simplify review.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] ath9k: fix getting tx duration for dynack

2014-09-30 Thread Felix Fietkau
On AR9003, tx control and tx status are in separate descriptor rings.
Tx duration is extracted from the tx control descriptor data, which
ar9003_hw_proc_txdesc cannot access.

Fix getting the duration by adding a separate callback for it.

Acked-by: Lorenzo Bianconi lorenzo.biancon...@gmail.com
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/ar9002_mac.c | 26 +++---
 drivers/net/wireless/ath/ath9k/ar9003_mac.c | 28 +++-
 drivers/net/wireless/ath/ath9k/dynack.c |  2 +-
 drivers/net/wireless/ath/ath9k/hw-ops.h |  6 ++
 drivers/net/wireless/ath/ath9k/hw.h |  1 +
 drivers/net/wireless/ath/ath9k/mac.h|  2 +-
 drivers/net/wireless/ath/ath9k/xmit.c   |  2 ++
 7 files changed, 49 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c 
b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 669cb37..2a93519 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -381,16 +381,27 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void 
*ds,
ts-evm1 = ads-AR_TxEVM1;
ts-evm2 = ads-AR_TxEVM2;
 
-   status = ACCESS_ONCE(ads-ds_ctl4);
-   ts-duration[0] = MS(status, AR_PacketDur0);
-   ts-duration[1] = MS(status, AR_PacketDur1);
-   status = ACCESS_ONCE(ads-ds_ctl5);
-   ts-duration[2] = MS(status, AR_PacketDur2);
-   ts-duration[3] = MS(status, AR_PacketDur3);
-
return 0;
 }
 
+static int ar9002_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
+{
+   struct ar5416_desc *ads = AR5416DESC(ds);
+
+   switch (index) {
+   case 0:
+   return MS(ACCESS_ONCE(ads-ds_ctl4), AR_PacketDur0);
+   case 1:
+   return MS(ACCESS_ONCE(ads-ds_ctl4), AR_PacketDur1);
+   case 2:
+   return MS(ACCESS_ONCE(ads-ds_ctl5), AR_PacketDur2);
+   case 3:
+   return MS(ACCESS_ONCE(ads-ds_ctl5), AR_PacketDur3);
+   default:
+   return -1;
+   }
+}
+
 void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
  u32 size, u32 flags)
 {
@@ -413,4 +424,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
ops-get_isr = ar9002_hw_get_isr;
ops-set_txdesc = ar9002_set_txdesc;
ops-proc_txdesc = ar9002_hw_proc_txdesc;
+   ops-get_duration = ar9002_hw_get_duration;
 }
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c 
b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index e5f7c11..057b165 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -355,11 +355,9 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void 
*ds,
 struct ath_tx_status *ts)
 {
struct ar9003_txs *ads;
-   struct ar9003_txc *adc;
u32 status;
 
ads = ah-ts_ring[ah-ts_tail];
-   adc = (struct ar9003_txc *)ads;
 
status = ACCESS_ONCE(ads-status8);
if ((status  AR_TxDone) == 0)
@@ -428,18 +426,29 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void 
*ds,
ts-ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
ts-ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
 
-   status = ACCESS_ONCE(adc-ctl15);
-   ts-duration[0] = MS(status, AR_PacketDur0);
-   ts-duration[1] = MS(status, AR_PacketDur1);
-   status = ACCESS_ONCE(adc-ctl16);
-   ts-duration[2] = MS(status, AR_PacketDur2);
-   ts-duration[3] = MS(status, AR_PacketDur3);
-
memset(ads, 0, sizeof(*ads));
 
return 0;
 }
 
+static int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
+{
+   const struct ar9003_txc *adc = ds;
+
+   switch (index) {
+   case 0:
+   return MS(ACCESS_ONCE(adc-ctl15), AR_PacketDur0);
+   case 1:
+   return MS(ACCESS_ONCE(adc-ctl15), AR_PacketDur1);
+   case 2:
+   return MS(ACCESS_ONCE(adc-ctl16), AR_PacketDur2);
+   case 3:
+   return MS(ACCESS_ONCE(adc-ctl16), AR_PacketDur3);
+   default:
+   return 0;
+   }
+}
+
 void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
 {
struct ath_hw_ops *ops = ath9k_hw_ops(hw);
@@ -449,6 +458,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
ops-get_isr = ar9003_hw_get_isr;
ops-set_txdesc = ar9003_set_txdesc;
ops-proc_txdesc = ar9003_hw_proc_txdesc;
+   ops-get_duration = ar9003_hw_get_duration;
 }
 
 void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
diff --git a/drivers/net/wireless/ath/ath9k/dynack.c 
b/drivers/net/wireless/ath/ath9k/dynack.c
index 6ae8e0b..22b3cc4 100644
--- a/drivers/net/wireless/ath/ath9k/dynack.c
+++ b/drivers/net/wireless/ath/ath9k/dynack.c
@@ -202,7 +202,7 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct 
sk_buff *skb,
ridx = ts-ts_rateindex;
 
da-st_rbf.ts[da-st_rbf.t_rb].tstamp = ts

Re: [PATCH] mac80211: minstrels: fix buffer overflow in HT debugfs rc_stats

2014-10-18 Thread Felix Fietkau
On 2014-10-17 20:34, Karl Beldan wrote:
 From: Karl Beldan karl.bel...@rivierawaves.com
 
 ATM an HT rc_stats line is 106 chars.
 Times 8(MCS_GROUP_RATES)*3(SS)*2(GI)*2(BW) + CCK(4), i.e. x100, this is
 well above the current 8192 - sizeof(*ms) currently allocated.
 
 Fix this by squeezing the output as follows (not that we're short on
 memory but this also improves readability and range, the new format adds
 one more digit to *ok/*cum and ok/cum):
 
 - Before (HT) (106 ch):
 type   rate throughput  ewma prob   this prob  retry   this 
 succ/attempt   successattempts
 CCK/LP  5.5M   0.00.0 0.0  0  
 0(  0) 0   0
 HT20/LGI ABCDP MCS00.00.0 0.0  1  
 0(  0) 0   0
 - After (75 ch):
 type   rate tpt eprob *prob ret  *ok(*cum)ok(  cum)
 CCK/LP  5.5M0.0   0.0   0.0   00(   0) 0(0)
 HT20/LGI ABCDP MCS0 0.0   0.0   0.0   10(   0) 0(0)
 
 - Align non-HT format Before (non-HT) (83 ch):
 rate  throughput  ewma prob  this prob  this succ/attempt   success
 attempts
 ABCDP  6 0.00.00.0 0(  0) 0   
 0
   54 0.00.00.0 0(  0) 0   
 0
 - After (61 ch):
 rate  tpt eprob *prob  *ok(*cum)ok(  cum)
 ABCDP  1  0.0   0.0   0.00(   0) 0(0)
   54  0.0   0.0   0.00(   0) 0(0)
 
 *This also adds dynamic checks for overflow, lowers the size of the
 non-HT request (allowing  30 entries) and replaces the buddy-rounded
 allocations (s/sizeof(*ms) + 8192/8192).
 
 Signed-off-by: Karl Beldan karl.bel...@rivierawaves.com
 Cc: Felix Fietkau n...@openwrt.org
Acked-by: Felix Fietkau n...@openwrt.org
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH v2 4/4] mac80211: minstrel_ht: add basic support for VHT rates = 3SS@80MHz

2014-10-18 Thread Felix Fietkau
On 2014-10-17 21:50, Karl Beldan wrote:
 From: Karl Beldan karl.bel...@rivierawaves.com
 
 When the new CONFIG_MAC80211_RC_MINSTREL_VHT is not set (default 'N'),
 there is no behavioral change including in sampling and MCS_GROUP_RATES
 remains 8.
 Otherwise MCS_GROUP_RATES is 10, and a module parameter *vht_only*
 (default 'true'), restricts the rates selection to VHT when vht is
 supported.
 
 Regarding the debugfs stats buffer:
 It is explicitly increased from 8k to 32k to fit every rates incl. when
 both ht and vht rates are enabled, as for the format, before:
 type   rate tpt eprob *prob ret  *ok(*cum)ok(  cum)
 HT20/LGI ABCDP MCS0 0.0   0.0   0.0   10(   0) 0(0)
 after:
  type   rate  tpt eprob *prob ret  *ok(*cum)ok(  cum)
  HT20/LGI ABCDP MCS0  0.0   0.0   0.0   10(   0) 0(0)
 VHT40/LGI   MCS5/20.0   0.0   0.0   00(   0) 0(0)
 
 Signed-off-by: Karl Beldan karl.bel...@rivierawaves.com
 Cc: Felix Fietkau n...@openwrt.org
Aside from the module parameter issue that you already pointed out, the
series looks good to me.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/10] ath9k: use a random MAC address if the EEPROM address is invalid

2014-10-18 Thread Felix Fietkau
Based on OpenWrt patch by Gabor Juhos

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/hw.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index 47f410e..ee9fb52 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -19,6 +19,7 @@
 #include linux/module.h
 #include linux/time.h
 #include linux/bitops.h
+#include linux/etherdevice.h
 #include asm/unaligned.h
 
 #include hw.h
@@ -446,8 +447,16 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah)
common-macaddr[2 * i] = eeval  8;
common-macaddr[2 * i + 1] = eeval  0xff;
}
-   if (sum == 0 || sum == 0x * 3)
-   return -EADDRNOTAVAIL;
+   if (!is_valid_ether_addr(common-macaddr)) {
+   ath_err(common,
+   eeprom contains invalid mac address: %pM\n,
+   common-macaddr);
+
+   random_ether_addr(common-macaddr);
+   ath_err(common,
+   random mac address will be used: %pM\n,
+   common-macaddr);
+   }
 
return 0;
 }
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/10] ath9k: add support for endian swap of eeprom from platform data

2014-10-18 Thread Felix Fietkau
On some devices (especially little-endian ones), the flash EEPROM data
has a different endian, which needs to be detected.
Add a flag to the platform data to allow overriding that behavior

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/eeprom_def.c | 31 ++---
 drivers/net/wireless/ath/ath9k/hw.h |  1 +
 drivers/net/wireless/ath/ath9k/init.c   |  2 ++
 include/linux/ath9k_platform.h  |  1 +
 4 files changed, 14 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c 
b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 3218ca9..122b846 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -262,7 +262,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
 {
struct ar5416_eeprom_def *eep = ah-eeprom.def;
struct ath_common *common = ath9k_hw_common(ah);
-   u16 *eepdata, temp, magic, magic2;
+   u16 *eepdata, temp, magic;
u32 sum = 0, el;
bool need_swap = false;
int i, addr, size;
@@ -272,27 +272,16 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
return false;
}
 
-   if (!ath9k_hw_use_flash(ah)) {
-   ath_dbg(common, EEPROM, Read Magic = 0x%04X\n, magic);
-
-   if (magic != AR5416_EEPROM_MAGIC) {
-   magic2 = swab16(magic);
-
-   if (magic2 == AR5416_EEPROM_MAGIC) {
-   size = sizeof(struct ar5416_eeprom_def);
-   need_swap = true;
-   eepdata = (u16 *) (ah-eeprom);
+   if (swab16(magic) == AR5416_EEPROM_MAGIC 
+   !(ah-ah_flags  AH_NO_EEP_SWAP)) {
+   size = sizeof(struct ar5416_eeprom_def);
+   need_swap = true;
+   eepdata = (u16 *) (ah-eeprom);
 
-   for (addr = 0; addr  size / sizeof(u16); 
addr++) {
-   temp = swab16(*eepdata);
-   *eepdata = temp;
-   eepdata++;
-   }
-   } else {
-   ath_err(common,
-   Invalid EEPROM Magic. Endianness 
mismatch.\n);
-   return -EINVAL;
-   }
+   for (addr = 0; addr  size / sizeof(u16); addr++) {
+   temp = swab16(*eepdata);
+   *eepdata = temp;
+   eepdata++;
}
}
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.h 
b/drivers/net/wireless/ath/ath9k/hw.h
index f204099..c6dba9b 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -731,6 +731,7 @@ enum ath_cal_list {
 #define AH_USE_EEPROM   0x1
 #define AH_UNPLUGGED0x2 /* The card has been physically removed. */
 #define AH_FASTCC   0x4
+#define AH_NO_EEP_SWAP  0x8 /* Do not swap EEPROM data */
 
 struct ath_hw {
struct ath_ops reg_ops;
diff --git a/drivers/net/wireless/ath/ath9k/init.c 
b/drivers/net/wireless/ath/ath9k/init.c
index 57a1760..5d9c711 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -531,6 +531,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
ah-is_clk_25mhz = pdata-is_clk_25mhz;
ah-get_mac_revision = pdata-get_mac_revision;
ah-external_reset = pdata-external_reset;
+   if (!pdata-endian_check)
+   ah-ah_flags |= AH_NO_EEP_SWAP;
}
 
common-ops = ah-reg_ops;
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
index a495a95..4350165 100644
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
@@ -31,6 +31,7 @@ struct ath9k_platform_data {
u32 gpio_mask;
u32 gpio_val;
 
+   bool endian_check;
bool is_clk_25mhz;
bool tx_gain_buffalo;
 
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/10] ath9k: fix processing RXORN interrupts

2014-10-18 Thread Felix Fietkau
The goto chip_reset is a bit misleading, because it does not actually
issue a chip reset. Instead it is bypassing processing of other
interrupts and assumes that the tasklet will issue a chip reset.

In the case of RXORN this does not happen, so bypassing processing of
other interrupts will simply allow them to fire again. Even if RXORN
was triggering a reset, it is not critical enough to need the bypass
here.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/main.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c 
b/drivers/net/wireless/ath/ath9k/main.c
index 6f6a974..e7d4833 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -539,11 +539,10 @@ irqreturn_t ath_isr(int irq, void *dev)
sched = true;
 
/*
-* If a FATAL or RXORN interrupt is received, we have to reset the
-* chip immediately.
+* If a FATAL interrupt is received, we have to reset the chip
+* immediately.
 */
-   if ((status  ATH9K_INT_FATAL) || ((status  ATH9K_INT_RXORN) 
-   !(ah-caps.hw_caps  ATH9K_HW_CAP_EDMA)))
+   if (status  ATH9K_INT_FATAL)
goto chip_reset;
 
if ((ah-config.hw_hang_checks  HW_BB_WATCHDOG) 
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/10] ath9k: allow disabling bands via platform data

2014-10-18 Thread Felix Fietkau
Some devices have multiple bands enables in the EEPROM data, even though
they are only calibrated for one. Allow platform data to disable
unsupported bands.

Signed-off-by: Gabor Juhos juh...@openwrt.org
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/hw.c   | 24 
 drivers/net/wireless/ath/ath9k/hw.h   |  2 ++
 drivers/net/wireless/ath/ath9k/init.c |  2 ++
 include/linux/ath9k_platform.h|  2 ++
 4 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index 85a7817..47f410e 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2344,17 +2344,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
}
 
eeval = ah-eep_ops-get_eeprom(ah, EEP_OP_MODE);
-   if ((eeval  (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
-   ath_err(common,
-   no band has been marked as supported in EEPROM\n);
-   return -EINVAL;
+
+   if (eeval  AR5416_OPFLAGS_11A) {
+   if (ah-disable_5ghz)
+   ath_warn(common, disabling 5GHz band\n);
+   else
+   pCap-hw_caps |= ATH9K_HW_CAP_5GHZ;
}
 
-   if (eeval  AR5416_OPFLAGS_11A)
-   pCap-hw_caps |= ATH9K_HW_CAP_5GHZ;
+   if (eeval  AR5416_OPFLAGS_11G) {
+   if (ah-disable_2ghz)
+   ath_warn(common, disabling 2GHz band\n);
+   else
+   pCap-hw_caps |= ATH9K_HW_CAP_2GHZ;
+   }
 
-   if (eeval  AR5416_OPFLAGS_11G)
-   pCap-hw_caps |= ATH9K_HW_CAP_2GHZ;
+   if ((pCap-hw_caps  (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) {
+   ath_err(common, both bands are disabled\n);
+   return -EINVAL;
+   }
 
if (AR_SREV_9485(ah) ||
AR_SREV_9285(ah) ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h 
b/drivers/net/wireless/ath/ath9k/hw.h
index c6dba9b..e49721e8 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -930,6 +930,8 @@ struct ath_hw {
bool is_clk_25mhz;
int (*get_mac_revision)(void);
int (*external_reset)(void);
+   bool disable_2ghz;
+   bool disable_5ghz;
 
const struct firmware *eeprom_blob;
 
diff --git a/drivers/net/wireless/ath/ath9k/init.c 
b/drivers/net/wireless/ath/ath9k/init.c
index 5d9c711..2294109 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -531,6 +531,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
ah-is_clk_25mhz = pdata-is_clk_25mhz;
ah-get_mac_revision = pdata-get_mac_revision;
ah-external_reset = pdata-external_reset;
+   ah-disable_2ghz = pdata-disable_2ghz;
+   ah-disable_5ghz = pdata-disable_5ghz;
if (!pdata-endian_check)
ah-ah_flags |= AH_NO_EEP_SWAP;
}
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
index 4350165..33eb274 100644
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
@@ -34,6 +34,8 @@ struct ath9k_platform_data {
bool endian_check;
bool is_clk_25mhz;
bool tx_gain_buffalo;
+   bool disable_2ghz;
+   bool disable_5ghz;
 
int (*get_mac_revision)(void);
int (*external_reset)(void);
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/10] ath9k_hw: do not run NF and periodic calibration at the same time

2014-10-18 Thread Felix Fietkau
It can cause inconsistent calibration results or in some cases turn the
radio deaf.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/ar9002_calib.c | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c 
b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 6bfdebf..77388fb 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -660,7 +660,6 @@ static void ar9002_hw_olc_temp_compensation(struct ath_hw 
*ah)
 static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
   u8 rxchainmask, bool longcal)
 {
-   bool iscaldone = true;
struct ath9k_cal_list *currCal = ah-cal_list_curr;
bool nfcal, nfcal_pending = false;
int ret;
@@ -672,15 +671,13 @@ static int ar9002_hw_calibrate(struct ath_hw *ah, struct 
ath9k_channel *chan,
if (currCal  !nfcal 
(currCal-calState == CAL_RUNNING ||
 currCal-calState == CAL_WAITING)) {
-   iscaldone = ar9002_hw_per_calibration(ah, chan,
- rxchainmask, currCal);
-   if (iscaldone) {
-   ah-cal_list_curr = currCal = currCal-calNext;
-
-   if (currCal-calState == CAL_WAITING) {
-   iscaldone = false;
-   ath9k_hw_reset_calibration(ah, currCal);
-   }
+   if (!ar9002_hw_per_calibration(ah, chan, rxchainmask, currCal))
+   return 0;
+
+   ah-cal_list_curr = currCal = currCal-calNext;
+   if (currCal-calState == CAL_WAITING) {
+   ath9k_hw_reset_calibration(ah, currCal);
+   return 0;
}
}
 
@@ -710,7 +707,7 @@ static int ar9002_hw_calibrate(struct ath_hw *ah, struct 
ath9k_channel *chan,
}
}
 
-   return iscaldone;
+   return 1;
 }
 
 /* Carrier leakage Calibration fix */
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 0/4] add VHT support to minstrel_ht

2014-10-18 Thread Felix Fietkau
On 2014-10-18 19:13, Karl Beldan wrote:
 From: Karl Beldan karl.bel...@rivierawaves.com
 
 
 Karl Beldan (4):
   mac80211: minstrel_ht: Increase the range of handled rate indexes
   mac80211: minstrel_ht: macros adjustments for future VHT_GROUPs
   mac80211: minstrel_ht: include type (cck/ht) in rates flag
   mac80211: minstrel_ht: add basic support for VHT rates = 3SS@80MHz
 v2:
 - typo in Kconfig
 - adjust room in debugfs rc_stats buffer
 - add a module param to mix ht rates with vht ones
 - default to 3SS instead of 2SS (with mac80211: minstrel_ht: macros
   adjustments for future VHT_GROUPs)
 - use common MINSTREL_MAX_STREAMS both for VHT and HT so that we can get
   rid of the 'MINSTREL_MAX_STREAMS = 3' checks for minstrel_mcs_groups
 v3:
 - put module param *vht_only* under CONFIG_MAC80211_RC_MINSTREL_VHT
Acked-by: Felix Fietkau n...@openwrt.org
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 01/10] ath9k_hw: make support for PC-OEM cards optional

2014-10-20 Thread Felix Fietkau
On 2014-10-20 09:57, Sujith Manoharan wrote:
 Felix Fietkau wrote:
 diff --git a/drivers/net/wireless/ath/ath9k/hw.h 
 b/drivers/net/wireless/ath/ath9k/hw.h
 index 975074f..7a81f5b 100644
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
 @@ -244,13 +244,20 @@ enum ath9k_hw_caps {
  ATH9K_HW_CAP_2GHZ   = BIT(11),
  ATH9K_HW_CAP_5GHZ   = BIT(12),
  ATH9K_HW_CAP_APM= BIT(13),
 +#ifdef CONFIG_ATH9K_PCOEM
  ATH9K_HW_CAP_RTT= BIT(14),
  ATH9K_HW_CAP_MCI= BIT(15),
 -ATH9K_HW_CAP_DFS= BIT(16),
 -ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17),
 -ATH9K_HW_CAP_PAPRD  = BIT(18),
 -ATH9K_HW_CAP_FCC_BAND_SWITCH= BIT(19),
 -ATH9K_HW_CAP_BT_ANT_DIV = BIT(20),
 +ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(16),
 +ATH9K_HW_CAP_BT_ANT_DIV = BIT(17),
 +#else
 +ATH9K_HW_CAP_RTT= 0,
 +ATH9K_HW_CAP_MCI= 0,
 +ATH9K_HW_WOW_DEVICE_CAPABLE = 0,
 +ATH9K_HW_CAP_BT_ANT_DIV = 0,
 +#endif
 +ATH9K_HW_CAP_DFS= BIT(18),
 +ATH9K_HW_CAP_PAPRD  = BIT(19),
 +ATH9K_HW_CAP_FCC_BAND_SWITCH= BIT(20),
  };
 
 Why is this needed ?
To allow the compiler to optimize out code checking for these features.
That way we don't have to #ifdef all those places where this gets used.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 02/10] ath9k_hw: remove support for UB124 tx gain table

2014-10-20 Thread Felix Fietkau
On 2014-10-20 09:58, Sujith Manoharan wrote:
 Felix Fietkau wrote:
 -else if (AR_SREV_9340(ah))
 -INIT_INI_ARRAY(ah-iniModesTxGain,
 -ar9340Modes_ub124_tx_gain_table_1p0);
 
 Shouldn't the array in ar9340_initvals.h also be removed ?
We can do that later (when we change the qca-swiss-army-knife code).
As long as it isn't referenced, the compiler will not emit the data into
object files.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 03/10] ath9k: fix processing RXORN interrupts

2014-10-20 Thread Felix Fietkau
On 2014-10-20 10:15, Sujith Manoharan wrote:
 Felix Fietkau wrote:
 The goto chip_reset is a bit misleading, because it does not actually
 issue a chip reset. Instead it is bypassing processing of other
 interrupts and assumes that the tasklet will issue a chip reset.
 
 Well, we kill interrupts and the tasklet sets ATH_OP_HW_RESET,
 so no more interrupts will be processed in ath_isr(), so this
 is a fair assumption.
Except it only does that for FATAL, not RXORN.

 In the case of RXORN this does not happen, so bypassing processing of
 other interrupts will simply allow them to fire again. Even if RXORN
 was triggering a reset, it is not critical enough to need the bypass
 here.
 
 Wouldn't this be fixed by just processing RXORN in the tasklet,
 along with FATAL ? Or are you saying that RXORN doesn't need a
 chip reset in both edma/legacy, since the edma check has been dropped ?
I'm not sure if we should actually do the chip reset for RXORN, but even
if we should, we don't need this 'goto chip_reset' in ath_isr.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: iwlwifi: Reason 7 periodic disconnect

2014-10-21 Thread Felix Fietkau
On 2014-10-21 07:02, Emmanuel Grumbach wrote:
 On Mon, Oct 20, 2014 at 10:29 PM, Laurențiu Nicola lnic...@dend.ro wrote:
 No, nothing in the DD-WRT syslog. The IP seems to be the one cached by
 my DHCP client. I also tried various suggestions found on the internet,
 but nothing helped.

 
 Can you please try to have another device in monitor mode to sniff the
 traffic going on?
 Felix, can you please tell me when DD-WRT can send a deauth with reason code 
 7?
What kind of device is it, and what software version?

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: iwlwifi: Reason 7 periodic disconnect

2014-10-21 Thread Felix Fietkau
On 2014-10-21 10:23, Laurențiu Nicola wrote:
 It's an ASUS RT-N66U running NEWD-2/K3X from r24160.
This is a Broadcom based device, so it should behave in the same way as
other APs/Routers running the Broadcom drivers.
The driver should only send Reason 7 when receiving a PS-Poll, BlockAck,
BlockAckReq or Action frame from a station that's not associated, so
probably it has already kicked out your iwlwifi client earlier. Not sure
why that doesn't show up in the log though.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] ath: use CTL region from cfg80211 if unset in EEPROM

2014-10-22 Thread Felix Fietkau
Many AP devices do not have the proper regulatory domain programmed in
EEPROM. Instead they expect the software to set the appropriate region.
For these devices, the country code defaults to US, and the driver uses
the US CTL tables as well.
On devices bought in Europe this can lead to tx power being set too high
on the band edges, even if the cfg80211 regdomain is set correctly.
Fix this issue by taking into account the DFS region, but only when the
EEPROM regdomain is set to default.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath.h  |  1 +
 drivers/net/wireless/ath/regd.c | 14 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 9c56ecb..999d24f 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -80,6 +80,7 @@ struct reg_dmn_pair_mapping {
 
 struct ath_regulatory {
char alpha2[2];
+   enum nl80211_dfs_regions region;
u16 country_code;
u16 max_power_level;
u16 current_rd;
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index 415393d..06ea6cc 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -515,6 +515,7 @@ void ath_reg_notifier_apply(struct wiphy *wiphy,
if (!request)
return;
 
+   reg-region = request-dfs_region;
switch (request-initiator) {
case NL80211_REGDOM_SET_BY_CORE:
/*
@@ -779,6 +780,19 @@ u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
return SD_NO_CTL;
}
 
+   if (ath_regd_get_eepromRD(reg) == CTRY_DEFAULT) {
+   switch (reg-region) {
+   case NL80211_DFS_FCC:
+   return CTL_FCC;
+   case NL80211_DFS_ETSI:
+   return CTL_ETSI;
+   case NL80211_DFS_JP:
+   return CTL_MKK;
+   default:
+   break;
+   }
+   }
+
switch (band) {
case IEEE80211_BAND_2GHZ:
return reg-regpair-reg_2ghz_ctl;
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] mac80211: add support for driver tx power reporting

2014-10-22 Thread Felix Fietkau
The configured tx power is often limited by hardware capabilities,
channel settings, antenna configuration, etc.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 include/net/mac80211.h | 5 +
 net/mac80211/cfg.c | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 0ad1f47..41b0e60 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2838,6 +2838,9 @@ enum ieee80211_roc_type {
  * @get_expected_throughput: extract the expected throughput towards the
  * specified station. The returned value is expressed in Kbps. It returns 0
  * if the RC algorithm does not have proper data to provide.
+ *
+ * @get_txpower: get current maximum tx power (in dBm) based on configuration
+ * and hardware limits.
  */
 struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -3039,6 +3042,8 @@ struct ieee80211_ops {
int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
u32 (*get_expected_throughput)(struct ieee80211_sta *sta);
+   int (*get_txpower)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+  int *dbm);
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index fb6a150..7cb31a8 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2081,6 +2081,9 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy,
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 
+   if (local-ops-get_txpower)
+   return local-ops-get_txpower(local-hw, sdata-vif, dbm);
+
if (!local-use_chanctx)
*dbm = local-hw.conf.power_level;
else
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] ath9k_common: always update value in ath9k_cmn_update_txpow

2014-10-22 Thread Felix Fietkau
In some cases the limit may be the same as reg-power_limit, but the
actual value that the hardware uses is not up to date. In that case, a
wrong value for current tx power is tracked internally.
Fix this by unconditionally updating it.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/common.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/common.c 
b/drivers/net/wireless/ath/ath9k/common.c
index c6dd7f1..33b0c7a 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -368,11 +368,11 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 
cur_txpow,
 {
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
 
-   if (reg-power_limit != new_txpow) {
+   if (reg-power_limit != new_txpow)
ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
-   /* read back in case value is clamped */
-   *txpower = reg-max_power_level;
-   }
+
+   /* read back in case value is clamped */
+   *txpower = reg-max_power_level;
 }
 EXPORT_SYMBOL(ath9k_cmn_update_txpow);
 
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] ath10k: add SURVEY_INFO_IN_USE for current channel on survey

2014-10-22 Thread Felix Fietkau
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath10k/mac.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c 
b/drivers/net/wireless/ath/ath10k/mac.c
index 4670930..bc440dc 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3975,6 +3975,9 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int 
idx,
 
survey-channel = sband-channels[idx];
 
+   if (ar-rx_channel == survey-channel)
+   survey-filled |= SURVEY_INFO_IN_USE;
+
 exit:
mutex_unlock(ar-conf_mutex);
return ret;
-- 
2.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] ath10k: add SURVEY_INFO_IN_USE for current channel on survey

2014-10-23 Thread Felix Fietkau
On 2014-10-23 09:13, Kalle Valo wrote:
 Felix Fietkau n...@openwrt.org writes:
 
 Signed-off-by: Felix Fietkau n...@openwrt.org
 ---
  drivers/net/wireless/ath/ath10k/mac.c | 3 +++
  1 file changed, 3 insertions(+)

 diff --git a/drivers/net/wireless/ath/ath10k/mac.c 
 b/drivers/net/wireless/ath/ath10k/mac.c
 index 4670930..bc440dc 100644
 --- a/drivers/net/wireless/ath/ath10k/mac.c
 +++ b/drivers/net/wireless/ath/ath10k/mac.c
 @@ -3975,6 +3975,9 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, 
 int idx,
  
  survey-channel = sband-channels[idx];
  
 +if (ar-rx_channel == survey-channel)
 +survey-filled |= SURVEY_INFO_IN_USE;
 +
 
 Why? Does this fix a visible bug? What changes from user space point of
 view? I'm asking because I want to add something to the commit log.
When user space requests survey info, it is useful to know which of the
survey data refers to the channel that is currently actively being used.
One of the use cases is getting the current channel noise for status output.
Without this flag you would have to look up the channel separately and
then compare it against the frequency in the survey output in user space.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 10/10] ath9k: use a random MAC address if the EEPROM address is invalid

2014-10-25 Thread Felix Fietkau
Based on OpenWrt patch by Gabor Juhos

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/hw.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index 47f410e..ee9fb52 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -19,6 +19,7 @@
 #include linux/module.h
 #include linux/time.h
 #include linux/bitops.h
+#include linux/etherdevice.h
 #include asm/unaligned.h
 
 #include hw.h
@@ -446,8 +447,16 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah)
common-macaddr[2 * i] = eeval  8;
common-macaddr[2 * i + 1] = eeval  0xff;
}
-   if (sum == 0 || sum == 0x * 3)
-   return -EADDRNOTAVAIL;
+   if (!is_valid_ether_addr(common-macaddr)) {
+   ath_err(common,
+   eeprom contains invalid mac address: %pM\n,
+   common-macaddr);
+
+   random_ether_addr(common-macaddr);
+   ath_err(common,
+   random mac address will be used: %pM\n,
+   common-macaddr);
+   }
 
return 0;
 }
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 04/10] ath9k: clean up debugfs print of reset causes

2014-10-25 Thread Felix Fietkau
Reduce code duplication

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/debug.c | 48 +++---
 1 file changed, 21 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/debug.c 
b/drivers/net/wireless/ath/ath9k/debug.c
index 46f20a3..cf4a98b 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -852,36 +852,30 @@ static ssize_t read_file_reset(struct file *file, char 
__user *user_buf,
   size_t count, loff_t *ppos)
 {
struct ath_softc *sc = file-private_data;
+   static const char * const reset_cause[__RESET_TYPE_MAX] = {
+   [RESET_TYPE_BB_HANG] = Baseband Hang,
+   [RESET_TYPE_BB_WATCHDOG] = Baseband Watchdog,
+   [RESET_TYPE_FATAL_INT] = Fatal HW Error,
+   [RESET_TYPE_TX_ERROR] = TX HW error,
+   [RESET_TYPE_TX_GTT] = Transmit timeout,
+   [RESET_TYPE_TX_HANG] = TX Path Hang,
+   [RESET_TYPE_PLL_HANG] = PLL RX Hang,
+   [RESET_TYPE_MAC_HANG] = MAC Hang,
+   [RESET_TYPE_BEACON_STUCK] = Stuck Beacon,
+   [RESET_TYPE_MCI] = MCI Reset,
+   };
char buf[512];
unsigned int len = 0;
+   int i;
 
-   len += scnprintf(buf + len, sizeof(buf) - len,
-%17s: %2d\n, Baseband Hang,
-sc-debug.stats.reset[RESET_TYPE_BB_HANG]);
-   len += scnprintf(buf + len, sizeof(buf) - len,
-%17s: %2d\n, Baseband Watchdog,
-sc-debug.stats.reset[RESET_TYPE_BB_WATCHDOG]);
-   len += scnprintf(buf + len, sizeof(buf) - len,
-%17s: %2d\n, Fatal HW Error,
-sc-debug.stats.reset[RESET_TYPE_FATAL_INT]);
-   len += scnprintf(buf + len, sizeof(buf) - len,
-%17s: %2d\n, TX HW error,
-sc-debug.stats.reset[RESET_TYPE_TX_ERROR]);
-   len += scnprintf(buf + len, sizeof(buf) - len,
-%17s: %2d\n, TX Path Hang,
-sc-debug.stats.reset[RESET_TYPE_TX_HANG]);
-   len += scnprintf(buf + len, sizeof(buf) - len,
-%17s: %2d\n, PLL RX Hang,
-sc-debug.stats.reset[RESET_TYPE_PLL_HANG]);
-   len += scnprintf(buf + len, sizeof(buf) - len,
-%17s: %2d\n, MAC Hang,
-sc-debug.stats.reset[RESET_TYPE_MAC_HANG]);
-   len += scnprintf(buf + len, sizeof(buf) - len,
-%17s: %2d\n, Stuck Beacon,
-sc-debug.stats.reset[RESET_TYPE_BEACON_STUCK]);
-   len += scnprintf(buf + len, sizeof(buf) - len,
-%17s: %2d\n, MCI Reset,
-sc-debug.stats.reset[RESET_TYPE_MCI]);
+   for (i = 0; i  ARRAY_SIZE(reset_cause); i++) {
+   if (!reset_cause[i])
+   continue;
+
+   len += scnprintf(buf + len, sizeof(buf) - len,
+%17s: %2d\n, reset_cause[i],
+sc-debug.stats.reset[i]);
+   }
 
if (len  sizeof(buf))
len = sizeof(buf);
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 05/10] ath9k: restart hardware after noise floor calibration failure

2014-10-25 Thread Felix Fietkau
When NF calibration fails, the radio often becomes deaf. The usual
hardware hang checks do not detect this, so it's better to issue a reset
when that happens.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/ar9002_calib.c | 11 ++-
 drivers/net/wireless/ath/ath9k/ar9003_calib.c | 11 ++-
 drivers/net/wireless/ath/ath9k/calib.c|  6 --
 drivers/net/wireless/ath/ath9k/calib.h|  2 +-
 drivers/net/wireless/ath/ath9k/debug.c|  1 +
 drivers/net/wireless/ath/ath9k/debug.h|  1 +
 drivers/net/wireless/ath/ath9k/hw-ops.h   |  7 +++
 drivers/net/wireless/ath/ath9k/hw.h   |  6 ++
 drivers/net/wireless/ath/ath9k/link.c | 12 +---
 9 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c 
b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index cdc7400..6bfdebf 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -657,14 +657,13 @@ static void ar9002_hw_olc_temp_compensation(struct ath_hw 
*ah)
ar9280_hw_olc_temp_compensation(ah);
 }
 
-static bool ar9002_hw_calibrate(struct ath_hw *ah,
-   struct ath9k_channel *chan,
-   u8 rxchainmask,
-   bool longcal)
+static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
+  u8 rxchainmask, bool longcal)
 {
bool iscaldone = true;
struct ath9k_cal_list *currCal = ah-cal_list_curr;
bool nfcal, nfcal_pending = false;
+   int ret;
 
nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL)  AR_PHY_AGC_CONTROL_NF);
if (ah-caldata)
@@ -698,7 +697,9 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah,
 * NF is slow time-variant, so it is OK to use a
 * historical value.
 */
-   ath9k_hw_loadnf(ah, ah-curchan);
+   ret = ath9k_hw_loadnf(ah, ah-curchan);
+   if (ret  0)
+   return ret;
}
 
if (longcal) {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c 
b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index ac8301e..06ab71d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -121,13 +121,12 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah,
return iscaldone;
 }
 
-static bool ar9003_hw_calibrate(struct ath_hw *ah,
-   struct ath9k_channel *chan,
-   u8 rxchainmask,
-   bool longcal)
+static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
+  u8 rxchainmask, bool longcal)
 {
bool iscaldone = true;
struct ath9k_cal_list *currCal = ah-cal_list_curr;
+   int ret;
 
/*
 * For given calibration:
@@ -163,7 +162,9 @@ static bool ar9003_hw_calibrate(struct ath_hw *ah,
 * NF is slow time-variant, so it is OK to use a historical
 * value.
 */
-   ath9k_hw_loadnf(ah, ah-curchan);
+   ret = ath9k_hw_loadnf(ah, ah-curchan);
+   if (ret  0)
+   return ret;
 
/* start NF calibration, without updating BB NF register */
ath9k_hw_start_nfcal(ah, false);
diff --git a/drivers/net/wireless/ath/ath9k/calib.c 
b/drivers/net/wireless/ath/ath9k/calib.c
index 278365b..e200a6e 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -234,7 +234,7 @@ void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update)
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 }
 
-void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
+int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
 {
struct ath9k_nfcal_hist *h = NULL;
unsigned i, j;
@@ -301,7 +301,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct 
ath9k_channel *chan)
ath_dbg(common, ANY,
Timeout while waiting for nf to load: 
AR_PHY_AGC_CONTROL=0x%x\n,
REG_READ(ah, AR_PHY_AGC_CONTROL));
-   return;
+   return -ETIMEDOUT;
}
 
/*
@@ -322,6 +322,8 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct 
ath9k_channel *chan)
}
}
REGWRITE_BUFFER_FLUSH(ah);
+
+   return 0;
 }
 
 
diff --git a/drivers/net/wireless/ath/ath9k/calib.h 
b/drivers/net/wireless/ath/ath9k/calib.h
index b8ed95e..87badf4 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -109,7 +109,7 @@ struct ath9k_pacal_info{
 
 bool ath9k_hw_reset_calvalid

[PATCH v2 06/10] ath9k_hw: do not run NF and periodic calibration at the same time

2014-10-25 Thread Felix Fietkau
It can cause inconsistent calibration results or in some cases turn the
radio deaf.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/ar9002_calib.c | 29 +--
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c 
b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 6bfdebf..07994e3 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -660,27 +660,26 @@ static void ar9002_hw_olc_temp_compensation(struct ath_hw 
*ah)
 static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
   u8 rxchainmask, bool longcal)
 {
-   bool iscaldone = true;
struct ath9k_cal_list *currCal = ah-cal_list_curr;
-   bool nfcal, nfcal_pending = false;
+   bool nfcal, nfcal_pending = false, percal_pending;
int ret;
 
nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL)  AR_PHY_AGC_CONTROL_NF);
if (ah-caldata)
nfcal_pending = test_bit(NFCAL_PENDING, 
ah-caldata-cal_flags);
 
-   if (currCal  !nfcal 
-   (currCal-calState == CAL_RUNNING ||
-currCal-calState == CAL_WAITING)) {
-   iscaldone = ar9002_hw_per_calibration(ah, chan,
- rxchainmask, currCal);
-   if (iscaldone) {
-   ah-cal_list_curr = currCal = currCal-calNext;
-
-   if (currCal-calState == CAL_WAITING) {
-   iscaldone = false;
-   ath9k_hw_reset_calibration(ah, currCal);
-   }
+   percal_pending = (currCal 
+ (currCal-calState == CAL_RUNNING ||
+  currCal-calState == CAL_WAITING));
+
+   if (percal_pending  !nfcal) {
+   if (!ar9002_hw_per_calibration(ah, chan, rxchainmask, currCal))
+   return 0;
+
+   ah-cal_list_curr = currCal = currCal-calNext;
+   if (currCal-calState == CAL_WAITING) {
+   ath9k_hw_reset_calibration(ah, currCal);
+   return 0;
}
}
 
@@ -710,7 +709,7 @@ static int ar9002_hw_calibrate(struct ath_hw *ah, struct 
ath9k_channel *chan,
}
}
 
-   return iscaldone;
+   return !percal_pending;
 }
 
 /* Carrier leakage Calibration fix */
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 07/10] ath9k_hw: start initial NF calibration after PA calibration on AR9003

2014-10-25 Thread Felix Fietkau
This makes the initial NF calibration less likely to fail.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/ar9002_calib.c | 2 ++
 drivers/net/wireless/ath/ath9k/hw.c   | 6 --
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c 
b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 07994e3..42190b6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -856,6 +856,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct 
ath9k_channel *chan)
 
/* Do PA Calibration */
ar9002_hw_pa_cal(ah, true);
+   ath9k_hw_loadnf(ah, chan);
+   ath9k_hw_start_nfcal(ah, true);
 
if (ah-caldata)
set_bit(NFCAL_PENDING, ah-caldata-cal_flags);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index 8be4b14..85a7817 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1953,8 +1953,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct 
ath9k_channel *chan,
if (ath9k_hw_mci_is_enabled(ah))
ar9003_mci_check_bt(ah);
 
-   ath9k_hw_loadnf(ah, chan);
-   ath9k_hw_start_nfcal(ah, true);
+   if (AR_SREV_9300_20_OR_LATER(ah)) {
+   ath9k_hw_loadnf(ah, chan);
+   ath9k_hw_start_nfcal(ah, true);
+   }
 
if (AR_SREV_9300_20_OR_LATER(ah))
ar9003_hw_bb_watchdog_config(ah);
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 02/10] ath9k_hw: remove support for UB124 tx gain table

2014-10-25 Thread Felix Fietkau
UB124 is a USB based reference design not supported by ath9k or
ath9k_htc.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/ar9003_hw.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c 
b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index ddef9ee..cb09102 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -670,9 +670,6 @@ static void ar9003_tx_gain_table_mode5(struct ath_hw *ah)
if (AR_SREV_9485_11_OR_LATER(ah))
INIT_INI_ARRAY(ah-iniModesTxGain,
ar9485Modes_green_ob_db_tx_gain_1_1);
-   else if (AR_SREV_9340(ah))
-   INIT_INI_ARRAY(ah-iniModesTxGain,
-   ar9340Modes_ub124_tx_gain_table_1p0);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(ah-iniModesTxGain,
ar9580_1p0_type5_tx_gain_table);
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 09/10] ath9k: allow disabling bands via platform data

2014-10-25 Thread Felix Fietkau
Some devices have multiple bands enables in the EEPROM data, even though
they are only calibrated for one. Allow platform data to disable
unsupported bands.

Signed-off-by: Gabor Juhos juh...@openwrt.org
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/hw.c   | 24 
 drivers/net/wireless/ath/ath9k/hw.h   |  2 ++
 drivers/net/wireless/ath/ath9k/init.c |  2 ++
 include/linux/ath9k_platform.h|  2 ++
 4 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index 85a7817..47f410e 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2344,17 +2344,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
}
 
eeval = ah-eep_ops-get_eeprom(ah, EEP_OP_MODE);
-   if ((eeval  (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
-   ath_err(common,
-   no band has been marked as supported in EEPROM\n);
-   return -EINVAL;
+
+   if (eeval  AR5416_OPFLAGS_11A) {
+   if (ah-disable_5ghz)
+   ath_warn(common, disabling 5GHz band\n);
+   else
+   pCap-hw_caps |= ATH9K_HW_CAP_5GHZ;
}
 
-   if (eeval  AR5416_OPFLAGS_11A)
-   pCap-hw_caps |= ATH9K_HW_CAP_5GHZ;
+   if (eeval  AR5416_OPFLAGS_11G) {
+   if (ah-disable_2ghz)
+   ath_warn(common, disabling 2GHz band\n);
+   else
+   pCap-hw_caps |= ATH9K_HW_CAP_2GHZ;
+   }
 
-   if (eeval  AR5416_OPFLAGS_11G)
-   pCap-hw_caps |= ATH9K_HW_CAP_2GHZ;
+   if ((pCap-hw_caps  (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) {
+   ath_err(common, both bands are disabled\n);
+   return -EINVAL;
+   }
 
if (AR_SREV_9485(ah) ||
AR_SREV_9285(ah) ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h 
b/drivers/net/wireless/ath/ath9k/hw.h
index c6dba9b..e49721e8 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -930,6 +930,8 @@ struct ath_hw {
bool is_clk_25mhz;
int (*get_mac_revision)(void);
int (*external_reset)(void);
+   bool disable_2ghz;
+   bool disable_5ghz;
 
const struct firmware *eeprom_blob;
 
diff --git a/drivers/net/wireless/ath/ath9k/init.c 
b/drivers/net/wireless/ath/ath9k/init.c
index 3a1da83..a4d69a0 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -531,6 +531,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
ah-is_clk_25mhz = pdata-is_clk_25mhz;
ah-get_mac_revision = pdata-get_mac_revision;
ah-external_reset = pdata-external_reset;
+   ah-disable_2ghz = pdata-disable_2ghz;
+   ah-disable_5ghz = pdata-disable_5ghz;
if (!pdata-endian_check)
ah-ah_flags |= AH_NO_EEP_SWAP;
}
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
index 4350165..33eb274 100644
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
@@ -34,6 +34,8 @@ struct ath9k_platform_data {
bool endian_check;
bool is_clk_25mhz;
bool tx_gain_buffalo;
+   bool disable_2ghz;
+   bool disable_5ghz;
 
int (*get_mac_revision)(void);
int (*external_reset)(void);
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 08/10] ath9k: add support for endian swap of eeprom from platform data

2014-10-25 Thread Felix Fietkau
On some devices (especially little-endian ones), the flash EEPROM data
has a different endian, which needs to be detected.
Add a flag to the platform data to allow overriding that behavior

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/eeprom_def.c | 31 ++---
 drivers/net/wireless/ath/ath9k/hw.h |  1 +
 drivers/net/wireless/ath/ath9k/init.c   |  2 ++
 include/linux/ath9k_platform.h  |  1 +
 4 files changed, 14 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c 
b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 3218ca9..122b846 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -262,7 +262,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
 {
struct ar5416_eeprom_def *eep = ah-eeprom.def;
struct ath_common *common = ath9k_hw_common(ah);
-   u16 *eepdata, temp, magic, magic2;
+   u16 *eepdata, temp, magic;
u32 sum = 0, el;
bool need_swap = false;
int i, addr, size;
@@ -272,27 +272,16 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
return false;
}
 
-   if (!ath9k_hw_use_flash(ah)) {
-   ath_dbg(common, EEPROM, Read Magic = 0x%04X\n, magic);
-
-   if (magic != AR5416_EEPROM_MAGIC) {
-   magic2 = swab16(magic);
-
-   if (magic2 == AR5416_EEPROM_MAGIC) {
-   size = sizeof(struct ar5416_eeprom_def);
-   need_swap = true;
-   eepdata = (u16 *) (ah-eeprom);
+   if (swab16(magic) == AR5416_EEPROM_MAGIC 
+   !(ah-ah_flags  AH_NO_EEP_SWAP)) {
+   size = sizeof(struct ar5416_eeprom_def);
+   need_swap = true;
+   eepdata = (u16 *) (ah-eeprom);
 
-   for (addr = 0; addr  size / sizeof(u16); 
addr++) {
-   temp = swab16(*eepdata);
-   *eepdata = temp;
-   eepdata++;
-   }
-   } else {
-   ath_err(common,
-   Invalid EEPROM Magic. Endianness 
mismatch.\n);
-   return -EINVAL;
-   }
+   for (addr = 0; addr  size / sizeof(u16); addr++) {
+   temp = swab16(*eepdata);
+   *eepdata = temp;
+   eepdata++;
}
}
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.h 
b/drivers/net/wireless/ath/ath9k/hw.h
index f204099..c6dba9b 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -731,6 +731,7 @@ enum ath_cal_list {
 #define AH_USE_EEPROM   0x1
 #define AH_UNPLUGGED0x2 /* The card has been physically removed. */
 #define AH_FASTCC   0x4
+#define AH_NO_EEP_SWAP  0x8 /* Do not swap EEPROM data */
 
 struct ath_hw {
struct ath_ops reg_ops;
diff --git a/drivers/net/wireless/ath/ath9k/init.c 
b/drivers/net/wireless/ath/ath9k/init.c
index 0d80011..3a1da83 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -531,6 +531,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
ah-is_clk_25mhz = pdata-is_clk_25mhz;
ah-get_mac_revision = pdata-get_mac_revision;
ah-external_reset = pdata-external_reset;
+   if (!pdata-endian_check)
+   ah-ah_flags |= AH_NO_EEP_SWAP;
}
 
common-ops = ah-reg_ops;
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
index a495a95..4350165 100644
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
@@ -31,6 +31,7 @@ struct ath9k_platform_data {
u32 gpio_mask;
u32 gpio_val;
 
+   bool endian_check;
bool is_clk_25mhz;
bool tx_gain_buffalo;
 
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3.18] mac80211: flush keys for AP mode on ieee80211_do_stop

2014-10-27 Thread Felix Fietkau
Userspace can add keys to an AP mode interface before start_ap has been
called. If there have been no calls to start_ap/stop_ap in the mean
time, the keys will still be around when the interface is brought down.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/iface.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index af23722..b8efd5b 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -931,9 +931,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data 
*sdata,
 * another CPU.
 */
ieee80211_free_keys(sdata, true);
-
-   /* fall through */
-   case NL80211_IFTYPE_AP:
skb_queue_purge(sdata-skb_queue);
}
 
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 01/10] ath9k_hw: make support for PC-OEM cards optional

2014-10-27 Thread Felix Fietkau
On 2014-10-27 12:40, Sujith Manoharan wrote:
 Hi,
 
 This series looks good to me...
Thanks for the review

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [ath9k-devel] strange MPDU loss pattern

2014-10-27 Thread Felix Fietkau
Hi Seongho,

that paper looks quite interesting.
Are you planning to publish code/patches for your implementation as well?
It would be nice to have dynamic A-MPDU limiting integrated in minstrel_ht.

Thanks,

- Felix

On 26/10/2014 12:14 AM, Seongho Byeon wrote:

 Hi, I am Ph.d. student in Seoul National University , Korea.
 Recently, we have dealt with the problem you observe, and we published
 a paper into CoNEXT 2014 which is a major conference in our field.

 Title of the paper 'MoFa: Mobility-aware Frame Aggregation in WiFi
 networks'.
 You can download it a site below.
 http://www.mwnl.snu.ac.kr/~schoi/publication/Conferences/14-CONEXT-BYEON.pdf
 http://www.mwnl.snu.ac.kr/%7Eschoi/publication/Conferences/14-CONEXT-BYEON.pdf
 If you have a question please contact me anytime.

 Best regards,
 Seongho Byeon.

 Thank you for sharing the story.
 Even if I consider interference as a possibility, still I can't
 justify the higher
 chance of frame loss in the second half of the aggregate frame.

 We use

 PCI-express 3 antenna dual band cards
 product: AR93xx Wireless Network Adapter
 and/or
 Atheors AR5B97 which is a 2.4 GHz dual antenna internal card in a laptop

 we also tried TP-LINK TL-WDN4200 N900as the receiver.

 However we see the same results.
 we mostly use MCS 20-23, sgi = 0, 20 MHz channels.

 The loss pattern is something like this
 (each line is an imaginary aggregated frame and each bit is the fate
 of the MPDU)

 00011
 11100011010110100
 1
 111010100
 110010101

 The interesting part is that with the start of the next frame error
 rate goes down initially
 then it goes up again in the second portion of the packet.

 Best,
 Ali


 On 25/10/2014 2:30 PM, Adrian Chadd wrote:

 On 25 October 2014 08:28, Ali Abedia2ab...@uwaterloo.ca
 mailto:a2ab...@uwaterloo.cawrote:

 Hi Adrian, We have a high end spectrum analyzer. So we are
 sure there is no background interference We run our
 experiments in the 5 GHZ spectrum. The channel conditions can
 still vary due to the movement of the people in the vicinity
 of the experiment setup. We select a rate that experiences at
 least 20% error on average. Since if the error is 100% or 0%
 it's not interesting for us. My point is if the channel
 conditions change the distribution of failed packets should be
 uniform. The first and second half of the packets have the
 same chance to be received successfully.

 Here's a little story. My first wifi contract had me spend months
 trying to figure out why an AP was losing its mind. It'd get stuck
 in a stuck beacon loop and only a hard powercycle of /all/ of
 the access points in an area would clear it. It turned out that
 the PCB design had some non-grounded / non-populated tracks that
 just happened to form a 2GHz resonator. Once we grounded those
 tracks, the APs started behaving themselves. The company in
 question spent months with high end spectrum analysis kit in the
 lab (where it never happened) and underground (where it did
 happen.) It's only after they stuck the spectrum analyser probe
 _inside the access point_ right up close to the NIC did they see
 it. Here's the spectrum analyser traces. You can see the
 peak.http://www.creative.net.au/ath/So, weirder crap has happened.
 Which NICs and which MCS rates are you using? -adrian

 ___
 ath9k-devel mailing list
 ath9k-de...@lists.ath9k.org mailto:ath9k-de...@lists.ath9k.org
 https://lists.ath9k.org/mailman/listinfo/ath9k-devel

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: MediaTek WiFi hardware support in upstream kernel

2014-10-29 Thread Felix Fietkau
Hi Hackers,

Just a quick heads up:
I'm working on a new driver for MT7662E/MT7612E, written from scratch.
It is already able to bring up the firmware, init the MAC and do basic
TX/RX DMA communication with the firmware.
I've decided to not integrate it with rt2x00, because I want to avoid
dealing with the the unnecessarily convoluted abstractions and legacy
code in there. I believe the result will be simpler and easier to
maintain as a new driver.
As soon as the basic structure is in place, I will put it on a public
git tree and post a link here.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] ath9k: Fix high tx power in multi-chain mode

2014-11-11 Thread Felix Fietkau
On 2014-11-11 08:07, Sujith Manoharan wrote:
 From: Miaoqing Pan miaoq...@qca.qualcomm.com
 
 For multi-chain chips, if the thermometer is switched off for a chain
 which can be disabled by software(e.g tx_chainmask=0x1), the measured tx
 power is about 5dB higher than target power.
 
 Set thermometer on for all chains to fix this issue.
That doesn't seem right to me. ah-caps.tx_chainmask is not altered
based on software antenna configuration.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/6] ath9k: disable overriding AR9340 SLP32 registers

2014-11-12 Thread Felix Fietkau
On 2014-11-11 08:07, Sujith Manoharan wrote:
 From: Miaoqing Pan miaoq...@qca.qualcomm.com
 
 For AR9340, the correct values for SLP32 registers are present
 in the initvals, so overriding them is not needed.
 
 Signed-off-by: Miaoqing Pan miaoq...@qca.qualcomm.com
 Signed-off-by: Sujith Manoharan c_man...@qca.qualcomm.com
What's the point in doing this? The writes don't hurt, and this change
is making the code uglier.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: MediaTek WiFi hardware support in upstream kernel

2014-11-12 Thread Felix Fietkau
On 2014-11-11 12:55, Oleksij Rempel wrote:
 Am 29.10.2014 um 11:17 schrieb Felix Fietkau:
 Hi Hackers,
 
 Just a quick heads up:
 I'm working on a new driver for MT7662E/MT7612E, written from scratch.
 It is already able to bring up the firmware, init the MAC and do basic
 TX/RX DMA communication with the firmware.
 I've decided to not integrate it with rt2x00, because I want to avoid
 dealing with the the unnecessarily convoluted abstractions and legacy
 code in there. I believe the result will be simpler and easier to
 maintain as a new driver.
 As soon as the basic structure is in place, I will put it on a public
 git tree and post a link here.
 
 - Felix
 
 Which chip would you suggest for starting?
The chips I'm working with are both MT7662 and MT7612. My driver already
works as a simple AP or station in 802.11n mode with some limited
aggregation support. I'm getting around 45-50 Mbit/s TCP throughput on
HT20 with iperf. I will post code soon, stay tuned!

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3.18 1/3] ath9k: prevent early IRQs from accessing hardware

2014-11-13 Thread Felix Fietkau
IRQs are suppressed if ah == NULL and ATH_OP_INVALID being set in
common-op_flags. Close a short time window between those two.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/init.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/init.c 
b/drivers/net/wireless/ath/ath9k/init.c
index c5bcddd..3c6ded9 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -529,10 +529,14 @@ static int ath9k_init_softc(u16 devid, struct ath_softc 
*sc,
ah-reg_ops.read = ath9k_ioread32;
ah-reg_ops.write = ath9k_iowrite32;
ah-reg_ops.rmw = ath9k_reg_rmw;
-   sc-sc_ah = ah;
pCap = ah-caps;
 
common = ath9k_hw_common(ah);
+
+   /* Will be cleared in ath9k_start() */
+   set_bit(ATH_OP_INVALID, common-op_flags);
+
+   sc-sc_ah = ah;
sc-dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
sc-tx99_power = MAX_RATE_POWER + 1;
init_waitqueue_head(sc-tx_wait);
@@ -893,9 +897,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
common = ath9k_hw_common(ah);
ath9k_set_hw_capab(sc, hw);
 
-   /* Will be cleared in ath9k_start() */
-   set_bit(ATH_OP_INVALID, common-op_flags);
-
/* Initialize regulatory */
error = ath_regd_init(common-regulatory, sc-hw-wiphy,
  ath9k_reg_notifier);
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3.18 3/3] ath9k: do not access hardware on IRQs during reset

2014-11-13 Thread Felix Fietkau
Instead of killing interrupts during reset when the first one happens,
kill them before issuing the reset.
This fixes an easy to reproduce crash with multiple cards sharing the
same IRQ.

Cc: sta...@vger.kernel.org
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/main.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c 
b/drivers/net/wireless/ath/ath9k/main.c
index ee67956..19cab65 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -512,16 +512,13 @@ irqreturn_t ath_isr(int irq, void *dev)
if (!ah || test_bit(ATH_OP_INVALID, common-op_flags))
return IRQ_NONE;
 
-   /* shared irq, not for us */
+   if (test_bit(ATH_OP_HW_RESET, common-op_flags))
+   return IRQ_NONE;
 
+   /* shared irq, not for us */
if (!ath9k_hw_intrpend(ah))
return IRQ_NONE;
 
-   if (test_bit(ATH_OP_HW_RESET, common-op_flags)) {
-   ath9k_hw_kill_interrupts(ah);
-   return IRQ_HANDLED;
-   }
-
/*
 * Figure out the reason(s) for the interrupt.  Note
 * that the hal returns a pseudo-ISR that may include
@@ -613,6 +610,7 @@ int ath_reset(struct ath_softc *sc, struct ath9k_channel 
*hchan)
struct ath_common *common = ath9k_hw_common(sc-sc_ah);
int r;
 
+   ath9k_hw_kill_interrupts(sc-sc_ah);
set_bit(ATH_OP_HW_RESET, common-op_flags);
 
ath9k_ps_wakeup(sc);
@@ -633,6 +631,7 @@ void ath9k_queue_reset(struct ath_softc *sc, enum 
ath_reset_type type)
 #ifdef CONFIG_ATH9K_DEBUGFS
RESET_STAT_INC(sc, type);
 #endif
+   ath9k_hw_kill_interrupts(sc-sc_ah);
set_bit(ATH_OP_HW_RESET, common-op_flags);
ieee80211_queue_work(sc-hw, sc-hw_reset_work);
 }
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3.18 2/3] ath9k: set ATH_OP_INVALID before disabling hardware

2014-11-13 Thread Felix Fietkau
Closes another small IRQ handler race

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c 
b/drivers/net/wireless/ath/ath9k/main.c
index 644552c..ee67956 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -885,6 +885,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
sc-cur_chan-chandef);
 
ath9k_hw_reset(ah, ah-curchan, ah-caldata, false);
+
+   set_bit(ATH_OP_INVALID, common-op_flags);
+
ath9k_hw_phy_disable(ah);
 
ath9k_hw_configpcipowersave(ah, true);
@@ -893,7 +896,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
ath9k_ps_restore(sc);
 
-   set_bit(ATH_OP_INVALID, common-op_flags);
sc-ps_idle = prev_idle;
 
mutex_unlock(sc-mutex);
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3.18 3/3] ath9k: do not access hardware on IRQs during reset

2014-11-15 Thread Felix Fietkau
On 2014-11-13 18:34, Felix Fietkau wrote:
 Instead of killing interrupts during reset when the first one happens,
 kill them before issuing the reset.
 This fixes an easy to reproduce crash with multiple cards sharing the
 same IRQ.
 
 Cc: sta...@vger.kernel.org
 Signed-off-by: Felix Fietkau n...@openwrt.org
Please disregard this series for now, it seems to be causing some issues
on a few SoC devices.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/6] mac80211: add tx_status_noskb to rate_control_ops

2014-11-15 Thread Felix Fietkau
This op works like .tx_status, except it does not need access to the
skb. This will be used by drivers that cannot match tx status
information to specific packets.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 include/net/mac80211.h | 4 
 net/mac80211/rate.h| 6 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5f203a6..32a779c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4727,6 +4727,10 @@ struct rate_control_ops {
void (*free_sta)(void *priv, struct ieee80211_sta *sta,
 void *priv_sta);
 
+   void (*tx_status_noskb)(void *priv,
+   struct ieee80211_supported_band *sband,
+   struct ieee80211_sta *sta, void *priv_sta,
+   struct ieee80211_tx_info *info);
void (*tx_status)(void *priv, struct ieee80211_supported_band *sband,
  struct ieee80211_sta *sta, void *priv_sta,
  struct sk_buff *skb);
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 18babe3..dd25964 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -37,11 +37,15 @@ static inline void rate_control_tx_status(struct 
ieee80211_local *local,
struct rate_control_ref *ref = local-rate_ctrl;
struct ieee80211_sta *ista = sta-sta;
void *priv_sta = sta-rate_ctrl_priv;
+   struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
return;
 
-   ref-ops-tx_status(ref-priv, sband, ista, priv_sta, skb);
+   if (ref-ops-tx_status)
+   ref-ops-tx_status(ref-priv, sband, ista, priv_sta, skb);
+   else
+   ref-ops-tx_status_noskb(ref-priv, sband, ista, priv_sta, 
info);
 }
 
 
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/6] mac80211: minstrel_ht: move aggregation check to .get_rate()

2014-11-15 Thread Felix Fietkau
Preparation for adding a no-skb tx status path

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/rc80211_minstrel_ht.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_ht.c 
b/net/mac80211/rc80211_minstrel_ht.c
index 62ff7cf..32b969f 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -782,9 +782,6 @@ minstrel_ht_tx_status(void *priv, struct 
ieee80211_supported_band *sband,
if (time_after(jiffies, mi-stats_update + (mp-update_interval / 2 * 
HZ) / 1000)) {
update = true;
minstrel_ht_update_stats(mp, mi);
-   if (!(info-flags  IEEE80211_TX_CTL_AMPDU) 
-   mi-max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
-   minstrel_aggr_check(sta, skb);
}
 
if (update)
@@ -1026,6 +1023,10 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta 
*sta, void *priv_sta,
if (!msp-is_ht)
return mac80211_minstrel.get_rate(priv, sta, msp-legacy, 
txrc);
 
+   if (!(info-flags  IEEE80211_TX_CTL_AMPDU) 
+   mi-max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
+   minstrel_aggr_check(sta, txrc-skb);
+
info-flags |= mi-tx_flags;
minstrel_ht_check_cck_shortpreamble(mp, mi, txrc-short_preamble);
 
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/6] mac80211: minstrel_ht: add a small optimization to minstrel_aggr_check

2014-11-15 Thread Felix Fietkau
Check the queue mapping earlier, skb-queue_mapping is more likely than
skb-data to still be in d-cache.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/rc80211_minstrel_ht.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_ht.c 
b/net/mac80211/rc80211_minstrel_ht.c
index c50fd94..62ff7cf 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -690,6 +690,9 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct 
sk_buff *skb)
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
u16 tid;
 
+   if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
+   return;
+
if (unlikely(!ieee80211_is_data_qos(hdr-frame_control)))
return;
 
@@ -700,9 +703,6 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct 
sk_buff *skb)
if (likely(sta-ampdu_mlme.tid_tx[tid]))
return;
 
-   if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
-   return;
-
ieee80211_start_tx_ba_session(pubsta, tid, 5000);
 }
 
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/6] mac80211: minstrel_ht: switch to .tx_status_noskb

2014-11-15 Thread Felix Fietkau
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/rc80211_minstrel_ht.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_ht.c 
b/net/mac80211/rc80211_minstrel_ht.c
index 32b969f..3775b06 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -709,11 +709,10 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct 
sk_buff *skb)
 static void
 minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
   struct ieee80211_sta *sta, void *priv_sta,
-  struct sk_buff *skb)
+  struct ieee80211_tx_info *info)
 {
struct minstrel_ht_sta_priv *msp = priv_sta;
struct minstrel_ht_sta *mi = msp-ht;
-   struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info-status.rates;
struct minstrel_rate_stats *rate, *rate2;
struct minstrel_priv *mp = priv;
@@ -721,7 +720,8 @@ minstrel_ht_tx_status(void *priv, struct 
ieee80211_supported_band *sband,
int i;
 
if (!msp-is_ht)
-   return mac80211_minstrel.tx_status(priv, sband, sta, 
msp-legacy, skb);
+   return mac80211_minstrel.tx_status_noskb(priv, sband, sta,
+msp-legacy, info);
 
/* This packet was aggregated but doesn't carry status info */
if ((info-flags  IEEE80211_TX_CTL_AMPDU) 
@@ -1343,7 +1343,7 @@ static u32 minstrel_ht_get_expected_throughput(void 
*priv_sta)
 
 static const struct rate_control_ops mac80211_minstrel_ht = {
.name = minstrel_ht,
-   .tx_status = minstrel_ht_tx_status,
+   .tx_status_noskb = minstrel_ht_tx_status,
.get_rate = minstrel_ht_get_rate,
.rate_init = minstrel_ht_rate_init,
.rate_update = minstrel_ht_rate_update,
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/6] mac80211: add ieee80211_tx_status_noskb

2014-11-15 Thread Felix Fietkau
This can be used by drivers that cannot reliably map tx status
information onto specific skbs.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 include/net/mac80211.h |  22 ++
 net/mac80211/rate.h|  17 
 net/mac80211/status.c  | 116 +++--
 3 files changed, 132 insertions(+), 23 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 32a779c..28ea999 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3517,6 +3517,28 @@ void ieee80211_tx_status(struct ieee80211_hw *hw,
 struct sk_buff *skb);
 
 /**
+ * ieee80211_tx_status_noskb - transmit status callback without skb
+ *
+ * This function can be used as a replacement for ieee80211_tx_status
+ * in drivers that cannot reliably map tx status information back to
+ * specific skbs.
+ *
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other. Calls
+ * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
+ * may not be mixed for a single hardware. Must not run concurrently with
+ * ieee80211_rx() or ieee80211_rx_ni().
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @sta: the receiver station to which this packet is sent
+ * (NULL for multicast packets)
+ * @info: tx status information
+ */
+void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
+  struct ieee80211_sta *sta,
+  struct ieee80211_tx_info *info);
+
+/**
  * ieee80211_tx_status_ni - transmit status callback (in process context)
  *
  * Like ieee80211_tx_status() but can be called in process context.
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index dd25964..a0b18a8 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -49,6 +49,23 @@ static inline void rate_control_tx_status(struct 
ieee80211_local *local,
 }
 
 
+static inline void
+rate_control_tx_status_noskb(struct ieee80211_local *local,
+struct ieee80211_supported_band *sband,
+struct sta_info *sta,
+struct ieee80211_tx_info *info)
+{
+   struct rate_control_ref *ref = local-rate_ctrl;
+   struct ieee80211_sta *ista = sta-sta;
+   void *priv_sta = sta-rate_ctrl_priv;
+
+   if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
+   return;
+
+   ref-ops-tx_status_noskb(ref-priv, sband, ista, priv_sta, info);
+}
+
+
 static inline void rate_control_rate_init(struct sta_info *sta)
 {
struct ieee80211_local *local = sta-sdata-local;
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 9612d89..8a6d3ad 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -541,10 +541,9 @@ static void ieee80211_tx_latency_end_msrmnt(struct 
ieee80211_local *local,
 #define STA_LOST_TDLS_PKT_THRESHOLD10
 #define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */
 
-static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
+static void ieee80211_lost_packet(struct sta_info *sta,
+ struct ieee80211_tx_info *info)
 {
-   struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
/* This packet was aggregated but doesn't carry status info */
if ((info-flags  IEEE80211_TX_CTL_AMPDU) 
!(info-flags  IEEE80211_TX_STAT_AMPDU))
@@ -571,24 +570,13 @@ static void ieee80211_lost_packet(struct sta_info *sta, 
struct sk_buff *skb)
sta-lost_packets = 0;
 }
 
-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+static int ieee80211_tx_get_rates(struct ieee80211_hw *hw,
+ struct ieee80211_tx_info *info,
+ int *retry_count)
 {
-   struct sk_buff *skb2;
-   struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb-data;
-   struct ieee80211_local *local = hw_to_local(hw);
-   struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-   __le16 fc;
-   struct ieee80211_supported_band *sband;
-   struct ieee80211_sub_if_data *sdata;
-   struct net_device *prev_dev = NULL;
-   struct sta_info *sta, *tmp;
-   int retry_count = -1, i;
int rates_idx = -1;
-   bool send_to_cooked;
-   bool acked;
-   struct ieee80211_bar *bar;
-   int rtap_len;
-   int shift = 0;
+   int count = -1;
+   int i;
 
for (i = 0; i  IEEE80211_TX_MAX_RATES; i++) {
if ((info-flags  IEEE80211_TX_CTL_AMPDU) 
@@ -606,12 +594,94 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct 
sk_buff *skb)
break;
}
 
-   retry_count += info-status.rates[i].count;
+   count += info-status.rates[i].count;
}
rates_idx = i - 1;
 
-   if (retry_count  0)
-   retry_count = 0

[PATCH 3.18] mac80211: minstrel_ht: fix a crash in rate sorting

2014-11-18 Thread Felix Fietkau
The commit 5935839ad73583781b8bbe8d91412f6826e218a4
mac80211: improve minstrel_ht rate sorting by throughput  probability

introduced a crash on rate sorting that occurs when the rate added to
the sorting array is faster than all the previous rates. Due to an
off-by-one error, it reads the rate index from tp_list[-1], which
contains uninitialized stack garbage, and then uses the resulting index
for accessing the group rate stats, leading to a crash if the garbage
value is big enough.

Cc: Thomas Huehn tho...@net.t-labs.tu-berlin.de
Reported-by: Jouni Malinen j...@w1.fi
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/rc80211_minstrel_ht.c | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_ht.c 
b/net/mac80211/rc80211_minstrel_ht.c
index c50fd94..7b038a4 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -394,19 +394,16 @@ minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta 
*mi, u16 index,
cur_thr = mi-groups[cur_group].rates[cur_idx].cur_tp;
cur_prob = mi-groups[cur_group].rates[cur_idx].probability;
 
-   tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
-   tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
-   tmp_thr = mi-groups[tmp_group].rates[tmp_idx].cur_tp;
-   tmp_prob = mi-groups[tmp_group].rates[tmp_idx].probability;
-
-   while (j  0  (cur_thr  tmp_thr ||
- (cur_thr == tmp_thr  cur_prob  tmp_prob))) {
-   j--;
+   do {
tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
tmp_thr = mi-groups[tmp_group].rates[tmp_idx].cur_tp;
tmp_prob = mi-groups[tmp_group].rates[tmp_idx].probability;
-   }
+   if (cur_thr  tmp_thr ||
+   (cur_thr == tmp_thr  cur_prob = tmp_prob))
+   break;
+   j--;
+   } while (j  0);
 
if (j  MAX_THR_RATES - 1) {
memmove(tp_list[j + 1], tp_list[j], (sizeof(*tp_list) *
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 3/7] mac80211: minstrel: switch to .tx_status_noskb

2014-11-19 Thread Felix Fietkau
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/rc80211_minstrel.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index c2b91bf..d51f6b1 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -223,11 +223,10 @@ minstrel_update_stats(struct minstrel_priv *mp, struct 
minstrel_sta_info *mi)
 static void
 minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
   struct ieee80211_sta *sta, void *priv_sta,
-  struct sk_buff *skb)
+  struct ieee80211_tx_info *info)
 {
struct minstrel_priv *mp = priv;
struct minstrel_sta_info *mi = priv_sta;
-   struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info-status.rates;
int i, ndx;
int success;
@@ -674,7 +673,7 @@ static u32 minstrel_get_expected_throughput(void *priv_sta)
 
 const struct rate_control_ops mac80211_minstrel = {
.name = minstrel,
-   .tx_status = minstrel_tx_status,
+   .tx_status_noskb = minstrel_tx_status,
.get_rate = minstrel_get_rate,
.rate_init = minstrel_rate_init,
.alloc = minstrel_alloc,
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/7] mac80211: add tx_status_noskb to rate_control_ops

2014-11-19 Thread Felix Fietkau
This op works like .tx_status, except it does not need access to the
skb. This will be used by drivers that cannot match tx status
information to specific packets.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 include/net/mac80211.h | 4 
 net/mac80211/rate.h| 6 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5f203a6..32a779c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4727,6 +4727,10 @@ struct rate_control_ops {
void (*free_sta)(void *priv, struct ieee80211_sta *sta,
 void *priv_sta);
 
+   void (*tx_status_noskb)(void *priv,
+   struct ieee80211_supported_band *sband,
+   struct ieee80211_sta *sta, void *priv_sta,
+   struct ieee80211_tx_info *info);
void (*tx_status)(void *priv, struct ieee80211_supported_band *sband,
  struct ieee80211_sta *sta, void *priv_sta,
  struct sk_buff *skb);
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 18babe3..dd25964 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -37,11 +37,15 @@ static inline void rate_control_tx_status(struct 
ieee80211_local *local,
struct rate_control_ref *ref = local-rate_ctrl;
struct ieee80211_sta *ista = sta-sta;
void *priv_sta = sta-rate_ctrl_priv;
+   struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
return;
 
-   ref-ops-tx_status(ref-priv, sband, ista, priv_sta, skb);
+   if (ref-ops-tx_status)
+   ref-ops-tx_status(ref-priv, sband, ista, priv_sta, skb);
+   else
+   ref-ops-tx_status_noskb(ref-priv, sband, ista, priv_sta, 
info);
 }
 
 
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/7] mac80211: minstrel_ht: move aggregation check to .get_rate()

2014-11-19 Thread Felix Fietkau
Preparation for adding a no-skb tx status path

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/rc80211_minstrel_ht.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_ht.c 
b/net/mac80211/rc80211_minstrel_ht.c
index 62ff7cf..2641dc8 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -782,9 +782,6 @@ minstrel_ht_tx_status(void *priv, struct 
ieee80211_supported_band *sband,
if (time_after(jiffies, mi-stats_update + (mp-update_interval / 2 * 
HZ) / 1000)) {
update = true;
minstrel_ht_update_stats(mp, mi);
-   if (!(info-flags  IEEE80211_TX_CTL_AMPDU) 
-   mi-max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
-   minstrel_aggr_check(sta, skb);
}
 
if (update)
@@ -1026,6 +1023,10 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta 
*sta, void *priv_sta,
if (!msp-is_ht)
return mac80211_minstrel.get_rate(priv, sta, msp-legacy, 
txrc);
 
+   if (!(info-flags  IEEE80211_TX_CTL_AMPDU) 
+   mi-max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
+   minstrel_aggr_check(sta, txrc-skb);
+
info-flags |= mi-tx_flags;
minstrel_ht_check_cck_shortpreamble(mp, mi, txrc-short_preamble);
 
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 4/7] mac80211: minstrel_ht: switch to .tx_status_noskb

2014-11-19 Thread Felix Fietkau
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/rc80211_minstrel_ht.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_ht.c 
b/net/mac80211/rc80211_minstrel_ht.c
index 2641dc8..b52996a 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -709,11 +709,10 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct 
sk_buff *skb)
 static void
 minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
   struct ieee80211_sta *sta, void *priv_sta,
-  struct sk_buff *skb)
+  struct ieee80211_tx_info *info)
 {
struct minstrel_ht_sta_priv *msp = priv_sta;
struct minstrel_ht_sta *mi = msp-ht;
-   struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info-status.rates;
struct minstrel_rate_stats *rate, *rate2;
struct minstrel_priv *mp = priv;
@@ -721,7 +720,8 @@ minstrel_ht_tx_status(void *priv, struct 
ieee80211_supported_band *sband,
int i;
 
if (!msp-is_ht)
-   return mac80211_minstrel.tx_status(priv, sband, sta, 
msp-legacy, skb);
+   return mac80211_minstrel.tx_status_noskb(priv, sband, sta,
+msp-legacy, info);
 
/* This packet was aggregated but doesn't carry status info */
if ((info-flags  IEEE80211_TX_CTL_AMPDU) 
@@ -1343,7 +1343,7 @@ static u32 minstrel_ht_get_expected_throughput(void 
*priv_sta)
 
 static const struct rate_control_ops mac80211_minstrel_ht = {
.name = minstrel_ht,
-   .tx_status = minstrel_ht_tx_status,
+   .tx_status_noskb = minstrel_ht_tx_status,
.get_rate = minstrel_ht_get_rate,
.rate_init = minstrel_ht_rate_init,
.rate_update = minstrel_ht_rate_update,
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC 2/3] ath9k: add TX power per-rate per-chain tables

2014-11-20 Thread Felix Fietkau
On 2014-11-20 14:31, Lorenzo Bianconi wrote:
 Add TX power per-rate per-chain tables for different MIMO modes (e.g STBC) in
 order to cap the maximum TX power value per-rate in the TX descriptor path.
 Cap TX power for self generated frames (ACK, RTS/CTS).
 Currently TPC is supported just by AR9003 based chips
 
 Signed-off-by: Lorenzo Bianconi lorenzo.biancon...@gmail.com
I think you should make the ah-txpower array one-dimensional and store
it for the current chainmask only - this will simplify the code.
The chainmask cannot be changed while the interface is up, so there's no
need to make this dynamically switchable.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3.18] mac80211: copy chandef from AP vif to VLANs

2014-11-24 Thread Felix Fietkau
Fixes a crash in nl80211_send_chandef, introduced in

commit c12bc4885f4b3bab0ed779c69d5d7e3223fa5003
mac80211: return the vif's chandef in ieee80211_cfg_get_channel()

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/chan.c  | 23 +++
 net/mac80211/iface.c |  1 +
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 4c74e8d..5ce13a7 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -929,6 +929,21 @@ ieee80211_vif_chanctx_reservation_complete(struct 
ieee80211_sub_if_data *sdata)
}
 }
 
+static void
+ieee80211_vif_update_chandef(struct ieee80211_sub_if_data *sdata,
+const struct cfg80211_chan_def *chandef)
+{
+   struct ieee80211_sub_if_data *vlan;
+
+   sdata-vif.bss_conf.chandef = *chandef;
+
+   if (sdata-vif.type != NL80211_IFTYPE_AP)
+   return;
+
+   list_for_each_entry(vlan, sdata-u.ap.vlans, u.vlan.list)
+   vlan-vif.bss_conf.chandef = *chandef;
+}
+
 static int
 ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
 {
@@ -991,7 +1006,7 @@ ieee80211_vif_use_reserved_reassign(struct 
ieee80211_sub_if_data *sdata)
if (sdata-vif.bss_conf.chandef.width != sdata-reserved_chandef.width)
changed = BSS_CHANGED_BANDWIDTH;
 
-   sdata-vif.bss_conf.chandef = sdata-reserved_chandef;
+   ieee80211_vif_update_chandef(sdata, sdata-reserved_chandef);
 
if (changed)
ieee80211_bss_info_change_notify(sdata, changed);
@@ -1333,7 +1348,7 @@ static int ieee80211_vif_use_reserved_switch(struct 
ieee80211_local *local)
sdata-reserved_chandef.width)
changed = BSS_CHANGED_BANDWIDTH;
 
-   sdata-vif.bss_conf.chandef = sdata-reserved_chandef;
+   ieee80211_vif_update_chandef(sdata, 
sdata-reserved_chandef);
if (changed)
ieee80211_bss_info_change_notify(sdata,
 changed);
@@ -1504,7 +1519,7 @@ int ieee80211_vif_use_channel(struct 
ieee80211_sub_if_data *sdata,
goto out;
}
 
-   sdata-vif.bss_conf.chandef = *chandef;
+   ieee80211_vif_update_chandef(sdata, chandef);
 
ret = ieee80211_assign_vif_chanctx(sdata, ctx);
if (ret) {
@@ -1646,7 +1661,7 @@ int ieee80211_vif_change_bandwidth(struct 
ieee80211_sub_if_data *sdata,
break;
}
 
-   sdata-vif.bss_conf.chandef = *chandef;
+   ieee80211_vif_update_chandef(sdata, chandef);
 
ieee80211_recalc_chanctx_chantype(local, ctx);
 
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 653f5eb..eeae0ab 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -511,6 +511,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool 
coming_up)
sdata-vif.cab_queue = master-vif.cab_queue;
memcpy(sdata-vif.hw_queue, master-vif.hw_queue,
   sizeof(sdata-vif.hw_queue));
+   sdata-vif.bss_conf.chandef = master-vif.bss_conf.chandef;
break;
}
case NL80211_IFTYPE_AP:
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] ath9k: fix BE/BK queue order

2014-11-30 Thread Felix Fietkau
Hardware queues are ordered by priority. Use queue index 0 for BK, which
has lower priority than BE.

Cc: sta...@vger.kernel.org
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/hw.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.h 
b/drivers/net/wireless/ath/ath9k/hw.h
index 96c6401..1cbd335 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -217,8 +217,8 @@
 #define AH_WOW_BEACON_MISS BIT(3)
 
 enum ath_hw_txq_subtype {
-   ATH_TXQ_AC_BE = 0,
-   ATH_TXQ_AC_BK = 1,
+   ATH_TXQ_AC_BK = 0,
+   ATH_TXQ_AC_BE = 1,
ATH_TXQ_AC_VI = 2,
ATH_TXQ_AC_VO = 3,
 };
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] ath9k_hw: fix hardware queue allocation

2014-11-30 Thread Felix Fietkau
The driver passes the desired hardware queue index for a WMM data queue
in qinfo-tqi_subtype. This was ignored in ath9k_hw_setuptxqueue, which
instead relied on the order in which the function is called.

Cc: sta...@vger.kernel.org
Reported-by: Hubert Feurstein h.feurst...@gmail.com
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/mac.c | 9 +
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/mac.c 
b/drivers/net/wireless/ath/ath9k/mac.c
index 275205a..3e58bfa 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -311,14 +311,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum 
ath9k_tx_queue type,
q = ATH9K_NUM_TX_QUEUES - 3;
break;
case ATH9K_TX_QUEUE_DATA:
-   for (q = 0; q  ATH9K_NUM_TX_QUEUES; q++)
-   if (ah-txq[q].tqi_type ==
-   ATH9K_TX_QUEUE_INACTIVE)
-   break;
-   if (q == ATH9K_NUM_TX_QUEUES) {
-   ath_err(common, No available TX queue\n);
-   return -1;
-   }
+   q = qinfo-tqi_subtype;
break;
default:
ath_err(common, Invalid TX queue type: %u\n, type);
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] ath5k: fix hardware queue index assignment

2014-11-30 Thread Felix Fietkau
Like with ath9k, ath5k queues also need to be ordered by priority.
queue_info-tqi_subtype already contains the correct index, so use it
instead of relying on the order of ath5k_hw_setup_tx_queue calls.

Cc: sta...@vger.kernel.org
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath5k/qcu.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/qcu.c 
b/drivers/net/wireless/ath/ath5k/qcu.c
index 0583c69..ddaad71 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -225,13 +225,7 @@ ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum 
ath5k_tx_queue queue_type,
} else {
switch (queue_type) {
case AR5K_TX_QUEUE_DATA:
-   for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
-   ah-ah_txq[queue].tqi_type !=
-   AR5K_TX_QUEUE_INACTIVE; queue++) {
-
-   if (queue  AR5K_TX_QUEUE_ID_DATA_MAX)
-   return -EINVAL;
-   }
+   queue = queue_info-tqi_subtype;
break;
case AR5K_TX_QUEUE_UAPSD:
queue = AR5K_TX_QUEUE_ID_UAPSD;
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/3] ath9k: prevent early IRQs from accessing hardware

2014-11-30 Thread Felix Fietkau
IRQs are suppressed if ah == NULL and ATH_OP_INVALID being set in
common-op_flags. Close a short time window between those two.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/init.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/init.c 
b/drivers/net/wireless/ath/ath9k/init.c
index 59d679c..d1c3934 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -532,10 +532,14 @@ static int ath9k_init_softc(u16 devid, struct ath_softc 
*sc,
ah-reg_ops.read = ath9k_ioread32;
ah-reg_ops.write = ath9k_iowrite32;
ah-reg_ops.rmw = ath9k_reg_rmw;
-   sc-sc_ah = ah;
pCap = ah-caps;
 
common = ath9k_hw_common(ah);
+
+   /* Will be cleared in ath9k_start() */
+   set_bit(ATH_OP_INVALID, common-op_flags);
+
+   sc-sc_ah = ah;
sc-dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
sc-tx99_power = MAX_RATE_POWER + 1;
init_waitqueue_head(sc-tx_wait);
@@ -896,9 +900,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
common = ath9k_hw_common(ah);
ath9k_set_hw_capab(sc, hw);
 
-   /* Will be cleared in ath9k_start() */
-   set_bit(ATH_OP_INVALID, common-op_flags);
-
/* Initialize regulatory */
error = ath_regd_init(common-regulatory, sc-hw-wiphy,
  ath9k_reg_notifier);
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 3/3] ath9k: do not access hardware on IRQs during reset

2014-11-30 Thread Felix Fietkau
Instead of killing interrupts during reset when the first one happens,
kill them before issuing the reset.
This fixes an easy to reproduce crash with multiple cards sharing the
same IRQ.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/main.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c 
b/drivers/net/wireless/ath/ath9k/main.c
index 9437365..9a72640 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -512,16 +512,13 @@ irqreturn_t ath_isr(int irq, void *dev)
if (!ah || test_bit(ATH_OP_INVALID, common-op_flags))
return IRQ_NONE;
 
-   /* shared irq, not for us */
+   if (!AR_SREV_9100(ah)  test_bit(ATH_OP_HW_RESET, common-op_flags))
+   return IRQ_NONE;
 
+   /* shared irq, not for us */
if (!ath9k_hw_intrpend(ah))
return IRQ_NONE;
 
-   if (test_bit(ATH_OP_HW_RESET, common-op_flags)) {
-   ath9k_hw_kill_interrupts(ah);
-   return IRQ_HANDLED;
-   }
-
/*
 * Figure out the reason(s) for the interrupt.  Note
 * that the hal returns a pseudo-ISR that may include
@@ -532,6 +529,9 @@ irqreturn_t ath_isr(int irq, void *dev)
ath9k_debug_sync_cause(sc, sync_cause);
status = ah-imask;/* discard unasked-for bits */
 
+   if (AR_SREV_9100(ah)  test_bit(ATH_OP_HW_RESET, common-op_flags))
+   return IRQ_HANDLED;
+
/*
 * If there are no status bits set, then this interrupt was not
 * for me (should have been caught above).
@@ -613,6 +613,7 @@ int ath_reset(struct ath_softc *sc, struct ath9k_channel 
*hchan)
struct ath_common *common = ath9k_hw_common(sc-sc_ah);
int r;
 
+   ath9k_hw_kill_interrupts(sc-sc_ah);
set_bit(ATH_OP_HW_RESET, common-op_flags);
 
ath9k_ps_wakeup(sc);
@@ -633,6 +634,7 @@ void ath9k_queue_reset(struct ath_softc *sc, enum 
ath_reset_type type)
 #ifdef CONFIG_ATH9K_DEBUGFS
RESET_STAT_INC(sc, type);
 #endif
+   ath9k_hw_kill_interrupts(sc-sc_ah);
set_bit(ATH_OP_HW_RESET, common-op_flags);
ieee80211_queue_work(sc-hw, sc-hw_reset_work);
 }
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/3] ath9k: set ATH_OP_INVALID before disabling hardware

2014-11-30 Thread Felix Fietkau
Closes another small IRQ handler race

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c 
b/drivers/net/wireless/ath/ath9k/main.c
index ebbbfc7..9437365 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -887,6 +887,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
sc-cur_chan-chandef);
 
ath9k_hw_reset(ah, ah-curchan, ah-caldata, false);
+
+   set_bit(ATH_OP_INVALID, common-op_flags);
+
ath9k_hw_phy_disable(ah);
 
ath9k_hw_configpcipowersave(ah, true);
@@ -895,7 +898,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
ath9k_ps_restore(sc);
 
-   set_bit(ATH_OP_INVALID, common-op_flags);
sc-ps_idle = prev_idle;
 
mutex_unlock(sc-mutex);
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] mac80211: add an intermediate software queue implementation

2014-12-12 Thread Felix Fietkau
On 2014-12-12 14:21, Johannes Berg wrote:
 On Wed, 2014-11-19 at 00:14 +0100, Felix Fietkau wrote:
 
 +struct txq_info *txq;
 +atomic_t txq_len[IEEE80211_NUM_ACS];
 
 I think you should consider renaming the latter to txqs_len or so - it
 doesn't just cover one txq as is be implied by the name now. Otherwise
 the skb_queue_head also maintains the length anyway, but I think you
 need the aggregate for all stations here...
 
 Some documentation for this and the vif.txq would be good too :)
 
 In fact - it might be worthwhile to take parts of the commit message and
 elaborate a bit on it and write a whole DOC: section?
Yeah, makes sense.

 --- a/net/mac80211/sta_info.h
 +++ b/net/mac80211/sta_info.h
 @@ -371,6 +371,7 @@ struct sta_info {
  struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
  struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
  unsigned long driver_buffered_tids;
 +void *txq;
 
 You can still use struct txq_info * here even when it's not declared yet
 (since it's in the other header file)
OK.

 +static void ieee80211_drv_tx(struct ieee80211_local *local,
 + struct ieee80211_vif *vif,
 + struct ieee80211_sta *pubsta,
 + struct sk_buff *skb)
 +{
 +struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb-data;
 +struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 +struct ieee80211_tx_control control = {
 +.sta = pubsta
 +};
 +struct ieee80211_txq *pubtxq = NULL;
 +struct txq_info *txq;
 +u8 ac;
 +
 +if (ieee80211_is_mgmt(hdr-frame_control) ||
 +ieee80211_is_ctl(hdr-frame_control))
 +goto tx_normal;
 +
 +if (pubsta) {
 +u8 tid = skb-priority  IEEE80211_QOS_CTL_TID_MASK;
 +pubtxq = pubsta-txq[tid];
 +} else {
 +pubtxq = vif-txq;
 +}
 
 This is a bit confusing - isn't this the same as sdata-txq.txq?
Right, I should probably use that.

 Then
 again what even sets vif-txq? Shouldn't those be per-AC? Do you really
 want to mix 'normal' and txq-TX?
Are we even using multiple ACs for packets that don't belong to a
particular sta? I thought normal mcast data frames only use non-QoS
frames. And yes, I'm currently mixing normal and txq-TX to prioritize
ctl/mgmt frames over other less important traffic.

 I think you should also use txqi as variables for txq_info - it gets
 cumbersome to distinguish the two everywhere.
Will do.

 Also in many cases where you have txq allocation failures you just
 continue as is, I'm not sure that's such a great idea. Those driver
 paths will practically never get tested.
It will just do normal tx in that case, which should work.

 +if (!pubtxq)
 +goto tx_normal;
 +
 +ac = pubtxq-ac;
 +txq = container_of(pubtxq, struct txq_info, txq);
 +atomic_inc(sdata-txq_len[ac]);
 +if (atomic_read(sdata-txq_len[ac]) = local-hw.txq_ac_max_pending)
 +netif_stop_subqueue(sdata-dev, ac);
 +
 +skb_queue_tail(txq-queue, skb);
 +drv_wake_tx_queue(local, txq);
 
 You might consider doing locking differently here - I think you probably
 don't need the txq-queue spinlock at all since you're in per-AC and
 mappings are static. Not sure how that interacts with other parts of the
 code though.
I wanted to use the lock to give the driver the freedom to call
ieee80211_tx_dequeue from outside of normal per-AC tx context.

 +int ieee80211_tx_dequeue(struct ieee80211_hw *hw, struct ieee80211_txq 
 *pubtxq,
 + struct sk_buff **dest)
 
 I'd prefer you return the skb and use ERR_PTR() for errors.
Will do

 +void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata,
 + struct sta_info *sta,
 + struct txq_info *txq, int tid)
 +{
 +skb_queue_head_init(txq-queue);
 +txq-txq.vif = sdata-vif;
 +
 +if (sta) {
 +txq-txq.sta = sta-sta;
 +sta-sta.txq[tid] = txq-txq;
 +txq-txq.ac = ieee802_1d_to_ac[tid  7];
 +} else {
 +sdata-vif.txq = txq-txq;
 +txq-txq.ac = IEEE80211_AC_BE;
 +}
 
 Again, I don't quite understand the single AC queue here per vif. It
 seems it should be one for each AC and possibly one for cab? Or none at
 all - I don't really see what this single one would be used for, in the
 TX code you seem to use it for mcast data only but then I don't really
 see the point. It's also not part of the queue length accounting.
I handle CAB through normal mac80211 mcast buffering.

 +void ieee80211_flush_tx_queue(struct ieee80211_local *local,
 +  struct ieee80211_txq *pubtxq)
 +{
 +struct txq_info *txq = container_of(pubtxq, struct txq_info, txq);
 +struct ieee80211_sub_if_data *sdata = vif_to_sdata(pubtxq-vif);
 +struct sk_buff *skb;
 +
 +while ((skb = skb_dequeue(txq-queue)) != NULL) {
 +atomic_dec(sdata-txq_len[pubtxq-ac

Re: [PATCH] mac80211: add an intermediate software queue implementation

2014-12-12 Thread Felix Fietkau
On 2014-12-12 15:01, Johannes Berg wrote:
 On Fri, 2014-12-12 at 14:40 +0100, Felix Fietkau wrote:
 
  Then
  again what even sets vif-txq? Shouldn't those be per-AC? Do you really
  want to mix 'normal' and txq-TX?
 Are we even using multiple ACs for packets that don't belong to a
 particular sta? I thought normal mcast data frames only use non-QoS
 frames. And yes, I'm currently mixing normal and txq-TX to prioritize
 ctl/mgmt frames over other less important traffic.
 
 Management (and maybe control) frames can have different priorities as
 well, this is only used for something with TDLS now I think though.
With my implementation, those would go through the normal tx codepath,
bypassing the software tx queues. Can you think of anything else that
would need per-AC vif queues?

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] ath: fix incorrect PPB on FCC radar type 5

2014-12-15 Thread Felix Fietkau
On 2014-12-15 19:55, Peter Oh wrote:
 The minimum number of pulses per burst on FCC radar type 5 is 1.
 Use this number for correct radar detection.
 
 Signed-off-by: Peter Oh p...@qca.qualcomm.com
 ---
  drivers/net/wireless/ath/dfs_pattern_detector.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c 
 b/drivers/net/wireless/ath/dfs_pattern_detector.c
 index cfd0554..3d57f87 100644
 --- a/drivers/net/wireless/ath/dfs_pattern_detector.c
 +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
 @@ -86,7 +86,7 @@ static const struct radar_detector_specs 
 fcc_radar_ref_types[] = {
   FCC_PATTERN(1, 0, 5, 150, 230, 1, 23),
   FCC_PATTERN(2, 6, 10, 200, 500, 1, 16),
   FCC_PATTERN(3, 11, 20, 200, 500, 1, 12),
 - FCC_PATTERN(4, 50, 100, 1000, 2000, 1, 20),
 + FCC_PATTERN(4, 50, 100, 1000, 2000, 1, 1),
Won't that significantly increase the false positive rate?
Here's the previous change on that pattern:

commit 562930f8baee7a1cb5b9f382b4338c9b6fbf1139
Author: Vivek Natarajan natar...@qti.qualcomm.com
Date:   Mon Nov 24 17:26:22 2014 +0530

ath: Fix a false radar detection pattern

For FCC and JP, in one of the radar patterns, PPB and PRF seems to be
interchanged leading to frequent incorrect radar detections.

Signed-off-by: Vivek Natarajan natar...@qti.qualcomm.com
Signed-off-by: John W. Linville linvi...@tuxdriver.com

diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c 
b/drivers/net/wireless/ath/dfs_pattern_detector.c
index 650be79..cfd0554 100644
--- a/drivers/net/wireless/ath/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
@@ -86,7 +86,7 @@ static const struct radar_detector_specs 
fcc_radar_ref_types[] = {
FCC_PATTERN(1, 0, 5, 150, 230, 1, 23),
FCC_PATTERN(2, 6, 10, 200, 500, 1, 16),
FCC_PATTERN(3, 11, 20, 200, 500, 1, 12),
-   FCC_PATTERN(4, 50, 100, 1000, 2000, 20, 1),
+   FCC_PATTERN(4, 50, 100, 1000, 2000, 1, 20),
FCC_PATTERN(5, 0, 1, 333, 333, 1, 9),
 };
 
@@ -105,7 +105,7 @@ static const struct radar_detector_specs 
jp_radar_ref_types[] = {
JP_PATTERN(4, 0, 5, 150, 230, 1, 23),
JP_PATTERN(5, 6, 10, 200, 500, 1, 16),
JP_PATTERN(6, 11, 20, 200, 500, 1, 12),
-   JP_PATTERN(7, 50, 100, 1000, 2000, 20, 1),
+   JP_PATTERN(7, 50, 100, 1000, 2000, 1, 20),
JP_PATTERN(5, 0, 1, 333, 333, 1, 9),
 };
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] mac80211: add an intermediate software queue implementation

2014-12-16 Thread Felix Fietkau
On 2014-12-16 00:25, Bartosz Szczepanek wrote:
 As for drv_wake_tx_queue and ieee80211_tx_dequeue - is it really
 necessary? There are ieee80211_tx_status and ieee80211_free_txskb
 already, which can be used to decide from mac80211 level when to
 dequeue packet. It could be used even in case of drivers that are not
 aware of new mechanism at all. We could compute difference between
 drv_tx and tx_status/free_txskb calls, therefore getting number of
 frames in HW. What could help us to keep queues short.
Keeping the driver queue short is a bad idea if the driver needs deeper
queues to do aggregation.

 I've already written some code. This http://pastebin.com/dSd1zWt7 is
 patch that implements counter of frames in hardware in the way
 described above. It was necessary to differentiate between free_txskb
 and free_txskb. Information about frames in HW is exported to debugfs.
 I thought I could submit it, but just now did I found this thread, so
 I hope that it's adequate place to propose that. I tested it on ath5k
 and brcmsmac.
For aggregation, different drivers need different kinds of scheduling.
Only packets belonging to the same sta/tid can be aggregated, and in AP
mode you can have concurrent traffic of multiple different sta/tid.
The only way to keep queues really short in that case without
sacrificing throughput is to let the aggregation code fetch packets
directly from sta/tid queues.
With ath5k there is no aggregation yet (we could add A-MSDU at some
point), and with brcmsmac, the driver has an internal layer of queueing
to create per-sta/tid queues.
What I'm proposing is having per-sta/tid queues that are shared between
mac80211 and the driver, which will significantly improve queue
management compared to having multiple competing layers of queueing.

 One more thing - why not to use local-pending for holding packets?
 There is tx_pending tasklet already. I'm not sure if I understand the
 idea of local-pending queues correctly, but it seems to be a bit
 incoherent to have both pending and proposed ieee80211_txq.
local-pending is useless for normal tx queueing purposes, because it's
not per-sta/tid.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3.19] mac80211: minstrel: reduce size of struct minstrel_rate_stats

2014-12-17 Thread Felix Fietkau
On minstrel_ht, the size of the per-sta struct is almost 18k, making it
an order-3 allocation.
A few fields inside the per-rate statistics are bigger than they need to
be. This patch reduces the size enough to cut down the per-sta struct to
about 13k (order-2 allocation).

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/rc80211_minstrel.c |  6 +++---
 net/mac80211/rc80211_minstrel.h | 15 ---
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index d51f6b1..7c86a00 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -263,12 +263,12 @@ static inline unsigned int
 minstrel_get_retry_count(struct minstrel_rate *mr,
 struct ieee80211_tx_info *info)
 {
-   unsigned int retry = mr-adjusted_retry_count;
+   u8 retry = mr-adjusted_retry_count;
 
if (info-control.use_rts)
-   retry = max(2U, min(mr-stats.retry_count_rtscts, retry));
+   retry = max_t(u8, 2, min(mr-stats.retry_count_rtscts, retry));
else if (info-control.use_cts_prot)
-   retry = max(2U, min(mr-retry_count_cts, retry));
+   retry = max_t(u8, 2, min(mr-retry_count_cts, retry));
return retry;
 }
 
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 97eca86..b49d663 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -33,8 +33,8 @@ minstrel_ewma(int old, int new, int weight)
 
 struct minstrel_rate_stats {
/* current / last sampling period attempts/success counters */
-   unsigned int attempts, last_attempts;
-   unsigned int success, last_success;
+   u16 attempts, last_attempts;
+   u16 success, last_success;
 
/* total attempts/success counters */
u64 att_hist, succ_hist;
@@ -46,8 +46,8 @@ struct minstrel_rate_stats {
unsigned int cur_prob, probability;
 
/* maximum retry counts */
-   unsigned int retry_count;
-   unsigned int retry_count_rtscts;
+   u8 retry_count;
+   u8 retry_count_rtscts;
 
u8 sample_skipped;
bool retry_updated;
@@ -55,14 +55,15 @@ struct minstrel_rate_stats {
 
 struct minstrel_rate {
int bitrate;
-   int rix;
+
+   u8 rix;
+   u8 retry_count_cts;
+   u8 adjusted_retry_count;
 
unsigned int perfect_tx_time;
unsigned int ack_time;
 
int sample_limit;
-   unsigned int retry_count_cts;
-   unsigned int adjusted_retry_count;
 
struct minstrel_rate_stats stats;
 };
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 3.19] mac80211: minstrel: reduce size of struct minstrel_rate_stats

2014-12-17 Thread Felix Fietkau
On minstrel_ht, the size of the per-sta struct is almost 18k, making it
an order-3 allocation.
A few fields inside the per-rate statistics are bigger than they need to
be. This patch reduces the size enough to cut down the per-sta struct to
about 13k (order-2 allocation).

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 net/mac80211/rc80211_minstrel.c |  6 +++---
 net/mac80211/rc80211_minstrel.h | 15 ---
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index d51f6b1..7c86a00 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -263,12 +263,12 @@ static inline unsigned int
 minstrel_get_retry_count(struct minstrel_rate *mr,
 struct ieee80211_tx_info *info)
 {
-   unsigned int retry = mr-adjusted_retry_count;
+   u8 retry = mr-adjusted_retry_count;
 
if (info-control.use_rts)
-   retry = max(2U, min(mr-stats.retry_count_rtscts, retry));
+   retry = max_t(u8, 2, min(mr-stats.retry_count_rtscts, retry));
else if (info-control.use_cts_prot)
-   retry = max(2U, min(mr-retry_count_cts, retry));
+   retry = max_t(u8, 2, min(mr-retry_count_cts, retry));
return retry;
 }
 
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 97eca86..410efe6 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -33,8 +33,8 @@ minstrel_ewma(int old, int new, int weight)
 
 struct minstrel_rate_stats {
/* current / last sampling period attempts/success counters */
-   unsigned int attempts, last_attempts;
-   unsigned int success, last_success;
+   u16 attempts, last_attempts;
+   u16 success, last_success;
 
/* total attempts/success counters */
u64 att_hist, succ_hist;
@@ -46,8 +46,8 @@ struct minstrel_rate_stats {
unsigned int cur_prob, probability;
 
/* maximum retry counts */
-   unsigned int retry_count;
-   unsigned int retry_count_rtscts;
+   u8 retry_count;
+   u8 retry_count_rtscts;
 
u8 sample_skipped;
bool retry_updated;
@@ -55,14 +55,15 @@ struct minstrel_rate_stats {
 
 struct minstrel_rate {
int bitrate;
-   int rix;
+
+   s8 rix;
+   u8 retry_count_cts;
+   u8 adjusted_retry_count;
 
unsigned int perfect_tx_time;
unsigned int ack_time;
 
int sample_limit;
-   unsigned int retry_count_cts;
-   unsigned int adjusted_retry_count;
 
struct minstrel_rate_stats stats;
 };
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3.19] ath9k: fix race condition in irq processing during hardware reset

2015-01-15 Thread Felix Fietkau
On 2015-01-15 10:09, Sujith Manoharan wrote:
 Felix Fietkau wrote:
 To fix invalid hardware accesses, the commit
 ath9k: do not access hardware on IRQs during reset made the irq
 handler ignore interrupts emitted after queueing a hardware reset (which
 disables the IRQ). This left a small time window for the IRQ to get
 re-enabled by the tasklet, which caused IRQ storms.
 Instead of returning IRQ_NONE when ATH_OP_HW_RESET is set, disable the
 IRQ entirely for the duration of the reset.
 
 Doesn't this make the kill_interrupts() that was added in the earlier
 commit unnecessary now ?
I think it's still a good idea to try to silence interrupts between
queueing a reset and actually performing it.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2] ath9k_htc: add adaptive usb receive flow control to repair soft lockup with monitor mode

2015-02-19 Thread Felix Fietkau
On 2015-02-10 11:34, Yuwei Zheng wrote:
 The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and 
 ath9k_rx_tasklet excute
 on the soft irq context. In other words, the ath9k_hif_usb_rx_cb have more 
 chance to excute than
 ath9k_rx_tasklet.  So in the worst condition,  the rx.rxbuf receive list is 
 always full,
 and the do {}while(true) loop will not be break. The kernel get a soft lockup 
 panic. 
  
 [59011.007210] BUG: soft lockup - CPU#0 stuck for 23s!
 [kworker/0:0:30609]
 [59011.030560] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
 [59013.804486] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
 [59013.858522] Kernel panic - not syncing: softlockup: hung tasks
  
 [59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
 [59014.046834] bc20:   
 de57b950 6113
 [59014.059579] bc40:  bb32bb32 6113 de57b948 de57b500 dc7bb440 
 df4bbcd0 
 [59014.072337] bc60: de57b950 6113 df4bbcd0 df4bbc80 c04c259d c04c25a0 
 6133 
 [59014.085233] [c04c28db] (__irq_svc+0x3b/0x5c) from [c04c25a0] 
 (_raw_spin_unlock_irqrestore+0xc/0x10)
 [59014.100437] [c04c25a0] (_raw_spin_unlock_irqrestore+0xc/0x10) from 
 [bf9c2089] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc])
 [59014.118267] [bf9c2089] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) from 
 [c0036d23] (tasklet_action+0x3b/0x98)
 [59014.134132] [c0036d23] (tasklet_action+0x3b/0x98) from [c0036709] 
 (__do_softirq+0x99/0x16c)
 [59014.147784] [c0036709] (__do_softirq+0x99/0x16c) from [c00369f7] 
 (irq_exit+0x5b/0x5c)
 [59014.160653] [c00369f7] (irq_exit+0x5b/0x5c) from [c000cfc3] 
 (handle_IRQ+0x37/0x78)
 [59014.173124] [c000cfc3] (handle_IRQ+0x37/0x78) from [c00085df] 
 (omap3_intc_handle_irq+0x5f/0x68)
 [59014.187225] [c00085df] (omap3_intc_handle_irq+0x5f/0x68) from 
 [c04c28db](__irq_svc+0x3b/0x5c)
  
 This bug can be see with low performance board, such as uniprocessor beagle 
 bone board. Add some debug 
 message in the ath9k_hif_usb_rx_cb function may trigger this bug quickly.
  
 Signed-off-by: Yuwei Zheng yuweizh...@139.com
This approach of interaction between tasklet and workqueue processing
seems quite complex to me. Wouldn't it be simpler and better to simply
always run the rx processing code in workqueue context?
That way it can go on processing forever (as long as there is data to be
received), while the scheduler ensures that it doesn't interfere with
other critical work on the CPU.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3.19] ath9k: fix race condition in irq processing during hardware reset

2015-01-14 Thread Felix Fietkau
To fix invalid hardware accesses, the commit
ath9k: do not access hardware on IRQs during reset made the irq
handler ignore interrupts emitted after queueing a hardware reset (which
disables the IRQ). This left a small time window for the IRQ to get
re-enabled by the tasklet, which caused IRQ storms.
Instead of returning IRQ_NONE when ATH_OP_HW_RESET is set, disable the
IRQ entirely for the duration of the reset.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/main.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c 
b/drivers/net/wireless/ath/ath9k/main.c
index 9a72640..62b0bf4 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -285,6 +285,7 @@ static int ath_reset_internal(struct ath_softc *sc, struct 
ath9k_channel *hchan)
 
__ath_cancel_work(sc);
 
+   disable_irq(sc-irq);
tasklet_disable(sc-intr_tq);
tasklet_disable(sc-bcon_tasklet);
spin_lock_bh(sc-sc_pcu_lock);
@@ -331,6 +332,7 @@ static int ath_reset_internal(struct ath_softc *sc, struct 
ath9k_channel *hchan)
r = -EIO;
 
 out:
+   enable_irq(sc-irq);
spin_unlock_bh(sc-sc_pcu_lock);
tasklet_enable(sc-bcon_tasklet);
tasklet_enable(sc-intr_tq);
@@ -512,9 +514,6 @@ irqreturn_t ath_isr(int irq, void *dev)
if (!ah || test_bit(ATH_OP_INVALID, common-op_flags))
return IRQ_NONE;
 
-   if (!AR_SREV_9100(ah)  test_bit(ATH_OP_HW_RESET, common-op_flags))
-   return IRQ_NONE;
-
/* shared irq, not for us */
if (!ath9k_hw_intrpend(ah))
return IRQ_NONE;
@@ -529,7 +528,7 @@ irqreturn_t ath_isr(int irq, void *dev)
ath9k_debug_sync_cause(sc, sync_cause);
status = ah-imask;/* discard unasked-for bits */
 
-   if (AR_SREV_9100(ah)  test_bit(ATH_OP_HW_RESET, common-op_flags))
+   if (test_bit(ATH_OP_HW_RESET, common-op_flags))
return IRQ_HANDLED;
 
/*
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4.0] ath9k: disable TPC support again (for now)

2015-03-15 Thread Felix Fietkau
TPC support has been observed to cause some tx power fluctuations on
some devices with at least AR934x and AR938x chips.
Disable it for now until the bugs have been found and fixed

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/hw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index 60aa8d7..8529014 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -424,7 +424,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah-power_mode = ATH9K_PM_UNDEFINED;
ah-htc_reset_init = true;
 
-   ah-tpc_enabled = true;
+   ah-tpc_enabled = false;
 
ah-ani_function = ATH9K_ANI_ALL;
if (!AR_SREV_9300_20_OR_LATER(ah))
-- 
2.2.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 08/10] mac80211: add max. lossless throughput per rate to rc_stats

2015-03-17 Thread Felix Fietkau
On 2015-02-13 15:57, Thomas Huehn wrote:
 This patch adds the new statistic maximum possible lossless
 throughput to Minstrels and Minstrel-HTs rc_stats (in debugfs). This
 enables comprehensive comparison between current per-rate throughput
 and max. achievable per-rate throughput.
 
 Signed-off-by: Thomas Huehn tho...@net.t-labs.tu-berlin.de
 ---
  net/mac80211/rc80211_minstrel.c| 12 
  net/mac80211/rc80211_minstrel.h|  1 +
  net/mac80211/rc80211_minstrel_debugfs.c| 18 +++---
  net/mac80211/rc80211_minstrel_ht.c | 19 +++
  net/mac80211/rc80211_minstrel_ht.h |  1 +
  net/mac80211/rc80211_minstrel_ht_debugfs.c | 20 
  6 files changed, 56 insertions(+), 15 deletions(-)
 
 diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
 index 28de2f7a..42dfef8 100644
 --- a/net/mac80211/rc80211_minstrel.c
 +++ b/net/mac80211/rc80211_minstrel.c
 @@ -87,7 +87,19 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr)
   return tp_avg;
  }
  
 +/* return max. potential lossless throughput */
 +int minstrel_get_tp_max(struct minstrel_rate *mr)
 +{
 + int tp_max, usecs;
  
 + usecs = mr-perfect_tx_time;
 + if (!usecs)
 + usecs = 100;
 +
 + tp_max = 10 / usecs;
 +
 + return tp_max;
 +}
This should probably be an inline function, and you can remove the
tp_max variable as well.
By the way, in the case of !usecs, the result (10 / 100) will be
0, so you can simplify the logic.


  /* find  sort topmost throughput rates */
  static inline void
 diff --git a/net/mac80211/rc80211_minstrel_ht.c 
 b/net/mac80211/rc80211_minstrel_ht.c
 index 2a55f63..b62b04e 100644
 --- a/net/mac80211/rc80211_minstrel_ht.c
 +++ b/net/mac80211/rc80211_minstrel_ht.c
 @@ -350,6 +350,25 @@ minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int 
 group, int rate)
  }
  
  /*
 + * Return max. potential lossless throughput based on the average A-MPDU
 + */
 +int
 +minstrel_ht_get_tp_max(struct minstrel_ht_sta *mi, int group, int rate)
 +{
 + unsigned int nsecs = 0;
 + unsigned int tp_max;
 +
 + if (group != MINSTREL_CCK_GROUP)
 + nsecs = 1000 * mi-overhead / MINSTREL_TRUNC(mi-avg_ampdu_len);
 +
 + nsecs += minstrel_mcs_groups[group].duration[rate];
 + tp_max = 1 / nsecs;
 +
 + return tp_max;
 +}
I don't like duplication of the throughput metric - gets annoying if we
ever decide to tweak it. How about unifying this with
minstrel_ht_get_tp_avg by passing in the prob value as a parameter.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 04/10] mac80211: add new Minstrel-HT statistic output via csv

2015-03-17 Thread Felix Fietkau
On 2015-02-13 15:57, Thomas Huehn wrote:
 This patch adds a new debugfs file rc_stats_csv to output
 Minstrel-HTs statistics in a common csv format that is easy
 to parse.
 
 Signed-off-by: Thomas Huehn tho...@net.t-labs.tu-berlin.de
 Signed-off-by: Stefan Venz ikstrea...@gmail.com
 ---
 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
 +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
 +static int
 +minstrel_ht_stats_csv_open(struct inode *inode, struct file *file)
 +{
 + struct minstrel_ht_sta_priv *msp = inode-i_private;
 + struct minstrel_ht_sta *mi = msp-ht;
 + struct minstrel_debugfs_info *ms;
 + struct timeval tv;
 + unsigned int i;
 + int ret;
 + char *p;
 +
 + do_gettimeofday(tv);
 +
 + if (!msp-is_ht) {
 + inode-i_private = msp-legacy;
 + ret = minstrel_stats_open(inode, file);
Should be minstrel_stats_csv_open here?

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 03/10] mac80211: add new Minstrel statistic output via csv

2015-03-17 Thread Felix Fietkau
On 2015-02-13 15:57, Thomas Huehn wrote:
 This patch adds a new debugfs file rc_stats_csv to output Minstrels
 statistics in a common csv format that is easy to parse.
 
 Signed-off-by: Thomas Huehn tho...@net.t-labs.tu-berlin.de
 Signed-off-by: Stefan Venz ikstrea...@gmail.com
 ---
  net/mac80211/rc80211_minstrel.h|  6 +-
  net/mac80211/rc80211_minstrel_debugfs.c| 95 
 ++
  net/mac80211/rc80211_minstrel_ht_debugfs.c |  2 +-
  3 files changed, 88 insertions(+), 15 deletions(-)
 

 diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c 
 b/net/mac80211/rc80211_minstrel_ht_debugfs.c
 index 7fc690f..b300513 100644
 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
 +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
 @@ -112,7 +112,7 @@ minstrel_ht_stats_open(struct inode *inode, struct file 
 *file)
  
   if (!msp-is_ht) {
   inode-i_private = msp-legacy;
 - ret = minstrel_stats_open(inode, file);
 + ret = minstrel_stats_csv_open(inode, file);
That does not look right to me.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3] mac80211: add an intermediate software queue implementation

2015-03-17 Thread Felix Fietkau
This allows drivers to request per-vif and per-sta-tid queues from which
they can pull frames. This makes it easier to keep the hardware queues
short, and to improve fairness between clients and vifs.

The task of scheduling packet transmission is left up to the driver -
queueing is controlled by mac80211. Drivers can only dequeue packets by
calling ieee80211_tx_dequeue. This makes it possible to add active queue
management later without changing drivers using this code.

This can also be used as a starting point to implement A-MSDU
aggregation in a way that does not add artificially induced latency.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 include/net/mac80211.h | 77 ++
 net/mac80211/driver-ops.h  | 17 ++
 net/mac80211/ieee80211_i.h | 14 
 net/mac80211/iface.c   | 26 +++
 net/mac80211/main.c|  3 ++
 net/mac80211/rx.c  | 15 +
 net/mac80211/sta_info.c| 83 +-
 net/mac80211/sta_info.h|  3 ++
 net/mac80211/trace.h   | 34 +++
 net/mac80211/tx.c  | 72 ++--
 net/mac80211/util.c| 38 +
 11 files changed, 370 insertions(+), 12 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a1db2ea..724e133 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -84,6 +84,33 @@
  *
  */
 
+/**
+ * DOC: mac80211 software tx queueing
+ *
+ * mac80211 provides an optional intermediate queueing implementation designed
+ * to allow the driver to keep hardware queues short and provide some fairness
+ * between different stations/interfaces.
+ * In this model, the driver pulls data frames from the mac80211 queue instead
+ * of letting mac80211 push them via drv_tx(). Management frames are still sent
+ * via drv_tx().
+ *
+ * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with a
+ * single per-vif queue for multicast data frames.
+ *
+ * The driver is expected to initialize its private per-queue data for stations
+ * and interfaces in the .add_interface and .sta_add ops.
+ *
+ * The driver can not access the queue directly. To dequeue a frame, it calls
+ * ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a queue, it
+ * calls the .wake_tx_queue driver op.
+ *
+ * For AP powersave TIM handling, the driver only needs to indicate if it has
+ * buffered packets in the driver specific data structures. For frames buffered
+ * in the ieee80211_txq struct, mac80211 sets TIM and the driver is expected
+ * to dequeue and transmit packets on demand via the .release_buffered_frames
+ * op.
+ */
+
 struct device;
 
 /**
@@ -1257,6 +1284,8 @@ struct ieee80211_vif {
u8 cab_queue;
u8 hw_queue[IEEE80211_NUM_ACS];
 
+   struct ieee80211_txq *txq;
+
struct ieee80211_chanctx_conf __rcu *chanctx_conf;
 
u32 driver_flags;
@@ -1519,6 +1548,8 @@ struct ieee80211_sta {
bool tdls_initiator;
bool mfp;
 
+   struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
 };
@@ -1547,6 +1578,27 @@ struct ieee80211_tx_control {
 };
 
 /**
+ * struct ieee80211_txq - Software intermediate tx queue
+ *
+ * @vif: struct ieee80211_vif pointer from the add_interface callback.
+ * @sta: station table entry, may be NULL for per-vif queue
+ * @tid: the TID for this queue (unset for per-vif queue)
+ * @ac: the AC for this queue
+ *
+ * The driver can obtain packets from this queue by calling
+ * ieee80211_tx_dequeue().
+ */
+struct ieee80211_txq {
+   struct ieee80211_vif *vif;
+   struct ieee80211_sta *sta;
+   u8 tid;
+   u8 ac;
+
+   /* must be last */
+   u8 drv_priv[0] __aligned(sizeof(void *));
+};
+
+/**
  * enum ieee80211_hw_flags - hardware flags
  *
  * These flags are used to indicate hardware capabilities to
@@ -1770,6 +1822,8 @@ enum ieee80211_hw_flags {
  * within struct ieee80211_sta.
  * @chanctx_data_size: size (in bytes) of the drv_priv data area
  * within struct ieee80211_chanctx_conf.
+ * @txq_data_size: size (in bytes) of the drv_priv data area
+ * within @struct ieee80211_txq.
  *
  * @max_rates: maximum number of alternate rate retry stages the hw
  * can handle.
@@ -1818,6 +1872,9 @@ enum ieee80211_hw_flags {
  * @n_cipher_schemes: a size of an array of cipher schemes definitions.
  * @cipher_schemes: a pointer to an array of cipher scheme definitions
  * supported by HW.
+ *
+ * @txq_ac_max_pending: maximum number of frames per AC pending in all txq
+ * entries for a vif.
  */
 struct ieee80211_hw {
struct ieee80211_conf conf;
@@ -1830,6 +1887,7 @@ struct ieee80211_hw {
int vif_data_size;
int sta_data_size;
int chanctx_data_size;
+   int txq_data_size;
u16 queues;
u16 max_listen_interval;
s8 max_signal

Re: [PATCH v3] mac80211: add an intermediate software queue implementation

2015-03-17 Thread Felix Fietkau
On 2015-03-17 12:24, Johannes Berg wrote:
 On Tue, 2015-03-17 at 11:21 +0100, Felix Fietkau wrote:
 @@ -1257,6 +1284,8 @@ struct ieee80211_vif {
  u8 cab_queue;
  u8 hw_queue[IEEE80211_NUM_ACS];
  
 +struct ieee80211_txq *txq;
 
 This is just one txq, the mcast one? Perhaps that should be cab_txq
 then?
That would be misleading, since this queue is only used when CAB isn't
(i.e. no sta in PS).

 Or is it multiple, then perhaps it should be txqs?
 
 +struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
 
 I wonder if there's a way to make this a single pointer here only? But I
 guess with variable-sized driver data this would be really difficult.
Maybe a potential optimization for later - I'd like to keep it simple
for now...

 @@ -1818,6 +1872,9 @@ enum ieee80211_hw_flags {
   * @n_cipher_schemes: a size of an array of cipher schemes definitions.
   * @cipher_schemes: a pointer to an array of cipher scheme definitions
   *  supported by HW.
 + *
 + * @txq_ac_max_pending: maximum number of frames per AC pending in all txq
 + *  entries for a vif.
 
 I think you should give some guidance on how to best set this value,
 like max aggregation size or something? I'm not really sure :)
I don't have any guidance for tuning this in the driver just yet.
For devices with software aggregation, it should just be left at the
default value.

 +if (sta_prepare_rate_control(local, sta, gfp))
 +goto free_txq;
 
 Does it even have to come before rate control?
It doesn't have to, but I figured cleanup is simpler that way.

 @@ -1090,10 +1119,25 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info 
 *sta)
  
  BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS)  1);
  sta-driver_buffered_tids = 0;
 +sta-txq_buffered_tids = 0;
  
  if (!(local-hw.flags  IEEE80211_HW_AP_LINK_PS))
  drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, sta-sta);
  
 +if (sta-txqi) {
 +for (i = 0; i  ARRAY_SIZE(sta-sta.txq); i++) {
 +struct txq_info *txqi;
 +
 +txqi = container_of(sta-sta.txq[i], struct txq_info,
 +txq);
 +
 +if (!skb_queue_len(txqi-queue))
 +continue;
 +
 +drv_wake_tx_queue(local, txqi);
 +}
 +}
 
 This could be an interesting race. If you wake the queue, and then the
 station goes to sleep again before the driver had a chance to pull
 frames, what happens? Should the driver be responsible for this? But you
 don't have unwake_tx_queue, so maybe you should not return any frame
 from the dequeue in such a case?
The driver is responsible for making sure that any queue of a sleeping
sta is not scheduled.

 @@ -1447,6 +1493,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
  
  sta_info_recalc_tim(sta);
  } else {
 +unsigned long tids = sta-txq_buffered_tids  
 driver_release_tids;
 
 I'm not sure I understand this. Are you treating txq_buffered_tids as
 driver-buffered?
Yes. As explained in the DOC section, PS delivery of txq buffered frames
goes through drv_release_buffered_frames. Maybe I could change the
wording a bit to make it more clear.

 @@ -368,6 +369,8 @@ struct sta_info {
  struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
  struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
  unsigned long driver_buffered_tids;
 +unsigned long txq_buffered_tids;
 +struct txq_info *txqi;
 
 Hm, so, internally you allocate one big thing and externally to the
 driver you have a per-TID array.
 
 Why not just remove this pointer, and keep only the per-TID array? You'd
 have to do a bit more container_of() but I don't think that's a big
 deal? Plus you can't really use this anyway since you can't index it,
 i.e. you cannot say sta-txqi[t] since the size doesn't match up.
Will do

 +static void ieee80211_drv_tx(struct ieee80211_local *local,
 + struct ieee80211_vif *vif,
 + struct ieee80211_sta *pubsta,
 + struct sk_buff *skb)
 +{
 +struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb-data;
 +struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 +struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 +struct ieee80211_tx_control control = {
 +.sta = pubsta
 +};
 +struct ieee80211_txq *txq = NULL;
 +struct txq_info *txqi;
 +u8 ac;
 +
 +if (info-control.flags  IEEE80211_TX_CTRL_PS_RESPONSE)
 +goto tx_normal;
 +
 +if (ieee80211_is_mgmt(hdr-frame_control) ||
 +ieee80211_is_ctl(hdr-frame_control))
 +goto tx_normal;
 
 Doesn't this become awkward with powersave handling for bufferable mgmt
 frames? They'd be stored on the per-station non-txq queues, but then the
 wakeup handling needs to see which ones to take first? Having these on
 the txqs might make that part easier?
I guess I'll change it to throw

Re: [PATCH 16/18] ath9k: use REG_RMW and rmw buffer in ath9k_hw_4k_set_gain

2015-03-20 Thread Felix Fietkau
On 2015-03-20 13:38, Oleksij Rempel wrote:
 it is possible to reduce time needed for this function
 by rplacing REG_WRITE with REG_RMW (plus dummy 0) and putt all commands
 in same buffer.
 
 Signed-off-by: Oleksij Rempel li...@rempel-privat.de
 ---
  drivers/net/wireless/ath/ath9k/eeprom_4k.c | 18 ++
  1 file changed, 10 insertions(+), 8 deletions(-)
 
 diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c 
 b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
 index 291c1d1..56621be 100644
 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
 +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
 @@ -772,15 +772,16 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
struct ar5416_eeprom_4k *eep,
u8 txRxAttenLocal)
  {
 - REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0,
 -   pModal-antCtrlChain[0]);
 + ENABLE_REG_RMW_BUFFER(ah);
 + REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0,
 + pModal-antCtrlChain[0], 0);
How about combining the WRITE/RMW buffering in ath9k_htc (automatically
deciding whether to use RMW or WRITE for the whole transaction), instead
of quirky looking REG_WRITE to REG_RMW conversions?

 - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0),
 -   (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) 
 -~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
 -  AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
 -   SM(pModal-iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
 -   SM(pModal-iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
 + REG_RMW(ah, AR_PHY_TIMING_CTRL4(0),
 + (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) 
 +  ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
 +AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
 + SM(pModal-iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
 + SM(pModal-iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF), 
 0);
If you translate it to REG_RMW, you should get rid of the REG_READ part.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 18/18] ath9k: use REG_RMW and rmw buffer in ath9k_hw_def_set_gain

2015-03-20 Thread Felix Fietkau
On 2015-03-20 13:38, Oleksij Rempel wrote:
 Signed-off-by: Oleksij Rempel li...@rempel-privat.de
 ---
  drivers/net/wireless/ath/ath9k/eeprom_def.c | 19 +++
  1 file changed, 11 insertions(+), 8 deletions(-)
 
 diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c 
 b/drivers/net/wireless/ath/ath9k/eeprom_def.c
 index 0980590..4b43539 100644
 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
 +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
 @@ -466,6 +466,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah,
 struct ar5416_eeprom_def *eep,
 u8 txRxAttenLocal, int regChainOffset, int i)
  {
 + ENABLE_REG_RMW_BUFFER(ah);
   if (AR5416_VER_MASK = AR5416_EEP_MINOR_VER_3) {
   txRxAttenLocal = pModal-txRxAttenCh[i];
  
 @@ -483,16 +484,16 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah,
 AR_PHY_GAIN_2GHZ_XATTEN2_DB,
 pModal-xatten2Db[i]);
   } else {
 - REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
 + REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) 
  ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
 | SM(pModal- bswMargin[i],
 -AR_PHY_GAIN_2GHZ_BSW_MARGIN));
 - REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
 +AR_PHY_GAIN_2GHZ_BSW_MARGIN), 0);
 + REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) 
  ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
 | SM(pModal-bswAtten[i],
 -AR_PHY_GAIN_2GHZ_BSW_ATTEN));
 +AR_PHY_GAIN_2GHZ_BSW_ATTEN), 0);
   }
   }
  
 @@ -504,17 +505,19 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah,
 AR_PHY_RXGAIN + regChainOffset,
 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal-rxTxMarginCh[i]);
   } else {
 - REG_WRITE(ah,
 + REG_RMW(ah,
 AR_PHY_RXGAIN + regChainOffset,
 (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) 
  ~AR_PHY_RXGAIN_TXRX_ATTEN)
 -   | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
 - REG_WRITE(ah,
 +   | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN), 0);
 + REG_RMW(ah,
 AR_PHY_GAIN_2GHZ + regChainOffset,
 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) 
  ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
 -   SM(pModal-rxTxMarginCh[i], 
 AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
 +   SM(pModal-rxTxMarginCh[i],
 +   AR_PHY_GAIN_2GHZ_RXTX_MARGIN), 0);
   }
 + REG_RMW_BUFFER_FLUSH(ah);
Same in those chunks as in the other patch, do proper conversion to
REG_RMW by eliminating the REG_READ.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 08/10] mac80211: add max. lossless throughput per rate to rc_stats

2015-03-21 Thread Felix Fietkau
On 2015-03-17 18:29, Thomas Huehn wrote:
 This patch adds the new statistic maximum possible lossless
 throughput to Minstrels and Minstrel-HTs rc_stats (in debugfs). This
 enables comprehensive comparison between current per-rate throughput
 and max. achievable per-rate throughput.
 
 Signed-off-by: Thomas Huehn tho...@net.t-labs.tu-berlin.de
 ---
  net/mac80211/rc80211_minstrel.c| 10 
  net/mac80211/rc80211_minstrel.h|  1 +
  net/mac80211/rc80211_minstrel_debugfs.c| 18 ---
  net/mac80211/rc80211_minstrel_ht.c | 84 
 --
  net/mac80211/rc80211_minstrel_ht.h |  4 +-
  net/mac80211/rc80211_minstrel_ht_debugfs.c | 24 +
  6 files changed, 83 insertions(+), 58 deletions(-)
 
 diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
 index d985227..c2afe51 100644
 --- a/net/mac80211/rc80211_minstrel.c
 +++ b/net/mac80211/rc80211_minstrel.c
 @@ -85,6 +85,16 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr)
   return MINSTREL_TRUNC(mr-stats.prob_ewma * (10 / usecs));
  }
  
 +/* return max. potential lossless throughput */
 +inline int
 +minstrel_get_tp_max(struct minstrel_rate *mr)
 +{
 + if (!mr-perfect_tx_time)
 + return 0;
 +
 + return 10 / mr-perfect_tx_time;
 +}
 +
  /* find  sort topmost throughput rates */
  static inline void
  minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
How about merging it with the _avg function, like in minstrel_ht.

 diff --git a/net/mac80211/rc80211_minstrel_ht.h 
 b/net/mac80211/rc80211_minstrel_ht.h
 index 68dce4f..850d352 100644
 --- a/net/mac80211/rc80211_minstrel_ht.h
 +++ b/net/mac80211/rc80211_minstrel_ht.h
 @@ -121,6 +121,8 @@ struct minstrel_ht_sta_priv {
  
  void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry 
 *dir);
  void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
 -int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate);
 +int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
 +int prob_ewma);
 +int minstrel_ht_get_tp_max(struct minstrel_ht_sta *mi, int group, int rate);
Nonexistant function declaration, please remove it.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4] mac80211: add an intermediate software queue implementation

2015-03-17 Thread Felix Fietkau
This allows drivers to request per-vif and per-sta-tid queues from which
they can pull frames. This makes it easier to keep the hardware queues
short, and to improve fairness between clients and vifs.

The task of scheduling packet transmission is left up to the driver -
queueing is controlled by mac80211. Drivers can only dequeue packets by
calling ieee80211_tx_dequeue. This makes it possible to add active queue
management later without changing drivers using this code.

This can also be used as a starting point to implement A-MSDU
aggregation in a way that does not add artificially induced latency.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 include/net/mac80211.h |  78 ++
 net/mac80211/agg-tx.c  |  42 +
 net/mac80211/driver-ops.h  |  12 +
 net/mac80211/ieee80211_i.h |  24 ++
 net/mac80211/iface.c   |  19 
 net/mac80211/main.c|   3 ++
 net/mac80211/rx.c  |  13 +
 net/mac80211/sta_info.c|  78 ++
 net/mac80211/sta_info.h|   2 +
 net/mac80211/trace.h   |  28 +++
 net/mac80211/tx.c  | 115 +
 net/mac80211/util.c|  38 +++
 12 files changed, 433 insertions(+), 19 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a1db2ea..aafa5eb 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -84,6 +84,34 @@
  *
  */
 
+/**
+ * DOC: mac80211 software tx queueing
+ *
+ * mac80211 provides an optional intermediate queueing implementation designed
+ * to allow the driver to keep hardware queues short and provide some fairness
+ * between different stations/interfaces.
+ * In this model, the driver pulls data frames from the mac80211 queue instead
+ * of letting mac80211 push them via drv_tx().
+ * Other frames (e.g. control or management) are still pushed using drv_tx().
+ *
+ * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with a
+ * single per-vif queue for multicast data frames.
+ *
+ * The driver is expected to initialize its private per-queue data for stations
+ * and interfaces in the .add_interface and .sta_add ops.
+ *
+ * The driver can not access the queue directly. To dequeue a frame, it calls
+ * ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a queue, it
+ * calls the .wake_tx_queue driver op.
+ *
+ * For AP powersave TIM handling, the driver only needs to indicate if it has
+ * buffered packets in the driver specific data structures by calling
+ * ieee80211_sta_set_buffered(). For frames buffered in the ieee80211_txq
+ * struct, mac80211 sets TIM and calls .release_buffered_frames().
+ * The driver is expected to release its own buffered frames and also call
+ * ieee80211_tx_dequeue() within that callback.
+ */
+
 struct device;
 
 /**
@@ -1257,6 +1285,8 @@ struct ieee80211_vif {
u8 cab_queue;
u8 hw_queue[IEEE80211_NUM_ACS];
 
+   struct ieee80211_txq *txq;
+
struct ieee80211_chanctx_conf __rcu *chanctx_conf;
 
u32 driver_flags;
@@ -1519,6 +1549,8 @@ struct ieee80211_sta {
bool tdls_initiator;
bool mfp;
 
+   struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
 };
@@ -1547,6 +1579,27 @@ struct ieee80211_tx_control {
 };
 
 /**
+ * struct ieee80211_txq - Software intermediate tx queue
+ *
+ * @vif: struct ieee80211_vif pointer from the add_interface callback.
+ * @sta: station table entry, may be NULL for per-vif queue
+ * @tid: the TID for this queue (unused for per-vif queue)
+ * @ac: the AC for this queue
+ *
+ * The driver can obtain packets from this queue by calling
+ * ieee80211_tx_dequeue().
+ */
+struct ieee80211_txq {
+   struct ieee80211_vif *vif;
+   struct ieee80211_sta *sta;
+   u8 tid;
+   u8 ac;
+
+   /* must be last */
+   u8 drv_priv[0] __aligned(sizeof(void *));
+};
+
+/**
  * enum ieee80211_hw_flags - hardware flags
  *
  * These flags are used to indicate hardware capabilities to
@@ -1770,6 +1823,8 @@ enum ieee80211_hw_flags {
  * within struct ieee80211_sta.
  * @chanctx_data_size: size (in bytes) of the drv_priv data area
  * within struct ieee80211_chanctx_conf.
+ * @txq_data_size: size (in bytes) of the drv_priv data area
+ * within @struct ieee80211_txq.
  *
  * @max_rates: maximum number of alternate rate retry stages the hw
  * can handle.
@@ -1818,6 +1873,9 @@ enum ieee80211_hw_flags {
  * @n_cipher_schemes: a size of an array of cipher schemes definitions.
  * @cipher_schemes: a pointer to an array of cipher scheme definitions
  * supported by HW.
+ *
+ * @txq_ac_max_pending: maximum number of frames per AC pending in all txq
+ * entries for a vif.
  */
 struct ieee80211_hw {
struct ieee80211_conf conf;
@@ -1830,6 +1888,7 @@ struct ieee80211_hw {
int vif_data_size;
int sta_data_size

[PATCH 4.0] ath9k: fix tracking of enabled AP beacons

2015-03-12 Thread Felix Fietkau
sc-nbcnvifs tracks assigned beacon slots, not enabled beacons.
Therefore, it cannot be used to decide if cur_conf-enable_beacon (bool)
should be updated, or if beacons have been enabled already.
With the current code (depending on the order of calls), beacons often
do not get enabled in an AP+STA setup.
To fix tracking of enabled beacons, convert cur_conf-enable_beacon to a
bitmask of enabled beacon slots.

Cc: sta...@vger.kernel.org
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/beacon.c | 20 
 drivers/net/wireless/ath/ath9k/common.h |  2 +-
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/beacon.c 
b/drivers/net/wireless/ath/ath9k/beacon.c
index cb366ad..f50a6bc 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -219,12 +219,15 @@ void ath9k_beacon_remove_slot(struct ath_softc *sc, 
struct ieee80211_vif *vif)
struct ath_common *common = ath9k_hw_common(sc-sc_ah);
struct ath_vif *avp = (void *)vif-drv_priv;
struct ath_buf *bf = avp-av_bcbuf;
+   struct ath_beacon_config *cur_conf = sc-cur_chan-beacon;
 
ath_dbg(common, CONFIG, Removing interface at beacon slot: %d\n,
avp-av_bslot);
 
tasklet_disable(sc-bcon_tasklet);
 
+   cur_conf-enable_beacon = ~BIT(avp-av_bslot);
+
if (bf  bf-bf_mpdu) {
struct sk_buff *skb = bf-bf_mpdu;
dma_unmap_single(sc-dev, bf-bf_buf_addr,
@@ -521,8 +524,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
}
 
if (sc-sc_ah-opmode == NL80211_IFTYPE_AP) {
-   if ((vif-type != NL80211_IFTYPE_AP) ||
-   (sc-nbcnvifs  1)) {
+   if (vif-type != NL80211_IFTYPE_AP) {
ath_dbg(common, CONFIG,
An AP interface is already present !\n);
return false;
@@ -616,12 +618,14 @@ void ath9k_beacon_config(struct ath_softc *sc, struct 
ieee80211_vif *vif,
 * enabling/disabling SWBA.
 */
if (changed  BSS_CHANGED_BEACON_ENABLED) {
-   if (!bss_conf-enable_beacon 
-   (sc-nbcnvifs = 1)) {
-   cur_conf-enable_beacon = false;
-   } else if (bss_conf-enable_beacon) {
-   cur_conf-enable_beacon = true;
-   ath9k_cache_beacon_config(sc, ctx, bss_conf);
+   bool enabled = cur_conf-enable_beacon;
+
+   if (!bss_conf-enable_beacon) {
+   cur_conf-enable_beacon = ~BIT(avp-av_bslot);
+   } else {
+   cur_conf-enable_beacon |= BIT(avp-av_bslot);
+   if (!enabled)
+   ath9k_cache_beacon_config(sc, ctx, bss_conf);
}
}
 
diff --git a/drivers/net/wireless/ath/ath9k/common.h 
b/drivers/net/wireless/ath/ath9k/common.h
index 2b79a56..d237373 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -54,7 +54,7 @@ struct ath_beacon_config {
u16 dtim_period;
u16 bmiss_timeout;
u8 dtim_count;
-   bool enable_beacon;
+   u8 enable_beacon;
bool ibss_creator;
u32 nexttbtt;
u32 intval;
-- 
2.2.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 0/10] Improve Minstrels Minstrel-HTs common code base statistics

2015-03-24 Thread Felix Fietkau
On 2015-03-24 21:09, Thomas Huehn wrote:
 This patch series adds several improvements to the readability, the
 output format of rc_stats and the calculated statistics of Minstrel
 and Minstrel-HT. Variable names got more consistent and functions
 got unified between both rate control algorithms.
Acked-by: Felix Fietkau n...@openwrt.org
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6] mac80211: add an intermediate software queue implementation

2015-03-27 Thread Felix Fietkau
This allows drivers to request per-vif and per-sta-tid queues from which
they can pull frames. This makes it easier to keep the hardware queues
short, and to improve fairness between clients and vifs.

The task of scheduling packet transmission is left up to the driver -
queueing is controlled by mac80211. Drivers can only dequeue packets by
calling ieee80211_tx_dequeue. This makes it possible to add active queue
management later without changing drivers using this code.

This can also be used as a starting point to implement A-MSDU
aggregation in a way that does not add artificially induced latency.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 include/net/mac80211.h |  79 ++
 net/mac80211/agg-tx.c  |  44 +
 net/mac80211/driver-ops.h  |  12 +
 net/mac80211/ieee80211_i.h |  21 
 net/mac80211/iface.c   |  21 +++-
 net/mac80211/main.c|   3 ++
 net/mac80211/rx.c  |  13 +
 net/mac80211/sta_info.c|  84 
 net/mac80211/sta_info.h|   2 +
 net/mac80211/trace.h   |  28 +++
 net/mac80211/tx.c  | 116 +
 net/mac80211/util.c|  22 +
 12 files changed, 425 insertions(+), 20 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a1db2ea..7801190 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -84,6 +84,35 @@
  *
  */
 
+/**
+ * DOC: mac80211 software tx queueing
+ *
+ * mac80211 provides an optional intermediate queueing implementation designed
+ * to allow the driver to keep hardware queues short and provide some fairness
+ * between different stations/interfaces.
+ * In this model, the driver pulls data frames from the mac80211 queue instead
+ * of letting mac80211 push them via drv_tx().
+ * Other frames (e.g. control or management) are still pushed using drv_tx().
+ *
+ * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with a
+ * single per-vif queue for multicast data frames.
+ *
+ * The driver is expected to initialize its private per-queue data for stations
+ * and interfaces in the .add_interface and .sta_add ops.
+ *
+ * The driver can not access the queue directly. To dequeue a frame, it calls
+ * ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a queue, it
+ * calls the .wake_tx_queue driver op.
+ *
+ * For AP powersave TIM handling, the driver only needs to indicate if it has
+ * buffered packets in the driver specific data structures by calling
+ * ieee80211_sta_set_buffered(). For frames buffered in the ieee80211_txq
+ * struct, mac80211 sets the appropriate TIM PVB bits and calls
+ * .release_buffered_frames().
+ * That callback is expected to release its own buffered frames and afterwards
+ * also frames from the ieee80211_txq (obtained via ieee80211_tx_dequeue).
+ */
+
 struct device;
 
 /**
@@ -1257,6 +1286,8 @@ struct ieee80211_vif {
u8 cab_queue;
u8 hw_queue[IEEE80211_NUM_ACS];
 
+   struct ieee80211_txq *txq;
+
struct ieee80211_chanctx_conf __rcu *chanctx_conf;
 
u32 driver_flags;
@@ -1519,6 +1550,8 @@ struct ieee80211_sta {
bool tdls_initiator;
bool mfp;
 
+   struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
 };
@@ -1547,6 +1580,27 @@ struct ieee80211_tx_control {
 };
 
 /**
+ * struct ieee80211_txq - Software intermediate tx queue
+ *
+ * @vif: struct ieee80211_vif pointer from the add_interface callback.
+ * @sta: station table entry, %NULL for per-vif queue
+ * @tid: the TID for this queue (unused for per-vif queue)
+ * @ac: the AC for this queue
+ *
+ * The driver can obtain packets from this queue by calling
+ * ieee80211_tx_dequeue().
+ */
+struct ieee80211_txq {
+   struct ieee80211_vif *vif;
+   struct ieee80211_sta *sta;
+   u8 tid;
+   u8 ac;
+
+   /* must be last */
+   u8 drv_priv[0] __aligned(sizeof(void *));
+};
+
+/**
  * enum ieee80211_hw_flags - hardware flags
  *
  * These flags are used to indicate hardware capabilities to
@@ -1770,6 +1824,8 @@ enum ieee80211_hw_flags {
  * within struct ieee80211_sta.
  * @chanctx_data_size: size (in bytes) of the drv_priv data area
  * within struct ieee80211_chanctx_conf.
+ * @txq_data_size: size (in bytes) of the drv_priv data area
+ * within @struct ieee80211_txq.
  *
  * @max_rates: maximum number of alternate rate retry stages the hw
  * can handle.
@@ -1818,6 +1874,9 @@ enum ieee80211_hw_flags {
  * @n_cipher_schemes: a size of an array of cipher schemes definitions.
  * @cipher_schemes: a pointer to an array of cipher scheme definitions
  * supported by HW.
+ *
+ * @txq_ac_max_pending: maximum number of frames per AC pending in all txq
+ * entries for a vif.
  */
 struct ieee80211_hw {
struct ieee80211_conf conf;
@@ -1830,6 +1889,7 @@ struct ieee80211_hw

Re: [ath9k-devel] AR9462 problems connecting again..

2015-02-24 Thread Felix Fietkau
On 2015-02-25 07:14, Jouni Malinen wrote:
 On Tue, Feb 24, 2015 at 06:54:47PM +0100, Thomas Hühn wrote:
 Currently Minstrel_HT just skips EAPOL packets for its rate sampling on 
 non-mrr chips by testing: (info-control.flags  
 IEEE80211_TX_CTRL_PORT_CTRL_PROTO)
 
 Yeah, I noticed that when going through the implementation, but it was
 indeed only for cases other than ath9k-like drivers.
 
 On mrr hardware it uses them for probing. 
 But the general MRR-chain should look like this for ath5k and ath9k chips 
 that support 4 mrr chains:
 
 mrr[0]:= max_tp_rate[0]
 mrr[1]:= max_tp_rate[1]
 mrr[2]:= max_prob_rate
 mrr[3]:= basic_rate
 
 Where is that mrr[3] part implemented? I did not find it when reviewing
 the design (hw-max_rates = 3 is used, but not = 4) and this does not
 match my experiments either when printing out all four values from
 ath9k. In every single case I observed, the last entry was unused (idx =
 -1) and only MCS values were used (i.e., not even a single case of basic
 rate visible; basic rates being 6, 12, 24 Mbps OFDM in this specific
 case with the AP that I used in the tests).
Minstrel_ht does *NOT* use mrr[3], nor should it. For normal data
packets, a little packet loss under tough conditions is good, otherwise
we risk lots of wasted airtime and bufferbloat.

 So for Minstrel Sampling Packets as well as for data packets, the 4th mrr 
 stage should use the slowest rate in case all other 3 mrr stages failed with 
 their retry attempts.
 
 I do see two possible options for control frames like EAPOL to be send out 
 in a more robust fashion:
  - exclude those frames from AMPDU aggragates 
 
 ath9k does that for IEEE80211_TX_CTL_RATE_CTRL_PROBE which seemed to
 get set for the initial EAPOL frames. I guess this could be done more
 generically for all EAPOL frames.
I agree.

  - change their mrr setup to be more conservative
 
 That mrr[3]:= basic_rate is the part I was really asking for as far as
 EAPOL frames are concerned.
I don't think we need that. If we just exclude EAPOL from both probing
and aggregation, it should be safe. While it's connecting, that leaves
in low rates in the retry chain anyway.

If it still fails often enough to be noticeable under normal conditions,
there must be something seriously wrong outside of rate control, and we
should not paper over it with a crude band-aid workaround.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7] mac80211: add an intermediate software queue implementation

2015-03-27 Thread Felix Fietkau
This allows drivers to request per-vif and per-sta-tid queues from which
they can pull frames. This makes it easier to keep the hardware queues
short, and to improve fairness between clients and vifs.

The task of scheduling packet transmission is left up to the driver -
queueing is controlled by mac80211. Drivers can only dequeue packets by
calling ieee80211_tx_dequeue. This makes it possible to add active queue
management later without changing drivers using this code.

This can also be used as a starting point to implement A-MSDU
aggregation in a way that does not add artificially induced latency.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 include/net/mac80211.h |  79 ++
 net/mac80211/agg-tx.c  |  44 +
 net/mac80211/driver-ops.h  |  12 +
 net/mac80211/ieee80211_i.h |  21 
 net/mac80211/iface.c   |  23 -
 net/mac80211/main.c|   3 ++
 net/mac80211/rx.c  |  13 +
 net/mac80211/sta_info.c|  84 
 net/mac80211/sta_info.h|   2 +
 net/mac80211/trace.h   |  28 +++
 net/mac80211/tx.c  | 116 +
 net/mac80211/util.c|  22 +
 12 files changed, 427 insertions(+), 20 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 825b516..d4ca3f3 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -84,6 +84,35 @@
  *
  */
 
+/**
+ * DOC: mac80211 software tx queueing
+ *
+ * mac80211 provides an optional intermediate queueing implementation designed
+ * to allow the driver to keep hardware queues short and provide some fairness
+ * between different stations/interfaces.
+ * In this model, the driver pulls data frames from the mac80211 queue instead
+ * of letting mac80211 push them via drv_tx().
+ * Other frames (e.g. control or management) are still pushed using drv_tx().
+ *
+ * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with a
+ * single per-vif queue for multicast data frames.
+ *
+ * The driver is expected to initialize its private per-queue data for stations
+ * and interfaces in the .add_interface and .sta_add ops.
+ *
+ * The driver can not access the queue directly. To dequeue a frame, it calls
+ * ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a queue, it
+ * calls the .wake_tx_queue driver op.
+ *
+ * For AP powersave TIM handling, the driver only needs to indicate if it has
+ * buffered packets in the driver specific data structures by calling
+ * ieee80211_sta_set_buffered(). For frames buffered in the ieee80211_txq
+ * struct, mac80211 sets the appropriate TIM PVB bits and calls
+ * .release_buffered_frames().
+ * That callback is expected to release its own buffered frames and afterwards
+ * also frames from the ieee80211_txq (obtained via ieee80211_tx_dequeue).
+ */
+
 struct device;
 
 /**
@@ -1257,6 +1286,8 @@ struct ieee80211_vif {
u8 cab_queue;
u8 hw_queue[IEEE80211_NUM_ACS];
 
+   struct ieee80211_txq *txq;
+
struct ieee80211_chanctx_conf __rcu *chanctx_conf;
 
u32 driver_flags;
@@ -1532,6 +1563,8 @@ struct ieee80211_sta {
bool tdls_initiator;
bool mfp;
 
+   struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
 };
@@ -1560,6 +1593,27 @@ struct ieee80211_tx_control {
 };
 
 /**
+ * struct ieee80211_txq - Software intermediate tx queue
+ *
+ * @vif: struct ieee80211_vif pointer from the add_interface callback.
+ * @sta: station table entry, %NULL for per-vif queue
+ * @tid: the TID for this queue (unused for per-vif queue)
+ * @ac: the AC for this queue
+ *
+ * The driver can obtain packets from this queue by calling
+ * ieee80211_tx_dequeue().
+ */
+struct ieee80211_txq {
+   struct ieee80211_vif *vif;
+   struct ieee80211_sta *sta;
+   u8 tid;
+   u8 ac;
+
+   /* must be last */
+   u8 drv_priv[0] __aligned(sizeof(void *));
+};
+
+/**
  * enum ieee80211_hw_flags - hardware flags
  *
  * These flags are used to indicate hardware capabilities to
@@ -1783,6 +1837,8 @@ enum ieee80211_hw_flags {
  * within struct ieee80211_sta.
  * @chanctx_data_size: size (in bytes) of the drv_priv data area
  * within struct ieee80211_chanctx_conf.
+ * @txq_data_size: size (in bytes) of the drv_priv data area
+ * within @struct ieee80211_txq.
  *
  * @max_rates: maximum number of alternate rate retry stages the hw
  * can handle.
@@ -1831,6 +1887,9 @@ enum ieee80211_hw_flags {
  * @n_cipher_schemes: a size of an array of cipher schemes definitions.
  * @cipher_schemes: a pointer to an array of cipher scheme definitions
  * supported by HW.
+ *
+ * @txq_ac_max_pending: maximum number of frames per AC pending in all txq
+ * entries for a vif.
  */
 struct ieee80211_hw {
struct ieee80211_conf conf;
@@ -1843,6 +1902,7 @@ struct ieee80211_hw

Re: [PATCH v4] mac80211: add an intermediate software queue implementation

2015-03-18 Thread Felix Fietkau
On 2015-03-18 20:41, Johannes Berg wrote:
 + * The driver is expected to release its own buffered frames and also call
 + * ieee80211_tx_dequeue() within that callback.
 
 Perhaps that should read
 The driver is expected to release its own buffered frames (if any) and
 request the remaining dequeued frames by calling
 ieee80211_tx_dequeue().
 
 I'm not really sure it needs to be within that callback? I see no
 particular reason for that.
Releasing multiple packets works, even if there is only one packet
buffered in the driver and the rest in the txq. It also keeps the code
more consistent.
Now that I'm thinking about this some more, it might even make sense to
skip the sta PS queue for txq-enabled drivers. That would allow all sta
data frames to either go through driver scheduling or
release_buffered_frames.

 + * @tid: the TID for this queue (unused for per-vif queue)
 + * @ac: the AC for this queue
 
 AC is also unused for per-vif I guess?
It's set to BE for per-vif to allow the driver to use it to pick the
right tx queue.

 +++ b/net/mac80211/agg-tx.c
 @@ -188,6 +188,41 @@ ieee80211_wake_queue_agg(struct ieee80211_sub_if_data 
 *sdata, int tid)
  __release(agg_queue);
  }
  
 +static void
 +ieee80211_agg_stop_txq(struct sta_info *sta, int tid)
 +{
 +struct ieee80211_txq *txq = sta-sta.txq[tid];
 +struct txq_info *txqi;
 +
 +if (!txq)
 +return;
 +
 +txqi = to_txq_info(txq);
 +spin_lock_bh(txqi-queue.lock);
 +set_bit(IEEE80211_TXQ_STOP, txqi-flags);
 +spin_unlock_bh(txqi-queue.lock);
 
 What's the point in locking here?
If I don't lock here, one last dequeue call might still be running on
another CPU. This would produce a theoretical race in accessing the
sequence number, which the caller of this function reads before setting
up the BA request.
Dequeueing happens outside of the normal network stack tx context, so
synchronize_net is not enough.

 +static void
 +ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable)
 +{
 +struct ieee80211_txq *txq = sta-sta.txq[tid];
 +struct txq_info *txqi;
 +
 +if (!txq)
 +return;
 +
 +txqi = to_txq_info(txq);
 +
 +if (enable)
 +set_bit(IEEE80211_TXQ_AMPDU, txqi-flags);
 +else
 +clear_bit(IEEE80211_TXQ_AMPDU, txqi-flags);
 +
 +clear_bit(IEEE80211_TXQ_STOP, txqi-flags);
 
 here you don't either
Here only the order of changing IEEE80211_TXQ_AMPDU vs clearing
IEEE80211_TXQ_STOP matters.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] mac80211: add an intermediate software queue implementation

2015-03-18 Thread Felix Fietkau
On 2015-03-18 21:07, Johannes Berg wrote:
 On Wed, 2015-03-18 at 21:03 +0100, Felix Fietkau wrote:
 On 2015-03-18 20:41, Johannes Berg wrote:
  + * The driver is expected to release its own buffered frames and also 
  call
  + * ieee80211_tx_dequeue() within that callback.
  
  Perhaps that should read
  The driver is expected to release its own buffered frames (if any) and
  request the remaining dequeued frames by calling
  ieee80211_tx_dequeue().
  
  I'm not really sure it needs to be within that callback? I see no
  particular reason for that.
 Releasing multiple packets works, even if there is only one packet
 buffered in the driver and the rest in the txq. It also keeps the code
 more consistent.
 
 Right. I still phrased that badly. I meant that the also should be
 limited by the number of frames really needed, i.e. use driver-buffered
 first and fill up with any mac80211-buffered by dequeuing. That's
 probably obvious enough though.
 
 Anyway - not sure it needs to be in the callback?
I think it makes things simpler this way. What would you prefer?

 If I don't lock here, one last dequeue call might still be running on
 another CPU. This would produce a theoretical race in accessing the
 sequence number, which the caller of this function reads before setting
 up the BA request.
 Dequeueing happens outside of the normal network stack tx context, so
 synchronize_net is not enough.
 
 Ah, makes sense, I didn't think of the seqno. Can you please put that in
 a comment somewhere? :)
Sure.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] bcma: use absolute base for SoC GPIO pins

2015-04-15 Thread Felix Fietkau
On some BCM5301x ARM devices, user space still needs to control some
system GPIO pins for which no driver exists. This is a lot easier to do
with a predictable GPIO base.

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/bcma/driver_gpio.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index 74ccb02..9b8d9bf 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -235,16 +235,17 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
}
 
/*
-* On MIPS we register GPIO devices (LEDs, buttons) using absolute GPIO
-* pin numbers. We don't have Device Tree there and we can't really use
-* relative (per chip) numbers.
-* So let's use predictable base for BCM47XX and random for all other.
+* Register SoC GPIO devices with absolute GPIO pin base.
+* On MIPS, we don't have Device Tree and we can't use relative (per 
chip)
+* GPIO numbers.
+* On some ARM devices, user space may want to access some system GPIO
+* pins directly, which is easier to do with a predictable GPIO base.
 */
-#if IS_BUILTIN(CONFIG_BCM47XX)
-   chip-base  = bus-num * BCMA_GPIO_MAX_PINS;
-#else
-   chip-base  = -1;
-#endif
+   if (IS_BUILTIN(CONFIG_BCM47XX) ||
+   cc-core-bus-hosttype == BCMA_HOSTTYPE_SOC)
+   chip-base  = bus-num * BCMA_GPIO_MAX_PINS;
+   else
+   chip-base  = -1;
 
err = bcma_gpio_irq_domain_init(cc);
if (err)
-- 
2.2.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] bcma: enable 32 GPIO pins for BCM4707

2015-04-15 Thread Felix Fietkau
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/bcma/driver_gpio.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index 9b8d9bf..5f6018e 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -226,6 +226,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
chip-of_node   = cc-core-dev.of_node;
 #endif
switch (bus-chipinfo.id) {
+   case BCMA_CHIP_ID_BCM4707:
case BCMA_CHIP_ID_BCM5357:
case BCMA_CHIP_ID_BCM53572:
chip-ngpio = 32;
-- 
2.2.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] bcma: use absolute base for SoC GPIO pins

2015-04-15 Thread Felix Fietkau
On 2015-04-15 16:33, Rafał Miłecki wrote:
 On 15 April 2015 at 15:07, Felix Fietkau n...@openwrt.org wrote:
 @@ -235,16 +235,17 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
 }

 /*
 -* On MIPS we register GPIO devices (LEDs, buttons) using absolute 
 GPIO
 -* pin numbers. We don't have Device Tree there and we can't really 
 use
 -* relative (per chip) numbers.
 -* So let's use predictable base for BCM47XX and random for all 
 other.
 +* Register SoC GPIO devices with absolute GPIO pin base.
 +* On MIPS, we don't have Device Tree and we can't use relative (per 
 chip)
 +* GPIO numbers.
 +* On some ARM devices, user space may want to access some system 
 GPIO
 +* pins directly, which is easier to do with a predictable GPIO base.
  */
 -#if IS_BUILTIN(CONFIG_BCM47XX)
 -   chip-base  = bus-num * BCMA_GPIO_MAX_PINS;
 -#else
 -   chip-base  = -1;
 -#endif
 +   if (IS_BUILTIN(CONFIG_BCM47XX) ||
 +   cc-core-bus-hosttype == BCMA_HOSTTYPE_SOC)
 +   chip-base  = bus-num * BCMA_GPIO_MAX_PINS;
 +   else
 +   chip-base  = -1;
 
 Is there any chance you will need predictable GPIO numbers of extra
 bcma buses on ARM? Like accessing GPIO of PCIe card from user space?
 Then you could prefer IS_BUILTIN(CONFIG_ARCH_BCM_5301X)
 
 Anyway, I'm OK with this patch.
I don't think I need it, and I didn't want this change to produce
conflicts on multi-arch builds, so I limited it to the SoC bus only.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] ath9k: fix soft lockup - CPU stuck

2015-04-16 Thread Felix Fietkau
On 2015-04-16 04:24, miaoq...@qti.qualcomm.com wrote:
 From: Miaoqing Pan miaoq...@qca.qualcomm.com
 
 BUG: soft lockup - CPU#0 stuck for 22s! [hostapd:965]
 CPU: 0 PID: 965 Comm: hostapd Not tainted 3.14.0 #1
 task: 82e29c40 ti: 82fb2000 task.ti: 82fb2000
 $ 0   :   83281f90 4018
 $ 4   : 832a0010 b810403c 4030 0600
 $ 8   : 8036a980 ffd23940  
 $12   : 0060 0007  000c
 $16   : 832a0010 00023f40 0002 
 $20   : 832a0010 832a0298 832ba994 832bb83c
 $24   : 0002 800aa2d4
 $28   : 82fb2000 82fb3c08 832bbf0c 8339edc4
 Hi: 0006
 Lo: 009b9500
 epc   : 8339ede0 ath9k_hw_enable_interrupts+0xf8/0x194 [ath9k_hw]
 Not tainted
 ra: 8339edc4 ath9k_hw_enable_interrupts+0xdc/0x194 [ath9k_hw]
 Status: 1000fc03  KERNEL EXL IE
 Cause : 5080d400
 PrId  : 00019374 (MIPS 24Kc)
   Kernel panic - not syncing: softlockup: hung tasks
 
 The original intention of commit e3f31175a3(ath9k: fix race condition
 in irq processing during hardware reset) is to avoid the IRQ storms,it
 disabled the IRQ entirely for the duration of the reset, but it introducted
 a new IRQ storms in handle_level_irq() when call ath9k_hw_enable_interrupts(),
 meanwhile the irq is disabled by disable_irq().
That sounds like it might be a bug in the platform IRQ handling code,
not ath9k. When I made this change, it uncovered multiple bugs in the
platform code. One was in the generic MIPS CPU IRQ code, fixed in
upstream commit a3e6c1eff54878506b2dddcc202df9cc8180facb.
The other bug was in the ar71xx platform handler code in OpenWrt, fixed
here: 
http://git.openwrt.org/?p=openwrt.git;a=blob;f=target/linux/ar71xx/patches-3.18/736-MIPS-ath79-fix-chained-irq-disable.patch;h=8cb38d3971678e3cf951d36e6ab2f4b170cd1f0c;hb=HEAD

 Remove disable_irq/enable_irq
 paire, instead of diabling tasklet to re-enable IRQ during the reset.
That is insufficient - it completely ignores the problem of shared
interrupts.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] ath9k: fix DMA stop sequence for AR9003+

2015-06-02 Thread Felix Fietkau
AR93xx and newer needs to stop rx before tx to avoid getting the DMA
engine or MAC into a stuck state.
This should reduce/fix the occurence of Failed to stop Tx DMA logspam.

Cc: sta...@vger.kernel.org
Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/main.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c 
b/drivers/net/wireless/ath/ath9k/main.c
index d285e3a..cfd45cb 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -216,11 +216,13 @@ static bool ath_prepare_reset(struct ath_softc *sc)
ath_stop_ani(sc);
ath9k_hw_disable_interrupts(ah);
 
-   if (!ath_drain_all_txq(sc))
-   ret = false;
-
-   if (!ath_stoprecv(sc))
-   ret = false;
+   if (AR_SREV_9300_20_OR_LATER(ah)) {
+   ret = ath_stoprecv(sc);
+   ret = ath_drain_all_txq(sc);
+   } else {
+   ret = ath_drain_all_txq(sc);
+   ret = ath_stoprecv(sc);
+   }
 
return ret;
 }
-- 
2.2.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] ath9k_hw: fix device ID check for AR956x

2015-06-21 Thread Felix Fietkau
Because of the missing return, the macVersion value was being
overwritten with an invalid register read

Signed-off-by: Felix Fietkau n...@openwrt.org
---
 drivers/net/wireless/ath/ath9k/hw.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
index 5e15e8e..a31a680 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -279,6 +279,7 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
return;
case AR9300_DEVID_QCA956X:
ah-hw_version.macVersion = AR_SREV_VERSION_9561;
+   return;
}
 
val = REG_READ(ah, AR_SREV)  AR_SREV_ID;
-- 
2.2.2

--
To unsubscribe from this list: send the line unsubscribe linux-wireless in


Re: [PATCH 2/3] ath9k: make rxfilter per HW

2015-06-22 Thread Felix Fietkau
On 2015-06-22 13:59, Johannes Berg wrote:
 On Mon, 2015-06-22 at 13:58 +0200, Johannes Berg wrote:
 On Mon, 2015-06-22 at 13:43 +0200, Janusz Dziedzic wrote:
  mac80211 configure rxfilter per HW,
  so we don't need this per channel.
 
 As I said before, I think there's value in mac80211 doing it per chanctx
 or even per vif, and it should be more efficient to do so.
 
 It's tempting to do it per vif and leave the chanctx work up to the
 driver, but perhaps with CSA and all that it gets complicated enough
 that doing it per chanctx in mac80211 would make sense?
 
 On the other hand, I think our device requires it per vif, so we'd
 probably have to do both.
 
 +Andrei, who was looking into this.
There's value in it, but I think it makes more sense to fix this bug
now, and rework the code again later when mac80211 has support for
per-vif or per-chanctx rxfilter.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in


Re: [RFC] ath9k: allow to receive probe request when offchannel

2015-06-15 Thread Felix Fietkau
On 2015-06-10 07:03, Janusz Dziedzic wrote:
 This fix problem that p2p group negotiation didn't work
 correctly when chanctx used, because we didn't receive
 probe requests when offchannel and use_chanctx=1
 
 Signed-off-by: Janusz Dziedzic janusz.dzied...@tieto.com
 ---
 @Felix, Sujith could you review? I am not sure I put this in correct place.
 
  drivers/net/wireless/ath/ath9k/channel.c | 6 ++
  1 file changed, 6 insertions(+)
 
 diff --git a/drivers/net/wireless/ath/ath9k/channel.c 
 b/drivers/net/wireless/ath/ath9k/channel.c
 index 2066650..6301d44 100644
 --- a/drivers/net/wireless/ath/ath9k/channel.c
 +++ b/drivers/net/wireless/ath/ath9k/channel.c
 @@ -1157,6 +1157,7 @@ static bool ath_chanctx_defer_switch(struct ath_softc 
 *sc)
  static void ath_offchannel_channel_change(struct ath_softc *sc)
  {
   struct ath_common *common = ath9k_hw_common(sc-sc_ah);
 + u32 rfilt;
  
   ath_dbg(common, CHAN_CTX, %s: offchannel state: %s\n,
   __func__, offchannel_state_string(sc-offchannel.state));
 @@ -1179,6 +1180,11 @@ static void ath_offchannel_channel_change(struct 
 ath_softc *sc)
   ath_scan_complete(sc, false);
   break;
   case ATH_OFFCHANNEL_ROC_START:
 + /* Allow to receive probe requests */
 + rfilt = ath_calcrxfilter(sc);
 + rfilt |= ATH9K_RX_FILTER_PROBEREQ;
I think ath_calcrxfilter should set this, otherwise it might be
overwritten, e.g. on BB watchdog reset.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFCv2] ath9k: make rxfilter per HW

2015-06-17 Thread Felix Fietkau
On 2015-06-17 10:20, Sujith Manoharan wrote:
 Janusz Dziedzic wrote:
 mac80211 configure rxfilter per HW,
 so we don't need this per channel.
 
 This fix problem when chanctx used and
 ath9k allocate new ath_chanctx. Then we loose
 rxfilter configuration.
 
 Eg. during p2p_find (when use_chanctx=1) during
 remain on channel, driver create new ath_chanctx
 with incorrect rxfilter. Then we didn't receive
 probe requests and fail p2p_find.
 
 The RX filter is calculated based on the operating mode
 of the HW. If we have a concurrent P2P-GO/station
 setup, for example, then the RX filter needs to be different for each
 context, (MYBEACON vs. BEACON etc.). I don't see how
 having a global filter will allow this ?
mac80211 calculates the filter per hw, not per channel context or per
vif. Setting it for the current channel context only would mean it might
be applied to the wrong context. This patch fixes that issue.
I agree that it might be a useful optimization to selectively apply
filters per channel context, but mac80211 does not provide an API to do
that right now.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFCv2] ath9k: make rxfilter per HW

2015-06-17 Thread Felix Fietkau
On 2015-06-17 11:39, Sujith Manoharan wrote:
 Janusz Dziedzic wrote:
 This is what I have with use_chanctx=1
 Jun 17 06:57:54 dell6430 kernel: [53297.753256] xxx ath_calcrxfilter
 filter: 0x207
 
 0x00080 is for probe_req
 
 Ok, so the probe_req filter is set before actually initiating
 RoC - this appears to be the current design in wpa_s.
 
 I am not sure if using a global filter that disregards
 the opmode of a context is the right approach, though...
The filter is intended to be global in the mac80211 API.
Treating it as per channel-context inside the driver is a bug.

- Felix
--
To unsubscribe from this list: send the line unsubscribe linux-wireless in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   3   4   5   6   7   >