* Re: brcsmac kernel panic
From: Arend van Spriel @ 2013-08-12 10:38 UTC (permalink / raw)
To: Daniel Wagner; +Cc: linux-wireless, linux-kernel
In-Reply-To: <5207BA00.3030709@monom.org>
[-- Attachment #1: Type: text/plain, Size: 798 bytes --]
On 08/11/2013 06:21 PM, Daniel Wagner wrote:
> Hi,
>
> I just updated my laptop (MacBook Air 2012) from 3.11-rc3+ to 3.11-rc4+
> and since then brcsmac crashes short after enabling it. Unfortunately, I
> did also change some config flags in the area of cpufreq (enabling
> p-state driver) so the configuration is not exactly the same. Before I
> try to figure out what I have changed, I am posting the picture of the
> crash. Maybe it is something obvious.
>
> v3.11-rc4-197-gd92581f
> http://www.monom.org/misc/brcmsmac/v3.11-rc4.config
> http://www.monom.org/misc/brcmsmac/IMAG0064.jpg
Thanks, Daniel
I was looking at this issue two weeks ago and just got back from my
vacation. Can you apply the patch and send me a kernel log?
Sharing pictures, huh. What about this one :-p
Regards,
Arend
[-- Attachment #2: barcelona-2012.jpg --]
[-- Type: image/jpeg, Size: 82908 bytes --]
[-- Attachment #3: 0001-brcmsmac-avoid-kernel-panic-due-to-divide-by-zero-er.patch --]
[-- Type: text/plain, Size: 1447 bytes --]
>From aeca211f0bb6186eefb7f3a6ad98115e2256e53a Mon Sep 17 00:00:00 2001
From: Arend van Spriel <arend@broadcom.com>
Date: Mon, 12 Aug 2013 12:34:45 +0200
Subject: [PATCH] brcmsmac: avoid kernel panic due to divide-by-zero error
The patch avoid the kernel panic and adds a few error log messages.
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 9fd6f2f..ea92ea2 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -630,10 +630,21 @@ static uint brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
if (preamble_type == BRCMS_MM_PREAMBLE)
dur += PREN_MM_EXT;
+
+ if (mcs > BRCMS_MAXMCS) {
+ brcms_err(wlc->hw->d11core, "wl%d: invalid mcs: %u\n",
+ wlc->pub->unit, mcs);
+ mcs = 0;
+ }
/* 1000Ndbps = kbps * 4 */
kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
rspec_issgi(ratespec)) * 4;
+ if (kNdps == 0) {
+ brcms_err(wlc->hw->d11core, "wl%d: invalid zero rate: rspec=0x%x\n",
+ wlc->pub->unit, ratespec);
+ kNdps = 6500 * 4;
+ }
if (rspec_stc(ratespec) == 0)
nsyms =
CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 12/12] brcmsmac: support 4313iPA
From: David Herrmann @ 2013-08-12 10:22 UTC (permalink / raw)
To: Arend van Spriel
Cc: Jonas Gorski, John W. Linville, linux-wireless, Piotr Haber
In-Reply-To: <5208B47B.6090903@broadcom.com>
Hi
On Mon, Aug 12, 2013 at 12:10 PM, Arend van Spriel <arend@broadcom.com> wrote:
> On 08/11/2013 02:48 PM, Jonas Gorski wrote:
>>
>> Hi,
>>
>> On Sat, Aug 10, 2013 at 12:27 PM, Arend van Spriel <arend@broadcom.com>
>> wrote:
>>>
>>> From: Piotr Haber <phaber@broadcom.com>
>>>
>>> Add support for 4313 iPA variant.
>>> It is a variant of already supported 4313 ePA,
>>> so this patch adds the required PHY changes to
>>> support it properly including an updated switch
>>> control table for BT-combo card variants.
>>
>>
>> Okay, I'll bite. Since this patch was already reverted once, it
>> warrants some additional scrutiny.
>
>
> That's the right attitude ;-) The revert made us cautious as well before
> sending out this patch, but thanks for making the effort.
>
>
>> First of all, the patch is quite large, and I wonder if it couldn't be
>> split into smaller patches, especially as it looks like there are
>> additional fixes/changes merged in it.
>
>
> It indeed seems rather large. The original work from Piotr were two patches
> that I squashed. I will break up this patch in more individual patches.
>
> John,
>
> Can you drop this patch from the series?
>
>
>> Detailed comments below ...
>>
>>> Tested-by: Maximilian Engelhardt <maxi@daemonizer.de>
>>> Tested-by: David Costa <david@zarel.net>
>>> Reviewed-by: Arend Van Spriel <arend@broadcom.com>
>>> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
>>> Signed-off-by: Piotr Haber <phaber@broadcom.com>
>>> Signed-off-by: Arend van Spriel <arend@broadcom.com>
>>> ---
>>
>>
>> This is obviously a V2 (or V(n+1) where n was the reverted version),
>> so there should be something describing the changes to the reverted
>> version. Why should we trust it now to not break things again? (Yes, I
>> see those Tested-bys ;-)
>
>
> This is a gray area. The original patch was taken into the tree so I
> considered this to be a new patch.
>
> We tested with a number of 4313 variants having some extra shipped that we
> did not have at the time of the original patch. I looked up the revert patch
> and noticed it is tagged with Reported-by. So I will ask David Herrmann to
> test V(n+2) before sending it (if you don't mind n will be 0).
If you add me to CC for the patch I will happily test it. But for now
I have no idea which patches I should try so I will wait for the next
revision, I guess?
Thanks for letting me know!
David
^ permalink raw reply
* Re: [PATCH 12/12] brcmsmac: support 4313iPA
From: Arend van Spriel @ 2013-08-12 10:10 UTC (permalink / raw)
To: Jonas Gorski, John W. Linville
Cc: linux-wireless, Piotr Haber, David Herrmann
In-Reply-To: <CAOiHx==iBf19ym=Q3HFOdKv_u-6tvz0uq_U61ziVfKS7LuWG5w@mail.gmail.com>
On 08/11/2013 02:48 PM, Jonas Gorski wrote:
> Hi,
>
> On Sat, Aug 10, 2013 at 12:27 PM, Arend van Spriel <arend@broadcom.com> wrote:
>> From: Piotr Haber <phaber@broadcom.com>
>>
>> Add support for 4313 iPA variant.
>> It is a variant of already supported 4313 ePA,
>> so this patch adds the required PHY changes to
>> support it properly including an updated switch
>> control table for BT-combo card variants.
>
> Okay, I'll bite. Since this patch was already reverted once, it
> warrants some additional scrutiny.
That's the right attitude ;-) The revert made us cautious as well before
sending out this patch, but thanks for making the effort.
> First of all, the patch is quite large, and I wonder if it couldn't be
> split into smaller patches, especially as it looks like there are
> additional fixes/changes merged in it.
It indeed seems rather large. The original work from Piotr were two
patches that I squashed. I will break up this patch in more individual
patches.
John,
Can you drop this patch from the series?
> Detailed comments below ...
>
>> Tested-by: Maximilian Engelhardt <maxi@daemonizer.de>
>> Tested-by: David Costa <david@zarel.net>
>> Reviewed-by: Arend Van Spriel <arend@broadcom.com>
>> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
>> Signed-off-by: Piotr Haber <phaber@broadcom.com>
>> Signed-off-by: Arend van Spriel <arend@broadcom.com>
>> ---
>
> This is obviously a V2 (or V(n+1) where n was the reverted version),
> so there should be something describing the changes to the reverted
> version. Why should we trust it now to not break things again? (Yes, I
> see those Tested-bys ;-)
This is a gray area. The original patch was taken into the tree so I
considered this to be a new patch.
We tested with a number of 4313 variants having some extra shipped that
we did not have at the time of the original patch. I looked up the
revert patch and noticed it is tagged with Reported-by. So I will ask
David Herrmann to test V(n+2) before sending it (if you don't mind n
will be 0).
>> .../net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c | 399 +++++++++++++--------
>> .../wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c | 289 +++++++++------
>> .../wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h | 1 +
>> 3 files changed, 436 insertions(+), 253 deletions(-)
>>
>> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
>> index 3d6b16c..b8ddaad 100644
>> --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
>> +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
>> @@ -1137,8 +1137,9 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
>> gain0_15 = ((biq1 & 0xf) << 12) |
>> ((tia & 0xf) << 8) |
>> ((lna2 & 0x3) << 6) |
>> - ((lna2 &
>> - 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
>> + ((lna2 & 0x3) << 4) |
>> + ((lna1 & 0x3) << 2) |
>> + ((lna1 & 0x3) << 0);
>
> Unrelated style change.
I will put this in a separate patch.
>>
>> mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
>> mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
>> @@ -1328,6 +1329,43 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
>> return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
>> }
>>
>> +static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
>> + u16 tia_gain, u16 lna2_gain)
>> +{
>> + u32 i_thresh_l, q_thresh_l;
>> + u32 i_thresh_h, q_thresh_h;
>> + struct lcnphy_iq_est iq_est_h, iq_est_l;
>> +
>> + wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
>> + lna2_gain, 0);
>> +
>> + wlc_lcnphy_rx_gain_override_enable(pi, true);
>> + wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
>> + udelay(500);
>> + write_radio_reg(pi, RADIO_2064_REG112, 0);
>> + if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
>> + return false;
>> +
>> + wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
>> + udelay(500);
>> + write_radio_reg(pi, RADIO_2064_REG112, 0);
>> + if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
>> + return false;
>> +
>> + i_thresh_l = (iq_est_l.i_pwr << 1);
>> + i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
>> +
>> + q_thresh_l = (iq_est_l.q_pwr << 1);
>> + q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
>
> So X_thresh_l == iq_est_l.X_pwr * 2 and X_thresh_h == iq_est_l.X_pwr *
> 5? Why not trust the compiler to use optimize it? It would be a bit
> more readable.
This is a bit personal. A C programmer is probably as familiar with
bitwise operators as with arithmetic. Anyways, my main reason for having
it this way is maintainability as it closely resembles the internal
driver code base. So I tend to leave it as is.
>> + if ((iq_est_h.i_pwr > i_thresh_l) &&
>> + (iq_est_h.i_pwr < i_thresh_h) &&
>> + (iq_est_h.q_pwr > q_thresh_l) &&
>> + (iq_est_h.q_pwr < q_thresh_h))
>> + return true;
>> +
>> + return false;
>> +}
>> +
>> static bool
>> wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
>> const struct lcnphy_rx_iqcomp *iqcomp,
>> @@ -1342,8 +1380,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
>> RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
>> rfoverride3_old, rfoverride3val_old, rfoverride4_old,
>> rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
>> - int tia_gain;
>> - u32 received_power, rx_pwr_threshold;
>> + int tia_gain, lna2_gain, biq1_gain;
>> + bool set_gain;
>> u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
>> u16 values_to_save[11];
>> s16 *ptr;
>> @@ -1368,126 +1406,134 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
>> goto cal_done;
>> }
>>
>> - if (module == 1) {
>> + WARN_ON(module != 1);
>> + tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
>> + wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
>>
>> - tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
>> - wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
>
> This indentation change makes it a bit harder to review, but luckily
> there is git show -b ...
I will do the indentation change with a separate patch.
>> + for (i = 0; i < 11; i++)
>> + values_to_save[i] =
>> + read_radio_reg(pi, rxiq_cal_rf_reg[i]);
>> + Core1TxControl_old = read_phy_reg(pi, 0x631);
>> +
>> + or_phy_reg(pi, 0x631, 0x0015);
>> +
>> + RFOverride0_old = read_phy_reg(pi, 0x44c);
>> + RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
>> + rfoverride2_old = read_phy_reg(pi, 0x4b0);
>> + rfoverride2val_old = read_phy_reg(pi, 0x4b1);
>> + rfoverride3_old = read_phy_reg(pi, 0x4f9);
>> + rfoverride3val_old = read_phy_reg(pi, 0x4fa);
>> + rfoverride4_old = read_phy_reg(pi, 0x938);
>> + rfoverride4val_old = read_phy_reg(pi, 0x939);
>> + afectrlovr_old = read_phy_reg(pi, 0x43b);
>> + afectrlovrval_old = read_phy_reg(pi, 0x43c);
>> + old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
>> + old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
>>
>> - for (i = 0; i < 11; i++)
>> - values_to_save[i] =
>> - read_radio_reg(pi, rxiq_cal_rf_reg[i]);
>> - Core1TxControl_old = read_phy_reg(pi, 0x631);
>> -
>> - or_phy_reg(pi, 0x631, 0x0015);
>> -
>> - RFOverride0_old = read_phy_reg(pi, 0x44c);
>> - RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
>> - rfoverride2_old = read_phy_reg(pi, 0x4b0);
>> - rfoverride2val_old = read_phy_reg(pi, 0x4b1);
>> - rfoverride3_old = read_phy_reg(pi, 0x4f9);
>> - rfoverride3val_old = read_phy_reg(pi, 0x4fa);
>> - rfoverride4_old = read_phy_reg(pi, 0x938);
>> - rfoverride4val_old = read_phy_reg(pi, 0x939);
>> - afectrlovr_old = read_phy_reg(pi, 0x43b);
>> - afectrlovrval_old = read_phy_reg(pi, 0x43c);
>> - old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
>> - old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
>> -
>> - tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
>> - if (tx_gain_override_old) {
>> - wlc_lcnphy_get_tx_gain(pi, &old_gains);
>> - tx_gain_index_old = pi_lcn->lcnphy_current_index;
>> - }
>> + tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
>> + if (tx_gain_override_old) {
>> + wlc_lcnphy_get_tx_gain(pi, &old_gains);
>> + tx_gain_index_old = pi_lcn->lcnphy_current_index;
>> + }
>>
>> - wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
>> + wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
>>
>> - mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
>> - mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
>> + mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
>> + mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
>>
>> - mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
>> - mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
>> + mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
>> + mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
>>
>> - write_radio_reg(pi, RADIO_2064_REG116, 0x06);
>> - write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
>> - write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
>> - write_radio_reg(pi, RADIO_2064_REG098, 0x03);
>> - write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
>> - mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
>> - write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
>> - write_radio_reg(pi, RADIO_2064_REG114, 0x01);
>> - write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
>> - write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
>> -
>> - mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
>> - mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
>> - mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
>> - mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
>> - mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
>> - mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
>> - mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
>> - mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
>> - mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
>> - mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
>> -
>> - mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
>> - mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
>> -
>> - wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
>> - write_phy_reg(pi, 0x6da, 0xffff);
>> - or_phy_reg(pi, 0x6db, 0x3);
>> - wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
>> - wlc_lcnphy_rx_gain_override_enable(pi, true);
>> -
>> - tia_gain = 8;
>> - rx_pwr_threshold = 950;
>> - while (tia_gain > 0) {
>> - tia_gain -= 1;
>> - wlc_lcnphy_set_rx_gain_by_distribution(pi,
>> - 0, 0, 2, 2,
>> - (u16)
>> - tia_gain, 1, 0);
>> - udelay(500);
>> + write_radio_reg(pi, RADIO_2064_REG116, 0x06);
>> + write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
>> + write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
>> + write_radio_reg(pi, RADIO_2064_REG098, 0x03);
>> + write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
>> + mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
>> + write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
>> + write_radio_reg(pi, RADIO_2064_REG114, 0x01);
>> + write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
>> + write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
>> +
>> + mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
>> + mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
>> + mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
>> + mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
>> + mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
>> + mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
>> + mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
>> + mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
>> + mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
>> + mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
>>
>> - received_power =
>> - wlc_lcnphy_measure_digital_power(pi, 2000);
>> - if (received_power < rx_pwr_threshold)
>> - break;
>> + mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
>> + mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
>> +
>> + write_phy_reg(pi, 0x6da, 0xffff);
>> + or_phy_reg(pi, 0x6db, 0x3);
>> +
>> + wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
>> + set_gain = false;
>> +
>> + lna2_gain = 3;
>> + while ((lna2_gain >= 0) && !set_gain) {
>> + tia_gain = 4;
>> +
>> + while ((tia_gain >= 0) && !set_gain) {
>> + biq1_gain = 6;
>> +
>> + while ((biq1_gain >= 0) && !set_gain) {
>> + set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
>> + (u16)
>> + biq1_gain,
>> + (u16)
>> + tia_gain,
>> + (u16)
>> + lna2_gain);
>> + biq1_gain -= 1;
>> + }
>> + tia_gain -= 1;
>> }
>> - result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
>> + lna2_gain -= 1;
>> + }
>
> This looks like it could be made more readable using for loops and a goto:
>
> for (lna_gain = 3; lna_gain >= 0; lna_gain--) {
> for (tia_gain = 4; tia_gain >= 0; tia_gain--) {
> for (big1_gain = 6; big1_gain >= 0; big1_gain--) {
> set_gain = wlc_lcnphy_rx_iq_cal_gain(...);
> if (set_gain)
> goto found;
> }
> }
> }
> found:
> ...
That is a sensible change. Will do.
>>
>> - wlc_lcnphy_stop_tx_tone(pi);
>> + if (set_gain)
>> + result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
>> + else
>> + result = false;
>>
>> - write_phy_reg(pi, 0x631, Core1TxControl_old);
>> + wlc_lcnphy_stop_tx_tone(pi);
>>
>> - write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
>> - write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
>> - write_phy_reg(pi, 0x4b0, rfoverride2_old);
>> - write_phy_reg(pi, 0x4b1, rfoverride2val_old);
>> - write_phy_reg(pi, 0x4f9, rfoverride3_old);
>> - write_phy_reg(pi, 0x4fa, rfoverride3val_old);
>> - write_phy_reg(pi, 0x938, rfoverride4_old);
>> - write_phy_reg(pi, 0x939, rfoverride4val_old);
>> - write_phy_reg(pi, 0x43b, afectrlovr_old);
>> - write_phy_reg(pi, 0x43c, afectrlovrval_old);
>> - write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
>> - write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
>> + write_phy_reg(pi, 0x631, Core1TxControl_old);
>> +
>> + write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
>> + write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
>> + write_phy_reg(pi, 0x4b0, rfoverride2_old);
>> + write_phy_reg(pi, 0x4b1, rfoverride2val_old);
>> + write_phy_reg(pi, 0x4f9, rfoverride3_old);
>> + write_phy_reg(pi, 0x4fa, rfoverride3val_old);
>> + write_phy_reg(pi, 0x938, rfoverride4_old);
>> + write_phy_reg(pi, 0x939, rfoverride4val_old);
>> + write_phy_reg(pi, 0x43b, afectrlovr_old);
>> + write_phy_reg(pi, 0x43c, afectrlovrval_old);
>> + write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
>> + write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
>>
>> - wlc_lcnphy_clear_trsw_override(pi);
>> + wlc_lcnphy_clear_trsw_override(pi);
>>
>> - mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
>> + mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
>>
>> - for (i = 0; i < 11; i++)
>> - write_radio_reg(pi, rxiq_cal_rf_reg[i],
>> - values_to_save[i]);
>> + for (i = 0; i < 11; i++)
>> + write_radio_reg(pi, rxiq_cal_rf_reg[i],
>> + values_to_save[i]);
>>
>> - if (tx_gain_override_old)
>> - wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
>> - else
>> - wlc_lcnphy_disable_tx_gain_override(pi);
>> + if (tx_gain_override_old)
>> + wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
>> + else
>> + wlc_lcnphy_disable_tx_gain_override(pi);
>>
>> - wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
>> - wlc_lcnphy_rx_gain_override_enable(pi, false);
>> - }
>> + wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
>> + wlc_lcnphy_rx_gain_override_enable(pi, false);
>>
>> cal_done:
>> kfree(ptr);
>> @@ -1789,6 +1835,17 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
>> write_radio_reg(pi, RADIO_2064_REG038, 3);
>> write_radio_reg(pi, RADIO_2064_REG091, 7);
>> }
>> +
>> + if (!(pi->sh->boardflags & BFL_FEM)) {
>> + u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
>> + 0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};
>> +
>> + write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
>> + write_radio_reg(pi, RADIO_2064_REG091, 0x3);
>> + write_radio_reg(pi, RADIO_2064_REG038, 0x3);
>> +
>> + write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
>> + }
>> }
>>
>> static int
>> @@ -1983,6 +2040,16 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
>> } else {
>> mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
>> mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
>> + mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
>> + mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
>> + mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
>> + mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
>> + mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
>> + mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
>> + mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
>> + mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
>> + mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
>> + mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
>
> What does this do? This seems to be applied regardless of iPA or ePA,
> so I looks like it fixes something? Or is this needed for iPA and
> harmless for ePA?
When reviewing this patch that was one of my comments as well. It was
added because the iPA changes were ported from a more recent branch of
our internal driver.
What changed is the TSSI algorithm for both ePA and iPA. I will try to
create a separate patch for that for ePA. Most of the comments below are
related to this.
>> }
>> } else {
>> mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
>> @@ -2069,12 +2136,14 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
>> (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
>>
>> mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
>> + mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
>
> Same here.
>
>> }
>>
>> static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
>> {
>> struct phytbl_info tab;
>> u32 rfseq, ind;
>> + u8 tssi_sel;
>>
>> tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
>> tab.tbl_width = 32;
>> @@ -2096,7 +2165,13 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
>>
>> mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
>>
>> - wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
>> + if (pi->sh->boardflags & BFL_FEM) {
>> + tssi_sel = 0x1;
>> + wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
>> + } else {
>> + tssi_sel = 0xe;
>> + wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA);
>> + }
>
> Doesn't this change change tssi_sel from 0xe to 0x1 for (already
> supported) ePA cards, and sets it to the old value 0xe for iPA ones? I
> would have expected 0xe for BFL_FEM /ePA and 0x1 for iPA ... .
>
>> mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
>>
>> mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
>> @@ -2132,9 +2207,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
>> mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
>>
>> if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
>> - mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
>> + mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel);
>> mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
>> } else {
>> + mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1);
>
> Okay, this one is new also for the ePA case, so I wonder why this
> wasn't needed before?
>
>> mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
>> mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
>> }
>> @@ -2181,6 +2257,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
>>
>> mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
>>
>> + mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
>> + mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
>> + mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
>> +
>
> Same for these three writes.
>
>> wlc_lcnphy_pwrctrl_rssiparams(pi);
>> }
>>
>> @@ -2799,6 +2879,8 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
>> read_radio_reg(pi, RADIO_2064_REG007) & 1;
>> u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
>> u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
>> + u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
>> +
>
> These changes also look at a first glance unrelated to iPA, as well as ...
>
>> idleTssi = read_phy_reg(pi, 0x4ab);
>> suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
>> MCTL_EN_MAC));
>> @@ -2816,6 +2898,12 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
>> mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
>> mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
>> wlc_lcnphy_tssi_setup(pi);
>> +
>> + mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
>> + mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
>> +
>> + wlc_lcnphy_set_bbmult(pi, 0x0);
>> +
>
> These ones.
>
>> wlc_phy_do_dummy_tx(pi, true, OFF);
>> idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
>> >> 0);
>> @@ -2837,6 +2925,7 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
>>
>> mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
>>
>> + wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
>> wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
>> wlc_lcnphy_set_tx_gain(pi, &old_gains);
>> wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
>> @@ -3050,6 +3139,11 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
>> wlc_lcnphy_write_table(pi, &tab);
>> tab.tbl_offset++;
>> }
>> + mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
>> + mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
>> + mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
>> + mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
>> + mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
>>
>> mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
>>
>> @@ -3851,7 +3945,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
>> target_gains.pad_gain = 21;
>> target_gains.dac_gain = 0;
>> wlc_lcnphy_set_tx_gain(pi, &target_gains);
>> - wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
>>
>> if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
>>
>> @@ -3862,6 +3955,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
>> lcnphy_recal ? LCNPHY_CAL_RECAL :
>> LCNPHY_CAL_FULL), false);
>> } else {
>> + wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
>> wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
>> }
>>
>> @@ -4286,17 +4380,22 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
>> if (CHSPEC_IS5G(pi->radio_chanspec))
>> pa_gain = 0x70;
>> else
>> - pa_gain = 0x70;
>> + pa_gain = 0x60;
>
> You are reducing the value for !BFL_FEM, I assume this is a fix for something?
Your guess is as good as mine. Internally, we get phy code deliveries
from system engineering team and unfortunately the changelog is pretty
high-level.
>>
>> if (pi->sh->boardflags & BFL_FEM)
>> pa_gain = 0x10;
>> +
>
> Unnecessary whitespace change.
Probably, Whitespace jEdit plugin did that for me. Sorry about that.
>> tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
>> tab.tbl_width = 32;
>> tab.tbl_len = 1;
>> tab.tbl_ptr = &val;
>>
>> for (j = 0; j < 128; j++) {
>> - gm_gain = gain_table[j].gm;
>> + if (pi->sh->boardflags & BFL_FEM)
>> + gm_gain = gain_table[j].gm;
>> + else
>> + gm_gain = 15;
>> +
>> val = (((u32) pa_gain << 24) |
>> (gain_table[j].pad << 16) |
>> (gain_table[j].pga << 8) | gm_gain);
>> @@ -4507,7 +4606,10 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
>>
>> write_phy_reg(pi, 0x4ea, 0x4688);
>>
>> - mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
>> + if (pi->sh->boardflags & BFL_FEM)
>> + mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
>> + else
>> + mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
>>
>> mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
>>
>> @@ -4518,6 +4620,13 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
>> wlc_lcnphy_rcal(pi);
>>
>> wlc_lcnphy_rc_cal(pi);
>> +
>> + if (!(pi->sh->boardflags & BFL_FEM)) {
>> + write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
>> + write_radio_reg(pi, RADIO_2064_REG033, 0x19);
>> + write_radio_reg(pi, RADIO_2064_REG039, 0xe);
>> + }
>> +
>> }
>>
>> static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
>> @@ -4530,6 +4639,7 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
>> uint idx;
>> u8 phybw40;
>> struct phytbl_info tab;
>> + const struct phytbl_info *tb;
>> u32 val;
>>
>> phybw40 = CHSPEC_IS40(pi->radio_chanspec);
>> @@ -4547,22 +4657,20 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
>> wlc_lcnphy_write_table(pi, &tab);
>> }
>>
>> - tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
>> - tab.tbl_width = 16;
>> - tab.tbl_ptr = &val;
>> - tab.tbl_len = 1;
>> -
>> - val = 114;
>> - tab.tbl_offset = 0;
>> - wlc_lcnphy_write_table(pi, &tab);
>> + if (!(pi->sh->boardflags & BFL_FEM)) {
>> + tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
>> + tab.tbl_width = 16;
>> + tab.tbl_ptr = &val;
>> + tab.tbl_len = 1;
>>
>> - val = 130;
>> - tab.tbl_offset = 1;
>> - wlc_lcnphy_write_table(pi, &tab);
>> + val = 150;
>> + tab.tbl_offset = 0;
>> + wlc_lcnphy_write_table(pi, &tab);
>>
>> - val = 6;
>> - tab.tbl_offset = 8;
>> - wlc_lcnphy_write_table(pi, &tab);
>> + val = 220;
>> + tab.tbl_offset = 1;
>> + wlc_lcnphy_write_table(pi, &tab);
>> + }
>
> So this isn't needed anymore for ePA cards?
Suspicious. I will look into this one.
>>
>> if (CHSPEC_IS2G(pi->radio_chanspec)) {
>> if (pi->sh->boardflags & BFL_FEM)
>> @@ -4576,7 +4684,6 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
>> }
>>
>> if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
>> - const struct phytbl_info *tb;
>> int l;
>>
>> if (CHSPEC_IS2G(pi->radio_chanspec)) {
>> @@ -4597,21 +4704,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
>> wlc_lcnphy_write_table(pi, &tb[idx]);
>> }
>>
>> - if ((pi->sh->boardflags & BFL_FEM)
>> - && !(pi->sh->boardflags & BFL_FEM_BT))
>> - wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
>> - else if (pi->sh->boardflags & BFL_FEM_BT) {
>> - if (pi->sh->boardrev < 0x1250)
>> - wlc_lcnphy_write_table(
>> - pi,
>> - &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
>> + if (pi->sh->boardflags & BFL_FEM) {
>> + if (pi->sh->boardflags & BFL_FEM_BT) {
>> + if (pi->sh->boardrev < 0x1250)
>> + tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
>> + else
>> + tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
>> + } else {
>> + tb = &dot11lcn_sw_ctrl_tbl_info_4313_epa;
>> + }
>> + } else {
>> + if (pi->sh->boardflags & BFL_FEM_BT)
>> + tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa;
>> else
>> - wlc_lcnphy_write_table(
>> - pi,
>> - &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
>> - } else
>> - wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
>> -
>> + tb = &dot11lcn_sw_ctrl_tbl_info_4313;
>> + }
>> + wlc_lcnphy_write_table(pi, tb);
>> wlc_lcnphy_load_rfpower(pi);
>>
>> wlc_lcnphy_clear_papd_comptable(pi);
>> @@ -4955,6 +5063,8 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
>> wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
>>
>> mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
>> + if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
>> + wlc_lcnphy_tssi_setup(pi);
>> }
>>
>> void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
>> @@ -4993,8 +5103,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
>> if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
>> return false;
>>
>> - if ((pi->sh->boardflags & BFL_FEM) &&
>> - (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
>> + if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
>> if (pi_lcn->lcnphy_tempsense_option == 3) {
>> pi->hwpwrctrl = true;
>> pi->hwpwrctrl_capable = true;
>> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
>> index 622c01c..9fb0ca2 100644
>> --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
>> +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
>> @@ -2058,6 +2058,73 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
>> 0x0005,
>> };
>>
>> +static const u16 dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo[] = {
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> + 0x0005,
>> + 0x0006,
>> + 0x0009,
>> + 0x000a,
>> +};
>> +
>> static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
>> 0x0004,
>> 0x0004,
>> @@ -2834,6 +2901,12 @@ const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = {
>> sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
>> };
>>
>> +const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa = {
>> + &dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo,
>> + sizeof(dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo) /
>> + sizeof(dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo[0]), 15, 0, 16
>
> Not necessarily in this patch but maybe in a follow up cleanup patch:
> ARRAY_SIZE() please?
As I am reworking the patch, I will incorporate this comment as well.
>
>
> I guess that's it from me.
Thanks again,
Arend
^ permalink raw reply
* [RFC 15/15] ath9k: Remove unused function argument
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index a00e1b6..49e9cce 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -885,7 +885,6 @@ static int ath9k_process_rate(struct ath_common *common,
static void ath9k_process_rssi(struct ath_common *common,
struct ieee80211_hw *hw,
- struct ieee80211_hdr *hdr,
struct ath_rx_status *rx_stats)
{
struct ath_softc *sc = hw->priv;
@@ -1150,7 +1149,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
ath_start_rx_poll(sc, 3);
}
- ath9k_process_rssi(common, hw, hdr, rx_stats);
+ ath9k_process_rssi(common, hw, rx_stats);
rx_status->band = hw->conf.chandef.chan->band;
rx_status->freq = hw->conf.chandef.chan->center_freq;
--
1.8.3.4
^ permalink raw reply related
* [RFC 14/15] ath9k: Fix error condition for corrupt descriptors
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
In case a descriptor has the "done" bit clear and the
next descriptor has it set, we drop both of them. If
the packet that is received after these two packets
is dropped for some reason, "discard_next" will not cleared.
Fix this.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 0965bf6..a00e1b6 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1068,6 +1068,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_hdr *hdr;
bool discard_current = sc->rx.discard_next;
+ int ret = 0;
/*
* Discard corrupt descriptors which are marked in
@@ -1106,8 +1107,10 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
* This is different from the other corrupt descriptor
* condition handled above.
*/
- if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC)
- return -EINVAL;
+ if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) {
+ ret = -EINVAL;
+ goto exit;
+ }
hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
@@ -1123,18 +1126,23 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
RX_STAT_INC(rx_spectral);
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
/*
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
*/
- if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
- return -EINVAL;
+ if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
+ ret = -EINVAL;
+ goto exit;
+ }
- if (ath9k_process_rate(common, hw, rx_stats, rx_status))
- return -EINVAL;
+ if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
+ ret = -EINVAL;
+ goto exit;
+ }
rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr);
if (rx_stats->is_mybeacon) {
@@ -1152,15 +1160,15 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
if (rx_stats->rs_moreaggr)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
- sc->rx.discard_next = false;
-
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
if (ieee80211_is_data_present(hdr->frame_control) &&
!ieee80211_is_qos_nullfunc(hdr->frame_control))
sc->rx.num_pkts++;
#endif
- return 0;
+exit:
+ sc->rx.discard_next = false;
+ return ret;
}
static void ath9k_rx_skb_postprocess(struct ath_common *common,
--
1.8.3.4
^ permalink raw reply related
* [RFC 13/15] ath9k: Handle corrupt descriptors properly
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
The MIC/PHYERR/CRC error bits are valid only for
the last desc. for chained packets. Check this early
in the preprocess() routine and bail out.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 7f327e9..0965bf6 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1099,6 +1099,16 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
if (rx_stats->rs_more)
return 0;
+ /*
+ * Return immediately if the RX descriptor has been marked
+ * as corrupt based on the various error bits.
+ *
+ * This is different from the other corrupt descriptor
+ * condition handled above.
+ */
+ if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC)
+ return -EINVAL;
+
hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
ath9k_process_tsf(rx_stats, rx_status, tsf);
@@ -1335,8 +1345,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
sc->rx.frag = skb;
goto requeue;
}
- if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC)
- goto requeue_drop_frag;
if (sc->rx.frag) {
int space = skb->len - skb_tailroom(hdr_skb);
--
1.8.3.4
^ permalink raw reply related
* [RFC 12/15] ath9k: Move the RX poll check to preprocess()
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 44f5a2b..7f327e9 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1127,6 +1127,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
return -EINVAL;
rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr);
+ if (rx_stats->is_mybeacon) {
+ sc->hw_busy_count = 0;
+ ath_start_rx_poll(sc, 3);
+ }
+
ath9k_process_rssi(common, hw, hdr, rx_stats);
rx_status->band = hw->conf.chandef.chan->band;
@@ -1277,10 +1282,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
if (retval)
goto requeue_drop_frag;
- if (rs.is_mybeacon) {
- sc->hw_busy_count = 0;
- ath_start_rx_poll(sc, 3);
- }
/* Ensure we always have an skb to requeue once we are done
* processing the current buffer's skb */
requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC);
--
1.8.3.4
^ permalink raw reply related
* [RFC 11/15] ath9k: Fix RX beacon processing
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Make sure that chained descriptors are handled correctly
before the packet is parsed to determine if it is a beacon.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 47 ++++++++++++++++-------------------
1 file changed, 21 insertions(+), 26 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 823b411..44f5a2b 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1037,13 +1037,28 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
#endif
}
+static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (ieee80211_is_beacon(hdr->frame_control)) {
+ RX_STAT_INC(rx_beacons);
+ if (!is_zero_ether_addr(common->curbssid) &&
+ ether_addr_equal(hdr->addr3, common->curbssid))
+ return true;
+ }
+
+ return false;
+}
+
/*
* For Decrypt or Demic errors, we only mark packet status here and always push
* up the frame up to let mac80211 handle the actual error case, be it no
* decryption key or real decryption error. This let us keep statistics there.
*/
static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
- struct ieee80211_hdr *hdr,
+ struct sk_buff *skb,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rx_status,
bool *decrypt_error, u64 tsf)
@@ -1051,6 +1066,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
struct ieee80211_hw *hw = sc->hw;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_hdr *hdr;
bool discard_current = sc->rx.discard_next;
/*
@@ -1083,6 +1099,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
if (rx_stats->rs_more)
return 0;
+ hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
+
ath9k_process_tsf(rx_stats, rx_status, tsf);
ath_debug_stat_rx(sc, rx_stats);
@@ -1108,6 +1126,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
return -EINVAL;
+ rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr);
ath9k_process_rssi(common, hw, hdr, rx_stats);
rx_status->band = hw->conf.chandef.chan->band;
@@ -1198,24 +1217,6 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc,
}
}
-static bool ath9k_is_mybeacon(struct ath_softc *sc, struct sk_buff *skb)
-{
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_hdr *hdr;
-
- hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
-
- if (ieee80211_is_beacon(hdr->frame_control)) {
- RX_STAT_INC(rx_beacons);
- if (!is_zero_ether_addr(common->curbssid) &&
- ether_addr_equal(hdr->addr3, common->curbssid))
- return true;
- }
-
- return false;
-}
-
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
{
struct ath_buf *bf;
@@ -1225,7 +1226,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_hdr *hdr;
int retval;
struct ath_rx_status rs;
enum ath9k_rx_qtype qtype;
@@ -1269,15 +1269,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
else
hdr_skb = skb;
- rs.is_mybeacon = ath9k_is_mybeacon(sc, hdr_skb);
-
- hdr = (struct ieee80211_hdr *) (hdr_skb->data +
- ah->caps.rx_status_len);
-
rxs = IEEE80211_SKB_RXCB(hdr_skb);
memset(rxs, 0, sizeof(struct ieee80211_rx_status));
- retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
+ retval = ath9k_rx_skb_preprocess(sc, hdr_skb, &rs, rxs,
&decrypt_error, tsf);
if (retval)
goto requeue_drop_frag;
--
1.8.3.4
^ permalink raw reply related
* [RFC 10/15] ath9k: Fix RX packet counter
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Handle chained descriptors and increment the RX counter
only for valid packets. Since this is used only by MCI,
use CONFIG_ATH9K_BTCOEX_SUPPORT.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 2d0017c..823b411 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1119,6 +1119,13 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
sc->rx.discard_next = false;
+
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+ if (ieee80211_is_data_present(hdr->frame_control) &&
+ !ieee80211_is_qos_nullfunc(hdr->frame_control))
+ sc->rx.num_pkts++;
+#endif
+
return 0;
}
@@ -1267,10 +1274,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
hdr = (struct ieee80211_hdr *) (hdr_skb->data +
ah->caps.rx_status_len);
- if (ieee80211_is_data_present(hdr->frame_control) &&
- !ieee80211_is_qos_nullfunc(hdr->frame_control))
- sc->rx.num_pkts++;
-
rxs = IEEE80211_SKB_RXCB(hdr_skb);
memset(rxs, 0, sizeof(struct ieee80211_rx_status));
--
1.8.3.4
^ permalink raw reply related
* [RFC 09/15] ath9k: Fix RX debug statistics
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
The various error bits that ath_debug_stat_rx()
checks are valid only for the last descriptor for
a chained packet, handle this correctly.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index e18adde..2d0017c 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1084,6 +1084,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
return 0;
ath9k_process_tsf(rx_stats, rx_status, tsf);
+ ath_debug_stat_rx(sc, rx_stats);
/*
* Process PHY errors and return so that the packet
@@ -1270,8 +1271,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
!ieee80211_is_qos_nullfunc(hdr->frame_control))
sc->rx.num_pkts++;
- ath_debug_stat_rx(sc, &rs);
-
rxs = IEEE80211_SKB_RXCB(hdr_skb);
memset(rxs, 0, sizeof(struct ieee80211_rx_status));
--
1.8.3.4
^ permalink raw reply related
* [RFC 08/15] ath9k: Fix PHY error processing
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Parse the PHY error details only for the last fragment
in case descriptors are chained.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 51e7d16..e18adde 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -803,8 +803,6 @@ static bool ath9k_rx_accept(struct ath_common *common,
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
mic_error = false;
}
- if (rx_stats->rs_status & ATH9K_RXERR_PHY)
- return false;
if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
(!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
@@ -1088,6 +1086,18 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
ath9k_process_tsf(rx_stats, rx_status, tsf);
/*
+ * Process PHY errors and return so that the packet
+ * can be dropped.
+ */
+ if (rx_stats->rs_status & ATH9K_RXERR_PHY) {
+ ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime);
+ if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
+ RX_STAT_INC(rx_spectral);
+
+ return -EINVAL;
+ }
+
+ /*
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
*/
@@ -1265,15 +1275,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
rxs = IEEE80211_SKB_RXCB(hdr_skb);
memset(rxs, 0, sizeof(struct ieee80211_rx_status));
- if (rs.rs_status & ATH9K_RXERR_PHY) {
- ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime);
-
- if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) {
- RX_STAT_INC(rx_spectral);
- goto requeue_drop_frag;
- }
- }
-
retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
&decrypt_error, tsf);
if (retval)
--
1.8.3.4
^ permalink raw reply related
* [RFC 07/15] ath9k: Reorder some functions
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 220 +++++++++++++++++-----------------
1 file changed, 110 insertions(+), 110 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 9fabd5f..51e7d16 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -929,6 +929,116 @@ static void ath9k_process_tsf(struct ath_rx_status *rs,
rxs->mactime += 0x100000000ULL;
}
+#ifdef CONFIG_ATH9K_DEBUGFS
+static s8 fix_rssi_inv_only(u8 rssi_val)
+{
+ if (rssi_val == 128)
+ rssi_val = 0;
+ return (s8) rssi_val;
+}
+#endif
+
+/* returns 1 if this was a spectral frame, even if not handled. */
+static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
+ struct ath_rx_status *rs, u64 tsf)
+{
+#ifdef CONFIG_ATH9K_DEBUGFS
+ struct ath_hw *ah = sc->sc_ah;
+ u8 bins[SPECTRAL_HT20_NUM_BINS];
+ u8 *vdata = (u8 *)hdr;
+ struct fft_sample_ht20 fft_sample;
+ struct ath_radar_info *radar_info;
+ struct ath_ht20_mag_info *mag_info;
+ int len = rs->rs_datalen;
+ int dc_pos;
+ u16 length, max_magnitude;
+
+ /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
+ * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
+ * yet, but this is supposed to be possible as well.
+ */
+ if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
+ rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
+ rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
+ return 0;
+
+ /* check if spectral scan bit is set. This does not have to be checked
+ * if received through a SPECTRAL phy error, but shouldn't hurt.
+ */
+ radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
+ if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
+ return 0;
+
+ /* Variation in the data length is possible and will be fixed later.
+ * Note that we only support HT20 for now.
+ *
+ * TODO: add HT20_40 support as well.
+ */
+ if ((len > SPECTRAL_HT20_TOTAL_DATA_LEN + 2) ||
+ (len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1))
+ return 1;
+
+ fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20;
+ length = sizeof(fft_sample) - sizeof(fft_sample.tlv);
+ fft_sample.tlv.length = __cpu_to_be16(length);
+
+ fft_sample.freq = __cpu_to_be16(ah->curchan->chan->center_freq);
+ fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
+ fft_sample.noise = ah->noise;
+
+ switch (len - SPECTRAL_HT20_TOTAL_DATA_LEN) {
+ case 0:
+ /* length correct, nothing to do. */
+ memcpy(bins, vdata, SPECTRAL_HT20_NUM_BINS);
+ break;
+ case -1:
+ /* first byte missing, duplicate it. */
+ memcpy(&bins[1], vdata, SPECTRAL_HT20_NUM_BINS - 1);
+ bins[0] = vdata[0];
+ break;
+ case 2:
+ /* MAC added 2 extra bytes at bin 30 and 32, remove them. */
+ memcpy(bins, vdata, 30);
+ bins[30] = vdata[31];
+ memcpy(&bins[31], &vdata[33], SPECTRAL_HT20_NUM_BINS - 31);
+ break;
+ case 1:
+ /* MAC added 2 extra bytes AND first byte is missing. */
+ bins[0] = vdata[0];
+ memcpy(&bins[0], vdata, 30);
+ bins[31] = vdata[31];
+ memcpy(&bins[32], &vdata[33], SPECTRAL_HT20_NUM_BINS - 32);
+ break;
+ default:
+ return 1;
+ }
+
+ /* DC value (value in the middle) is the blind spot of the spectral
+ * sample and invalid, interpolate it.
+ */
+ dc_pos = SPECTRAL_HT20_NUM_BINS / 2;
+ bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2;
+
+ /* mag data is at the end of the frame, in front of radar_info */
+ mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
+
+ /* copy raw bins without scaling them */
+ memcpy(fft_sample.data, bins, SPECTRAL_HT20_NUM_BINS);
+ fft_sample.max_exp = mag_info->max_exp & 0xf;
+
+ max_magnitude = spectral_max_magnitude(mag_info->all_bins);
+ fft_sample.max_magnitude = __cpu_to_be16(max_magnitude);
+ fft_sample.max_index = spectral_max_index(mag_info->all_bins);
+ fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins);
+ fft_sample.tsf = __cpu_to_be64(tsf);
+
+ ath_debug_send_fft_sample(sc, &fft_sample.tlv);
+ return 1;
+#else
+ return 0;
+#endif
+}
+
/*
* For Decrypt or Demic errors, we only mark packet status here and always push
* up the frame up to let mac80211 handle the actual error case, be it no
@@ -1052,116 +1162,6 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
rxs->flag &= ~RX_FLAG_DECRYPTED;
}
-#ifdef CONFIG_ATH9K_DEBUGFS
-static s8 fix_rssi_inv_only(u8 rssi_val)
-{
- if (rssi_val == 128)
- rssi_val = 0;
- return (s8) rssi_val;
-}
-#endif
-
-/* returns 1 if this was a spectral frame, even if not handled. */
-static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
- struct ath_rx_status *rs, u64 tsf)
-{
-#ifdef CONFIG_ATH9K_DEBUGFS
- struct ath_hw *ah = sc->sc_ah;
- u8 bins[SPECTRAL_HT20_NUM_BINS];
- u8 *vdata = (u8 *)hdr;
- struct fft_sample_ht20 fft_sample;
- struct ath_radar_info *radar_info;
- struct ath_ht20_mag_info *mag_info;
- int len = rs->rs_datalen;
- int dc_pos;
- u16 length, max_magnitude;
-
- /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
- * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
- * yet, but this is supposed to be possible as well.
- */
- if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
- rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
- rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
- return 0;
-
- /* check if spectral scan bit is set. This does not have to be checked
- * if received through a SPECTRAL phy error, but shouldn't hurt.
- */
- radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
- if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
- return 0;
-
- /* Variation in the data length is possible and will be fixed later.
- * Note that we only support HT20 for now.
- *
- * TODO: add HT20_40 support as well.
- */
- if ((len > SPECTRAL_HT20_TOTAL_DATA_LEN + 2) ||
- (len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1))
- return 1;
-
- fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20;
- length = sizeof(fft_sample) - sizeof(fft_sample.tlv);
- fft_sample.tlv.length = __cpu_to_be16(length);
-
- fft_sample.freq = __cpu_to_be16(ah->curchan->chan->center_freq);
- fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
- fft_sample.noise = ah->noise;
-
- switch (len - SPECTRAL_HT20_TOTAL_DATA_LEN) {
- case 0:
- /* length correct, nothing to do. */
- memcpy(bins, vdata, SPECTRAL_HT20_NUM_BINS);
- break;
- case -1:
- /* first byte missing, duplicate it. */
- memcpy(&bins[1], vdata, SPECTRAL_HT20_NUM_BINS - 1);
- bins[0] = vdata[0];
- break;
- case 2:
- /* MAC added 2 extra bytes at bin 30 and 32, remove them. */
- memcpy(bins, vdata, 30);
- bins[30] = vdata[31];
- memcpy(&bins[31], &vdata[33], SPECTRAL_HT20_NUM_BINS - 31);
- break;
- case 1:
- /* MAC added 2 extra bytes AND first byte is missing. */
- bins[0] = vdata[0];
- memcpy(&bins[0], vdata, 30);
- bins[31] = vdata[31];
- memcpy(&bins[32], &vdata[33], SPECTRAL_HT20_NUM_BINS - 32);
- break;
- default:
- return 1;
- }
-
- /* DC value (value in the middle) is the blind spot of the spectral
- * sample and invalid, interpolate it.
- */
- dc_pos = SPECTRAL_HT20_NUM_BINS / 2;
- bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2;
-
- /* mag data is at the end of the frame, in front of radar_info */
- mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
-
- /* copy raw bins without scaling them */
- memcpy(fft_sample.data, bins, SPECTRAL_HT20_NUM_BINS);
- fft_sample.max_exp = mag_info->max_exp & 0xf;
-
- max_magnitude = spectral_max_magnitude(mag_info->all_bins);
- fft_sample.max_magnitude = __cpu_to_be16(max_magnitude);
- fft_sample.max_index = spectral_max_index(mag_info->all_bins);
- fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins);
- fft_sample.tsf = __cpu_to_be64(tsf);
-
- ath_debug_send_fft_sample(sc, &fft_sample.tlv);
- return 1;
-#else
- return 0;
-#endif
-}
-
static void ath9k_apply_ampdu_details(struct ath_softc *sc,
struct ath_rx_status *rs, struct ieee80211_rx_status *rxs)
{
--
1.8.3.4
^ permalink raw reply related
* [RFC 06/15] ath9k: Fix TSF processing
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
There is no need to calculate the mactime for chained
descriptor packets, so make sure that this is done
only for the last fragment of valid packets.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index b04a971..9fabd5f 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -913,6 +913,22 @@ static void ath9k_process_rssi(struct ath_common *common,
ah->stats.avgbrssi = rssi;
}
+static void ath9k_process_tsf(struct ath_rx_status *rs,
+ struct ieee80211_rx_status *rxs,
+ u64 tsf)
+{
+ u32 tsf_lower = tsf & 0xffffffff;
+
+ rxs->mactime = (tsf & ~0xffffffffULL) | rs->rs_tstamp;
+ if (rs->rs_tstamp > tsf_lower &&
+ unlikely(rs->rs_tstamp - tsf_lower > 0x10000000))
+ rxs->mactime -= 0x100000000ULL;
+
+ if (rs->rs_tstamp < tsf_lower &&
+ unlikely(tsf_lower - rs->rs_tstamp > 0x10000000))
+ rxs->mactime += 0x100000000ULL;
+}
+
/*
* For Decrypt or Demic errors, we only mark packet status here and always push
* up the frame up to let mac80211 handle the actual error case, be it no
@@ -922,7 +938,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
struct ieee80211_hdr *hdr,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rx_status,
- bool *decrypt_error)
+ bool *decrypt_error, u64 tsf)
{
struct ieee80211_hw *hw = sc->hw;
struct ath_hw *ah = sc->sc_ah;
@@ -959,6 +975,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
if (rx_stats->rs_more)
return 0;
+ ath9k_process_tsf(rx_stats, rx_status, tsf);
+
/*
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
@@ -1196,7 +1214,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
int dma_type;
u64 tsf = 0;
- u32 tsf_lower = 0;
unsigned long flags;
dma_addr_t new_buf_addr;
@@ -1208,7 +1225,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
tsf = ath9k_hw_gettsf64(ah);
- tsf_lower = tsf & 0xffffffff;
do {
bool decrypt_error = false;
@@ -1249,15 +1265,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
rxs = IEEE80211_SKB_RXCB(hdr_skb);
memset(rxs, 0, sizeof(struct ieee80211_rx_status));
- rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
- if (rs.rs_tstamp > tsf_lower &&
- unlikely(rs.rs_tstamp - tsf_lower > 0x10000000))
- rxs->mactime -= 0x100000000ULL;
-
- if (rs.rs_tstamp < tsf_lower &&
- unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
- rxs->mactime += 0x100000000ULL;
-
if (rs.rs_status & ATH9K_RXERR_PHY) {
ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime);
@@ -1268,7 +1275,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
}
retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
- &decrypt_error);
+ &decrypt_error, tsf);
if (retval)
goto requeue_drop_frag;
--
1.8.3.4
^ permalink raw reply related
* [RFC 05/15] ath9k: Fix RX crypto processing
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
The keymiss events are valid only in the last descriptor
of a packet. Fix this by making sure that we return
early in case of chained descriptors.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index f8cc2b3..b04a971 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -785,10 +785,6 @@ static bool ath9k_rx_accept(struct ath_common *common,
!test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
- /* Only use error bits from the last fragment */
- if (rx_stats->rs_more)
- return true;
-
mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
!ieee80211_has_morefrags(fc) &&
!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
@@ -959,6 +955,10 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
return -EINVAL;
}
+ /* Only use status info from the last fragment */
+ if (rx_stats->rs_more)
+ return 0;
+
/*
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
@@ -966,10 +966,6 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
return -EINVAL;
- /* Only use status info from the last fragment */
- if (rx_stats->rs_more)
- return 0;
-
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
return -EINVAL;
--
1.8.3.4
^ permalink raw reply related
* [RFC 04/15] ath9k: Discard invalid frames early
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Frames with invalid or zero length can be discarded
early, there is no need to check the crypto bits.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 38 ++++++++++++++++++++---------------
1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 83b3fc5..f8cc2b3 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -764,7 +764,6 @@ static bool ath9k_rx_accept(struct ath_common *common,
bool is_mc, is_valid_tkip, strip_mic, mic_error;
struct ath_hw *ah = common->ah;
__le16 fc;
- u8 rx_status_len = ah->caps.rx_status_len;
fc = hdr->frame_control;
@@ -786,21 +785,6 @@ static bool ath9k_rx_accept(struct ath_common *common,
!test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
- if (!rx_stats->rs_datalen) {
- RX_STAT_INC(rx_len_err);
- return false;
- }
-
- /*
- * rs_status follows rs_datalen so if rs_datalen is too large
- * we can take a hint that hardware corrupted it, so ignore
- * those frames.
- */
- if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) {
- RX_STAT_INC(rx_len_err);
- return false;
- }
-
/* Only use error bits from the last fragment */
if (rx_stats->rs_more)
return true;
@@ -949,11 +933,33 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
struct ath_common *common = ath9k_hw_common(ah);
bool discard_current = sc->rx.discard_next;
+ /*
+ * Discard corrupt descriptors which are marked in
+ * ath_get_next_rx_buf().
+ */
sc->rx.discard_next = rx_stats->rs_more;
if (discard_current)
return -EINVAL;
/*
+ * Discard zero-length packets.
+ */
+ if (!rx_stats->rs_datalen) {
+ RX_STAT_INC(rx_len_err);
+ return -EINVAL;
+ }
+
+ /*
+ * rs_status follows rs_datalen so if rs_datalen is too large
+ * we can take a hint that hardware corrupted it, so ignore
+ * those frames.
+ */
+ if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {
+ RX_STAT_INC(rx_len_err);
+ return -EINVAL;
+ }
+
+ /*
* everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame.
*/
--
1.8.3.4
^ permalink raw reply related
* [RFC 01/15] ath9k: Add MAX_AMSDU to supported HT capabilities
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/init.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 3b56c2e..6c1875e 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -258,7 +258,8 @@ static void setup_ht_cap(struct ath_softc *sc,
ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_SM_PS |
IEEE80211_HT_CAP_SGI_40 |
- IEEE80211_HT_CAP_DSSSCCK40;
+ IEEE80211_HT_CAP_DSSSCCK40 |
+ IEEE80211_HT_CAP_MAX_AMSDU;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC)
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
--
1.8.3.4
^ permalink raw reply related
* [RFC 02/15] ath9k: Use a subroutine to check for "mybeacon"
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 36 ++++++++++++++++++++++-------------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 2dd851a..0c23053 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1160,6 +1160,24 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc,
}
}
+static bool ath9k_is_mybeacon(struct ath_softc *sc, struct sk_buff *skb)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_hdr *hdr;
+
+ hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
+
+ if (ieee80211_is_beacon(hdr->frame_control)) {
+ RX_STAT_INC(rx_beacons);
+ if (!is_zero_ether_addr(common->curbssid) &&
+ ether_addr_equal(hdr->addr3, common->curbssid))
+ return true;
+ }
+
+ return false;
+}
+
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
{
struct ath_buf *bf;
@@ -1175,7 +1193,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
enum ath9k_rx_qtype qtype;
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
int dma_type;
- u8 rx_status_len = ah->caps.rx_status_len;
u64 tsf = 0;
u32 tsf_lower = 0;
unsigned long flags;
@@ -1216,18 +1233,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
else
hdr_skb = skb;
- hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
- rxs = IEEE80211_SKB_RXCB(hdr_skb);
- if (ieee80211_is_beacon(hdr->frame_control)) {
- RX_STAT_INC(rx_beacons);
- if (!is_zero_ether_addr(common->curbssid) &&
- ether_addr_equal(hdr->addr3, common->curbssid))
- rs.is_mybeacon = true;
- else
- rs.is_mybeacon = false;
- }
- else
- rs.is_mybeacon = false;
+ rs.is_mybeacon = ath9k_is_mybeacon(sc, hdr_skb);
+
+ hdr = (struct ieee80211_hdr *) (hdr_skb->data +
+ ah->caps.rx_status_len);
if (ieee80211_is_data_present(hdr->frame_control) &&
!ieee80211_is_qos_nullfunc(hdr->frame_control))
@@ -1235,6 +1244,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
ath_debug_stat_rx(sc, &rs);
+ rxs = IEEE80211_SKB_RXCB(hdr_skb);
memset(rxs, 0, sizeof(struct ieee80211_rx_status));
rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
--
1.8.3.4
^ permalink raw reply related
* [RFC 03/15] ath9k: Fix phy error handling for DFS
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1376300502-2741-1-git-send-email-sujith@msujith.org>
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Since the DFS code appears to process the phy errors
ATH9K_PHYERR_RADAR and ATH9K_PHYERR_FALSE_RADAR_EXT,
check for the correct phyerr status in the main RX
tasklet routine.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 0c23053..83b3fc5 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1256,10 +1256,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
rxs->mactime += 0x100000000ULL;
- if (rs.rs_phyerr == ATH9K_PHYERR_RADAR)
+ if (rs.rs_status & ATH9K_RXERR_PHY) {
ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime);
- if (rs.rs_status & ATH9K_RXERR_PHY) {
if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) {
RX_STAT_INC(rx_spectral);
goto requeue_drop_frag;
--
1.8.3.4
^ permalink raw reply related
* [RFC 00/15] ath9k patches
From: Sujith Manoharan @ 2013-08-12 9:41 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Various fixes/cleanups for the RX path. Please review !
Sujith Manoharan (15):
ath9k: Add MAX_AMSDU to supported HT capabilities
ath9k: Use a subroutine to check for "mybeacon"
ath9k: Fix phy error handling for DFS
ath9k: Discard invalid frames early
ath9k: Fix RX crypto processing
ath9k: Fix TSF processing
ath9k: Reorder some functions
ath9k: Fix PHY error processing
ath9k: Fix RX debug statistics
ath9k: Fix RX packet counter
ath9k: Fix RX beacon processing
ath9k: Move the RX poll check to preprocess()
ath9k: Handle corrupt descriptors properly
ath9k: Fix error condition for corrupt descriptors
ath9k: Remove unused function argument
drivers/net/wireless/ath/ath9k/init.c | 3 +-
drivers/net/wireless/ath/ath9k/recv.c | 364 ++++++++++++++++++----------------
2 files changed, 200 insertions(+), 167 deletions(-)
--
1.8.3.4
^ permalink raw reply
* Re: 80211s with DFS
From: Volker von Hoesslin @ SKBX Systems @ 2013-08-12 9:27 UTC (permalink / raw)
To: Simon Wunderlich; +Cc: linux-wireless
In-Reply-To: <20130812091158.GA17024@pandem0nium>
> I'm currently working on IBSS, I don't if/who will work on
> 802.11s DFS ...
>
it is possible to speed up this work? maybe pay for it!
^ permalink raw reply
* Re: 80211s with DFS
From: Simon Wunderlich @ 2013-08-12 9:11 UTC (permalink / raw)
To: Volker von Hoesslin @ SKBX Systems; +Cc: linux-wireless
In-Reply-To: <5207FC2A.4040207@skbx.de>
[-- Attachment #1: Type: text/plain, Size: 528 bytes --]
On Sun, Aug 11, 2013 at 11:03:38PM +0200, Volker von Hoesslin @ SKBX Systems wrote:
> i think this error is from the "netlink lib(libnl genl)"...
>
> if i use a channel without DFS, it works fine (in germany channel
> like 36-48)... so how it is possible to use mesh (80211s) with DFS ?
mac80211 does not support DFS in mesh mode so far, the only DFS
support implemented is AP mode (and only with ath9k compatible chips).
I'm currently working on IBSS, I don't if/who will work on
802.11s DFS ...
Cheers,
Simon
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [PATCH v2 3.11] genetlink: fix family dump race
From: Johannes Berg @ 2013-08-12 8:54 UTC (permalink / raw)
To: David Miller
Cc: linux-wireless, netdev, tgraf, andrei.otcheretianski, ilan.peer,
stable, Pravin B Shelar
In-Reply-To: <20130811.212942.413012801159758438.davem@davemloft.net>
On Sun, 2013-08-11 at 21:29 -0700, David Miller wrote:
> > BUG: unable to handle kernel paging request at f8467360
> > IP: [<c14c56bb>] ctrl_dumpfamily+0x6b/0xe0
> > EIP: 0060:[<c14c56bb>] EFLAGS: 00210297 CPU: 2
> > EIP is at ctrl_dumpfamily+0x6b/0xe0
> > EAX: f8467378 EBX: f8467340 ECX: 00000000 EDX: ec1610c4
> > ESI: 00000001 EDI: c2077cc0 EBP: c46c3c00 ESP: c46c3bd4
> > DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
> > CR0: 80050033 CR2: f8467360 CR3: 26e54000 CR4: 001407d0
> > DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
> > DR6: ffff0ff0 DR7: 00000400
> > Process wpa_supplicant (pid: 20081, ti=c46c2000 task=c44640b0 task.ti=c46c2000)
> > Call Trace:
> > [<c14c20bc>] netlink_dump+0x5c/0x200
> > [<c14c3450>] __netlink_dump_start+0x140/0x160
> > [<c14c5172>] genl_rcv_msg+0x102/0x270
> > [<c14c4b5e>] netlink_rcv_skb+0x8e/0xb0
> > [<c14c505c>] genl_rcv+0x1c/0x30
> > [<c14c456b>] netlink_unicast+0x17b/0x1c0
> > [<c14c47d4>] netlink_sendmsg+0x224/0x370
> > [<c1485adf>] sock_sendmsg+0xff/0x120
>
> I completely agree with your analysis that we need locking here, but
> the crash OOPS backtrace doesn't make any sense to me.
>
> The bug should trigger when we enter the dump continuation path, which
> would look like:
>
> ctrl_dumpfamily()
> netlink_dump()
> netlink_recvmsg()
> ...
>
> Since this is the only way we get into ctrl_dumpfamily() without
> holding genl_lock().
>
> But in your trace we're going through genl_rcv() which means this is
> the first call of the dump, and genl_rcv() takes the necessary locks.
Huh, yes, I only looked at the crash info as far as I needed to see that
it was crashing at accessing "rt->netnsok" with a not totally invalid
pointer "rt" (it's in EBX) and then went from the code ...
Ok, I see what's going on here. The bug was reported to me against an
old kernel (3.4.47!) and that actually did an unlock in genl_rcv_msg()
before calling netlink_dump_start():
if (nlh->nlmsg_flags & NLM_F_DUMP) {
if (ops->dumpit == NULL)
return -EOPNOTSUPP;
genl_unlock();
{
struct netlink_dump_control c = {
.dump = ops->dumpit,
.done = ops->done,
};
err = netlink_dump_start(net->genl_sock, skb,
nlh, &c);
}
genl_lock();
return err;
}
That was changed in Pravin's commit
def3117493eafd9dfa1f809d861e0031b2cc8a07
"genl: Allow concurrent genl callbacks." very recently - I'm not sure if
that was intentional, it's not described in the commit log.
I think for the current code the fix would still be correct, I can
change the commit message if you like. For backporting, we'll have to
check which tree has Pravin's change and which doesn't and change this
accordingly, I suppose.
johannes
^ permalink raw reply
* RE: [PATCH] iwlwifi: mvm: make debugfs write() operations write up to count bytes
From: Berg, Johannes @ 2013-08-12 8:19 UTC (permalink / raw)
To: Djalal Harouni, Grumbach, Emmanuel, Intel Linux Wireless,
John W. Linville, linux-kernel@vger.kernel.org,
linux-wireless@vger.kernel.org
In-Reply-To: <1376267972-5636-1-git-send-email-tixxdz@opendz.org>
> Some debugfs write() operations of the MVM Firmware will ignore the count
> argument, and will copy more bytes than what was specified.
> Fix this by getting the right count of bytes.
>
> This will also honor restrictions put on the number of bytes to write.
That makes some sense.
> To be consitant this patch also switches the initializer from 'char buf[x] = {}' to
> the explicit memset() as it is done in other places of the same file.
I'd rather this (a) be done in a separate patch, and (b) the other way around, switch everything to C99.
> Cc: stable@vger.kernel.org
That doesn't really make sense for the debugfs interface.
> + memset(buf, 0, sizeof(buf));
> + if (count > sizeof(buf) - 1)
> + count = sizeof(buf) - 1;
Why -1? And why not use min()/min_t()?
johannes
--
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
^ permalink raw reply
* Re: [patch] iwlwifi: pcie: returning positive instead of negative
From: Johannes Berg @ 2013-08-12 8:11 UTC (permalink / raw)
To: Dan Carpenter
Cc: Emmanuel Grumbach, Intel Linux Wireless, John W. Linville,
linux-wireless, kernel-janitors
In-Reply-To: <20130810230321.GA19051@elgon.mountain>
On Sun, 2013-08-11 at 02:03 +0300, Dan Carpenter wrote:
> There is a missing '-' character here so we return positive 'ENOMEM'
> instead of negative. The caller doesn't care. All non-zero returns
> are translated to '-ENOMEM' in iwl_pcie_nic_init().
>
> This is just a cleanup.
Applied, thanks.
johannes
^ permalink raw reply
* Re: FUSB200 xhci issue
From: Oleksij Rempel @ 2013-08-12 7:58 UTC (permalink / raw)
To: Alan Stern
Cc: Christian Lamparter, Sarah Sharp, Seth Forshee, ath9k_htc_fw,
USB list, linux-wireless, Sujith Manoharan
In-Reply-To: <Pine.LNX.4.44L0.1308100755250.31571-100000@netrider.rowland.org>
Am 10.08.2013 13:57, schrieb Alan Stern:
> On Sat, 10 Aug 2013, Oleksij Rempel wrote:
>
>> usb reset do not affect behaviour of firmware. At least after i remove
>> all attempts to reboot FW from driver.
>> If adapter will got reset signal, FW will be notified about it. Then FW
>> will remove reset flag and will just continue to work. After usb reset,
>> lsusb show correct, update information - EP3 and EP4 was updated from
>> INT to BULK.
>>
>> I assume, no i need to add to the driver some kind of firmware check.
>> What is the proper way to do it?
>
> The simplest way is to put a new value for the device descriptor's
> bcdDevice value in the firmware. Then all you have to do is check that
> value.
Since adding fw check will need fw version update. I would like to do
quick fix for current kernel and firmware version.
I will revert EP3 and EP4 from bulk back to interrupt. But, before
sending patch to the list i would like to know, how to reproduce the bug
which was fixed by converting this endpoints from interrupt to bulk.
--
Regards,
Oleksij
--
Regards,
Oleksij
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox