From yeohchunyeow at gmail.com  Tue Jul  1 00:17:06 2014
From: yeohchunyeow at gmail.com (Yeoh Chun-Yeow)
Date: Tue, 1 Jul 2014 15:17:06 +0800
Subject: Frame Injection in Monitor Mode
Message-ID: <CAEFj984N4HSVosxx52s9e-sX3STK=YjOmh_UUwJWDJRQZAZdcg@mail.gmail.com>

Hi, all

Anyone has tried the frame injection using the standalone monitor mode
on AP firmware.

I have tried this but no luck not working.

-----
Chun-Yeow


From michal.kazior at tieto.com  Tue Jul  1 00:29:41 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 1 Jul 2014 09:29:41 +0200
Subject: Frame Injection in Monitor Mode
In-Reply-To: <CAEFj984N4HSVosxx52s9e-sX3STK=YjOmh_UUwJWDJRQZAZdcg@mail.gmail.com>
References: <CAEFj984N4HSVosxx52s9e-sX3STK=YjOmh_UUwJWDJRQZAZdcg@mail.gmail.com>
Message-ID: <CA+BoTQnAVooNEHZbmqaudUpoCGCzSi-nWM8xarwqv+mLq14Dcw@mail.gmail.com>

On 1 July 2014 09:17, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
> Hi, all
>
> Anyone has tried the frame injection using the standalone monitor mode
> on AP firmware.
>
> I have tried this but no luck not working.

I played with this a little a while ago.

Raw tx on 10.1.467 is broken. It needs htt tx command to be modified
to send a fixed up msdu len (msdu->len -
ieee80211_hdrlen(hdr->frame_control) + sizeof(struct ethhdr) if my
memory serves right) however firmware crashes on null dereference as
soon as the frame completion is handled.

I haven't tried this with CT firmware from Ben - maybe you should give it a try?


Micha?


From yeohchunyeow at gmail.com  Tue Jul  1 01:04:40 2014
From: yeohchunyeow at gmail.com (Yeoh Chun-Yeow)
Date: Tue, 1 Jul 2014 16:04:40 +0800
Subject: Frame Injection in Monitor Mode
In-Reply-To: <CA+BoTQnAVooNEHZbmqaudUpoCGCzSi-nWM8xarwqv+mLq14Dcw@mail.gmail.com>
References: <CAEFj984N4HSVosxx52s9e-sX3STK=YjOmh_UUwJWDJRQZAZdcg@mail.gmail.com>
 <CA+BoTQnAVooNEHZbmqaudUpoCGCzSi-nWM8xarwqv+mLq14Dcw@mail.gmail.com>
Message-ID: <CAEFj984+jp4L3x0W2euEPsUbq9QsbDid0h0iTrTu36LHZh-URw@mail.gmail.com>

On Tue, Jul 1, 2014 at 3:29 PM, Michal Kazior <michal.kazior at tieto.com> wrote:
> On 1 July 2014 09:17, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
>> Hi, all
>>
>> Anyone has tried the frame injection using the standalone monitor mode
>> on AP firmware.
>>
>> I have tried this but no luck not working.
>
> I played with this a little a while ago.
>
> Raw tx on 10.1.467 is broken. It needs htt tx command to be modified
> to send a fixed up msdu len (msdu->len -
> ieee80211_hdrlen(hdr->frame_control) + sizeof(struct ethhdr) if my

So with this msdu->len, it means that there is no 802.11 MAC header in
the frame submission for transmission, and only Ethernet header. So
the transmit mode is ATH10K_HW_TXRX_ETHERNET, am I right?

Please advice. Thanks

Regards,
Chun-Yeow


From michal.kazior at tieto.com  Tue Jul  1 01:47:19 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 1 Jul 2014 10:47:19 +0200
Subject: Frame Injection in Monitor Mode
In-Reply-To: <CAEFj984+jp4L3x0W2euEPsUbq9QsbDid0h0iTrTu36LHZh-URw@mail.gmail.com>
References: <CAEFj984N4HSVosxx52s9e-sX3STK=YjOmh_UUwJWDJRQZAZdcg@mail.gmail.com>
 <CA+BoTQnAVooNEHZbmqaudUpoCGCzSi-nWM8xarwqv+mLq14Dcw@mail.gmail.com>
 <CAEFj984+jp4L3x0W2euEPsUbq9QsbDid0h0iTrTu36LHZh-URw@mail.gmail.com>
Message-ID: <CA+BoTQkkR0yi38xEDwEDsRdDx8kXRbGCOfy-q1TvRupAW9zt-g@mail.gmail.com>

On 1 July 2014 10:04, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
> On Tue, Jul 1, 2014 at 3:29 PM, Michal Kazior <michal.kazior at tieto.com> wrote:
>> On 1 July 2014 09:17, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
>>> Hi, all
>>>
>>> Anyone has tried the frame injection using the standalone monitor mode
>>> on AP firmware.
>>>
>>> I have tried this but no luck not working.
>>
>> I played with this a little a while ago.
>>
>> Raw tx on 10.1.467 is broken. It needs htt tx command to be modified
>> to send a fixed up msdu len (msdu->len -
>> ieee80211_hdrlen(hdr->frame_control) + sizeof(struct ethhdr) if my
>
> So with this msdu->len, it means that there is no 802.11 MAC header in
> the frame submission for transmission, and only Ethernet header. So
> the transmit mode is ATH10K_HW_TXRX_ETHERNET, am I right?

This calculation is necessary for TXRX_RAW actually. There seems to be
a bug in fw and this tricks it to send the raw frame correctly.


Micha?


From yeohchunyeow at gmail.com  Tue Jul  1 02:37:20 2014
From: yeohchunyeow at gmail.com (Yeoh Chun-Yeow)
Date: Tue, 1 Jul 2014 17:37:20 +0800
Subject: Frame Injection in Monitor Mode
In-Reply-To: <CA+BoTQkkR0yi38xEDwEDsRdDx8kXRbGCOfy-q1TvRupAW9zt-g@mail.gmail.com>
References: <CAEFj984N4HSVosxx52s9e-sX3STK=YjOmh_UUwJWDJRQZAZdcg@mail.gmail.com>
 <CA+BoTQnAVooNEHZbmqaudUpoCGCzSi-nWM8xarwqv+mLq14Dcw@mail.gmail.com>
 <CAEFj984+jp4L3x0W2euEPsUbq9QsbDid0h0iTrTu36LHZh-URw@mail.gmail.com>
 <CA+BoTQkkR0yi38xEDwEDsRdDx8kXRbGCOfy-q1TvRupAW9zt-g@mail.gmail.com>
Message-ID: <CAEFj985F2nrZ8VBf-fwVkeYFQ8bXkB-KtwWyC2sY5CEysj5WsA@mail.gmail.com>

I have tried to set the following:

flags0 |= SM(ATH10K_HW_TXRX_RAW, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);

But both AP and CT firmware crashed.

----
Chun-Yeow

On Tue, Jul 1, 2014 at 4:47 PM, Michal Kazior <michal.kazior at tieto.com> wrote:
> On 1 July 2014 10:04, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
>> On Tue, Jul 1, 2014 at 3:29 PM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>> On 1 July 2014 09:17, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
>>>> Hi, all
>>>>
>>>> Anyone has tried the frame injection using the standalone monitor mode
>>>> on AP firmware.
>>>>
>>>> I have tried this but no luck not working.
>>>
>>> I played with this a little a while ago.
>>>
>>> Raw tx on 10.1.467 is broken. It needs htt tx command to be modified
>>> to send a fixed up msdu len (msdu->len -
>>> ieee80211_hdrlen(hdr->frame_control) + sizeof(struct ethhdr) if my
>>
>> So with this msdu->len, it means that there is no 802.11 MAC header in
>> the frame submission for transmission, and only Ethernet header. So
>> the transmit mode is ATH10K_HW_TXRX_ETHERNET, am I right?
>
> This calculation is necessary for TXRX_RAW actually. There seems to be
> a bug in fw and this tricks it to send the raw frame correctly.
>
>
> Micha?


From kvalo at qca.qualcomm.com  Wed Jul  2 01:10:47 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 2 Jul 2014 11:10:47 +0300
Subject: ath10k OTP loading issues
In-Reply-To: <53AD2EEE.4040704@marcant.net> (=?utf-8?Q?=22Andr=C3=A9?=
 Valentin"'s message of "Fri, 27 Jun 2014 10:44:30 +0200")
References: <53AD2EEE.4040704@marcant.net>
Message-ID: <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>

Hi,

please always CC ath10k list, that way you get attention of all ath10k
developers.

Andr? Valentin <avalentin at marcant.net> writes:

> I got problems initializing my ath10k PCI card in my Zyxel NBG 6716.
> It worked until some weeks, now, the driver does not load. I debugged
> a bit and this is what I got:
>
> Fri Jun 27 08:03:42 2014 kern.info kernel: [62908.290000] ath10k_pci 0000:01:00.0: BAR 0: assigned [mem 0x12000000-0x121fffff 64bit]
> Fri Jun 27 08:03:43 2014 kern.info kernel: [62908.610000] ath10k: pci irq legacy irq_mode 0 reset_mode 0
> Fri Jun 27 08:03:43 2014 kern.err kernel: [62908.620000] ath10k: boot upload otp to 0x1234 len 6917
> Fri Jun 27 08:03:43 2014 kern.err kernel: [62908.780000] ath10k: otp calibration failed: 2
> Fri Jun 27 08:03:43 2014 kern.err kernel: [62908.790000] ath10k: failed to run otp: -22
> Fri Jun 27 08:03:43 2014 kern.err kernel: [62908.790000] ath10k: could not init core (-22)
> Fri Jun 27 08:03:43 2014 kern.err kernel: [62909.060000] ath10k: could not probe fw (-22)
> Fri Jun 27 08:03:43 2014 kern.err kernel: [62909.060000] ath10k: failed to register driver core: -22
> Fri Jun 27 08:03:43 2014 kern.warn kernel: [62909.060000] ath10k_pci: probe of 0000:01:00.0 failed with error -22
>
> If I remove OTP loading the card initializes fine, but I think I will
> not have a good performance. So bad idea.

All that was changed recently was that we now check the error code
coming from otp.bin. So you have had this issue all along, it was just
hidden before.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Jul  2 01:13:38 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 2 Jul 2014 11:13:38 +0300
Subject: ath10k OTP loading issues
In-Reply-To: <53AD4F17.6070604@marcant.net> (=?utf-8?Q?=22Andr=C3=A9?=
 Valentin"'s message of "Fri, 27 Jun 2014 13:01:43 +0200")
References: <53AD2EEE.4040704@marcant.net> <53AD4F17.6070604@marcant.net>
Message-ID: <87pphop499.fsf@kamboji.qca.qualcomm.com>

Andr? Valentin <avalentin at marcant.net> writes:

> I just saw the old thread about the same point. So I'm trying to look
> in the flash of my router if the OTP is stored there. Does this OTP
> have some kind of magic so I can identify it?

MAC addresses are good one to check. Basically it should be similar data
as in board.bin.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Jul  2 01:56:09 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 2 Jul 2014 11:56:09 +0300
Subject: ath10k OTP loading issues
In-Reply-To: <53B3C3FF.1060207@marcant.net> (=?utf-8?Q?=22Andr=C3=A9?=
 Valentin"'s message of "Wed, 2 Jul 2014 10:34:07 +0200")
References: <53AD2EEE.4040704@marcant.net> <53AD4F17.6070604@marcant.net>
 <87pphop499.fsf@kamboji.qca.qualcomm.com>
 <53B3C3FF.1060207@marcant.net>
Message-ID: <87egy4p2ae.fsf@kamboji.qca.qualcomm.com>

Andr? Valentin <avalentin at marcant.net> writes:

> Hi!
>
>>> have some kind of magic so I can identify it?
>> 
>> MAC addresses are good one to check. Basically it should be similar data
>> as in board.bin.
>
> Of course I already tried this. But no luck.

How exactly did you search for it? Are you sure you used the correct MAC
address?

> Do you have another idea. Or is the MAC somehow encrypted ?

Nothing special, the MAC address should should be within the first 20
bytes. For example, here's 00:03:07:12:34:56:

$ od -t x1 board.bin  | head -1
0000000 44 08 df 30 02 04 00 03 07 12 34 56 00 00 6a 00

But of course I might be missing something. Or the calibration data is
somehow encrypted on the flash.

-- 
Kalle Valo


From avalentin at marcant.net  Wed Jul  2 01:34:07 2014
From: avalentin at marcant.net (=?UTF-8?B?QW5kcsOpIFZhbGVudGlu?=)
Date: Wed, 02 Jul 2014 10:34:07 +0200
Subject: ath10k OTP loading issues
In-Reply-To: <87pphop499.fsf@kamboji.qca.qualcomm.com>
References: <53AD2EEE.4040704@marcant.net> <53AD4F17.6070604@marcant.net>
 <87pphop499.fsf@kamboji.qca.qualcomm.com>
Message-ID: <53B3C3FF.1060207@marcant.net>

Hi!

>> have some kind of magic so I can identify it?
> 
> MAC addresses are good one to check. Basically it should be similar data
> as in board.bin.

Of course I already tried this. But no luck. Do you have another idea.
Or is the MAC somehow encrypted ? I searched for the ASCII represantation and
a binary string generated from the MAC bytes.

Thanks,

Andr?


From michal.kazior at tieto.com  Wed Jul  2 09:49:52 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 2 Jul 2014 18:49:52 +0200
Subject: A-MSDU reception not working?
In-Reply-To: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
Message-ID: <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>

On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
> In iperf tests using a MacBook STA bridging through an ath10k AP to an
> Ethernet server, I'm noticing very selective packet loss. The second
> and subsequent frames in an A-MSDU packet appear to be dropped.
>
> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
> sends A-MSDU packets containing two TCP frames. So far as I can tell,
> the first TCP frame from an A-MSDU aggregate is delivered and the
> second is consistently lost. The MacBook generally retransmits the
> lost frame as a singleton with no aggregation, and the retransmitted
> frame makes it through.
>
> This became more noticeable after the reordering fixes in
> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>
> I see this A-MSDU packet loss behavior both with and without the
> reordering fixes, the first packet in an A-MSDU is delivered while the
> second is dropped. However, *without* the reordering fixes (and
> therefore with packets delivered out of order) the MacBook sends
> relatively few A-MSDU frames. *With* the reordering fixes, so all
> packets are delivered in order, the MacBook keeps sending A-MSDU and
> therefore has to deal with more packet loss. I suspect it is an
> interaction with the MacOS TCP congestion window which I'm likely
> never going to fully understand, its stuck in a region of the
> congestion window where the Wifi driver keeps choosing to using
> A-MSDU.

I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.

ath10k fw reports A-MSDU subframes separately. To avoid memory
copying/allocation overhead each subframe is reported as a singly
A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
A-MPDU reordering intereferes with A-MSDU now?


Micha?


From denton.gentry at gmail.com  Fri Jul  4 11:58:51 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Fri, 4 Jul 2014 11:58:51 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
Message-ID: <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>

Yes, after some more testing it does look like an unfortunate
interaction between the reorder buffer and A-MSDU. The disaggregated
subframes all carry the same sequence number. The first subframe is
released from the reorder buffer and increments the head_seq_num.
Subsequent subframes are all discarded as being out of date.

[  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
head=0xb06
[  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
head=0xb0b
[  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
head=0xb10
[  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
head=0xb15
[  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
head=0xb1a
[  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
head=0xb1f
[  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
head=0xb24


On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>> Ethernet server, I'm noticing very selective packet loss. The second
>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>
>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>> the first TCP frame from an A-MSDU aggregate is delivered and the
>> second is consistently lost. The MacBook generally retransmits the
>> lost frame as a singleton with no aggregation, and the retransmitted
>> frame makes it through.
>>
>> This became more noticeable after the reordering fixes in
>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>
>> I see this A-MSDU packet loss behavior both with and without the
>> reordering fixes, the first packet in an A-MSDU is delivered while the
>> second is dropped. However, *without* the reordering fixes (and
>> therefore with packets delivered out of order) the MacBook sends
>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>> therefore has to deal with more packet loss. I suspect it is an
>> interaction with the MacOS TCP congestion window which I'm likely
>> never going to fully understand, its stuck in a region of the
>> congestion window where the Wifi driver keeps choosing to using
>> A-MSDU.
>
> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>
> ath10k fw reports A-MSDU subframes separately. To avoid memory
> copying/allocation overhead each subframe is reported as a singly
> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
> A-MPDU reordering intereferes with A-MSDU now?
>
>
> Micha?


From denton.gentry at gmail.com  Sat Jul  5 06:55:07 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Sat, 5 Jul 2014 06:55:07 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
Message-ID: <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>

There are two issues in handling the dis-aggregated A-MSDU subframes
in ieee80211_sta_manage_reorder_buf:

1. The out-of-date check:

        /* frame with out of date sequence number */
        if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
                dev_kfree_skb(skb);
                goto out;
        }

As all of the subframes carry the same sequence number, the first
subframe will be delivered and increment head_seq_num and then all
subsequent subframes will be discarded.


2. The duplicates check a bit later in the routine:

        /* check if we already stored this frame */
        if (tid_agg_rx->reorder_buf[index]) {
                dev_kfree_skb(skb);
                goto out;
        }

If there is enough packet loss that packets are queued in the reorder
buffer and not immediately released, then only the first subframe will
be stored. Subsequent subframes will be discarded as duplicates.


An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
the reordering buffer changes, and dropped to about 8 Mbps with the
reorder buffer. Hacking around the out-of-date sequence number check
to allow all subframes to egress restores it to 170 Mbps.

In the area where I'm testing there isn't enough 5 GHz noise to make
the duplicates-check issue happen very often. By adding a printk I can
see that it does happen, but it doesn't impact the throughput and I
can't report the impact of fixing it.

----

I do wonder if both of these are symptoms of dis-aggregating the
A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
at a time, and the ath10k A-MSDU case is sending it subframes instead.
Trying to make the ath10k code send up all of the subframes as a chain
of skbs didn't immediately work, but I do wonder if that would better
match the mac80211 expectations.



On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
> Yes, after some more testing it does look like an unfortunate
> interaction between the reorder buffer and A-MSDU. The disaggregated
> subframes all carry the same sequence number. The first subframe is
> released from the reorder buffer and increments the head_seq_num.
> Subsequent subframes are all discarded as being out of date.
>
> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
> head=0xb06
> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
> head=0xb0b
> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
> head=0xb10
> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
> head=0xb15
> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
> head=0xb1a
> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
> head=0xb1f
> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
> head=0xb24
>
>
> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>> Ethernet server, I'm noticing very selective packet loss. The second
>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>
>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>> second is consistently lost. The MacBook generally retransmits the
>>> lost frame as a singleton with no aggregation, and the retransmitted
>>> frame makes it through.
>>>
>>> This became more noticeable after the reordering fixes in
>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>
>>> I see this A-MSDU packet loss behavior both with and without the
>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>> second is dropped. However, *without* the reordering fixes (and
>>> therefore with packets delivered out of order) the MacBook sends
>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>> therefore has to deal with more packet loss. I suspect it is an
>>> interaction with the MacOS TCP congestion window which I'm likely
>>> never going to fully understand, its stuck in a region of the
>>> congestion window where the Wifi driver keeps choosing to using
>>> A-MSDU.
>>
>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>
>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>> copying/allocation overhead each subframe is reported as a singly
>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>> A-MPDU reordering intereferes with A-MSDU now?
>>
>>
>> Micha?


From greearb at candelatech.com  Sat Jul  5 07:16:31 2014
From: greearb at candelatech.com (Ben Greear)
Date: Sat, 05 Jul 2014 07:16:31 -0700
Subject: Question on beacon-miss handling.
Message-ID: <53B808BF.8070000@candelatech.com>

While poking around in the firmware, I notice that ath10k
driver only requests a few vdevs to be supported by
the beacon-miss firmware logic, though the driver
supposedly supports more vdevs than that...

Any idea how this is supposed to work with more vdevs
than bmiss_offload_max_vdev?

Maybe it is best to just disable beacon-miss logic in
firmware entirely and let the driver/host handle it?

Thanks,
Ben

-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From adrian at freebsd.org  Sat Jul  5 19:14:34 2014
From: adrian at freebsd.org (Adrian Chadd)
Date: Sat, 5 Jul 2014 19:14:34 -0700
Subject: Question on beacon-miss handling.
In-Reply-To: <53B808BF.8070000@candelatech.com>
References: <53B808BF.8070000@candelatech.com>
Message-ID: <CAJ-Vmo=8pO0eVpL5L28AVALn+rpYPxhOw5kYkaGieBt-RzN3iQ@mail.gmail.com>

Where is it in the firmware again?

The beacon miss stuff is a little .. odd. Mostly because there's only
one (and maybe two) timers for it and they're a pain in the ass to
configure correctly. Having it scale (correctly) to more than two
vdevs may be a little challenging.



-a


On 5 July 2014 07:16, Ben Greear <greearb at candelatech.com> wrote:
> While poking around in the firmware, I notice that ath10k
> driver only requests a few vdevs to be supported by
> the beacon-miss firmware logic, though the driver
> supposedly supports more vdevs than that...
>
> Any idea how this is supposed to work with more vdevs
> than bmiss_offload_max_vdev?
>
> Maybe it is best to just disable beacon-miss logic in
> firmware entirely and let the driver/host handle it?
>
> Thanks,
> Ben
>
> --
> Ben Greear <greearb at candelatech.com>
> Candela Technologies Inc  http://www.candelatech.com
>
>
> _______________________________________________
> ath10k mailing list
> ath10k at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/ath10k


From adrian at freebsd.org  Sat Jul  5 19:27:03 2014
From: adrian at freebsd.org (Adrian Chadd)
Date: Sat, 5 Jul 2014 19:27:03 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
Message-ID: <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>

I think you may have to tell mac80211 that it's okay and not to drop the frames.

The earlier atheros chips would just give you the AMSDU frames as
deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
net80211 and it'd ull it apart. But if the driver is doing it (or,
well, the chip is doing it) then mac80211 needs to know not to drop
those sub-frames.

I wonder if you'll ever get notified before the complete A-MPDU has
been received. That happens on previous chips. eg, you have an A-MPDU
of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
half of one MPDU before you hit EOL, the next notification you process
will be the next MSDU in the same MPDU - and then you'll hit the
reordering hilarity again.

So hm, i will face the same issue in FreeBSD at some point, so I'd
likely do what you're thinking of doing - pass up a chain of mbufs
representing the current MPDU and treat the whole lot as the frame(s)
to care about. Honestly though, I'm kind of wondering whether I should
mostly just do what the Atheros reference driver does and treat it as
ethernet payload frames (ie, it's already de-encapsulated and the
reordering is already done) and just tack on the wifi header bit via
another of the DMA rings.

Ugh, I really should sit down and write the FreeBSD version of this.



-a

(I'm still having flashbacks from working on this firmware at QCA. Aiee.)


On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
> There are two issues in handling the dis-aggregated A-MSDU subframes
> in ieee80211_sta_manage_reorder_buf:
>
> 1. The out-of-date check:
>
>         /* frame with out of date sequence number */
>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>                 dev_kfree_skb(skb);
>                 goto out;
>         }
>
> As all of the subframes carry the same sequence number, the first
> subframe will be delivered and increment head_seq_num and then all
> subsequent subframes will be discarded.
>
>
> 2. The duplicates check a bit later in the routine:
>
>         /* check if we already stored this frame */
>         if (tid_agg_rx->reorder_buf[index]) {
>                 dev_kfree_skb(skb);
>                 goto out;
>         }
>
> If there is enough packet loss that packets are queued in the reorder
> buffer and not immediately released, then only the first subframe will
> be stored. Subsequent subframes will be discarded as duplicates.
>
>
> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
> the reordering buffer changes, and dropped to about 8 Mbps with the
> reorder buffer. Hacking around the out-of-date sequence number check
> to allow all subframes to egress restores it to 170 Mbps.
>
> In the area where I'm testing there isn't enough 5 GHz noise to make
> the duplicates-check issue happen very often. By adding a printk I can
> see that it does happen, but it doesn't impact the throughput and I
> can't report the impact of fixing it.
>
> ----
>
> I do wonder if both of these are symptoms of dis-aggregating the
> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
> at a time, and the ath10k A-MSDU case is sending it subframes instead.
> Trying to make the ath10k code send up all of the subframes as a chain
> of skbs didn't immediately work, but I do wonder if that would better
> match the mac80211 expectations.
>
>
>
> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>> Yes, after some more testing it does look like an unfortunate
>> interaction between the reorder buffer and A-MSDU. The disaggregated
>> subframes all carry the same sequence number. The first subframe is
>> released from the reorder buffer and increments the head_seq_num.
>> Subsequent subframes are all discarded as being out of date.
>>
>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>> head=0xb06
>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>> head=0xb0b
>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>> head=0xb10
>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>> head=0xb15
>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>> head=0xb1a
>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>> head=0xb1f
>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>> head=0xb24
>>
>>
>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>
>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>> second is consistently lost. The MacBook generally retransmits the
>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>> frame makes it through.
>>>>
>>>> This became more noticeable after the reordering fixes in
>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>
>>>> I see this A-MSDU packet loss behavior both with and without the
>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>> second is dropped. However, *without* the reordering fixes (and
>>>> therefore with packets delivered out of order) the MacBook sends
>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>> therefore has to deal with more packet loss. I suspect it is an
>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>> never going to fully understand, its stuck in a region of the
>>>> congestion window where the Wifi driver keeps choosing to using
>>>> A-MSDU.
>>>
>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>
>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>> copying/allocation overhead each subframe is reported as a singly
>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>> A-MPDU reordering intereferes with A-MSDU now?
>>>
>>>
>>> Micha?
>
> _______________________________________________
> ath10k mailing list
> ath10k at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/ath10k


From greearb at candelatech.com  Sat Jul  5 20:39:11 2014
From: greearb at candelatech.com (Ben Greear)
Date: Sat, 05 Jul 2014 20:39:11 -0700
Subject: Question on beacon-miss handling.
In-Reply-To: <CAJ-Vmo=8pO0eVpL5L28AVALn+rpYPxhOw5kYkaGieBt-RzN3iQ@mail.gmail.com>
References: <53B808BF.8070000@candelatech.com>
 <CAJ-Vmo=8pO0eVpL5L28AVALn+rpYPxhOw5kYkaGieBt-RzN3iQ@mail.gmail.com>
Message-ID: <53B8C4DF.5000308@candelatech.com>

On 07/05/2014 07:14 PM, Adrian Chadd wrote:
> Where is it in the firmware again?

wlan_swbmiss_offload.c

> The beacon miss stuff is a little .. odd. Mostly because there's only
> one (and maybe two) timers for it and they're a pain in the ass to
> configure correctly. Having it scale (correctly) to more than two
> vdevs may be a little challenging.

I've seen other funny stuff where an AP will crash hard(-ish?) and the associated stations
take a long time to figure out their AP is dead.  Could be related to this
maybe..or maybe was something else.  I have not investigated closely.

I'd be happy to have all the beacon miss stuff move to the driver..seems
a waste of limited resources in the firmware.

Thanks,
Ben

>
>
>
> -a
>
>
> On 5 July 2014 07:16, Ben Greear <greearb at candelatech.com> wrote:
>> While poking around in the firmware, I notice that ath10k
>> driver only requests a few vdevs to be supported by
>> the beacon-miss firmware logic, though the driver
>> supposedly supports more vdevs than that...
>>
>> Any idea how this is supposed to work with more vdevs
>> than bmiss_offload_max_vdev?
>>
>> Maybe it is best to just disable beacon-miss logic in
>> firmware entirely and let the driver/host handle it?
>>
>> Thanks,
>> Ben
>>
>> --
>> Ben Greear <greearb at candelatech.com>
>> Candela Technologies Inc  http://www.candelatech.com
>>
>>
>> _______________________________________________
>> ath10k mailing list
>> ath10k at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/ath10k
>
> _______________________________________________
> ath10k mailing list
> ath10k at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/ath10k
>


-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From adrian at freebsd.org  Sat Jul  5 21:39:04 2014
From: adrian at freebsd.org (Adrian Chadd)
Date: Sat, 5 Jul 2014 21:39:04 -0700
Subject: Question on beacon-miss handling.
In-Reply-To: <53B8C4DF.5000308@candelatech.com>
References: <53B808BF.8070000@candelatech.com>
 <CAJ-Vmo=8pO0eVpL5L28AVALn+rpYPxhOw5kYkaGieBt-RzN3iQ@mail.gmail.com>
 <53B8C4DF.5000308@candelatech.com>
Message-ID: <CAJ-Vmo=tjqCAns3N2_PY08r6A85Q9e8CoSWCV7g5KCQHRmqN-g@mail.gmail.com>

On 5 July 2014 20:39, Ben Greear <greearb at candelatech.com> wrote:
> On 07/05/2014 07:14 PM, Adrian Chadd wrote:
>>
>> Where is it in the firmware again?
>
>
> wlan_swbmiss_offload.c
>
>
>> The beacon miss stuff is a little .. odd. Mostly because there's only
>> one (and maybe two) timers for it and they're a pain in the ass to
>> configure correctly. Having it scale (correctly) to more than two
>> vdevs may be a little challenging.
>
>
> I've seen other funny stuff where an AP will crash hard(-ish?) and the
> associated stations
> take a long time to figure out their AP is dead.  Could be related to this
> maybe..or maybe was something else.  I have not investigated closely.
>
> I'd be happy to have all the beacon miss stuff move to the driver..seems
> a waste of limited resources in the firmware.

Think about it in terms of "minimising how much the host is woken up."

That's what the target market of the STA firmware for this chip is
thinking about.


-a


From sujith at msujith.org  Sat Jul  5 23:01:45 2014
From: sujith at msujith.org (Sujith Manoharan)
Date: Sun, 6 Jul 2014 11:31:45 +0530
Subject: Question on beacon-miss handling.
In-Reply-To: <CAJ-Vmo=tjqCAns3N2_PY08r6A85Q9e8CoSWCV7g5KCQHRmqN-g@mail.gmail.com>
References: <53B808BF.8070000@candelatech.com>
 <CAJ-Vmo=8pO0eVpL5L28AVALn+rpYPxhOw5kYkaGieBt-RzN3iQ@mail.gmail.com>
 <53B8C4DF.5000308@candelatech.com>
 <CAJ-Vmo=tjqCAns3N2_PY08r6A85Q9e8CoSWCV7g5KCQHRmqN-g@mail.gmail.com>
Message-ID: <21432.58953.39322.640936@gargle.gargle.HOWL>

Adrian Chadd wrote:
> Think about it in terms of "minimising how much the host is woken up."
> 
> That's what the target market of the STA firmware for this chip is
> thinking about.

I don't think beacon filtering is enabled for ath10k, which means
all beacons are sent to mac80211 anyway. HW/FW connection monitoring
(in STA mode) is also not enabled in ath10k, so mac80211's beacon loss/miss
infrastructure is already used, no ?

Sujith


From adrian at freebsd.org  Sun Jul  6 00:18:25 2014
From: adrian at freebsd.org (Adrian Chadd)
Date: Sun, 6 Jul 2014 00:18:25 -0700
Subject: Question on beacon-miss handling.
In-Reply-To: <21432.58953.39322.640936@gargle.gargle.HOWL>
References: <53B808BF.8070000@candelatech.com>
 <CAJ-Vmo=8pO0eVpL5L28AVALn+rpYPxhOw5kYkaGieBt-RzN3iQ@mail.gmail.com>
 <53B8C4DF.5000308@candelatech.com>
 <CAJ-Vmo=tjqCAns3N2_PY08r6A85Q9e8CoSWCV7g5KCQHRmqN-g@mail.gmail.com>
 <21432.58953.39322.640936@gargle.gargle.HOWL>
Message-ID: <CAJ-Vmo=argSM0Y6buF3+TBSxSN6XgMHsnjh1Js0SW7F9UR-+UA@mail.gmail.com>

On 5 July 2014 23:01, Sujith Manoharan <sujith at msujith.org> wrote:
> Adrian Chadd wrote:
>> Think about it in terms of "minimising how much the host is woken up."
>>
>> That's what the target market of the STA firmware for this chip is
>> thinking about.
>
> I don't think beacon filtering is enabled for ath10k, which means
> all beacons are sent to mac80211 anyway. HW/FW connection monitoring
> (in STA mode) is also not enabled in ath10k, so mac80211's beacon loss/miss
> infrastructure is already used, no ?

Sure, but my response was just describing the "why" behind why the
firmware would want to be doing beacon offload processing.


-a


From greearb at candelatech.com  Sun Jul  6 01:54:09 2014
From: greearb at candelatech.com (Ben Greear)
Date: Sun, 06 Jul 2014 01:54:09 -0700
Subject: Question on beacon-miss handling.
In-Reply-To: <21432.58953.39322.640936@gargle.gargle.HOWL>
References: <53B808BF.8070000@candelatech.com>	<CAJ-Vmo=8pO0eVpL5L28AVALn+rpYPxhOw5kYkaGieBt-RzN3iQ@mail.gmail.com>	<53B8C4DF.5000308@candelatech.com>	<CAJ-Vmo=tjqCAns3N2_PY08r6A85Q9e8CoSWCV7g5KCQHRmqN-g@mail.gmail.com>
 <21432.58953.39322.640936@gargle.gargle.HOWL>
Message-ID: <53B90EB1.8020305@candelatech.com>

On 07/05/2014 11:01 PM, Sujith Manoharan wrote:
> Adrian Chadd wrote:
>> Think about it in terms of "minimising how much the host is woken up."
>>
>> That's what the target market of the STA firmware for this chip is
>> thinking about.
>
> I don't think beacon filtering is enabled for ath10k, which means
> all beacons are sent to mac80211 anyway. HW/FW connection monitoring
> (in STA mode) is also not enabled in ath10k, so mac80211's beacon loss/miss
> infrastructure is already used, no ?

Maybe the driver should make this 0 instead of 2 then?

hw.h:#define TARGET_10X_BMISS_OFFLOAD_MAX_VDEV	2

That would save resources in the firmware.

Thanks,
Ben

>
> Sujith
>


-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From sujith at msujith.org  Sun Jul  6 20:37:53 2014
From: sujith at msujith.org (Sujith Manoharan)
Date: Mon, 7 Jul 2014 09:07:53 +0530
Subject: Question on beacon-miss handling.
In-Reply-To: <53B90EB1.8020305@candelatech.com>
References: <53B808BF.8070000@candelatech.com>
 <CAJ-Vmo=8pO0eVpL5L28AVALn+rpYPxhOw5kYkaGieBt-RzN3iQ@mail.gmail.com>
 <53B8C4DF.5000308@candelatech.com>
 <CAJ-Vmo=tjqCAns3N2_PY08r6A85Q9e8CoSWCV7g5KCQHRmqN-g@mail.gmail.com>
 <21432.58953.39322.640936@gargle.gargle.HOWL>
 <53B90EB1.8020305@candelatech.com>
Message-ID: <21434.5649.615843.633424@gargle.gargle.HOWL>

Ben Greear wrote:
> Maybe the driver should make this 0 instead of 2 then?
> hw.h:#define TARGET_10X_BMISS_OFFLOAD_MAX_VDEV	2
> That would save resources in the firmware.

Yes, it would. ath10k doesn't seem to be handling roam
events too, so maybe that can be set to 0 - not sure if
there are plans to properly enable and use roaming functionality
that is already in the firmware.

Sujith


From greearb at candelatech.com  Sun Jul  6 21:35:31 2014
From: greearb at candelatech.com (Ben Greear)
Date: Sun, 06 Jul 2014 21:35:31 -0700
Subject: Question on beacon-miss handling.
In-Reply-To: <21434.5649.615843.633424@gargle.gargle.HOWL>
References: <53B808BF.8070000@candelatech.com>	<CAJ-Vmo=8pO0eVpL5L28AVALn+rpYPxhOw5kYkaGieBt-RzN3iQ@mail.gmail.com>	<53B8C4DF.5000308@candelatech.com>	<CAJ-Vmo=tjqCAns3N2_PY08r6A85Q9e8CoSWCV7g5KCQHRmqN-g@mail.gmail.com>	<21432.58953.39322.640936@gargle.gargle.HOWL>	<53B90EB1.8020305@candelatech.com>
 <21434.5649.615843.633424@gargle.gargle.HOWL>
Message-ID: <53BA2393.8020409@candelatech.com>

On 07/06/2014 08:37 PM, Sujith Manoharan wrote:
> Ben Greear wrote:
>> Maybe the driver should make this 0 instead of 2 then?
>> hw.h:#define TARGET_10X_BMISS_OFFLOAD_MAX_VDEV	2
>> That would save resources in the firmware.
>
> Yes, it would. ath10k doesn't seem to be handling roam
> events too, so maybe that can be set to 0 - not sure if
> there are plans to properly enable and use roaming functionality
> that is already in the firmware.

I have set both to zero when using my firmware, and so far, everything
seems to be working fine.

I am tempted to just compile the roaming and beacon-miss code entirely
out of the firmware to save a bit of memory, but I guess that might
possibly break some driver, so if I do, I will have to add a new
firmware image variant...

Thanks,
Ben

-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From bartosz.markowski at tieto.com  Sun Jul  6 23:57:37 2014
From: bartosz.markowski at tieto.com (Bartosz Markowski)
Date: Mon, 7 Jul 2014 08:57:37 +0200
Subject: Question on beacon-miss handling.
In-Reply-To: <21434.5649.615843.633424@gargle.gargle.HOWL>
References: <53B808BF.8070000@candelatech.com>
 <CAJ-Vmo=8pO0eVpL5L28AVALn+rpYPxhOw5kYkaGieBt-RzN3iQ@mail.gmail.com>
 <53B8C4DF.5000308@candelatech.com>
 <CAJ-Vmo=tjqCAns3N2_PY08r6A85Q9e8CoSWCV7g5KCQHRmqN-g@mail.gmail.com>
 <21432.58953.39322.640936@gargle.gargle.HOWL>
 <53B90EB1.8020305@candelatech.com>
 <21434.5649.615843.633424@gargle.gargle.HOWL>
Message-ID: <CACKGw+FN5R_FQmEFHG4HrazXzV-b+QiG=DnOrOmWBFvapFk0hw@mail.gmail.com>

On 7 July 2014 05:37, Sujith Manoharan <sujith at msujith.org> wrote:
> Ben Greear wrote:
>> Maybe the driver should make this 0 instead of 2 then?
>> hw.h:#define TARGET_10X_BMISS_OFFLOAD_MAX_VDEV        2
>> That would save resources in the firmware.
>
> Yes, it would. ath10k doesn't seem to be handling roam
> events too, so maybe that can be set to 0 - not sure if
> there are plans to properly enable and use roaming functionality
> that is already in the firmware.

That is correct. ath10k does not currently support hw/fw conn
monitoring. Things may change in future as we upgrade to support 10.2
firmware, but AFAIK there's no direct plan to use this offloads. And
regarding the initialization of BMISS/ROAM_OFFLOADs, yes looks like
this can be erased to save some firmware memory.

-Bartosz


From janusz.dziedzic at tieto.com  Mon Jul  7 01:30:28 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Mon, 7 Jul 2014 10:30:28 +0200
Subject: A-MSDU reception not working?
In-Reply-To: <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
Message-ID: <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>

On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>
> The earlier atheros chips would just give you the AMSDU frames as
> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
> net80211 and it'd ull it apart. But if the driver is doing it (or,
> well, the chip is doing it) then mac80211 needs to know not to drop
> those sub-frames.
>
> I wonder if you'll ever get notified before the complete A-MPDU has
> been received. That happens on previous chips. eg, you have an A-MPDU
> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
> half of one MPDU before you hit EOL, the next notification you process
> will be the next MSDU in the same MPDU - and then you'll hit the
> reordering hilarity again.
>
> So hm, i will face the same issue in FreeBSD at some point, so I'd
> likely do what you're thinking of doing - pass up a chain of mbufs
> representing the current MPDU and treat the whole lot as the frame(s)
> to care about. Honestly though, I'm kind of wondering whether I should
> mostly just do what the Atheros reference driver does and treat it as
> ethernet payload frames (ie, it's already de-encapsulated and the
> reordering is already done) and just tack on the wifi header bit via
> another of the DMA rings.
>
> Ugh, I really should sit down and write the FreeBSD version of this.
>
>
>
> -a
>
> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>
>
> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>> There are two issues in handling the dis-aggregated A-MSDU subframes
>> in ieee80211_sta_manage_reorder_buf:
>>
>> 1. The out-of-date check:
>>
>>         /* frame with out of date sequence number */
>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>                 dev_kfree_skb(skb);
>>                 goto out;
>>         }
>>
>> As all of the subframes carry the same sequence number, the first
>> subframe will be delivered and increment head_seq_num and then all
>> subsequent subframes will be discarded.
>>
>>
>> 2. The duplicates check a bit later in the routine:
>>
>>         /* check if we already stored this frame */
>>         if (tid_agg_rx->reorder_buf[index]) {
>>                 dev_kfree_skb(skb);
>>                 goto out;
>>         }
>>
>> If there is enough packet loss that packets are queued in the reorder
>> buffer and not immediately released, then only the first subframe will
>> be stored. Subsequent subframes will be discarded as duplicates.
>>
>>
>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>> the reordering buffer changes, and dropped to about 8 Mbps with the
>> reorder buffer. Hacking around the out-of-date sequence number check
>> to allow all subframes to egress restores it to 170 Mbps.
>>
>> In the area where I'm testing there isn't enough 5 GHz noise to make
>> the duplicates-check issue happen very often. By adding a printk I can
>> see that it does happen, but it doesn't impact the throughput and I
>> can't report the impact of fixing it.
>>
>> ----
>>
>> I do wonder if both of these are symptoms of dis-aggregating the
>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>> Trying to make the ath10k code send up all of the subframes as a chain
>> of skbs didn't immediately work, but I do wonder if that would better
>> match the mac80211 expectations.
>>
>>
>>
>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>> Yes, after some more testing it does look like an unfortunate
>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>> subframes all carry the same sequence number. The first subframe is
>>> released from the reorder buffer and increments the head_seq_num.
>>> Subsequent subframes are all discarded as being out of date.
>>>
>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>> head=0xb06
>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>> head=0xb0b
>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>> head=0xb10
>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>> head=0xb15
>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>> head=0xb1a
>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>> head=0xb1f
>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>> head=0xb24
>>>
>>>
>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>
>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>> frame makes it through.
>>>>>
>>>>> This became more noticeable after the reordering fixes in
>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>
>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>> never going to fully understand, its stuck in a region of the
>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>> A-MSDU.
>>>>
>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>
>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>> copying/allocation overhead each subframe is reported as a singly
>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>
Denton could you try attached patch: report amsdu in one big frame.
If help, we can add amsdu skb list support to mac80211/cfg80211 - to
improve performance and reduce memcpy, while currently we have skb
frames, put them in one big skb and next cfg80211 split them again
into msdus and report to stack.

BR
Janusz
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-ath10k-amsdu-rx-buid-one-big-frame.patch
Type: text/x-diff
Size: 4209 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/ath10k/attachments/20140707/5379efce/attachment.bin>

From avalentin at marcant.net  Mon Jul  7 07:51:45 2014
From: avalentin at marcant.net (=?UTF-8?B?QW5kcsOpIFZhbGVudGlu?=)
Date: Mon, 07 Jul 2014 16:51:45 +0200
Subject: ath10k OTP loading issues
In-Reply-To: <87egy4p2ae.fsf@kamboji.qca.qualcomm.com>
References: <53AD2EEE.4040704@marcant.net>
 <53AD4F17.6070604@marcant.net>	<87pphop499.fsf@kamboji.qca.qualcomm.com>	<53B3C3FF.1060207@marcant.net>
 <87egy4p2ae.fsf@kamboji.qca.qualcomm.com>
Message-ID: <53BAB401.3080406@marcant.net>

Hi!

Thanks for your hint. I now found at least the correct board.bin. Also I disabled the OTP check because it always throws an error.

By the way, can I overwrite the MAC address? I changed it in board.bin to the device MAC, but it did not work. Also if I set it
with ifconfig, it is only temorarily. Hostapd doesn't use it at all, it somehow reads the MAC from the device. Do you have an idea?

Andr?

On 02.07.2014 10:56, Kalle Valo wrote:
>>>> have some kind of magic so I can identify it?
>>>
>>> MAC addresses are good one to check. Basically it should be similar data
>>> as in board.bin.
>>
>> Of course I already tried this. But no luck.
> 
> How exactly did you search for it? Are you sure you used the correct MAC
> address?
> 
>> Do you have another idea. Or is the MAC somehow encrypted ?
> 
> Nothing special, the MAC address should should be within the first 20
> bytes. For example, here's 00:03:07:12:34:56:
> 
> $ od -t x1 board.bin  | head -1
> 0000000 44 08 df 30 02 04 00 03 07 12 34 56 00 00 6a 00
> 
> But of course I might be missing something. Or the calibration data is
> somehow encrypted on the flash.
> 


From helmut.schaa at googlemail.com  Mon Jul  7 08:40:32 2014
From: helmut.schaa at googlemail.com (Helmut Schaa)
Date: Mon, 7 Jul 2014 17:40:32 +0200
Subject: ath10k OTP loading issues
In-Reply-To: <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
References: <53AD2EEE.4040704@marcant.net>
 <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>

Hi,

On Wed, Jul 2, 2014 at 10:10 AM, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Andr? Valentin <avalentin at marcant.net> writes:
>
>> I got problems initializing my ath10k PCI card in my Zyxel NBG 6716.
>> It worked until some weeks, now, the driver does not load. I debugged
>> a bit and this is what I got:
>>
>> Fri Jun 27 08:03:42 2014 kern.info kernel: [62908.290000] ath10k_pci 0000:01:00.0: BAR 0: assigned [mem 0x12000000-0x121fffff 64bit]
>> Fri Jun 27 08:03:43 2014 kern.info kernel: [62908.610000] ath10k: pci irq legacy irq_mode 0 reset_mode 0
>> Fri Jun 27 08:03:43 2014 kern.err kernel: [62908.620000] ath10k: boot upload otp to 0x1234 len 6917
>> Fri Jun 27 08:03:43 2014 kern.err kernel: [62908.780000] ath10k: otp calibration failed: 2
>> Fri Jun 27 08:03:43 2014 kern.err kernel: [62908.790000] ath10k: failed to run otp: -22
>> Fri Jun 27 08:03:43 2014 kern.err kernel: [62908.790000] ath10k: could not init core (-22)
>> Fri Jun 27 08:03:43 2014 kern.err kernel: [62909.060000] ath10k: could not probe fw (-22)
>> Fri Jun 27 08:03:43 2014 kern.err kernel: [62909.060000] ath10k: failed to register driver core: -22
>> Fri Jun 27 08:03:43 2014 kern.warn kernel: [62909.060000] ath10k_pci: probe of 0000:01:00.0 failed with error -22
>>
>> If I remove OTP loading the card initializes fine, but I think I will
>> not have a good performance. So bad idea.
>
> All that was changed recently was that we now check the error code
> coming from otp.bin. So you have had this issue all along, it was just
> hidden before.

Same issue here.

Is it correct that board.bin should contain the calibration data of
the actual board?
I tried copying it from the APs ART partition but still no luck.

Any hint on how to debug further why the otp calibration fails?

Thanks,
Helmut


From denton.gentry at gmail.com  Mon Jul  7 12:26:03 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Mon, 7 Jul 2014 12:26:03 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
Message-ID: <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>

The initial results are not promising: a MacOS 802.11ac client gets
between 0-2 Mbps with this change, where it was getting about 8 Mbps
prior to this change and ~170 Mbps prior to the reordering fix. A pcap
from the receiving system shows a very large number of out of order
frames, likely due to TCP retransmission.

An 802.11n MacBook gets very good throughput, only the 802.11ac
MacBook shows the very poor result. I'm trying to figure out why.


One specific note (and probably not related to the throughput): I
believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
correctly?


On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
<janusz.dziedzic at tieto.com> wrote:
> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>
>> The earlier atheros chips would just give you the AMSDU frames as
>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>> well, the chip is doing it) then mac80211 needs to know not to drop
>> those sub-frames.
>>
>> I wonder if you'll ever get notified before the complete A-MPDU has
>> been received. That happens on previous chips. eg, you have an A-MPDU
>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>> half of one MPDU before you hit EOL, the next notification you process
>> will be the next MSDU in the same MPDU - and then you'll hit the
>> reordering hilarity again.
>>
>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>> likely do what you're thinking of doing - pass up a chain of mbufs
>> representing the current MPDU and treat the whole lot as the frame(s)
>> to care about. Honestly though, I'm kind of wondering whether I should
>> mostly just do what the Atheros reference driver does and treat it as
>> ethernet payload frames (ie, it's already de-encapsulated and the
>> reordering is already done) and just tack on the wifi header bit via
>> another of the DMA rings.
>>
>> Ugh, I really should sit down and write the FreeBSD version of this.
>>
>>
>>
>> -a
>>
>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>
>>
>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>> in ieee80211_sta_manage_reorder_buf:
>>>
>>> 1. The out-of-date check:
>>>
>>>         /* frame with out of date sequence number */
>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>                 dev_kfree_skb(skb);
>>>                 goto out;
>>>         }
>>>
>>> As all of the subframes carry the same sequence number, the first
>>> subframe will be delivered and increment head_seq_num and then all
>>> subsequent subframes will be discarded.
>>>
>>>
>>> 2. The duplicates check a bit later in the routine:
>>>
>>>         /* check if we already stored this frame */
>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>                 dev_kfree_skb(skb);
>>>                 goto out;
>>>         }
>>>
>>> If there is enough packet loss that packets are queued in the reorder
>>> buffer and not immediately released, then only the first subframe will
>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>
>>>
>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>> reorder buffer. Hacking around the out-of-date sequence number check
>>> to allow all subframes to egress restores it to 170 Mbps.
>>>
>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>> the duplicates-check issue happen very often. By adding a printk I can
>>> see that it does happen, but it doesn't impact the throughput and I
>>> can't report the impact of fixing it.
>>>
>>> ----
>>>
>>> I do wonder if both of these are symptoms of dis-aggregating the
>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>> Trying to make the ath10k code send up all of the subframes as a chain
>>> of skbs didn't immediately work, but I do wonder if that would better
>>> match the mac80211 expectations.
>>>
>>>
>>>
>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>> Yes, after some more testing it does look like an unfortunate
>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>> subframes all carry the same sequence number. The first subframe is
>>>> released from the reorder buffer and increments the head_seq_num.
>>>> Subsequent subframes are all discarded as being out of date.
>>>>
>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>> head=0xb06
>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>> head=0xb0b
>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>> head=0xb10
>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>> head=0xb15
>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>> head=0xb1a
>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>> head=0xb1f
>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>> head=0xb24
>>>>
>>>>
>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>
>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>> frame makes it through.
>>>>>>
>>>>>> This became more noticeable after the reordering fixes in
>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>
>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>> never going to fully understand, its stuck in a region of the
>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>> A-MSDU.
>>>>>
>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>
>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>
> Denton could you try attached patch: report amsdu in one big frame.
> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
> improve performance and reduce memcpy, while currently we have skb
> frames, put them in one big skb and next cfg80211 split them again
> into msdus and report to stack.
>
> BR
> Janusz


From adrian at freebsd.org  Mon Jul  7 12:41:32 2014
From: adrian at freebsd.org (Adrian Chadd)
Date: Mon, 7 Jul 2014 12:41:32 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
Message-ID: <CAJ-VmonvHSYzPHCOPBQKt-ycpdTVO8s0DoP=zRXMJRfE7zSoMQ@mail.gmail.com>

.. why not disable AMSDU reception for now? Until these things are fixed?



-a


On 7 July 2014 12:26, Denton Gentry <denton.gentry at gmail.com> wrote:
> The initial results are not promising: a MacOS 802.11ac client gets
> between 0-2 Mbps with this change, where it was getting about 8 Mbps
> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
> from the receiving system shows a very large number of out of order
> frames, likely due to TCP retransmission.
>
> An 802.11n MacBook gets very good throughput, only the 802.11ac
> MacBook shows the very poor result. I'm trying to figure out why.
>
>
> One specific note (and probably not related to the throughput): I
> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
> correctly?
>
>
> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
> <janusz.dziedzic at tieto.com> wrote:
>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>
>>> The earlier atheros chips would just give you the AMSDU frames as
>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>> those sub-frames.
>>>
>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>> half of one MPDU before you hit EOL, the next notification you process
>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>> reordering hilarity again.
>>>
>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>> representing the current MPDU and treat the whole lot as the frame(s)
>>> to care about. Honestly though, I'm kind of wondering whether I should
>>> mostly just do what the Atheros reference driver does and treat it as
>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>> reordering is already done) and just tack on the wifi header bit via
>>> another of the DMA rings.
>>>
>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>
>>>
>>>
>>> -a
>>>
>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>
>>>
>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>> in ieee80211_sta_manage_reorder_buf:
>>>>
>>>> 1. The out-of-date check:
>>>>
>>>>         /* frame with out of date sequence number */
>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>                 dev_kfree_skb(skb);
>>>>                 goto out;
>>>>         }
>>>>
>>>> As all of the subframes carry the same sequence number, the first
>>>> subframe will be delivered and increment head_seq_num and then all
>>>> subsequent subframes will be discarded.
>>>>
>>>>
>>>> 2. The duplicates check a bit later in the routine:
>>>>
>>>>         /* check if we already stored this frame */
>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>                 dev_kfree_skb(skb);
>>>>                 goto out;
>>>>         }
>>>>
>>>> If there is enough packet loss that packets are queued in the reorder
>>>> buffer and not immediately released, then only the first subframe will
>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>
>>>>
>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>
>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>> see that it does happen, but it doesn't impact the throughput and I
>>>> can't report the impact of fixing it.
>>>>
>>>> ----
>>>>
>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>> match the mac80211 expectations.
>>>>
>>>>
>>>>
>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>> Yes, after some more testing it does look like an unfortunate
>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>> subframes all carry the same sequence number. The first subframe is
>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>
>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>> head=0xb06
>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>> head=0xb0b
>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>> head=0xb10
>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>> head=0xb15
>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>> head=0xb1a
>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>> head=0xb1f
>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>> head=0xb24
>>>>>
>>>>>
>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>
>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>> frame makes it through.
>>>>>>>
>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>
>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>> A-MSDU.
>>>>>>
>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>
>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>
>> Denton could you try attached patch: report amsdu in one big frame.
>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>> improve performance and reduce memcpy, while currently we have skb
>> frames, put them in one big skb and next cfg80211 split them again
>> into msdus and report to stack.
>>
>> BR
>> Janusz
>
> _______________________________________________
> ath10k mailing list
> ath10k at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/ath10k


From denton.gentry at gmail.com  Mon Jul  7 12:53:23 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Mon, 7 Jul 2014 12:53:23 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CAJ-VmonvHSYzPHCOPBQKt-ycpdTVO8s0DoP=zRXMJRfE7zSoMQ@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CAJ-VmonvHSYzPHCOPBQKt-ycpdTVO8s0DoP=zRXMJRfE7zSoMQ@mail.gmail.com>
Message-ID: <CABnBrYXzrTvH2xNYAR=+2RXO9t7rm3zKkL8rnZj9jz+isYX7Pw@mail.gmail.com>

I don't know of a way to tell the STA to not use A-MSDU; is there one?
A-MSDU reception is mandatory in the specifications, it didn't look
like there was a way to communicate that it isn't allowed.

We can disable our own sending of A-MSDUs, but that isn't the issue here.

With 802.11ac the minimum MPDU size appears to be 3895 bytes, which is
big enough to hold two 1500 byte subframes. If there were a way to
force it the MPDU size smaller that could effectively prevent the STA
from using A-MSDU, but I don't see a way to do that either.



On Mon, Jul 7, 2014 at 12:41 PM, Adrian Chadd <adrian at freebsd.org> wrote:
> .. why not disable AMSDU reception for now? Until these things are fixed?
>
>
>
> -a
>
>
> On 7 July 2014 12:26, Denton Gentry <denton.gentry at gmail.com> wrote:
>> The initial results are not promising: a MacOS 802.11ac client gets
>> between 0-2 Mbps with this change, where it was getting about 8 Mbps
>> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
>> from the receiving system shows a very large number of out of order
>> frames, likely due to TCP retransmission.
>>
>> An 802.11n MacBook gets very good throughput, only the 802.11ac
>> MacBook shows the very poor result. I'm trying to figure out why.
>>
>>
>> One specific note (and probably not related to the throughput): I
>> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
>> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
>> correctly?
>>
>>
>> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
>> <janusz.dziedzic at tieto.com> wrote:
>>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>>
>>>> The earlier atheros chips would just give you the AMSDU frames as
>>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>>> those sub-frames.
>>>>
>>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>>> half of one MPDU before you hit EOL, the next notification you process
>>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>>> reordering hilarity again.
>>>>
>>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>>> representing the current MPDU and treat the whole lot as the frame(s)
>>>> to care about. Honestly though, I'm kind of wondering whether I should
>>>> mostly just do what the Atheros reference driver does and treat it as
>>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>>> reordering is already done) and just tack on the wifi header bit via
>>>> another of the DMA rings.
>>>>
>>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>>
>>>>
>>>>
>>>> -a
>>>>
>>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>>
>>>>
>>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>>> in ieee80211_sta_manage_reorder_buf:
>>>>>
>>>>> 1. The out-of-date check:
>>>>>
>>>>>         /* frame with out of date sequence number */
>>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>>                 dev_kfree_skb(skb);
>>>>>                 goto out;
>>>>>         }
>>>>>
>>>>> As all of the subframes carry the same sequence number, the first
>>>>> subframe will be delivered and increment head_seq_num and then all
>>>>> subsequent subframes will be discarded.
>>>>>
>>>>>
>>>>> 2. The duplicates check a bit later in the routine:
>>>>>
>>>>>         /* check if we already stored this frame */
>>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>>                 dev_kfree_skb(skb);
>>>>>                 goto out;
>>>>>         }
>>>>>
>>>>> If there is enough packet loss that packets are queued in the reorder
>>>>> buffer and not immediately released, then only the first subframe will
>>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>>
>>>>>
>>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>>
>>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>>> see that it does happen, but it doesn't impact the throughput and I
>>>>> can't report the impact of fixing it.
>>>>>
>>>>> ----
>>>>>
>>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>>> match the mac80211 expectations.
>>>>>
>>>>>
>>>>>
>>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>> Yes, after some more testing it does look like an unfortunate
>>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>>> subframes all carry the same sequence number. The first subframe is
>>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>>
>>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>>> head=0xb06
>>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>>> head=0xb0b
>>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>>> head=0xb10
>>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>>> head=0xb15
>>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>>> head=0xb1a
>>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>>> head=0xb1f
>>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>>> head=0xb24
>>>>>>
>>>>>>
>>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>>
>>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>>> frame makes it through.
>>>>>>>>
>>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>>
>>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>>> A-MSDU.
>>>>>>>
>>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>>
>>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>>
>>> Denton could you try attached patch: report amsdu in one big frame.
>>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>>> improve performance and reduce memcpy, while currently we have skb
>>> frames, put them in one big skb and next cfg80211 split them again
>>> into msdus and report to stack.
>>>
>>> BR
>>> Janusz
>>
>> _______________________________________________
>> ath10k mailing list
>> ath10k at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/ath10k


From cfliu.tw at gmail.com  Mon Jul  7 22:58:22 2014
From: cfliu.tw at gmail.com (Liu CF/TW)
Date: Mon, 7 Jul 2014 22:58:22 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CABnBrYXzrTvH2xNYAR=+2RXO9t7rm3zKkL8rnZj9jz+isYX7Pw@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CAJ-VmonvHSYzPHCOPBQKt-ycpdTVO8s0DoP=zRXMJRfE7zSoMQ@mail.gmail.com>
 <CABnBrYXzrTvH2xNYAR=+2RXO9t7rm3zKkL8rnZj9jz+isYX7Pw@mail.gmail.com>
Message-ID: <CAG5N3qFkht-uf-+BUCHGx3rt1vPOonGry3JFpjmYdhd3B7SEVw@mail.gmail.com>

I wonder is it the firmware or mac80211 at AP side that handles ADDBA
requests from MacBook in this case?

- If it is mac80211, then we can try disabling AMSDU-in-AMPDU. in
agg_rx.c by setting the 'policy' argument to 0:

ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
dialog_token, status, 0, buf_size, timeout);

- if it is inside the firmware, then in ath10k WMI, it seems FW does
support the following BA related commands (but alas there are no
details how these commands could be used ie. no C structure defined to
know how to fill the command)

If ADDBA req is handled by FW when AP is the recipient,  I guess
WMI_10X_ADDBA_SET_RESP_CMDID could be used to disable AMSDU-in-AMPDU
during BA negotiation:

/* commands to directly control ba negotiation directly from host. */
WMI_10X_ADDBA_CLEAR_RESP_CMDID,
WMI_10X_ADDBA_SEND_CMDID,
WMI_10X_ADDBA_STATUS_CMDID,
WMI_10X_DELBA_SEND_CMDID,
WMI_10X_ADDBA_SET_RESP_CMDID,
WMI_10X_SEND_SINGLEAMSDU_CMDID,

In general, I think AMSDU-in-AMPDU shouldn't be hard coded as always
enabled in mac80211 but should be a policy. Iterating through AMSDU
subframes is not just slow on embedded CPUs, but the nature they all
share the same PN and same CRC makes it inferior to AMPDU, where MPDUs
aggregated using AMPDU could independently acknowledged, encrypted &
integrity-checked. (Although it is indeed a valid workaround to sender
larger PPDU  (4Kx64=256K) since BA bitmap size hasn't been increased
since 11n)

Does anyone know more details about how WMI_10X_ADDBA_SET_RESP_CMDID
could be used?

Thanks,
cfliu

2014-07-07 12:53 GMT-07:00 Denton Gentry <denton.gentry at gmail.com>:
> I don't know of a way to tell the STA to not use A-MSDU; is there one?
> A-MSDU reception is mandatory in the specifications, it didn't look
> like there was a way to communicate that it isn't allowed.
>
> We can disable our own sending of A-MSDUs, but that isn't the issue here.
>
> With 802.11ac the minimum MPDU size appears to be 3895 bytes, which is
> big enough to hold two 1500 byte subframes. If there were a way to
> force it the MPDU size smaller that could effectively prevent the STA
> from using A-MSDU, but I don't see a way to do that either.
>
>
>
> On Mon, Jul 7, 2014 at 12:41 PM, Adrian Chadd <adrian at freebsd.org> wrote:
>> .. why not disable AMSDU reception for now? Until these things are fixed?
>>
>>
>>
>> -a
>>
>>
>> On 7 July 2014 12:26, Denton Gentry <denton.gentry at gmail.com> wrote:
>>> The initial results are not promising: a MacOS 802.11ac client gets
>>> between 0-2 Mbps with this change, where it was getting about 8 Mbps
>>> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
>>> from the receiving system shows a very large number of out of order
>>> frames, likely due to TCP retransmission.
>>>
>>> An 802.11n MacBook gets very good throughput, only the 802.11ac
>>> MacBook shows the very poor result. I'm trying to figure out why.
>>>
>>>
>>> One specific note (and probably not related to the throughput): I
>>> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
>>> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
>>> correctly?
>>>
>>>
>>> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
>>> <janusz.dziedzic at tieto.com> wrote:
>>>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>>>
>>>>> The earlier atheros chips would just give you the AMSDU frames as
>>>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>>>> those sub-frames.
>>>>>
>>>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>>>> half of one MPDU before you hit EOL, the next notification you process
>>>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>>>> reordering hilarity again.
>>>>>
>>>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>>>> representing the current MPDU and treat the whole lot as the frame(s)
>>>>> to care about. Honestly though, I'm kind of wondering whether I should
>>>>> mostly just do what the Atheros reference driver does and treat it as
>>>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>>>> reordering is already done) and just tack on the wifi header bit via
>>>>> another of the DMA rings.
>>>>>
>>>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>>>
>>>>>
>>>>>
>>>>> -a
>>>>>
>>>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>>>
>>>>>
>>>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>>>> in ieee80211_sta_manage_reorder_buf:
>>>>>>
>>>>>> 1. The out-of-date check:
>>>>>>
>>>>>>         /* frame with out of date sequence number */
>>>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>>>                 dev_kfree_skb(skb);
>>>>>>                 goto out;
>>>>>>         }
>>>>>>
>>>>>> As all of the subframes carry the same sequence number, the first
>>>>>> subframe will be delivered and increment head_seq_num and then all
>>>>>> subsequent subframes will be discarded.
>>>>>>
>>>>>>
>>>>>> 2. The duplicates check a bit later in the routine:
>>>>>>
>>>>>>         /* check if we already stored this frame */
>>>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>>>                 dev_kfree_skb(skb);
>>>>>>                 goto out;
>>>>>>         }
>>>>>>
>>>>>> If there is enough packet loss that packets are queued in the reorder
>>>>>> buffer and not immediately released, then only the first subframe will
>>>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>>>
>>>>>>
>>>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>>>
>>>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>>>> see that it does happen, but it doesn't impact the throughput and I
>>>>>> can't report the impact of fixing it.
>>>>>>
>>>>>> ----
>>>>>>
>>>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>>>> match the mac80211 expectations.
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>> Yes, after some more testing it does look like an unfortunate
>>>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>>>> subframes all carry the same sequence number. The first subframe is
>>>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>>>
>>>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>>>> head=0xb06
>>>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>>>> head=0xb0b
>>>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>>>> head=0xb10
>>>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>>>> head=0xb15
>>>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>>>> head=0xb1a
>>>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>>>> head=0xb1f
>>>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>>>> head=0xb24
>>>>>>>
>>>>>>>
>>>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>>>
>>>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>>>> frame makes it through.
>>>>>>>>>
>>>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>>>
>>>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>>>> A-MSDU.
>>>>>>>>
>>>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>>>
>>>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>>>
>>>> Denton could you try attached patch: report amsdu in one big frame.
>>>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>>>> improve performance and reduce memcpy, while currently we have skb
>>>> frames, put them in one big skb and next cfg80211 split them again
>>>> into msdus and report to stack.
>>>>
>>>> BR
>>>> Janusz
>>>
>>> _______________________________________________
>>> ath10k mailing list
>>> ath10k at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/ath10k
>
> _______________________________________________
> ath10k mailing list
> ath10k at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/ath10k


From janusz.dziedzic at tieto.com  Mon Jul  7 23:43:09 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Tue, 8 Jul 2014 08:43:09 +0200
Subject: A-MSDU reception not working?
In-Reply-To: <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
Message-ID: <CALhHN=rBO+pQb7fZRcHd70jYTi2gsGtNhrsnOxmbEUiGtzFbaw@mail.gmail.com>

On 7 July 2014 21:26, Denton Gentry <denton.gentry at gmail.com> wrote:
> The initial results are not promising: a MacOS 802.11ac client gets
> between 0-2 Mbps with this change, where it was getting about 8 Mbps
> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
> from the receiving system shows a very large number of out of order
> frames, likely due to TCP retransmission.
>
Thanks for test. I used ath10k as a STA with forced AMSDU (almost all
the time 3 A-MSDU packets used when TCP STA --> AP).
But seems still some issues with your card. I will check how fast we
can get MacOS 80211ac.
Could you share airlogs (best using additional sniffer)?

BTW.
We can try to disable AMSDU reordering in mac80211 for drivers that
prefer to report AMSDU as a separate frames (RX_FLAG_AMSDU_MORE),
while this case is not handled correctly (few packets with the same
serial number) in mac80211. So, before we will add correct
implementation we can disable this I think. Could you try this +
Michal`s reordering patch (without big frame patch):

index 394e201..914e22c 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -924,6 +924,10 @@ static void ieee80211_rx_reorder_ampdu(struct
ieee80211_rx_data *rx,
        if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
                goto dont_reorder;

+       /* not impelemented correctly when driver report separete A-MSDUs */
+        if (status->flag & RX_FLAG_AMSDU_MORE)
+               goto dont_reorder;
+

This disabling patch I think is still not complete while last A-MSDU
frame don't have this MORE flag, but anyway we can try. I will check
how to disable this correctly.


> An 802.11n MacBook gets very good throughput, only the 802.11ac
> MacBook shows the very poor result. I'm trying to figure out why.
>
This is also with/without reordering/big_frame patches? Or 80211n
don't use amsdu/reordering?

>
> One specific note (and probably not related to the throughput): I
> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
> correctly?
Yes you right this is tasklet and should be ATOMIC.

>
>
> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
> <janusz.dziedzic at tieto.com> wrote:
>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>
>>> The earlier atheros chips would just give you the AMSDU frames as
>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>> those sub-frames.
>>>
>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>> half of one MPDU before you hit EOL, the next notification you process
>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>> reordering hilarity again.
>>>
>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>> representing the current MPDU and treat the whole lot as the frame(s)
>>> to care about. Honestly though, I'm kind of wondering whether I should
>>> mostly just do what the Atheros reference driver does and treat it as
>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>> reordering is already done) and just tack on the wifi header bit via
>>> another of the DMA rings.
>>>
>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>
>>>
>>>
>>> -a
>>>
>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>
>>>
>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>> in ieee80211_sta_manage_reorder_buf:
>>>>
>>>> 1. The out-of-date check:
>>>>
>>>>         /* frame with out of date sequence number */
>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>                 dev_kfree_skb(skb);
>>>>                 goto out;
>>>>         }
>>>>
>>>> As all of the subframes carry the same sequence number, the first
>>>> subframe will be delivered and increment head_seq_num and then all
>>>> subsequent subframes will be discarded.
>>>>
>>>>
>>>> 2. The duplicates check a bit later in the routine:
>>>>
>>>>         /* check if we already stored this frame */
>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>                 dev_kfree_skb(skb);
>>>>                 goto out;
>>>>         }
>>>>
>>>> If there is enough packet loss that packets are queued in the reorder
>>>> buffer and not immediately released, then only the first subframe will
>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>
>>>>
>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>
>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>> see that it does happen, but it doesn't impact the throughput and I
>>>> can't report the impact of fixing it.
>>>>
>>>> ----
>>>>
>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>> match the mac80211 expectations.
>>>>
>>>>
>>>>
>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>> Yes, after some more testing it does look like an unfortunate
>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>> subframes all carry the same sequence number. The first subframe is
>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>
>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>> head=0xb06
>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>> head=0xb0b
>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>> head=0xb10
>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>> head=0xb15
>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>> head=0xb1a
>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>> head=0xb1f
>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>> head=0xb24
>>>>>
>>>>>
>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>
>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>> frame makes it through.
>>>>>>>
>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>
>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>> A-MSDU.
>>>>>>
>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>
>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>
>> Denton could you try attached patch: report amsdu in one big frame.
>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>> improve performance and reduce memcpy, while currently we have skb
>> frames, put them in one big skb and next cfg80211 split them again
>> into msdus and report to stack.
>>
>> BR
>> Janusz


From denton.gentry at gmail.com  Mon Jul  7 23:43:25 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Mon, 7 Jul 2014 23:43:25 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
Message-ID: <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>

I think I know what is happening now, though I've no idea why. The
throughput is low because we have many TCP retransmissions. We have
retransmissions because the TCP checksum is wrong on a number of
frames, and I do find data corruption in the payload so the checksum
definitely should be wrong. All of the corrupted frames were
originally one of the subframes in an A-MSDU packet.

An example follows at the end of this message, as dissected by
Wireshark. iperf sends a very regular data pattern of "0123456789..."
over and over. Note how in subframe #2 offset 0x1e0 the bytes "32 33
34" have been replaced by "72 36 35"

01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567

I added printks at the bottom of ath10k_htt_rx_amsdu immediately
before the call to ath10k_process_rx. I found this same packet, and we
see the "72 36 35" corruption in the printk. So I think it happened in
ath10k_process_rx or before, not anything weird after passing it up to
mac80211.

[  101.863712] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
[  101.863727] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
[  101.863742] ath10k: 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32
[  101.863757] ath10k: 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37 38
[  101.863773] ath10k: 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34
[  101.863788] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
[  101.863803] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36


I've found a number of examples of similar corruption, always with
between one and four bytes replaced.

35363738 -> e52c6e07
3435 -> b43f
3839 -> c238
31 -> 7f
3435 -> 7436
30 -> 50
3233 -> bc37


The packet described above, dissected by Wireshark:

No.     Time        Source                Destination
Protocol Length Info
   2235 18.953349   192.168.144.79        192.168.144.13        TCP
  3112   52697 > 5001 [ACK] Seq=1391553 Ack=1 Win=131760 [TCP CHECKSUM
INCORRECT] Len=1448 TSval=1298580657 TSecr=4294947481

Frame 2235: 3112 bytes on wire (24896 bits), 3112 bytes captured (24896 bits)
    Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
    Arrival Time: Jul  7, 2014 23:03:37.763365000 PDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1404799417.763365000 seconds
    [Time delta from previous captured frame: 0.003476000 seconds]
    [Time delta from previous displayed frame: 0.515641000 seconds]
    [Time since reference or first frame: 18.953349000 seconds]
    Frame Number: 2235
    Frame Length: 3112 bytes (24896 bits)
    Capture Length: 3112 bytes (24896 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
    [Coloring Rule Name: TCP]
    [Coloring Rule String: tcp]
Radiotap Header v0, Length 38
    Header revision: 0
    Header pad: 0
    Header length: 38
    Present flags
        .... .... .... .... .... .... .... ...1 = TSFT: True
        .... .... .... .... .... .... .... ..1. = Flags: True
        .... .... .... .... .... .... .... .0.. = Rate: False
        .... .... .... .... .... .... .... 1... = Channel: True
        .... .... .... .... .... .... ...0 .... = FHSS: False
        .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
        .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
        .... .... .... .... .... .... 0... .... = Lock Quality: False
        .... .... .... .... .... ...0 .... .... = TX Attenuation: False
        .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
        .... .... .... .... .... .0.. .... .... = dBm TX Power: False
        .... .... .... .... .... 1... .... .... = Antenna: True
        .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
        .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
        .... .... .... .... .1.. .... .... .... = RX flags: True
        .... .... .... .0.. .... .... .... .... = Channel+: False
        .... .... .... 0... .... .... .... .... = HT information: False
        .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
        .... .... ..1. .... .... .... .... .... = VHT information: True
        ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
        ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
        .0.. .... .... .... .... .... .... .... = Vendor NS next: False
        0... .... .... .... .... .... .... .... = Ext: False
    MAC timestamp: 78051063
    Flags: 0x00
        .... ...0 = CFP: False
        .... ..0. = Preamble: Long
        .... .0.. = WEP: False
        .... 0... = Fragmentation: False
        ...0 .... = FCS at end: False
        ..0. .... = Data Pad: False
        .0.. .... = Bad FCS: False
        0... .... = Short GI: False
    Channel frequency: 5745 [A 149]
    Channel type: 802.11a (0x0140)
        .... .... ...0 .... = Turbo: False
        .... .... ..0. .... = Complementary Code Keying (CCK): False
        .... .... .1.. .... = Orthogonal Frequency-Division
Multiplexing (OFDM): True
        .... .... 0... .... = 2 GHz spectrum: False
        .... ...1 .... .... = 5 GHz spectrum: True
        .... ..0. .... .... = Passive: False
        .... .0.. .... .... = Dynamic CCK-OFDM: False
        .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
        ...0 .... .... .... = GSM (900MHz): False
        ..0. .... .... .... = Static Turbo: False
        .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
        0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
    SSI Signal: -53 dBm
    Antenna: 0
    RX flags: 0x0000
        .... .... .... .... .... ..0. = Bad PLCP: False
    VHT information
        Known VHT information: 0x44
            .... .... .... ...0 = STBC: False
            .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
            .... .... .... .1.. = Guard interval: True
            .... .... .... 0... = SGI Nsym disambiguation: False
            .... .... ...0 .... = LDPC extra OFDM symbol: False
            .... .... ..0. .... = Beamformed: False
            .... .... .1.. .... = Bandwidth: True
            .... .... 0... .... = Group ID: False
            .... ...0 .... .... = Partial AID: False
        .... .0.. = Guard interval: long (0)
        Bandwidth: 80 MHz (4)
        User 0: MCS 8
            1000 .... = MCS index 0: 8 (256-QAM 3/4)
            .... 0010 = Spatial streams 0: 2
            Space-time streams 0: 2
            Coding 0: BCC (0)
            [Data Rate: 702.0 Mb/s]
IEEE 802.11 QoS Data, Flags: .......T
    Type/Subtype: QoS Data (0x28)
    Frame Control Field: 0x8801
        .... ..00 = Version: 0
        .... 10.. = Type: Data frame (2)
        1000 .... = Subtype: 8
        Flags: 0x01
            .... ..01 = DS status: Frame from STA to DS via an AP (To
DS: 1 From DS: 0) (0x01)
            .... .0.. = More Fragments: This is the last fragment
            .... 0... = Retry: Frame is not being retransmitted
            ...0 .... = PWR MGT: STA will stay up
            ..0. .... = More Data: No data buffered
            .0.. .... = Protected flag: Data is not protected
            0... .... = Order flag: Not strictly ordered
    .000 0000 0011 0000 = Duration: 48 microseconds
    Receiver address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
    BSS Id: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
    Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
    Source address: Apple_67:24:54 (84:38:35:67:24:54)
    Destination address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
    Fragment number: 0
    Sequence number: 1021
    Qos Control: 0x0080
        .... .... .... 0000 = TID: 0
        [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
        .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control
field are TXOP Duration Requested
        .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
        .... .... 1... .... = Payload Type: A-MSDU
        0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
IEEE 802.11 Aggregate MSDU
    A-MSDU Subframe #1
        Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
        Source address: Apple_67:24:54 (84:38:35:67:24:54)
        A-MSDU Length: 1510
        Logical-Link Control
            DSAP: SNAP (0xaa)
            IG Bit: Individual
            SSAP: SNAP (0xaa)
            CR Bit: Command
            Control field: U, func=UI (0x03)
                000. 00.. = Command: Unnumbered Information (0x00)
                .... ..11 = Frame type: Unnumbered frame (0x03)
            Organization Code: Encapsulated Ethernet (0x000000)
            Type: IP (0x0800)
        Internet Protocol Version 4, Src: 192.168.144.79
(192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
            Version: 4
            Header length: 20 bytes
            Differentiated Services Field: 0x00 (DSCP 0x00: Default;
ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
                0000 00.. = Differentiated Services Codepoint: Default (0x00)
                .... ..00 = Explicit Congestion Notification: Not-ECT
(Not ECN-Capable Transport) (0x00)
            Total Length: 1500
            Identification: 0xc622 (50722)
            Flags: 0x00
                0... .... = Reserved bit: Not set
                .0.. .... = Don't fragment: Not set
                ..0. .... = More fragments: Not set
            Fragment offset: 0
            Time to live: 64
            Protocol: TCP (6)
            Header checksum: 0x0d4c [correct]
                [Good: True]
                [Bad: False]
            Source: 192.168.144.79 (192.168.144.79)
            Destination: 192.168.144.13 (192.168.144.13)
            [Source GeoIP: Unknown]
            [Destination GeoIP: Unknown]
        Transmission Control Protocol, Src Port: 52697 (52697), Dst
Port: 5001 (5001), Seq: 1390105, Ack: 1, Len: 1448
            Source port: 52697 (52697)
            Destination port: 5001 (5001)
            [Stream index: 0]
            Sequence number: 1390105    (relative sequence number)
            [Next sequence number: 1391553    (relative sequence number)]
            Acknowledgment number: 1    (relative ack number)
            Header length: 32 bytes
            Flags: 0x010 (ACK)
                000. .... .... = Reserved: Not set
                ...0 .... .... = Nonce: Not set
                .... 0... .... = Congestion Window Reduced (CWR): Not set
                .... .0.. .... = ECN-Echo: Not set
                .... ..0. .... = Urgent: Not set
                .... ...1 .... = Acknowledgment: Set
                .... .... 0... = Push: Not set
                .... .... .0.. = Reset: Not set
                .... .... ..0. = Syn: Not set
                .... .... ...0 = Fin: Not set
            Window size value: 8235
            [Calculated window size: 131760]
            [Window size scaling factor: 16]
            Checksum: 0xa1c0 [correct]
                [Good Checksum: True]
                [Bad Checksum: False]
            Options: (12 bytes), No-Operation (NOP), No-Operation
(NOP), Timestamps
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                Timestamps: TSval 1298580657, TSecr 4294947481
                    Kind: Timestamp (8)
                    Length: 10
                    Timestamp value: 1298580657
                    Timestamp echo reply: 4294947481
        Data (1448 bytes)

0000  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0010  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0020  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0030  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0040  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0050  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0060  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0070  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0080  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0090  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
00c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0100  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0110  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0120  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0130  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0140  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0150  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0160  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0170  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0180  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0190  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
01a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
01c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
01d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
01f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0200  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0210  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0220  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0230  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0240  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0250  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0260  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0270  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0280  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0290  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
02c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0300  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0310  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0320  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0330  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0340  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0350  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0360  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0370  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0380  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0390  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
03c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
03d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0400  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0410  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0420  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0430  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0440  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0450  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0460  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0470  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0480  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0490  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
04c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0500  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0510  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0520  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0530  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0540  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0550  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0560  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0570  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0580  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0590  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
05a0  34 35 36 37 38 39 30 31                           45678901
            Data: 343536373839303132333435363738393031323334353637...
            [Length: 1448]
    A-MSDU Subframe #2
        Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
        Source address: Apple_67:24:54 (84:38:35:67:24:54)
        A-MSDU Length: 1510
        Logical-Link Control
            DSAP: SNAP (0xaa)
            IG Bit: Individual
            SSAP: SNAP (0xaa)
            CR Bit: Command
            Control field: U, func=UI (0x03)
                000. 00.. = Command: Unnumbered Information (0x00)
                .... ..11 = Frame type: Unnumbered frame (0x03)
            Organization Code: Encapsulated Ethernet (0x000000)
            Type: IP (0x0800)
        Internet Protocol Version 4, Src: 192.168.144.79
(192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
            Version: 4
            Header length: 20 bytes
            Differentiated Services Field: 0x00 (DSCP 0x00: Default;
ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
                0000 00.. = Differentiated Services Codepoint: Default (0x00)
                .... ..00 = Explicit Congestion Notification: Not-ECT
(Not ECN-Capable Transport) (0x00)
            Total Length: 1500
            Identification: 0xda09 (55817)
            Flags: 0x00
                0... .... = Reserved bit: Not set
                .0.. .... = Don't fragment: Not set
                ..0. .... = More fragments: Not set
            Fragment offset: 0
            Time to live: 64
            Protocol: TCP (6)
            Header checksum: 0xf964 [correct]
                [Good: True]
                [Bad: False]
            Source: 192.168.144.79 (192.168.144.79)
            Destination: 192.168.144.13 (192.168.144.13)
            [Source GeoIP: Unknown]
            [Destination GeoIP: Unknown]
        Transmission Control Protocol, Src Port: 52697 (52697), Dst
Port: 5001 (5001), Seq: 1391553, Ack: 1, Len: 1448
            Source port: 52697 (52697)
            Destination port: 5001 (5001)
            [Stream index: 0]
            Sequence number: 1391553    (relative sequence number)
            [Next sequence number: 1393001    (relative sequence number)]
            Acknowledgment number: 1    (relative ack number)
            Header length: 32 bytes
            Flags: 0x010 (ACK)
                000. .... .... = Reserved: Not set
                ...0 .... .... = Nonce: Not set
                .... 0... .... = Congestion Window Reduced (CWR): Not set
                .... .0.. .... = ECN-Echo: Not set
                .... ..0. .... = Urgent: Not set
                .... ...1 .... = Acknowledgment: Set
                .... .... 0... = Push: Not set
                .... .... .0.. = Reset: Not set
                .... .... ..0. = Syn: Not set
                .... .... ...0 = Fin: Not set
            Window size value: 8235
            [Calculated window size: 131760]
            [Window size scaling factor: 16]
            Checksum: 0x9a16 [incorrect, should be 0x5913 (maybe
caused by "TCP checksum offload"?)]
                [Good Checksum: False]
                [Bad Checksum: True]
                    [Expert Info (Error/Checksum): Bad checksum]
                        [Message: Bad checksum]
                        [Severity level: Error]
                        [Group: Checksum]
            Options: (12 bytes), No-Operation (NOP), No-Operation
(NOP), Timestamps
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                Timestamps: TSval 1298580657, TSecr 4294947481
                    Kind: Timestamp (8)
                    Length: 10
                    Timestamp value: 1298580657
                    Timestamp echo reply: 4294947481
        Data (1448 bytes)

0000  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0010  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0020  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0030  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0040  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0050  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0060  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0070  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0080  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0090  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
00e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0100  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0110  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0120  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0130  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0140  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0150  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0160  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0170  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0180  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0190  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
01a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
01c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
01f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0200  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0210  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0220  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0230  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0240  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0250  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0260  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0270  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0280  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0290  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
02e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0300  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0310  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0320  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0330  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0340  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0350  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0360  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0370  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0380  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0390  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
03a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
03e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
03f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0400  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0410  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0420  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0430  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0440  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0450  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0460  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0470  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0480  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0490  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
04e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0500  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0510  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0520  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0530  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0540  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0550  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0560  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0570  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0580  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0590  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
05a0  32 33 34 35 36 37 38 39                           23456789
            Data: 323334353637383930313233343536373839303132333435...
            [Length: 1448]

On Mon, Jul 7, 2014 at 12:26 PM, Denton Gentry <denton.gentry at gmail.com> wrote:
> The initial results are not promising: a MacOS 802.11ac client gets
> between 0-2 Mbps with this change, where it was getting about 8 Mbps
> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
> from the receiving system shows a very large number of out of order
> frames, likely due to TCP retransmission.
>
> An 802.11n MacBook gets very good throughput, only the 802.11ac
> MacBook shows the very poor result. I'm trying to figure out why.
>
>
> One specific note (and probably not related to the throughput): I
> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
> correctly?
>
>
> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
> <janusz.dziedzic at tieto.com> wrote:
>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>
>>> The earlier atheros chips would just give you the AMSDU frames as
>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>> those sub-frames.
>>>
>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>> half of one MPDU before you hit EOL, the next notification you process
>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>> reordering hilarity again.
>>>
>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>> representing the current MPDU and treat the whole lot as the frame(s)
>>> to care about. Honestly though, I'm kind of wondering whether I should
>>> mostly just do what the Atheros reference driver does and treat it as
>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>> reordering is already done) and just tack on the wifi header bit via
>>> another of the DMA rings.
>>>
>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>
>>>
>>>
>>> -a
>>>
>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>
>>>
>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>> in ieee80211_sta_manage_reorder_buf:
>>>>
>>>> 1. The out-of-date check:
>>>>
>>>>         /* frame with out of date sequence number */
>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>                 dev_kfree_skb(skb);
>>>>                 goto out;
>>>>         }
>>>>
>>>> As all of the subframes carry the same sequence number, the first
>>>> subframe will be delivered and increment head_seq_num and then all
>>>> subsequent subframes will be discarded.
>>>>
>>>>
>>>> 2. The duplicates check a bit later in the routine:
>>>>
>>>>         /* check if we already stored this frame */
>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>                 dev_kfree_skb(skb);
>>>>                 goto out;
>>>>         }
>>>>
>>>> If there is enough packet loss that packets are queued in the reorder
>>>> buffer and not immediately released, then only the first subframe will
>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>
>>>>
>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>
>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>> see that it does happen, but it doesn't impact the throughput and I
>>>> can't report the impact of fixing it.
>>>>
>>>> ----
>>>>
>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>> match the mac80211 expectations.
>>>>
>>>>
>>>>
>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>> Yes, after some more testing it does look like an unfortunate
>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>> subframes all carry the same sequence number. The first subframe is
>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>
>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>> head=0xb06
>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>> head=0xb0b
>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>> head=0xb10
>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>> head=0xb15
>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>> head=0xb1a
>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>> head=0xb1f
>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>> head=0xb24
>>>>>
>>>>>
>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>
>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>> frame makes it through.
>>>>>>>
>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>
>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>> A-MSDU.
>>>>>>
>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>
>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>
>> Denton could you try attached patch: report amsdu in one big frame.
>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>> improve performance and reduce memcpy, while currently we have skb
>> frames, put them in one big skb and next cfg80211 split them again
>> into msdus and report to stack.
>>
>> BR
>> Janusz


From janusz.dziedzic at tieto.com  Mon Jul  7 23:50:39 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Tue, 8 Jul 2014 08:50:39 +0200
Subject: A-MSDU reception not working?
In-Reply-To: <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
Message-ID: <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>

On 8 July 2014 08:43, Denton Gentry <denton.gentry at gmail.com> wrote:
> I think I know what is happening now, though I've no idea why. The
> throughput is low because we have many TCP retransmissions. We have
> retransmissions because the TCP checksum is wrong on a number of
> frames, and I do find data corruption in the payload so the checksum
> definitely should be wrong. All of the corrupted frames were
> originally one of the subframes in an A-MSDU packet.
>
> An example follows at the end of this message, as dissected by
> Wireshark. iperf sends a very regular data pattern of "0123456789..."
> over and over. Note how in subframe #2 offset 0x1e0 the bytes "32 33
> 34" have been replaced by "72 36 35"
>
> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>
> I added printks at the bottom of ath10k_htt_rx_amsdu immediately
> before the call to ath10k_process_rx. I found this same packet, and we
> see the "72 36 35" corruption in the printk. So I think it happened in
> ath10k_process_rx or before, not anything weird after passing it up to
> mac80211.
>
> [  101.863712] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
> [  101.863727] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
> [  101.863742] ath10k: 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32
> [  101.863757] ath10k: 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37 38
> [  101.863773] ath10k: 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34
> [  101.863788] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
> [  101.863803] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>
>
> I've found a number of examples of similar corruption, always with
> between one and four bytes replaced.
>
> 35363738 -> e52c6e07
> 3435 -> b43f
> 3839 -> c238
> 31 -> 7f
> 3435 -> 7436
> 30 -> 50
> 3233 -> bc37
>
Seems this could be because of:

+ /* cfg80211 expect this padding */
+ padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
+ skb_put(skb, padding);

>
> The packet described above, dissected by Wireshark:
>
> No.     Time        Source                Destination
> Protocol Length Info
>    2235 18.953349   192.168.144.79        192.168.144.13        TCP
>   3112   52697 > 5001 [ACK] Seq=1391553 Ack=1 Win=131760 [TCP CHECKSUM
> INCORRECT] Len=1448 TSval=1298580657 TSecr=4294947481
>
> Frame 2235: 3112 bytes on wire (24896 bits), 3112 bytes captured (24896 bits)
>     Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
>     Arrival Time: Jul  7, 2014 23:03:37.763365000 PDT
>     [Time shift for this packet: 0.000000000 seconds]
>     Epoch Time: 1404799417.763365000 seconds
>     [Time delta from previous captured frame: 0.003476000 seconds]
>     [Time delta from previous displayed frame: 0.515641000 seconds]
>     [Time since reference or first frame: 18.953349000 seconds]
>     Frame Number: 2235
>     Frame Length: 3112 bytes (24896 bits)
>     Capture Length: 3112 bytes (24896 bits)
>     [Frame is marked: False]
>     [Frame is ignored: False]
>     [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
>     [Coloring Rule Name: TCP]
>     [Coloring Rule String: tcp]
> Radiotap Header v0, Length 38
>     Header revision: 0
>     Header pad: 0
>     Header length: 38
>     Present flags
>         .... .... .... .... .... .... .... ...1 = TSFT: True
>         .... .... .... .... .... .... .... ..1. = Flags: True
>         .... .... .... .... .... .... .... .0.. = Rate: False
>         .... .... .... .... .... .... .... 1... = Channel: True
>         .... .... .... .... .... .... ...0 .... = FHSS: False
>         .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
>         .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
>         .... .... .... .... .... .... 0... .... = Lock Quality: False
>         .... .... .... .... .... ...0 .... .... = TX Attenuation: False
>         .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
>         .... .... .... .... .... .0.. .... .... = dBm TX Power: False
>         .... .... .... .... .... 1... .... .... = Antenna: True
>         .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
>         .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
>         .... .... .... .... .1.. .... .... .... = RX flags: True
>         .... .... .... .0.. .... .... .... .... = Channel+: False
>         .... .... .... 0... .... .... .... .... = HT information: False
>         .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
>         .... .... ..1. .... .... .... .... .... = VHT information: True
>         ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
>         ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
>         .0.. .... .... .... .... .... .... .... = Vendor NS next: False
>         0... .... .... .... .... .... .... .... = Ext: False
>     MAC timestamp: 78051063
>     Flags: 0x00
>         .... ...0 = CFP: False
>         .... ..0. = Preamble: Long
>         .... .0.. = WEP: False
>         .... 0... = Fragmentation: False
>         ...0 .... = FCS at end: False
>         ..0. .... = Data Pad: False
>         .0.. .... = Bad FCS: False
>         0... .... = Short GI: False
>     Channel frequency: 5745 [A 149]
>     Channel type: 802.11a (0x0140)
>         .... .... ...0 .... = Turbo: False
>         .... .... ..0. .... = Complementary Code Keying (CCK): False
>         .... .... .1.. .... = Orthogonal Frequency-Division
> Multiplexing (OFDM): True
>         .... .... 0... .... = 2 GHz spectrum: False
>         .... ...1 .... .... = 5 GHz spectrum: True
>         .... ..0. .... .... = Passive: False
>         .... .0.. .... .... = Dynamic CCK-OFDM: False
>         .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
>         ...0 .... .... .... = GSM (900MHz): False
>         ..0. .... .... .... = Static Turbo: False
>         .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
>         0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
>     SSI Signal: -53 dBm
>     Antenna: 0
>     RX flags: 0x0000
>         .... .... .... .... .... ..0. = Bad PLCP: False
>     VHT information
>         Known VHT information: 0x44
>             .... .... .... ...0 = STBC: False
>             .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
>             .... .... .... .1.. = Guard interval: True
>             .... .... .... 0... = SGI Nsym disambiguation: False
>             .... .... ...0 .... = LDPC extra OFDM symbol: False
>             .... .... ..0. .... = Beamformed: False
>             .... .... .1.. .... = Bandwidth: True
>             .... .... 0... .... = Group ID: False
>             .... ...0 .... .... = Partial AID: False
>         .... .0.. = Guard interval: long (0)
>         Bandwidth: 80 MHz (4)
>         User 0: MCS 8
>             1000 .... = MCS index 0: 8 (256-QAM 3/4)
>             .... 0010 = Spatial streams 0: 2
>             Space-time streams 0: 2
>             Coding 0: BCC (0)
>             [Data Rate: 702.0 Mb/s]
> IEEE 802.11 QoS Data, Flags: .......T
>     Type/Subtype: QoS Data (0x28)
>     Frame Control Field: 0x8801
>         .... ..00 = Version: 0
>         .... 10.. = Type: Data frame (2)
>         1000 .... = Subtype: 8
>         Flags: 0x01
>             .... ..01 = DS status: Frame from STA to DS via an AP (To
> DS: 1 From DS: 0) (0x01)
>             .... .0.. = More Fragments: This is the last fragment
>             .... 0... = Retry: Frame is not being retransmitted
>             ...0 .... = PWR MGT: STA will stay up
>             ..0. .... = More Data: No data buffered
>             .0.. .... = Protected flag: Data is not protected
>             0... .... = Order flag: Not strictly ordered
>     .000 0000 0011 0000 = Duration: 48 microseconds
>     Receiver address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>     BSS Id: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>     Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
>     Source address: Apple_67:24:54 (84:38:35:67:24:54)
>     Destination address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>     Fragment number: 0
>     Sequence number: 1021
>     Qos Control: 0x0080
>         .... .... .... 0000 = TID: 0
>         [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
>         .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control
> field are TXOP Duration Requested
>         .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
>         .... .... 1... .... = Payload Type: A-MSDU
>         0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
> IEEE 802.11 Aggregate MSDU
>     A-MSDU Subframe #1
>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>         A-MSDU Length: 1510
>         Logical-Link Control
>             DSAP: SNAP (0xaa)
>             IG Bit: Individual
>             SSAP: SNAP (0xaa)
>             CR Bit: Command
>             Control field: U, func=UI (0x03)
>                 000. 00.. = Command: Unnumbered Information (0x00)
>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>             Organization Code: Encapsulated Ethernet (0x000000)
>             Type: IP (0x0800)
>         Internet Protocol Version 4, Src: 192.168.144.79
> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>             Version: 4
>             Header length: 20 bytes
>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>                 .... ..00 = Explicit Congestion Notification: Not-ECT
> (Not ECN-Capable Transport) (0x00)
>             Total Length: 1500
>             Identification: 0xc622 (50722)
>             Flags: 0x00
>                 0... .... = Reserved bit: Not set
>                 .0.. .... = Don't fragment: Not set
>                 ..0. .... = More fragments: Not set
>             Fragment offset: 0
>             Time to live: 64
>             Protocol: TCP (6)
>             Header checksum: 0x0d4c [correct]
>                 [Good: True]
>                 [Bad: False]
>             Source: 192.168.144.79 (192.168.144.79)
>             Destination: 192.168.144.13 (192.168.144.13)
>             [Source GeoIP: Unknown]
>             [Destination GeoIP: Unknown]
>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
> Port: 5001 (5001), Seq: 1390105, Ack: 1, Len: 1448
>             Source port: 52697 (52697)
>             Destination port: 5001 (5001)
>             [Stream index: 0]
>             Sequence number: 1390105    (relative sequence number)
>             [Next sequence number: 1391553    (relative sequence number)]
>             Acknowledgment number: 1    (relative ack number)
>             Header length: 32 bytes
>             Flags: 0x010 (ACK)
>                 000. .... .... = Reserved: Not set
>                 ...0 .... .... = Nonce: Not set
>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>                 .... .0.. .... = ECN-Echo: Not set
>                 .... ..0. .... = Urgent: Not set
>                 .... ...1 .... = Acknowledgment: Set
>                 .... .... 0... = Push: Not set
>                 .... .... .0.. = Reset: Not set
>                 .... .... ..0. = Syn: Not set
>                 .... .... ...0 = Fin: Not set
>             Window size value: 8235
>             [Calculated window size: 131760]
>             [Window size scaling factor: 16]
>             Checksum: 0xa1c0 [correct]
>                 [Good Checksum: True]
>                 [Bad Checksum: False]
>             Options: (12 bytes), No-Operation (NOP), No-Operation
> (NOP), Timestamps
>                 No-Operation (NOP)
>                     Type: 1
>                         0... .... = Copy on fragmentation: No
>                         .00. .... = Class: Control (0)
>                         ...0 0001 = Number: No-Operation (NOP) (1)
>                 No-Operation (NOP)
>                     Type: 1
>                         0... .... = Copy on fragmentation: No
>                         .00. .... = Class: Control (0)
>                         ...0 0001 = Number: No-Operation (NOP) (1)
>                 Timestamps: TSval 1298580657, TSecr 4294947481
>                     Kind: Timestamp (8)
>                     Length: 10
>                     Timestamp value: 1298580657
>                     Timestamp echo reply: 4294947481
>         Data (1448 bytes)
>
> 0000  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0010  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0020  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0030  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0040  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0050  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0060  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0070  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0080  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0090  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 00a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 00b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 00c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 00d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 00e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 00f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0100  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0110  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0120  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0130  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0140  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0150  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0160  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0170  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0180  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0190  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 01a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 01b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 01c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 01d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 01e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 01f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0200  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0210  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0220  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0230  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0240  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0250  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0260  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0270  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0280  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0290  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 02a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 02b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 02c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 02d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 02e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 02f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0300  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0310  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0320  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0330  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0340  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0350  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0360  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0370  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0380  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0390  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 03a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 03b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 03c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 03d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 03e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 03f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0400  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0410  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0420  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0430  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0440  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0450  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0460  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0470  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0480  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0490  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 04a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 04b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 04c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 04d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 04e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 04f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0500  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0510  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0520  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0530  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0540  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0550  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0560  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0570  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0580  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0590  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 05a0  34 35 36 37 38 39 30 31                           45678901
>             Data: 343536373839303132333435363738393031323334353637...
>             [Length: 1448]
>     A-MSDU Subframe #2
>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>         A-MSDU Length: 1510
>         Logical-Link Control
>             DSAP: SNAP (0xaa)
>             IG Bit: Individual
>             SSAP: SNAP (0xaa)
>             CR Bit: Command
>             Control field: U, func=UI (0x03)
>                 000. 00.. = Command: Unnumbered Information (0x00)
>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>             Organization Code: Encapsulated Ethernet (0x000000)
>             Type: IP (0x0800)
>         Internet Protocol Version 4, Src: 192.168.144.79
> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>             Version: 4
>             Header length: 20 bytes
>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>                 .... ..00 = Explicit Congestion Notification: Not-ECT
> (Not ECN-Capable Transport) (0x00)
>             Total Length: 1500
>             Identification: 0xda09 (55817)
>             Flags: 0x00
>                 0... .... = Reserved bit: Not set
>                 .0.. .... = Don't fragment: Not set
>                 ..0. .... = More fragments: Not set
>             Fragment offset: 0
>             Time to live: 64
>             Protocol: TCP (6)
>             Header checksum: 0xf964 [correct]
>                 [Good: True]
>                 [Bad: False]
>             Source: 192.168.144.79 (192.168.144.79)
>             Destination: 192.168.144.13 (192.168.144.13)
>             [Source GeoIP: Unknown]
>             [Destination GeoIP: Unknown]
>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
> Port: 5001 (5001), Seq: 1391553, Ack: 1, Len: 1448
>             Source port: 52697 (52697)
>             Destination port: 5001 (5001)
>             [Stream index: 0]
>             Sequence number: 1391553    (relative sequence number)
>             [Next sequence number: 1393001    (relative sequence number)]
>             Acknowledgment number: 1    (relative ack number)
>             Header length: 32 bytes
>             Flags: 0x010 (ACK)
>                 000. .... .... = Reserved: Not set
>                 ...0 .... .... = Nonce: Not set
>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>                 .... .0.. .... = ECN-Echo: Not set
>                 .... ..0. .... = Urgent: Not set
>                 .... ...1 .... = Acknowledgment: Set
>                 .... .... 0... = Push: Not set
>                 .... .... .0.. = Reset: Not set
>                 .... .... ..0. = Syn: Not set
>                 .... .... ...0 = Fin: Not set
>             Window size value: 8235
>             [Calculated window size: 131760]
>             [Window size scaling factor: 16]
>             Checksum: 0x9a16 [incorrect, should be 0x5913 (maybe
> caused by "TCP checksum offload"?)]
>                 [Good Checksum: False]
>                 [Bad Checksum: True]
>                     [Expert Info (Error/Checksum): Bad checksum]
>                         [Message: Bad checksum]
>                         [Severity level: Error]
>                         [Group: Checksum]
>             Options: (12 bytes), No-Operation (NOP), No-Operation
> (NOP), Timestamps
>                 No-Operation (NOP)
>                     Type: 1
>                         0... .... = Copy on fragmentation: No
>                         .00. .... = Class: Control (0)
>                         ...0 0001 = Number: No-Operation (NOP) (1)
>                 No-Operation (NOP)
>                     Type: 1
>                         0... .... = Copy on fragmentation: No
>                         .00. .... = Class: Control (0)
>                         ...0 0001 = Number: No-Operation (NOP) (1)
>                 Timestamps: TSval 1298580657, TSecr 4294947481
>                     Kind: Timestamp (8)
>                     Length: 10
>                     Timestamp value: 1298580657
>                     Timestamp echo reply: 4294947481
>         Data (1448 bytes)
>
> 0000  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0010  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0020  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0030  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0040  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0050  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0060  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0070  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0080  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0090  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 00a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 00b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 00c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 00d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 00e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 00f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0100  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0110  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0120  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0130  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0140  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0150  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0160  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0170  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0180  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0190  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 01a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 01b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 01c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 01d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
> 01f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0200  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0210  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0220  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0230  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0240  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0250  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0260  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0270  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0280  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0290  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 02a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 02b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 02c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 02d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 02e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 02f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0300  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0310  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0320  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0330  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0340  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0350  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0360  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0370  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0380  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0390  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 03a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 03b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 03c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 03d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 03e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 03f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0400  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0410  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0420  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0430  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0440  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0450  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0460  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0470  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0480  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0490  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 04a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 04b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 04c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 04d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 04e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 04f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0500  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0510  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0520  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0530  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0540  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 0550  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
> 0560  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
> 0570  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
> 0580  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
> 0590  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
> 05a0  32 33 34 35 36 37 38 39                           23456789
>             Data: 323334353637383930313233343536373839303132333435...
>             [Length: 1448]
>
> On Mon, Jul 7, 2014 at 12:26 PM, Denton Gentry <denton.gentry at gmail.com> wrote:
>> The initial results are not promising: a MacOS 802.11ac client gets
>> between 0-2 Mbps with this change, where it was getting about 8 Mbps
>> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
>> from the receiving system shows a very large number of out of order
>> frames, likely due to TCP retransmission.
>>
>> An 802.11n MacBook gets very good throughput, only the 802.11ac
>> MacBook shows the very poor result. I'm trying to figure out why.
>>
>>
>> One specific note (and probably not related to the throughput): I
>> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
>> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
>> correctly?
>>
>>
>> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
>> <janusz.dziedzic at tieto.com> wrote:
>>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>>
>>>> The earlier atheros chips would just give you the AMSDU frames as
>>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>>> those sub-frames.
>>>>
>>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>>> half of one MPDU before you hit EOL, the next notification you process
>>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>>> reordering hilarity again.
>>>>
>>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>>> representing the current MPDU and treat the whole lot as the frame(s)
>>>> to care about. Honestly though, I'm kind of wondering whether I should
>>>> mostly just do what the Atheros reference driver does and treat it as
>>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>>> reordering is already done) and just tack on the wifi header bit via
>>>> another of the DMA rings.
>>>>
>>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>>
>>>>
>>>>
>>>> -a
>>>>
>>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>>
>>>>
>>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>>> in ieee80211_sta_manage_reorder_buf:
>>>>>
>>>>> 1. The out-of-date check:
>>>>>
>>>>>         /* frame with out of date sequence number */
>>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>>                 dev_kfree_skb(skb);
>>>>>                 goto out;
>>>>>         }
>>>>>
>>>>> As all of the subframes carry the same sequence number, the first
>>>>> subframe will be delivered and increment head_seq_num and then all
>>>>> subsequent subframes will be discarded.
>>>>>
>>>>>
>>>>> 2. The duplicates check a bit later in the routine:
>>>>>
>>>>>         /* check if we already stored this frame */
>>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>>                 dev_kfree_skb(skb);
>>>>>                 goto out;
>>>>>         }
>>>>>
>>>>> If there is enough packet loss that packets are queued in the reorder
>>>>> buffer and not immediately released, then only the first subframe will
>>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>>
>>>>>
>>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>>
>>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>>> see that it does happen, but it doesn't impact the throughput and I
>>>>> can't report the impact of fixing it.
>>>>>
>>>>> ----
>>>>>
>>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>>> match the mac80211 expectations.
>>>>>
>>>>>
>>>>>
>>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>> Yes, after some more testing it does look like an unfortunate
>>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>>> subframes all carry the same sequence number. The first subframe is
>>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>>
>>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>>> head=0xb06
>>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>>> head=0xb0b
>>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>>> head=0xb10
>>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>>> head=0xb15
>>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>>> head=0xb1a
>>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>>> head=0xb1f
>>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>>> head=0xb24
>>>>>>
>>>>>>
>>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>>
>>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>>> frame makes it through.
>>>>>>>>
>>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>>
>>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>>> A-MSDU.
>>>>>>>
>>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>>
>>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>>
>>> Denton could you try attached patch: report amsdu in one big frame.
>>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>>> improve performance and reduce memcpy, while currently we have skb
>>> frames, put them in one big skb and next cfg80211 split them again
>>> into msdus and report to stack.
>>>
>>> BR
>>> Janusz


From janusz.dziedzic at tieto.com  Tue Jul  8 00:02:01 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Tue, 8 Jul 2014 09:02:01 +0200
Subject: A-MSDU reception not working?
In-Reply-To: <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
 <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>
Message-ID: <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>

On 8 July 2014 08:50, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
> On 8 July 2014 08:43, Denton Gentry <denton.gentry at gmail.com> wrote:
>> I think I know what is happening now, though I've no idea why. The
>> throughput is low because we have many TCP retransmissions. We have
>> retransmissions because the TCP checksum is wrong on a number of
>> frames, and I do find data corruption in the payload so the checksum
>> definitely should be wrong. All of the corrupted frames were
>> originally one of the subframes in an A-MSDU packet.
>>
>> An example follows at the end of this message, as dissected by
>> Wireshark. iperf sends a very regular data pattern of "0123456789..."
>> over and over. Note how in subframe #2 offset 0x1e0 the bytes "32 33
>> 34" have been replaced by "72 36 35"
>>
>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>
>> I added printks at the bottom of ath10k_htt_rx_amsdu immediately
>> before the call to ath10k_process_rx. I found this same packet, and we
>> see the "72 36 35" corruption in the printk. So I think it happened in
>> ath10k_process_rx or before, not anything weird after passing it up to
>> mac80211.
>>
>> [  101.863712] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>> [  101.863727] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>> [  101.863742] ath10k: 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32
>> [  101.863757] ath10k: 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37 38
>> [  101.863773] ath10k: 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34
>> [  101.863788] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>> [  101.863803] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>
>>
>> I've found a number of examples of similar corruption, always with
>> between one and four bytes replaced.
>>
>> 35363738 -> e52c6e07
>> 3435 -> b43f
>> 3839 -> c238
>> 31 -> 7f
>> 3435 -> 7436
>> 30 -> 50
>> 3233 -> bc37
>>
> Seems this could be because of:
>
> + /* cfg80211 expect this padding */
> + padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
> + skb_put(skb, padding);
>

BTW, when AP (ath10k) send TCP ACK - are this packets also AMSDU?
I see in my case AP can send 3 x A-MSDU (with total size 304 bytes)
small frames aggregated. Maybe your HW have problems with that.
As I remember correctly someone some time ago report problems with
MacBook pro retina but I am not sure this is the same, while no one
tests the fix.

>>
>> The packet described above, dissected by Wireshark:
>>
>> No.     Time        Source                Destination
>> Protocol Length Info
>>    2235 18.953349   192.168.144.79        192.168.144.13        TCP
>>   3112   52697 > 5001 [ACK] Seq=1391553 Ack=1 Win=131760 [TCP CHECKSUM
>> INCORRECT] Len=1448 TSval=1298580657 TSecr=4294947481
>>
>> Frame 2235: 3112 bytes on wire (24896 bits), 3112 bytes captured (24896 bits)
>>     Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
>>     Arrival Time: Jul  7, 2014 23:03:37.763365000 PDT
>>     [Time shift for this packet: 0.000000000 seconds]
>>     Epoch Time: 1404799417.763365000 seconds
>>     [Time delta from previous captured frame: 0.003476000 seconds]
>>     [Time delta from previous displayed frame: 0.515641000 seconds]
>>     [Time since reference or first frame: 18.953349000 seconds]
>>     Frame Number: 2235
>>     Frame Length: 3112 bytes (24896 bits)
>>     Capture Length: 3112 bytes (24896 bits)
>>     [Frame is marked: False]
>>     [Frame is ignored: False]
>>     [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
>>     [Coloring Rule Name: TCP]
>>     [Coloring Rule String: tcp]
>> Radiotap Header v0, Length 38
>>     Header revision: 0
>>     Header pad: 0
>>     Header length: 38
>>     Present flags
>>         .... .... .... .... .... .... .... ...1 = TSFT: True
>>         .... .... .... .... .... .... .... ..1. = Flags: True
>>         .... .... .... .... .... .... .... .0.. = Rate: False
>>         .... .... .... .... .... .... .... 1... = Channel: True
>>         .... .... .... .... .... .... ...0 .... = FHSS: False
>>         .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
>>         .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
>>         .... .... .... .... .... .... 0... .... = Lock Quality: False
>>         .... .... .... .... .... ...0 .... .... = TX Attenuation: False
>>         .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
>>         .... .... .... .... .... .0.. .... .... = dBm TX Power: False
>>         .... .... .... .... .... 1... .... .... = Antenna: True
>>         .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
>>         .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
>>         .... .... .... .... .1.. .... .... .... = RX flags: True
>>         .... .... .... .0.. .... .... .... .... = Channel+: False
>>         .... .... .... 0... .... .... .... .... = HT information: False
>>         .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
>>         .... .... ..1. .... .... .... .... .... = VHT information: True
>>         ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
>>         ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
>>         .0.. .... .... .... .... .... .... .... = Vendor NS next: False
>>         0... .... .... .... .... .... .... .... = Ext: False
>>     MAC timestamp: 78051063
>>     Flags: 0x00
>>         .... ...0 = CFP: False
>>         .... ..0. = Preamble: Long
>>         .... .0.. = WEP: False
>>         .... 0... = Fragmentation: False
>>         ...0 .... = FCS at end: False
>>         ..0. .... = Data Pad: False
>>         .0.. .... = Bad FCS: False
>>         0... .... = Short GI: False
>>     Channel frequency: 5745 [A 149]
>>     Channel type: 802.11a (0x0140)
>>         .... .... ...0 .... = Turbo: False
>>         .... .... ..0. .... = Complementary Code Keying (CCK): False
>>         .... .... .1.. .... = Orthogonal Frequency-Division
>> Multiplexing (OFDM): True
>>         .... .... 0... .... = 2 GHz spectrum: False
>>         .... ...1 .... .... = 5 GHz spectrum: True
>>         .... ..0. .... .... = Passive: False
>>         .... .0.. .... .... = Dynamic CCK-OFDM: False
>>         .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
>>         ...0 .... .... .... = GSM (900MHz): False
>>         ..0. .... .... .... = Static Turbo: False
>>         .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
>>         0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
>>     SSI Signal: -53 dBm
>>     Antenna: 0
>>     RX flags: 0x0000
>>         .... .... .... .... .... ..0. = Bad PLCP: False
>>     VHT information
>>         Known VHT information: 0x44
>>             .... .... .... ...0 = STBC: False
>>             .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
>>             .... .... .... .1.. = Guard interval: True
>>             .... .... .... 0... = SGI Nsym disambiguation: False
>>             .... .... ...0 .... = LDPC extra OFDM symbol: False
>>             .... .... ..0. .... = Beamformed: False
>>             .... .... .1.. .... = Bandwidth: True
>>             .... .... 0... .... = Group ID: False
>>             .... ...0 .... .... = Partial AID: False
>>         .... .0.. = Guard interval: long (0)
>>         Bandwidth: 80 MHz (4)
>>         User 0: MCS 8
>>             1000 .... = MCS index 0: 8 (256-QAM 3/4)
>>             .... 0010 = Spatial streams 0: 2
>>             Space-time streams 0: 2
>>             Coding 0: BCC (0)
>>             [Data Rate: 702.0 Mb/s]
>> IEEE 802.11 QoS Data, Flags: .......T
>>     Type/Subtype: QoS Data (0x28)
>>     Frame Control Field: 0x8801
>>         .... ..00 = Version: 0
>>         .... 10.. = Type: Data frame (2)
>>         1000 .... = Subtype: 8
>>         Flags: 0x01
>>             .... ..01 = DS status: Frame from STA to DS via an AP (To
>> DS: 1 From DS: 0) (0x01)
>>             .... .0.. = More Fragments: This is the last fragment
>>             .... 0... = Retry: Frame is not being retransmitted
>>             ...0 .... = PWR MGT: STA will stay up
>>             ..0. .... = More Data: No data buffered
>>             .0.. .... = Protected flag: Data is not protected
>>             0... .... = Order flag: Not strictly ordered
>>     .000 0000 0011 0000 = Duration: 48 microseconds
>>     Receiver address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>     BSS Id: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>     Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
>>     Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>     Destination address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>     Fragment number: 0
>>     Sequence number: 1021
>>     Qos Control: 0x0080
>>         .... .... .... 0000 = TID: 0
>>         [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
>>         .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control
>> field are TXOP Duration Requested
>>         .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
>>         .... .... 1... .... = Payload Type: A-MSDU
>>         0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
>> IEEE 802.11 Aggregate MSDU
>>     A-MSDU Subframe #1
>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>         A-MSDU Length: 1510
>>         Logical-Link Control
>>             DSAP: SNAP (0xaa)
>>             IG Bit: Individual
>>             SSAP: SNAP (0xaa)
>>             CR Bit: Command
>>             Control field: U, func=UI (0x03)
>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>             Organization Code: Encapsulated Ethernet (0x000000)
>>             Type: IP (0x0800)
>>         Internet Protocol Version 4, Src: 192.168.144.79
>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>             Version: 4
>>             Header length: 20 bytes
>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>> (Not ECN-Capable Transport) (0x00)
>>             Total Length: 1500
>>             Identification: 0xc622 (50722)
>>             Flags: 0x00
>>                 0... .... = Reserved bit: Not set
>>                 .0.. .... = Don't fragment: Not set
>>                 ..0. .... = More fragments: Not set
>>             Fragment offset: 0
>>             Time to live: 64
>>             Protocol: TCP (6)
>>             Header checksum: 0x0d4c [correct]
>>                 [Good: True]
>>                 [Bad: False]
>>             Source: 192.168.144.79 (192.168.144.79)
>>             Destination: 192.168.144.13 (192.168.144.13)
>>             [Source GeoIP: Unknown]
>>             [Destination GeoIP: Unknown]
>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>> Port: 5001 (5001), Seq: 1390105, Ack: 1, Len: 1448
>>             Source port: 52697 (52697)
>>             Destination port: 5001 (5001)
>>             [Stream index: 0]
>>             Sequence number: 1390105    (relative sequence number)
>>             [Next sequence number: 1391553    (relative sequence number)]
>>             Acknowledgment number: 1    (relative ack number)
>>             Header length: 32 bytes
>>             Flags: 0x010 (ACK)
>>                 000. .... .... = Reserved: Not set
>>                 ...0 .... .... = Nonce: Not set
>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>                 .... .0.. .... = ECN-Echo: Not set
>>                 .... ..0. .... = Urgent: Not set
>>                 .... ...1 .... = Acknowledgment: Set
>>                 .... .... 0... = Push: Not set
>>                 .... .... .0.. = Reset: Not set
>>                 .... .... ..0. = Syn: Not set
>>                 .... .... ...0 = Fin: Not set
>>             Window size value: 8235
>>             [Calculated window size: 131760]
>>             [Window size scaling factor: 16]
>>             Checksum: 0xa1c0 [correct]
>>                 [Good Checksum: True]
>>                 [Bad Checksum: False]
>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>> (NOP), Timestamps
>>                 No-Operation (NOP)
>>                     Type: 1
>>                         0... .... = Copy on fragmentation: No
>>                         .00. .... = Class: Control (0)
>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>                 No-Operation (NOP)
>>                     Type: 1
>>                         0... .... = Copy on fragmentation: No
>>                         .00. .... = Class: Control (0)
>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>                     Kind: Timestamp (8)
>>                     Length: 10
>>                     Timestamp value: 1298580657
>>                     Timestamp echo reply: 4294947481
>>         Data (1448 bytes)
>>
>> 0000  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0010  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0020  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0030  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0040  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0050  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0060  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0070  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0080  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0090  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 00a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 00b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 00c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 00d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 00e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 00f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0100  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0110  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0120  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0130  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0140  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0150  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0160  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0170  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0180  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0190  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 01a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 01b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 01c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 01d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 01e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 01f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0200  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0210  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0220  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0230  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0240  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0250  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0260  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0270  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0280  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0290  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 02a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 02b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 02c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 02d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 02e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 02f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0300  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0310  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0320  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0330  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0340  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0350  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0360  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0370  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0380  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0390  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 03a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 03b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 03c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 03d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 03e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 03f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0400  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0410  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0420  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0430  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0440  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0450  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0460  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0470  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0480  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0490  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 04a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 04b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 04c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 04d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 04e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 04f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0500  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0510  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0520  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0530  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0540  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0550  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0560  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0570  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0580  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0590  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 05a0  34 35 36 37 38 39 30 31                           45678901
>>             Data: 343536373839303132333435363738393031323334353637...
>>             [Length: 1448]
>>     A-MSDU Subframe #2
>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>         A-MSDU Length: 1510
>>         Logical-Link Control
>>             DSAP: SNAP (0xaa)
>>             IG Bit: Individual
>>             SSAP: SNAP (0xaa)
>>             CR Bit: Command
>>             Control field: U, func=UI (0x03)
>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>             Organization Code: Encapsulated Ethernet (0x000000)
>>             Type: IP (0x0800)
>>         Internet Protocol Version 4, Src: 192.168.144.79
>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>             Version: 4
>>             Header length: 20 bytes
>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>> (Not ECN-Capable Transport) (0x00)
>>             Total Length: 1500
>>             Identification: 0xda09 (55817)
>>             Flags: 0x00
>>                 0... .... = Reserved bit: Not set
>>                 .0.. .... = Don't fragment: Not set
>>                 ..0. .... = More fragments: Not set
>>             Fragment offset: 0
>>             Time to live: 64
>>             Protocol: TCP (6)
>>             Header checksum: 0xf964 [correct]
>>                 [Good: True]
>>                 [Bad: False]
>>             Source: 192.168.144.79 (192.168.144.79)
>>             Destination: 192.168.144.13 (192.168.144.13)
>>             [Source GeoIP: Unknown]
>>             [Destination GeoIP: Unknown]
>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>> Port: 5001 (5001), Seq: 1391553, Ack: 1, Len: 1448
>>             Source port: 52697 (52697)
>>             Destination port: 5001 (5001)
>>             [Stream index: 0]
>>             Sequence number: 1391553    (relative sequence number)
>>             [Next sequence number: 1393001    (relative sequence number)]
>>             Acknowledgment number: 1    (relative ack number)
>>             Header length: 32 bytes
>>             Flags: 0x010 (ACK)
>>                 000. .... .... = Reserved: Not set
>>                 ...0 .... .... = Nonce: Not set
>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>                 .... .0.. .... = ECN-Echo: Not set
>>                 .... ..0. .... = Urgent: Not set
>>                 .... ...1 .... = Acknowledgment: Set
>>                 .... .... 0... = Push: Not set
>>                 .... .... .0.. = Reset: Not set
>>                 .... .... ..0. = Syn: Not set
>>                 .... .... ...0 = Fin: Not set
>>             Window size value: 8235
>>             [Calculated window size: 131760]
>>             [Window size scaling factor: 16]
>>             Checksum: 0x9a16 [incorrect, should be 0x5913 (maybe
>> caused by "TCP checksum offload"?)]
>>                 [Good Checksum: False]
>>                 [Bad Checksum: True]
>>                     [Expert Info (Error/Checksum): Bad checksum]
>>                         [Message: Bad checksum]
>>                         [Severity level: Error]
>>                         [Group: Checksum]
>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>> (NOP), Timestamps
>>                 No-Operation (NOP)
>>                     Type: 1
>>                         0... .... = Copy on fragmentation: No
>>                         .00. .... = Class: Control (0)
>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>                 No-Operation (NOP)
>>                     Type: 1
>>                         0... .... = Copy on fragmentation: No
>>                         .00. .... = Class: Control (0)
>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>                     Kind: Timestamp (8)
>>                     Length: 10
>>                     Timestamp value: 1298580657
>>                     Timestamp echo reply: 4294947481
>>         Data (1448 bytes)
>>
>> 0000  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0010  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0020  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0030  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0040  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0050  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0060  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0070  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0080  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0090  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 00a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 00b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 00c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 00d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 00e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 00f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0100  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0110  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0120  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0130  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0140  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0150  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0160  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0170  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0180  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0190  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 01a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 01b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 01c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 01d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>> 01f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0200  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0210  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0220  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0230  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0240  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0250  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0260  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0270  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0280  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0290  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 02a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 02b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 02c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 02d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 02e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 02f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0300  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0310  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0320  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0330  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0340  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0350  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0360  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0370  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0380  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0390  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 03a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 03b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 03c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 03d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 03e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 03f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0400  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0410  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0420  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0430  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0440  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0450  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0460  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0470  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0480  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0490  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 04a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 04b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 04c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 04d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 04e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 04f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0500  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0510  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0520  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0530  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0540  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 0550  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>> 0560  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>> 0570  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>> 0580  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>> 0590  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>> 05a0  32 33 34 35 36 37 38 39                           23456789
>>             Data: 323334353637383930313233343536373839303132333435...
>>             [Length: 1448]
>>
>> On Mon, Jul 7, 2014 at 12:26 PM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>> The initial results are not promising: a MacOS 802.11ac client gets
>>> between 0-2 Mbps with this change, where it was getting about 8 Mbps
>>> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
>>> from the receiving system shows a very large number of out of order
>>> frames, likely due to TCP retransmission.
>>>
>>> An 802.11n MacBook gets very good throughput, only the 802.11ac
>>> MacBook shows the very poor result. I'm trying to figure out why.
>>>
>>>
>>> One specific note (and probably not related to the throughput): I
>>> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
>>> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
>>> correctly?
>>>
>>>
>>> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
>>> <janusz.dziedzic at tieto.com> wrote:
>>>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>>>
>>>>> The earlier atheros chips would just give you the AMSDU frames as
>>>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>>>> those sub-frames.
>>>>>
>>>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>>>> half of one MPDU before you hit EOL, the next notification you process
>>>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>>>> reordering hilarity again.
>>>>>
>>>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>>>> representing the current MPDU and treat the whole lot as the frame(s)
>>>>> to care about. Honestly though, I'm kind of wondering whether I should
>>>>> mostly just do what the Atheros reference driver does and treat it as
>>>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>>>> reordering is already done) and just tack on the wifi header bit via
>>>>> another of the DMA rings.
>>>>>
>>>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>>>
>>>>>
>>>>>
>>>>> -a
>>>>>
>>>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>>>
>>>>>
>>>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>>>> in ieee80211_sta_manage_reorder_buf:
>>>>>>
>>>>>> 1. The out-of-date check:
>>>>>>
>>>>>>         /* frame with out of date sequence number */
>>>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>>>                 dev_kfree_skb(skb);
>>>>>>                 goto out;
>>>>>>         }
>>>>>>
>>>>>> As all of the subframes carry the same sequence number, the first
>>>>>> subframe will be delivered and increment head_seq_num and then all
>>>>>> subsequent subframes will be discarded.
>>>>>>
>>>>>>
>>>>>> 2. The duplicates check a bit later in the routine:
>>>>>>
>>>>>>         /* check if we already stored this frame */
>>>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>>>                 dev_kfree_skb(skb);
>>>>>>                 goto out;
>>>>>>         }
>>>>>>
>>>>>> If there is enough packet loss that packets are queued in the reorder
>>>>>> buffer and not immediately released, then only the first subframe will
>>>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>>>
>>>>>>
>>>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>>>
>>>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>>>> see that it does happen, but it doesn't impact the throughput and I
>>>>>> can't report the impact of fixing it.
>>>>>>
>>>>>> ----
>>>>>>
>>>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>>>> match the mac80211 expectations.
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>> Yes, after some more testing it does look like an unfortunate
>>>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>>>> subframes all carry the same sequence number. The first subframe is
>>>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>>>
>>>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>>>> head=0xb06
>>>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>>>> head=0xb0b
>>>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>>>> head=0xb10
>>>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>>>> head=0xb15
>>>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>>>> head=0xb1a
>>>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>>>> head=0xb1f
>>>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>>>> head=0xb24
>>>>>>>
>>>>>>>
>>>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>>>
>>>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>>>> frame makes it through.
>>>>>>>>>
>>>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>>>
>>>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>>>> A-MSDU.
>>>>>>>>
>>>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>>>
>>>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>>>
>>>> Denton could you try attached patch: report amsdu in one big frame.
>>>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>>>> improve performance and reduce memcpy, while currently we have skb
>>>> frames, put them in one big skb and next cfg80211 split them again
>>>> into msdus and report to stack.
>>>>
>>>> BR
>>>> Janusz


From johannes at sipsolutions.net  Tue Jul  8 00:10:07 2014
From: johannes at sipsolutions.net (Johannes Berg)
Date: Tue, 08 Jul 2014 09:10:07 +0200
Subject: [RFC/RFT 1/2] mac80211: add support for Rx reordering offloading
In-Reply-To: <1403860015-31601-2-git-send-email-michal.kazior@tieto.com>
 (sfid-20140627_111730_127587_DA36C97E)
References: <1403860015-31601-1-git-send-email-michal.kazior@tieto.com>
 <1403860015-31601-2-git-send-email-michal.kazior@tieto.com>
 (sfid-20140627_111730_127587_DA36C97E)
Message-ID: <1404803407.4419.3.camel@jlt4.sipsolutions.net>

On Fri, 2014-06-27 at 11:06 +0200, Michal Kazior wrote:

> +/**
> + * ieee80211_start_rx_ba_session_offl - start a Rx BA session
> + *
> + * Some device drivers may offload part of the Rx aggregation flow including
> + * AddBa/DelBa negotiation but may otherwise be incapable of full Rx
> + * reordering.
> + *
> + * Create structures responsible for reordering so device drivers may call here
> + * when they complete AddBa negotiation.
> + *
> + * @vif: &struct ieee80211_vif pointer from the add_interface callback
> + * @addr: station mac address
> + * @dialog_token:
> + * @timeout: session timeout (in TU)

Why would you need the dialog token (and why no docs?) and timeout?

> + * @start_seq_num: starting frame sequence number
> + * @tid: the rx tid

> + * @buf_size: max number of frames in reorder buffer

The buf_size also isn't really needed, is it? We are allowed to use a
bigger buffer, I believe?

> +void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
> +					const u8 *addr, u8 dialog_token,
> +					u16 timeout, u16 start_seq_num,
> +					u16 tid, u16 buf_size)
> +{
> +	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
> +	struct ieee80211_local *local = sdata->local;
> +	struct ieee80211_rx_agg *rx_agg;
> +	struct sk_buff *skb = dev_alloc_skb(0);
> +
> +	if (unlikely(!skb))
> +		return;
> +
> +	rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
> +	memcpy(&rx_agg->addr, addr, ETH_ALEN);
> +	rx_agg->dialog_token = dialog_token;
> +	rx_agg->timeout = timeout;
> +	rx_agg->start_seq_num = start_seq_num;
> +	rx_agg->ba_policy = 1;
> +	rx_agg->tid = tid;
> +	rx_agg->buf_size = buf_size;
> +
> +	skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START;
> +	skb_queue_tail(&sdata->skb_queue, skb);
> +	ieee80211_queue_work(&local->hw, &sdata->work);

This seems problematic, since packets might be received immediately.

On the teardown path it should probably also be invalidated immediately,
no?

Then again, we have the same problem already? Hmm.

johannes



From janusz.dziedzic at tieto.com  Tue Jul  8 00:29:32 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Tue, 8 Jul 2014 09:29:32 +0200
Subject: A-MSDU reception not working?
In-Reply-To: <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
 <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>
 <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>
Message-ID: <CALhHN=pvh8qocDzoMvK--__hJD1PVe5CrPBVriC1w=Bx1cpxpg@mail.gmail.com>

On 8 July 2014 09:02, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
> On 8 July 2014 08:50, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>> On 8 July 2014 08:43, Denton Gentry <denton.gentry at gmail.com> wrote:
>>> I think I know what is happening now, though I've no idea why. The
>>> throughput is low because we have many TCP retransmissions. We have
>>> retransmissions because the TCP checksum is wrong on a number of
>>> frames, and I do find data corruption in the payload so the checksum
>>> definitely should be wrong. All of the corrupted frames were
>>> originally one of the subframes in an A-MSDU packet.
>>>
>>> An example follows at the end of this message, as dissected by
>>> Wireshark. iperf sends a very regular data pattern of "0123456789..."
>>> over and over. Note how in subframe #2 offset 0x1e0 the bytes "32 33
>>> 34" have been replaced by "72 36 35"
>>>
>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>
>>> I added printks at the bottom of ath10k_htt_rx_amsdu immediately
>>> before the call to ath10k_process_rx. I found this same packet, and we
>>> see the "72 36 35" corruption in the printk. So I think it happened in
>>> ath10k_process_rx or before, not anything weird after passing it up to
>>> mac80211.
>>>
>>> [  101.863712] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>> [  101.863727] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>> [  101.863742] ath10k: 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32
>>> [  101.863757] ath10k: 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37 38
>>> [  101.863773] ath10k: 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34
>>> [  101.863788] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>> [  101.863803] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>
>>>
>>> I've found a number of examples of similar corruption, always with
>>> between one and four bytes replaced.
>>>
>>> 35363738 -> e52c6e07
>>> 3435 -> b43f
>>> 3839 -> c238
>>> 31 -> 7f
>>> 3435 -> 7436
>>> 30 -> 50
>>> 3233 -> bc37
>>>
>> Seems this could be because of:
>>
>> + /* cfg80211 expect this padding */
>> + padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
>> + skb_put(skb, padding);
>>
>
> BTW, when AP (ath10k) send TCP ACK - are this packets also AMSDU?
> I see in my case AP can send 3 x A-MSDU (with total size 304 bytes)
> small frames aggregated. Maybe your HW have problems with that.
> As I remember correctly someone some time ago report problems with
> MacBook pro retina but I am not sure this is the same, while no one
> tests the fix.
>
>>>
>>> The packet described above, dissected by Wireshark:
>>>
>>> No.     Time        Source                Destination
>>> Protocol Length Info
>>>    2235 18.953349   192.168.144.79        192.168.144.13        TCP
>>>   3112   52697 > 5001 [ACK] Seq=1391553 Ack=1 Win=131760 [TCP CHECKSUM
>>> INCORRECT] Len=1448 TSval=1298580657 TSecr=4294947481
>>>
>>> Frame 2235: 3112 bytes on wire (24896 bits), 3112 bytes captured (24896 bits)
>>>     Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
>>>     Arrival Time: Jul  7, 2014 23:03:37.763365000 PDT
>>>     [Time shift for this packet: 0.000000000 seconds]
>>>     Epoch Time: 1404799417.763365000 seconds
>>>     [Time delta from previous captured frame: 0.003476000 seconds]
>>>     [Time delta from previous displayed frame: 0.515641000 seconds]
>>>     [Time since reference or first frame: 18.953349000 seconds]
>>>     Frame Number: 2235
>>>     Frame Length: 3112 bytes (24896 bits)
>>>     Capture Length: 3112 bytes (24896 bits)
>>>     [Frame is marked: False]
>>>     [Frame is ignored: False]
>>>     [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
>>>     [Coloring Rule Name: TCP]
>>>     [Coloring Rule String: tcp]
>>> Radiotap Header v0, Length 38
>>>     Header revision: 0
>>>     Header pad: 0
>>>     Header length: 38
>>>     Present flags
>>>         .... .... .... .... .... .... .... ...1 = TSFT: True
>>>         .... .... .... .... .... .... .... ..1. = Flags: True
>>>         .... .... .... .... .... .... .... .0.. = Rate: False
>>>         .... .... .... .... .... .... .... 1... = Channel: True
>>>         .... .... .... .... .... .... ...0 .... = FHSS: False
>>>         .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
>>>         .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
>>>         .... .... .... .... .... .... 0... .... = Lock Quality: False
>>>         .... .... .... .... .... ...0 .... .... = TX Attenuation: False
>>>         .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
>>>         .... .... .... .... .... .0.. .... .... = dBm TX Power: False
>>>         .... .... .... .... .... 1... .... .... = Antenna: True
>>>         .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
>>>         .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
>>>         .... .... .... .... .1.. .... .... .... = RX flags: True
>>>         .... .... .... .0.. .... .... .... .... = Channel+: False
>>>         .... .... .... 0... .... .... .... .... = HT information: False
>>>         .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
>>>         .... .... ..1. .... .... .... .... .... = VHT information: True
>>>         ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
>>>         ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
>>>         .0.. .... .... .... .... .... .... .... = Vendor NS next: False
>>>         0... .... .... .... .... .... .... .... = Ext: False
>>>     MAC timestamp: 78051063
>>>     Flags: 0x00
>>>         .... ...0 = CFP: False
>>>         .... ..0. = Preamble: Long
>>>         .... .0.. = WEP: False
>>>         .... 0... = Fragmentation: False
>>>         ...0 .... = FCS at end: False
>>>         ..0. .... = Data Pad: False
>>>         .0.. .... = Bad FCS: False
>>>         0... .... = Short GI: False
>>>     Channel frequency: 5745 [A 149]
>>>     Channel type: 802.11a (0x0140)
>>>         .... .... ...0 .... = Turbo: False
>>>         .... .... ..0. .... = Complementary Code Keying (CCK): False
>>>         .... .... .1.. .... = Orthogonal Frequency-Division
>>> Multiplexing (OFDM): True
>>>         .... .... 0... .... = 2 GHz spectrum: False
>>>         .... ...1 .... .... = 5 GHz spectrum: True
>>>         .... ..0. .... .... = Passive: False
>>>         .... .0.. .... .... = Dynamic CCK-OFDM: False
>>>         .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
>>>         ...0 .... .... .... = GSM (900MHz): False
>>>         ..0. .... .... .... = Static Turbo: False
>>>         .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
>>>         0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
>>>     SSI Signal: -53 dBm
>>>     Antenna: 0
>>>     RX flags: 0x0000
>>>         .... .... .... .... .... ..0. = Bad PLCP: False
>>>     VHT information
>>>         Known VHT information: 0x44
>>>             .... .... .... ...0 = STBC: False
>>>             .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
>>>             .... .... .... .1.. = Guard interval: True
>>>             .... .... .... 0... = SGI Nsym disambiguation: False
>>>             .... .... ...0 .... = LDPC extra OFDM symbol: False
>>>             .... .... ..0. .... = Beamformed: False
>>>             .... .... .1.. .... = Bandwidth: True
>>>             .... .... 0... .... = Group ID: False
>>>             .... ...0 .... .... = Partial AID: False
>>>         .... .0.. = Guard interval: long (0)
>>>         Bandwidth: 80 MHz (4)
>>>         User 0: MCS 8
>>>             1000 .... = MCS index 0: 8 (256-QAM 3/4)
>>>             .... 0010 = Spatial streams 0: 2
>>>             Space-time streams 0: 2
>>>             Coding 0: BCC (0)
>>>             [Data Rate: 702.0 Mb/s]
>>> IEEE 802.11 QoS Data, Flags: .......T
>>>     Type/Subtype: QoS Data (0x28)
>>>     Frame Control Field: 0x8801
>>>         .... ..00 = Version: 0
>>>         .... 10.. = Type: Data frame (2)
>>>         1000 .... = Subtype: 8
>>>         Flags: 0x01
>>>             .... ..01 = DS status: Frame from STA to DS via an AP (To
>>> DS: 1 From DS: 0) (0x01)
>>>             .... .0.. = More Fragments: This is the last fragment
>>>             .... 0... = Retry: Frame is not being retransmitted
>>>             ...0 .... = PWR MGT: STA will stay up
>>>             ..0. .... = More Data: No data buffered
>>>             .0.. .... = Protected flag: Data is not protected
>>>             0... .... = Order flag: Not strictly ordered
>>>     .000 0000 0011 0000 = Duration: 48 microseconds
>>>     Receiver address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>     BSS Id: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>     Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
>>>     Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>     Destination address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>     Fragment number: 0
>>>     Sequence number: 1021
>>>     Qos Control: 0x0080
>>>         .... .... .... 0000 = TID: 0
>>>         [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
>>>         .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control
>>> field are TXOP Duration Requested
>>>         .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
>>>         .... .... 1... .... = Payload Type: A-MSDU
>>>         0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
>>> IEEE 802.11 Aggregate MSDU
>>>     A-MSDU Subframe #1
>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>         A-MSDU Length: 1510
>>>         Logical-Link Control
>>>             DSAP: SNAP (0xaa)
>>>             IG Bit: Individual
>>>             SSAP: SNAP (0xaa)
>>>             CR Bit: Command
>>>             Control field: U, func=UI (0x03)
>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>             Type: IP (0x0800)
>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>             Version: 4
>>>             Header length: 20 bytes
>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>> (Not ECN-Capable Transport) (0x00)
>>>             Total Length: 1500
>>>             Identification: 0xc622 (50722)
>>>             Flags: 0x00
>>>                 0... .... = Reserved bit: Not set
>>>                 .0.. .... = Don't fragment: Not set
>>>                 ..0. .... = More fragments: Not set
>>>             Fragment offset: 0
>>>             Time to live: 64
>>>             Protocol: TCP (6)
>>>             Header checksum: 0x0d4c [correct]
>>>                 [Good: True]
>>>                 [Bad: False]
>>>             Source: 192.168.144.79 (192.168.144.79)
>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>             [Source GeoIP: Unknown]
>>>             [Destination GeoIP: Unknown]
>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>> Port: 5001 (5001), Seq: 1390105, Ack: 1, Len: 1448
>>>             Source port: 52697 (52697)
>>>             Destination port: 5001 (5001)
>>>             [Stream index: 0]
>>>             Sequence number: 1390105    (relative sequence number)
>>>             [Next sequence number: 1391553    (relative sequence number)]
>>>             Acknowledgment number: 1    (relative ack number)
>>>             Header length: 32 bytes
>>>             Flags: 0x010 (ACK)
>>>                 000. .... .... = Reserved: Not set
>>>                 ...0 .... .... = Nonce: Not set
>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>                 .... .0.. .... = ECN-Echo: Not set
>>>                 .... ..0. .... = Urgent: Not set
>>>                 .... ...1 .... = Acknowledgment: Set
>>>                 .... .... 0... = Push: Not set
>>>                 .... .... .0.. = Reset: Not set
>>>                 .... .... ..0. = Syn: Not set
>>>                 .... .... ...0 = Fin: Not set
>>>             Window size value: 8235
>>>             [Calculated window size: 131760]
>>>             [Window size scaling factor: 16]
>>>             Checksum: 0xa1c0 [correct]
>>>                 [Good Checksum: True]
>>>                 [Bad Checksum: False]
>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>> (NOP), Timestamps
>>>                 No-Operation (NOP)
>>>                     Type: 1
>>>                         0... .... = Copy on fragmentation: No
>>>                         .00. .... = Class: Control (0)
>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>                 No-Operation (NOP)
>>>                     Type: 1
>>>                         0... .... = Copy on fragmentation: No
>>>                         .00. .... = Class: Control (0)
>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>                     Kind: Timestamp (8)
>>>                     Length: 10
>>>                     Timestamp value: 1298580657
>>>                     Timestamp echo reply: 4294947481
>>>         Data (1448 bytes)
>>>
>>> 0000  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0010  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0020  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0030  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0040  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0050  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0060  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0070  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0080  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0090  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 00a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 00b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 00c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 00d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 00e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 00f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0100  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0110  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0120  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0130  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0140  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0150  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0160  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0170  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0180  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0190  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 01a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 01b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 01c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 01d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 01e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 01f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0200  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0210  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0220  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0230  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0240  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0250  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0260  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0270  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0280  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0290  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 02a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 02b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 02c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 02d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 02e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 02f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0300  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0310  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0320  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0330  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0340  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0350  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0360  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0370  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0380  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0390  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 03a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 03b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 03c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 03d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 03e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 03f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0400  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0410  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0420  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0430  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0440  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0450  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0460  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0470  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0480  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0490  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 04a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 04b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 04c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 04d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 04e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 04f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0500  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0510  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0520  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0530  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0540  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0550  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0560  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0570  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0580  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0590  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 05a0  34 35 36 37 38 39 30 31                           45678901
>>>             Data: 343536373839303132333435363738393031323334353637...
>>>             [Length: 1448]
>>>     A-MSDU Subframe #2
>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>         A-MSDU Length: 1510
>>>         Logical-Link Control
>>>             DSAP: SNAP (0xaa)
>>>             IG Bit: Individual
>>>             SSAP: SNAP (0xaa)
>>>             CR Bit: Command
>>>             Control field: U, func=UI (0x03)
>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>             Type: IP (0x0800)
>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>             Version: 4
>>>             Header length: 20 bytes
>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>> (Not ECN-Capable Transport) (0x00)
>>>             Total Length: 1500
>>>             Identification: 0xda09 (55817)
>>>             Flags: 0x00
>>>                 0... .... = Reserved bit: Not set
>>>                 .0.. .... = Don't fragment: Not set
>>>                 ..0. .... = More fragments: Not set
>>>             Fragment offset: 0
>>>             Time to live: 64
>>>             Protocol: TCP (6)
>>>             Header checksum: 0xf964 [correct]
>>>                 [Good: True]
>>>                 [Bad: False]
>>>             Source: 192.168.144.79 (192.168.144.79)
>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>             [Source GeoIP: Unknown]
>>>             [Destination GeoIP: Unknown]
>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>> Port: 5001 (5001), Seq: 1391553, Ack: 1, Len: 1448
>>>             Source port: 52697 (52697)
>>>             Destination port: 5001 (5001)
>>>             [Stream index: 0]
>>>             Sequence number: 1391553    (relative sequence number)
>>>             [Next sequence number: 1393001    (relative sequence number)]
>>>             Acknowledgment number: 1    (relative ack number)
>>>             Header length: 32 bytes
>>>             Flags: 0x010 (ACK)
>>>                 000. .... .... = Reserved: Not set
>>>                 ...0 .... .... = Nonce: Not set
>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>                 .... .0.. .... = ECN-Echo: Not set
>>>                 .... ..0. .... = Urgent: Not set
>>>                 .... ...1 .... = Acknowledgment: Set
>>>                 .... .... 0... = Push: Not set
>>>                 .... .... .0.. = Reset: Not set
>>>                 .... .... ..0. = Syn: Not set
>>>                 .... .... ...0 = Fin: Not set
>>>             Window size value: 8235
>>>             [Calculated window size: 131760]
>>>             [Window size scaling factor: 16]
>>>             Checksum: 0x9a16 [incorrect, should be 0x5913 (maybe
>>> caused by "TCP checksum offload"?)]

And yes we are using checksum offload in ath10k.
Best is using standalone 80211ac sniffer for that case to be sure
about checksum.

>>>                 [Good Checksum: False]
>>>                 [Bad Checksum: True]
>>>                     [Expert Info (Error/Checksum): Bad checksum]
>>>                         [Message: Bad checksum]
>>>                         [Severity level: Error]
>>>                         [Group: Checksum]
>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>> (NOP), Timestamps
>>>                 No-Operation (NOP)
>>>                     Type: 1
>>>                         0... .... = Copy on fragmentation: No
>>>                         .00. .... = Class: Control (0)
>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>                 No-Operation (NOP)
>>>                     Type: 1
>>>                         0... .... = Copy on fragmentation: No
>>>                         .00. .... = Class: Control (0)
>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>                     Kind: Timestamp (8)
>>>                     Length: 10
>>>                     Timestamp value: 1298580657
>>>                     Timestamp echo reply: 4294947481
>>>         Data (1448 bytes)
>>>
>>> 0000  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0010  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0020  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0030  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0040  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0050  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0060  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0070  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0080  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0090  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 00a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 00b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 00c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 00d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 00e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 00f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0100  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0110  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0120  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0130  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0140  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0150  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0160  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0170  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0180  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0190  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 01a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 01b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 01c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 01d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>> 01f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0200  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0210  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0220  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0230  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0240  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0250  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0260  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0270  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0280  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0290  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 02a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 02b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 02c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 02d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 02e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 02f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0300  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0310  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0320  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0330  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0340  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0350  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0360  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0370  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0380  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0390  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 03a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 03b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 03c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 03d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 03e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 03f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0400  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0410  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0420  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0430  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0440  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0450  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0460  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0470  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0480  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0490  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 04a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 04b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 04c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 04d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 04e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 04f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0500  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0510  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0520  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0530  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0540  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 0550  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>> 0560  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>> 0570  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>> 0580  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>> 0590  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>> 05a0  32 33 34 35 36 37 38 39                           23456789
>>>             Data: 323334353637383930313233343536373839303132333435...
>>>             [Length: 1448]
>>>
>>> On Mon, Jul 7, 2014 at 12:26 PM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>> The initial results are not promising: a MacOS 802.11ac client gets
>>>> between 0-2 Mbps with this change, where it was getting about 8 Mbps
>>>> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
>>>> from the receiving system shows a very large number of out of order
>>>> frames, likely due to TCP retransmission.
>>>>
>>>> An 802.11n MacBook gets very good throughput, only the 802.11ac
>>>> MacBook shows the very poor result. I'm trying to figure out why.
>>>>
>>>>
>>>> One specific note (and probably not related to the throughput): I
>>>> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
>>>> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
>>>> correctly?
>>>>
>>>>
>>>> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
>>>> <janusz.dziedzic at tieto.com> wrote:
>>>>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>>>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>>>>
>>>>>> The earlier atheros chips would just give you the AMSDU frames as
>>>>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>>>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>>>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>>>>> those sub-frames.
>>>>>>
>>>>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>>>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>>>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>>>>> half of one MPDU before you hit EOL, the next notification you process
>>>>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>>>>> reordering hilarity again.
>>>>>>
>>>>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>>>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>>>>> representing the current MPDU and treat the whole lot as the frame(s)
>>>>>> to care about. Honestly though, I'm kind of wondering whether I should
>>>>>> mostly just do what the Atheros reference driver does and treat it as
>>>>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>>>>> reordering is already done) and just tack on the wifi header bit via
>>>>>> another of the DMA rings.
>>>>>>
>>>>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>>>>
>>>>>>
>>>>>>
>>>>>> -a
>>>>>>
>>>>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>>>>
>>>>>>
>>>>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>>>>> in ieee80211_sta_manage_reorder_buf:
>>>>>>>
>>>>>>> 1. The out-of-date check:
>>>>>>>
>>>>>>>         /* frame with out of date sequence number */
>>>>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>                 goto out;
>>>>>>>         }
>>>>>>>
>>>>>>> As all of the subframes carry the same sequence number, the first
>>>>>>> subframe will be delivered and increment head_seq_num and then all
>>>>>>> subsequent subframes will be discarded.
>>>>>>>
>>>>>>>
>>>>>>> 2. The duplicates check a bit later in the routine:
>>>>>>>
>>>>>>>         /* check if we already stored this frame */
>>>>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>                 goto out;
>>>>>>>         }
>>>>>>>
>>>>>>> If there is enough packet loss that packets are queued in the reorder
>>>>>>> buffer and not immediately released, then only the first subframe will
>>>>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>>>>
>>>>>>>
>>>>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>>>>
>>>>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>>>>> see that it does happen, but it doesn't impact the throughput and I
>>>>>>> can't report the impact of fixing it.
>>>>>>>
>>>>>>> ----
>>>>>>>
>>>>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>>>>> match the mac80211 expectations.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>> Yes, after some more testing it does look like an unfortunate
>>>>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>>>>> subframes all carry the same sequence number. The first subframe is
>>>>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>>>>
>>>>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>>>>> head=0xb06
>>>>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>>>>> head=0xb0b
>>>>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>>>>> head=0xb10
>>>>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>>>>> head=0xb15
>>>>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>>>>> head=0xb1a
>>>>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>>>>> head=0xb1f
>>>>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>>>>> head=0xb24
>>>>>>>>
>>>>>>>>
>>>>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>>>>
>>>>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>>>>> frame makes it through.
>>>>>>>>>>
>>>>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>>>>
>>>>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>>>>> A-MSDU.
>>>>>>>>>
>>>>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>>>>
>>>>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>>>>
>>>>> Denton could you try attached patch: report amsdu in one big frame.
>>>>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>>>>> improve performance and reduce memcpy, while currently we have skb
>>>>> frames, put them in one big skb and next cfg80211 split them again
>>>>> into msdus and report to stack.
>>>>>
>>>>> BR
>>>>> Janusz


From bartosz.markowski at tieto.com  Tue Jul  8 03:46:09 2014
From: bartosz.markowski at tieto.com (Bartosz Markowski)
Date: Tue, 8 Jul 2014 12:46:09 +0200
Subject: [RFC 1/2] ath10k: add implementation for configure max amsdu,
 ampdu
In-Reply-To: <871tvv9qll.fsf@kamboji.qca.qualcomm.com>
References: <1400151186-24949-1-git-send-email-janusz.dziedzic@tieto.com>
 <87egzv9te9.fsf@kamboji.qca.qualcomm.com>
 <CALhHN=o_KUjGWN4sEWaGxc3xKmXt2TdmcYsBT9O8rnixcv2q=A@mail.gmail.com>
 <871tvv9qll.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CACKGw+GGXjwVgcY-akTMT31uqG+a3wo+ghd5HUmQWe-1jjCL5Q@mail.gmail.com>

On 15 May 2014 14:24, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:
>
>> On 15 May 2014 13:24, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>>
>>> Did you somehow check that this command works as it should?
>>
>> Added WMI_DEBUG_EVENT in FW (_htt_tgt_tx_aggr_cfg):
>>
>> May 15 12:47:30 dell kernel: [ 6777.355444] ath10k: wmi event debug
>> print 'xxx amsdu: 3, ampdu: 64' // This is default :)
>> May 15 12:47:30 dell kernel: [ 6777.355477] ath10k: wmi event debug
>> print 'xxx data: 0x00014005, 81925'
>> May 15 12:47:30 dell kernel: [ 6777.355520] ath10k: wmi event debug
>> print 'xxx amsdu: 1, ampdu: 64'
>
> Ok, that's one way to test as well. I was more thinking about using
> sniffer or another way to check what's really happening on the air.

ok, so we have finally testing this (V2:
http://permalink.gmane.org/gmane.linux.kernel.wireless.general/124128)
today as it looks like the root issue may be similar to the macBook
IOT problem reported by Denton here:
http://lists.infradead.org/pipermail/ath10k/2014-July/002576.html

Anyway the commands are working fine and we can set the desired
aggregation settings.

-Bartosz


From bartosz.markowski at tieto.com  Tue Jul  8 03:59:11 2014
From: bartosz.markowski at tieto.com (Bartosz Markowski)
Date: Tue, 8 Jul 2014 12:59:11 +0200
Subject: A-MSDU reception not working?
In-Reply-To: <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
 <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>
 <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>
Message-ID: <CACKGw+HAsUHk2u5MF_cOzi-J+krv67VJeyCUtBeKaqwaMHGRdQ@mail.gmail.com>

On 8 July 2014 09:02, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:

[...]

> BTW, when AP (ath10k) send TCP ACK - are this packets also AMSDU?
> I see in my case AP can send 3 x A-MSDU (with total size 304 bytes)
> small frames aggregated. Maybe your HW have problems with that.

@Denton - could you please try to apply this patch -->
http://permalink.gmane.org/gmane.linux.kernel.wireless.general/124128
(adds debugfs entires so you can manually configure ampdu/amsdu
settings) and check whether setting the amsdu to 1 will bypass the
problem (gets rid of aggregated TCP ACKs)

echo "1 64" > htt_max_amsdu_ampdu

As Janusz wrote ath10k has enabled checksum offloads, so we do not
think the retransmissions you noticed, by sniffing via ath10k device,
are due to the CRC erorrs.

> As I remember correctly someone some time ago report problems with
> MacBook pro retina but I am not sure this is the same, while no one
> tests the fix.

This is it: http://lists.infradead.org/pipermail/ath10k/2014-May/001917.html.
We checked that time and got a hint from firmware guys there was an
IOT problem with amsdu 3 setting in our AP with BRCM sta. Can follow
up on this if that's the case here also.

-Bartosz


From denton.gentry at gmail.com  Tue Jul  8 22:42:55 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Tue, 8 Jul 2014 22:42:55 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CACKGw+HAsUHk2u5MF_cOzi-J+krv67VJeyCUtBeKaqwaMHGRdQ@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
 <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>
 <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>
 <CACKGw+HAsUHk2u5MF_cOzi-J+krv67VJeyCUtBeKaqwaMHGRdQ@mail.gmail.com>
Message-ID: <CABnBrYX+8uaPPvJsoUhjMOy45F+7Z-isXJkVyc-b9-J5Tb2FGA@mail.gmail.com>

On Tue, Jul 8, 2014 at 3:59 AM, Bartosz Markowski
<bartosz.markowski at tieto.com> wrote:
> On 8 July 2014 09:02, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>
> [...]
>
>> BTW, when AP (ath10k) send TCP ACK - are this packets also AMSDU?
>> I see in my case AP can send 3 x A-MSDU (with total size 304 bytes)
>> small frames aggregated. Maybe your HW have problems with that.
>
> @Denton - could you please try to apply this patch -->
> http://permalink.gmane.org/gmane.linux.kernel.wireless.general/124128
> (adds debugfs entires so you can manually configure ampdu/amsdu
> settings) and check whether setting the amsdu to 1 will bypass the
> problem (gets rid of aggregated TCP ACKs)
>
> echo "1 64" > htt_max_amsdu_ampdu

I applied the patch and used echo "1 64" >
/sys/.../htt_max_amsdu_ampdu. It did not improve the throughput of the
802.11ac MacBook Air.

Even without applying this patch, the sniffer trace does not show the
TCP ACKs going back to the MacBook being aggregated as A-MSDU. They
are either individual frames or A-MPDU.


> As Janusz wrote ath10k has enabled checksum offloads, so we do not
> think the retransmissions you noticed, by sniffing via ath10k device,
> are due to the CRC erorrs.
>
>> As I remember correctly someone some time ago report problems with
>> MacBook pro retina but I am not sure this is the same, while no one
>> tests the fix.
>
> This is it: http://lists.infradead.org/pipermail/ath10k/2014-May/001917.html.
> We checked that time and got a hint from firmware guys there was an
> IOT problem with amsdu 3 setting in our AP with BRCM sta. Can follow
> up on this if that's the case here also.
>
> -Bartosz


From denton.gentry at gmail.com  Tue Jul  8 23:09:05 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Tue, 8 Jul 2014 23:09:05 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CALhHN=pvh8qocDzoMvK--__hJD1PVe5CrPBVriC1w=Bx1cpxpg@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
 <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>
 <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>
 <CALhHN=pvh8qocDzoMvK--__hJD1PVe5CrPBVriC1w=Bx1cpxpg@mail.gmail.com>
Message-ID: <CABnBrYVY_KY8mMAKhy-DV1s3+vut8oR_LohyBJX3GtW7RT=3XA@mail.gmail.com>

I ran iperf on an 802.11ac MacBook Air, through my ath10 AP, and to an
Ubuntu system connected to the AP via Ethernet. The AP was running the
reorder buffer patches, the patch to make A-MSDU bypass the reorder
buffer, and the patch to make amsdu aggregation configurable via
debugfs.

http://lists.infradead.org/pipermail/ath10k/2014-June/002551.html
http://lists.infradead.org/pipermail/ath10k/2014-June/002553.html
http://lists.infradead.org/pipermail/ath10k/2014-July/002597.html
http://permalink.gmane.org/gmane.linux.kernel.wireless.general/124128

It was notably not running the patch from earlier in this thread to
copy A-MSDU subframes into one skb.


I used a second ath10k AP configured in monitor mode as a Wifi
sniffer. I also gathered pcaps on the MacBook Air and on the Ubuntu
system. Wireshark on the MacBook cannot gather radiotap headers nor
put the interface into monitor mode, so we see only Ethernet frames
and we don't see retransmissions on the Wifi link.

I've attached decodes of the same two packets as captured by the
MacBook, by the sniffer, and by the Ubuntu server.

The MacBook sends two frames, TCP sequence numbers 3065441 and 3066889
(the Wireshark "relative sequence number"). In the Wifi sniffer we see
these being aggregated as two subframes in an A-MSDU frame. The first
time this A-MSDU is sent it is corrupted in the air. We see the TCP
checksum of one of the subframes is wrong, and a few bytes of the
payload replaced with "&gt%'g9(1$".

The A-MSDU is retransmitted a short time later, and the second time
the TCP checksum of both subframes is correct.

This is all fine so far.

However in the pcap taken from the Ubuntu server, we see TCP sequence
number 3065441 being delivered *twice.* The first time, the TCP
checksum is wrong. The second time the TCP checksum is correct.

To me, it looks like A-MSDU frames with bad FCS are not being
discarded after ieee80211_rx_monitor(). The corrupted frames are being
delivered. Delivering the corrupted frames results in sending more TCP
Dup ACKs for the same sequence number back to the MacBook, and I think
this is what causes the MacBook to decide there is congestion and slow
down.

One note: the wifi sniffer does not show the same corruption to the
same packet as the pcap from the Ubuntu system shows. I think that is
normal: the sniffer won't see precisely the same noise, won't have
precisely the same receive sensitivity, and its antennas are not
pointing in the same direction as the primary AP. If I do this test
again, I'll gather a pcap on the primary AP as well to compare to what
we see on the Ubuntu system.


On Tue, Jul 8, 2014 at 12:29 AM, Janusz Dziedzic
<janusz.dziedzic at tieto.com> wrote:
> On 8 July 2014 09:02, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>> On 8 July 2014 08:50, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>>> On 8 July 2014 08:43, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>> I think I know what is happening now, though I've no idea why. The
>>>> throughput is low because we have many TCP retransmissions. We have
>>>> retransmissions because the TCP checksum is wrong on a number of
>>>> frames, and I do find data corruption in the payload so the checksum
>>>> definitely should be wrong. All of the corrupted frames were
>>>> originally one of the subframes in an A-MSDU packet.
>>>>
>>>> An example follows at the end of this message, as dissected by
>>>> Wireshark. iperf sends a very regular data pattern of "0123456789..."
>>>> over and over. Note how in subframe #2 offset 0x1e0 the bytes "32 33
>>>> 34" have been replaced by "72 36 35"
>>>>
>>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>>
>>>> I added printks at the bottom of ath10k_htt_rx_amsdu immediately
>>>> before the call to ath10k_process_rx. I found this same packet, and we
>>>> see the "72 36 35" corruption in the printk. So I think it happened in
>>>> ath10k_process_rx or before, not anything weird after passing it up to
>>>> mac80211.
>>>>
>>>> [  101.863712] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>>> [  101.863727] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>> [  101.863742] ath10k: 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32
>>>> [  101.863757] ath10k: 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37 38
>>>> [  101.863773] ath10k: 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34
>>>> [  101.863788] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>>> [  101.863803] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>>
>>>>
>>>> I've found a number of examples of similar corruption, always with
>>>> between one and four bytes replaced.
>>>>
>>>> 35363738 -> e52c6e07
>>>> 3435 -> b43f
>>>> 3839 -> c238
>>>> 31 -> 7f
>>>> 3435 -> 7436
>>>> 30 -> 50
>>>> 3233 -> bc37
>>>>
>>> Seems this could be because of:
>>>
>>> + /* cfg80211 expect this padding */
>>> + padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
>>> + skb_put(skb, padding);
>>>
>>
>> BTW, when AP (ath10k) send TCP ACK - are this packets also AMSDU?
>> I see in my case AP can send 3 x A-MSDU (with total size 304 bytes)
>> small frames aggregated. Maybe your HW have problems with that.
>> As I remember correctly someone some time ago report problems with
>> MacBook pro retina but I am not sure this is the same, while no one
>> tests the fix.
>>
>>>>
>>>> The packet described above, dissected by Wireshark:
>>>>
>>>> No.     Time        Source                Destination
>>>> Protocol Length Info
>>>>    2235 18.953349   192.168.144.79        192.168.144.13        TCP
>>>>   3112   52697 > 5001 [ACK] Seq=1391553 Ack=1 Win=131760 [TCP CHECKSUM
>>>> INCORRECT] Len=1448 TSval=1298580657 TSecr=4294947481
>>>>
>>>> Frame 2235: 3112 bytes on wire (24896 bits), 3112 bytes captured (24896 bits)
>>>>     Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
>>>>     Arrival Time: Jul  7, 2014 23:03:37.763365000 PDT
>>>>     [Time shift for this packet: 0.000000000 seconds]
>>>>     Epoch Time: 1404799417.763365000 seconds
>>>>     [Time delta from previous captured frame: 0.003476000 seconds]
>>>>     [Time delta from previous displayed frame: 0.515641000 seconds]
>>>>     [Time since reference or first frame: 18.953349000 seconds]
>>>>     Frame Number: 2235
>>>>     Frame Length: 3112 bytes (24896 bits)
>>>>     Capture Length: 3112 bytes (24896 bits)
>>>>     [Frame is marked: False]
>>>>     [Frame is ignored: False]
>>>>     [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
>>>>     [Coloring Rule Name: TCP]
>>>>     [Coloring Rule String: tcp]
>>>> Radiotap Header v0, Length 38
>>>>     Header revision: 0
>>>>     Header pad: 0
>>>>     Header length: 38
>>>>     Present flags
>>>>         .... .... .... .... .... .... .... ...1 = TSFT: True
>>>>         .... .... .... .... .... .... .... ..1. = Flags: True
>>>>         .... .... .... .... .... .... .... .0.. = Rate: False
>>>>         .... .... .... .... .... .... .... 1... = Channel: True
>>>>         .... .... .... .... .... .... ...0 .... = FHSS: False
>>>>         .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
>>>>         .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
>>>>         .... .... .... .... .... .... 0... .... = Lock Quality: False
>>>>         .... .... .... .... .... ...0 .... .... = TX Attenuation: False
>>>>         .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
>>>>         .... .... .... .... .... .0.. .... .... = dBm TX Power: False
>>>>         .... .... .... .... .... 1... .... .... = Antenna: True
>>>>         .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
>>>>         .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
>>>>         .... .... .... .... .1.. .... .... .... = RX flags: True
>>>>         .... .... .... .0.. .... .... .... .... = Channel+: False
>>>>         .... .... .... 0... .... .... .... .... = HT information: False
>>>>         .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
>>>>         .... .... ..1. .... .... .... .... .... = VHT information: True
>>>>         ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
>>>>         ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
>>>>         .0.. .... .... .... .... .... .... .... = Vendor NS next: False
>>>>         0... .... .... .... .... .... .... .... = Ext: False
>>>>     MAC timestamp: 78051063
>>>>     Flags: 0x00
>>>>         .... ...0 = CFP: False
>>>>         .... ..0. = Preamble: Long
>>>>         .... .0.. = WEP: False
>>>>         .... 0... = Fragmentation: False
>>>>         ...0 .... = FCS at end: False
>>>>         ..0. .... = Data Pad: False
>>>>         .0.. .... = Bad FCS: False
>>>>         0... .... = Short GI: False
>>>>     Channel frequency: 5745 [A 149]
>>>>     Channel type: 802.11a (0x0140)
>>>>         .... .... ...0 .... = Turbo: False
>>>>         .... .... ..0. .... = Complementary Code Keying (CCK): False
>>>>         .... .... .1.. .... = Orthogonal Frequency-Division
>>>> Multiplexing (OFDM): True
>>>>         .... .... 0... .... = 2 GHz spectrum: False
>>>>         .... ...1 .... .... = 5 GHz spectrum: True
>>>>         .... ..0. .... .... = Passive: False
>>>>         .... .0.. .... .... = Dynamic CCK-OFDM: False
>>>>         .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
>>>>         ...0 .... .... .... = GSM (900MHz): False
>>>>         ..0. .... .... .... = Static Turbo: False
>>>>         .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
>>>>         0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
>>>>     SSI Signal: -53 dBm
>>>>     Antenna: 0
>>>>     RX flags: 0x0000
>>>>         .... .... .... .... .... ..0. = Bad PLCP: False
>>>>     VHT information
>>>>         Known VHT information: 0x44
>>>>             .... .... .... ...0 = STBC: False
>>>>             .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
>>>>             .... .... .... .1.. = Guard interval: True
>>>>             .... .... .... 0... = SGI Nsym disambiguation: False
>>>>             .... .... ...0 .... = LDPC extra OFDM symbol: False
>>>>             .... .... ..0. .... = Beamformed: False
>>>>             .... .... .1.. .... = Bandwidth: True
>>>>             .... .... 0... .... = Group ID: False
>>>>             .... ...0 .... .... = Partial AID: False
>>>>         .... .0.. = Guard interval: long (0)
>>>>         Bandwidth: 80 MHz (4)
>>>>         User 0: MCS 8
>>>>             1000 .... = MCS index 0: 8 (256-QAM 3/4)
>>>>             .... 0010 = Spatial streams 0: 2
>>>>             Space-time streams 0: 2
>>>>             Coding 0: BCC (0)
>>>>             [Data Rate: 702.0 Mb/s]
>>>> IEEE 802.11 QoS Data, Flags: .......T
>>>>     Type/Subtype: QoS Data (0x28)
>>>>     Frame Control Field: 0x8801
>>>>         .... ..00 = Version: 0
>>>>         .... 10.. = Type: Data frame (2)
>>>>         1000 .... = Subtype: 8
>>>>         Flags: 0x01
>>>>             .... ..01 = DS status: Frame from STA to DS via an AP (To
>>>> DS: 1 From DS: 0) (0x01)
>>>>             .... .0.. = More Fragments: This is the last fragment
>>>>             .... 0... = Retry: Frame is not being retransmitted
>>>>             ...0 .... = PWR MGT: STA will stay up
>>>>             ..0. .... = More Data: No data buffered
>>>>             .0.. .... = Protected flag: Data is not protected
>>>>             0... .... = Order flag: Not strictly ordered
>>>>     .000 0000 0011 0000 = Duration: 48 microseconds
>>>>     Receiver address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>     BSS Id: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>     Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>     Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>     Destination address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>     Fragment number: 0
>>>>     Sequence number: 1021
>>>>     Qos Control: 0x0080
>>>>         .... .... .... 0000 = TID: 0
>>>>         [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
>>>>         .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control
>>>> field are TXOP Duration Requested
>>>>         .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
>>>>         .... .... 1... .... = Payload Type: A-MSDU
>>>>         0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
>>>> IEEE 802.11 Aggregate MSDU
>>>>     A-MSDU Subframe #1
>>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>         A-MSDU Length: 1510
>>>>         Logical-Link Control
>>>>             DSAP: SNAP (0xaa)
>>>>             IG Bit: Individual
>>>>             SSAP: SNAP (0xaa)
>>>>             CR Bit: Command
>>>>             Control field: U, func=UI (0x03)
>>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>>             Type: IP (0x0800)
>>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>>             Version: 4
>>>>             Header length: 20 bytes
>>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>>> (Not ECN-Capable Transport) (0x00)
>>>>             Total Length: 1500
>>>>             Identification: 0xc622 (50722)
>>>>             Flags: 0x00
>>>>                 0... .... = Reserved bit: Not set
>>>>                 .0.. .... = Don't fragment: Not set
>>>>                 ..0. .... = More fragments: Not set
>>>>             Fragment offset: 0
>>>>             Time to live: 64
>>>>             Protocol: TCP (6)
>>>>             Header checksum: 0x0d4c [correct]
>>>>                 [Good: True]
>>>>                 [Bad: False]
>>>>             Source: 192.168.144.79 (192.168.144.79)
>>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>>             [Source GeoIP: Unknown]
>>>>             [Destination GeoIP: Unknown]
>>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>>> Port: 5001 (5001), Seq: 1390105, Ack: 1, Len: 1448
>>>>             Source port: 52697 (52697)
>>>>             Destination port: 5001 (5001)
>>>>             [Stream index: 0]
>>>>             Sequence number: 1390105    (relative sequence number)
>>>>             [Next sequence number: 1391553    (relative sequence number)]
>>>>             Acknowledgment number: 1    (relative ack number)
>>>>             Header length: 32 bytes
>>>>             Flags: 0x010 (ACK)
>>>>                 000. .... .... = Reserved: Not set
>>>>                 ...0 .... .... = Nonce: Not set
>>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>>                 .... .0.. .... = ECN-Echo: Not set
>>>>                 .... ..0. .... = Urgent: Not set
>>>>                 .... ...1 .... = Acknowledgment: Set
>>>>                 .... .... 0... = Push: Not set
>>>>                 .... .... .0.. = Reset: Not set
>>>>                 .... .... ..0. = Syn: Not set
>>>>                 .... .... ...0 = Fin: Not set
>>>>             Window size value: 8235
>>>>             [Calculated window size: 131760]
>>>>             [Window size scaling factor: 16]
>>>>             Checksum: 0xa1c0 [correct]
>>>>                 [Good Checksum: True]
>>>>                 [Bad Checksum: False]
>>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>>> (NOP), Timestamps
>>>>                 No-Operation (NOP)
>>>>                     Type: 1
>>>>                         0... .... = Copy on fragmentation: No
>>>>                         .00. .... = Class: Control (0)
>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>                 No-Operation (NOP)
>>>>                     Type: 1
>>>>                         0... .... = Copy on fragmentation: No
>>>>                         .00. .... = Class: Control (0)
>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>>                     Kind: Timestamp (8)
>>>>                     Length: 10
>>>>                     Timestamp value: 1298580657
>>>>                     Timestamp echo reply: 4294947481
>>>>         Data (1448 bytes)
>>>>
>>>> 0000  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0010  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0020  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0030  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0040  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0050  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0060  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0070  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0080  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0090  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 00a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 00b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 00c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 00d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 00e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 00f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0100  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0110  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0120  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0130  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0140  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0150  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0160  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0170  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0180  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0190  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 01a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 01b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 01c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 01d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 01e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 01f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0200  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0210  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0220  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0230  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0240  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0250  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0260  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0270  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0280  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0290  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 02a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 02b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 02c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 02d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 02e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 02f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0300  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0310  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0320  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0330  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0340  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0350  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0360  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0370  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0380  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0390  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 03a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 03b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 03c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 03d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 03e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 03f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0400  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0410  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0420  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0430  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0440  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0450  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0460  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0470  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0480  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0490  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 04a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 04b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 04c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 04d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 04e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 04f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0500  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0510  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0520  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0530  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0540  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0550  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0560  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0570  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0580  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0590  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 05a0  34 35 36 37 38 39 30 31                           45678901
>>>>             Data: 343536373839303132333435363738393031323334353637...
>>>>             [Length: 1448]
>>>>     A-MSDU Subframe #2
>>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>         A-MSDU Length: 1510
>>>>         Logical-Link Control
>>>>             DSAP: SNAP (0xaa)
>>>>             IG Bit: Individual
>>>>             SSAP: SNAP (0xaa)
>>>>             CR Bit: Command
>>>>             Control field: U, func=UI (0x03)
>>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>>             Type: IP (0x0800)
>>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>>             Version: 4
>>>>             Header length: 20 bytes
>>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>>> (Not ECN-Capable Transport) (0x00)
>>>>             Total Length: 1500
>>>>             Identification: 0xda09 (55817)
>>>>             Flags: 0x00
>>>>                 0... .... = Reserved bit: Not set
>>>>                 .0.. .... = Don't fragment: Not set
>>>>                 ..0. .... = More fragments: Not set
>>>>             Fragment offset: 0
>>>>             Time to live: 64
>>>>             Protocol: TCP (6)
>>>>             Header checksum: 0xf964 [correct]
>>>>                 [Good: True]
>>>>                 [Bad: False]
>>>>             Source: 192.168.144.79 (192.168.144.79)
>>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>>             [Source GeoIP: Unknown]
>>>>             [Destination GeoIP: Unknown]
>>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>>> Port: 5001 (5001), Seq: 1391553, Ack: 1, Len: 1448
>>>>             Source port: 52697 (52697)
>>>>             Destination port: 5001 (5001)
>>>>             [Stream index: 0]
>>>>             Sequence number: 1391553    (relative sequence number)
>>>>             [Next sequence number: 1393001    (relative sequence number)]
>>>>             Acknowledgment number: 1    (relative ack number)
>>>>             Header length: 32 bytes
>>>>             Flags: 0x010 (ACK)
>>>>                 000. .... .... = Reserved: Not set
>>>>                 ...0 .... .... = Nonce: Not set
>>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>>                 .... .0.. .... = ECN-Echo: Not set
>>>>                 .... ..0. .... = Urgent: Not set
>>>>                 .... ...1 .... = Acknowledgment: Set
>>>>                 .... .... 0... = Push: Not set
>>>>                 .... .... .0.. = Reset: Not set
>>>>                 .... .... ..0. = Syn: Not set
>>>>                 .... .... ...0 = Fin: Not set
>>>>             Window size value: 8235
>>>>             [Calculated window size: 131760]
>>>>             [Window size scaling factor: 16]
>>>>             Checksum: 0x9a16 [incorrect, should be 0x5913 (maybe
>>>> caused by "TCP checksum offload"?)]
>
> And yes we are using checksum offload in ath10k.
> Best is using standalone 80211ac sniffer for that case to be sure
> about checksum.
>
>>>>                 [Good Checksum: False]
>>>>                 [Bad Checksum: True]
>>>>                     [Expert Info (Error/Checksum): Bad checksum]
>>>>                         [Message: Bad checksum]
>>>>                         [Severity level: Error]
>>>>                         [Group: Checksum]
>>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>>> (NOP), Timestamps
>>>>                 No-Operation (NOP)
>>>>                     Type: 1
>>>>                         0... .... = Copy on fragmentation: No
>>>>                         .00. .... = Class: Control (0)
>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>                 No-Operation (NOP)
>>>>                     Type: 1
>>>>                         0... .... = Copy on fragmentation: No
>>>>                         .00. .... = Class: Control (0)
>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>>                     Kind: Timestamp (8)
>>>>                     Length: 10
>>>>                     Timestamp value: 1298580657
>>>>                     Timestamp echo reply: 4294947481
>>>>         Data (1448 bytes)
>>>>
>>>> 0000  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0010  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0020  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0030  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0040  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0050  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0060  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0070  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0080  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0090  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 00a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 00b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 00c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 00d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 00e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 00f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0100  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0110  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0120  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0130  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0140  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0150  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0160  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0170  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0180  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0190  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 01a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 01b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 01c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 01d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>> 01f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0200  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0210  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0220  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0230  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0240  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0250  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0260  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0270  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0280  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0290  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 02a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 02b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 02c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 02d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 02e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 02f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0300  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0310  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0320  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0330  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0340  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0350  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0360  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0370  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0380  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0390  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 03a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 03b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 03c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 03d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 03e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 03f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0400  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0410  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0420  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0430  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0440  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0450  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0460  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0470  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0480  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0490  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 04a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 04b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 04c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 04d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 04e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 04f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0500  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0510  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0520  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0530  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0540  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 0550  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>> 0560  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>> 0570  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>> 0580  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>> 0590  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>> 05a0  32 33 34 35 36 37 38 39                           23456789
>>>>             Data: 323334353637383930313233343536373839303132333435...
>>>>             [Length: 1448]
>>>>
>>>> On Mon, Jul 7, 2014 at 12:26 PM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>> The initial results are not promising: a MacOS 802.11ac client gets
>>>>> between 0-2 Mbps with this change, where it was getting about 8 Mbps
>>>>> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
>>>>> from the receiving system shows a very large number of out of order
>>>>> frames, likely due to TCP retransmission.
>>>>>
>>>>> An 802.11n MacBook gets very good throughput, only the 802.11ac
>>>>> MacBook shows the very poor result. I'm trying to figure out why.
>>>>>
>>>>>
>>>>> One specific note (and probably not related to the throughput): I
>>>>> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
>>>>> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
>>>>> correctly?
>>>>>
>>>>>
>>>>> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
>>>>> <janusz.dziedzic at tieto.com> wrote:
>>>>>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>>>>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>>>>>
>>>>>>> The earlier atheros chips would just give you the AMSDU frames as
>>>>>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>>>>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>>>>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>>>>>> those sub-frames.
>>>>>>>
>>>>>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>>>>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>>>>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>>>>>> half of one MPDU before you hit EOL, the next notification you process
>>>>>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>>>>>> reordering hilarity again.
>>>>>>>
>>>>>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>>>>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>>>>>> representing the current MPDU and treat the whole lot as the frame(s)
>>>>>>> to care about. Honestly though, I'm kind of wondering whether I should
>>>>>>> mostly just do what the Atheros reference driver does and treat it as
>>>>>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>>>>>> reordering is already done) and just tack on the wifi header bit via
>>>>>>> another of the DMA rings.
>>>>>>>
>>>>>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> -a
>>>>>>>
>>>>>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>>>>>
>>>>>>>
>>>>>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>>>>>> in ieee80211_sta_manage_reorder_buf:
>>>>>>>>
>>>>>>>> 1. The out-of-date check:
>>>>>>>>
>>>>>>>>         /* frame with out of date sequence number */
>>>>>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>>                 goto out;
>>>>>>>>         }
>>>>>>>>
>>>>>>>> As all of the subframes carry the same sequence number, the first
>>>>>>>> subframe will be delivered and increment head_seq_num and then all
>>>>>>>> subsequent subframes will be discarded.
>>>>>>>>
>>>>>>>>
>>>>>>>> 2. The duplicates check a bit later in the routine:
>>>>>>>>
>>>>>>>>         /* check if we already stored this frame */
>>>>>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>>                 goto out;
>>>>>>>>         }
>>>>>>>>
>>>>>>>> If there is enough packet loss that packets are queued in the reorder
>>>>>>>> buffer and not immediately released, then only the first subframe will
>>>>>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>>>>>
>>>>>>>>
>>>>>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>>>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>>>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>>>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>>>>>
>>>>>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>>>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>>>>>> see that it does happen, but it doesn't impact the throughput and I
>>>>>>>> can't report the impact of fixing it.
>>>>>>>>
>>>>>>>> ----
>>>>>>>>
>>>>>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>>>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>>>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>>>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>>>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>>>>>> match the mac80211 expectations.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>> Yes, after some more testing it does look like an unfortunate
>>>>>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>>>>>> subframes all carry the same sequence number. The first subframe is
>>>>>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>>>>>
>>>>>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>>>>>> head=0xb06
>>>>>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>>>>>> head=0xb0b
>>>>>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>>>>>> head=0xb10
>>>>>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>>>>>> head=0xb15
>>>>>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>>>>>> head=0xb1a
>>>>>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>>>>>> head=0xb1f
>>>>>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>>>>>> head=0xb24
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>>>>>
>>>>>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>>>>>> frame makes it through.
>>>>>>>>>>>
>>>>>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>>>>>
>>>>>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>>>>>> A-MSDU.
>>>>>>>>>>
>>>>>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>>>>>
>>>>>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>>>>>
>>>>>> Denton could you try attached patch: report amsdu in one big frame.
>>>>>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>>>>>> improve performance and reduce memcpy, while currently we have skb
>>>>>> frames, put them in one big skb and next cfg80211 split them again
>>>>>> into msdus and report to stack.
>>>>>>
>>>>>> BR
>>>>>> Janusz
-------------- next part --------------
No.     Time           Source                Destination           Protocol Length Info
   3793 5.784865000    192.168.254.52        192.168.254.1         TCP      1514   52734 > 5001 [ACK] Seq=3065441 Ack=1 Win=131760 Len=1448 TSval=1302514011 TSecr=328746582

Frame 3793: 1514 bytes on wire (12112 bits), 1514 bytes captured (12112 bits) on interface 0
    Interface id: 0
    Encapsulation type: Ethernet (1)
    Arrival Time: Jul  8, 2014 11:24:38.171552000 PDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1404843878.171552000 seconds
    [Time delta from previous captured frame: 0.000001000 seconds]
    [Time delta from previous displayed frame: 0.000001000 seconds]
    [Time since reference or first frame: 5.784865000 seconds]
    Frame Number: 3793
    Frame Length: 1514 bytes (12112 bits)
    Capture Length: 1514 bytes (12112 bits)
    [Frame is marked: True]
    [Frame is ignored: False]
    [Protocols in frame: eth:ip:tcp:data]
    [Coloring Rule Name: TCP]
    [Coloring Rule String: tcp]
Ethernet II, Src: Apple_67:24:54 (84:38:35:67:24:54), Dst: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
    Destination: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        Address: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Apple_67:24:54 (84:38:35:67:24:54)
        Address: Apple_67:24:54 (84:38:35:67:24:54)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IP (0x0800)
Internet Protocol Version 4, Src: 192.168.254.52 (192.168.254.52), Dst: 192.168.254.1 (192.168.254.1)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
        0000 00.. = Differentiated Services Codepoint: Default (0x00)
        .... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)
    Total Length: 1500
    Identification: 0xa03d (41021)
    Flags: 0x02 (Don't Fragment)
        0... .... = Reserved bit: Not set
        .1.. .... = Don't fragment: Set
        ..0. .... = More fragments: Not set
    Fragment offset: 0
    Time to live: 64
    Protocol: TCP (6)
    Header checksum: 0x1757 [correct]
        [Good: True]
        [Bad: False]
    Source: 192.168.254.52 (192.168.254.52)
    Destination: 192.168.254.1 (192.168.254.1)
    [Source GeoIP: Unknown]
    [Destination GeoIP: Unknown]
Transmission Control Protocol, Src Port: 52734 (52734), Dst Port: 5001 (5001), Seq: 3065441, Ack: 1, Len: 1448
    Source port: 52734 (52734)
    Destination port: 5001 (5001)
    [Stream index: 0]
    Sequence number: 3065441    (relative sequence number)
    [Next sequence number: 3066889    (relative sequence number)]
    Acknowledgment number: 1    (relative ack number)
    Header length: 32 bytes
    Flags: 0x010 (ACK)
        000. .... .... = Reserved: Not set
        ...0 .... .... = Nonce: Not set
        .... 0... .... = Congestion Window Reduced (CWR): Not set
        .... .0.. .... = ECN-Echo: Not set
        .... ..0. .... = Urgent: Not set
        .... ...1 .... = Acknowledgment: Set
        .... .... 0... = Push: Not set
        .... .... .0.. = Reset: Not set
        .... .... ..0. = Syn: Not set
        .... .... ...0 = Fin: Not set
    Window size value: 8235
    [Calculated window size: 131760]
    [Window size scaling factor: 16]
    Checksum: 0x1b72 [correct]
        [Good Checksum: True]
        [Bad Checksum: False]
    Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
        No-Operation (NOP)
            Type: 1
                0... .... = Copy on fragmentation: No
                .00. .... = Class: Control (0)
                ...0 0001 = Number: No-Operation (NOP) (1)
        No-Operation (NOP)
            Type: 1
                0... .... = Copy on fragmentation: No
                .00. .... = Class: Control (0)
                ...0 0001 = Number: No-Operation (NOP) (1)
        Timestamps: TSval 1302514011, TSecr 328746582
            Kind: Timestamp (8)
            Length: 10
            Timestamp value: 1302514011
            Timestamp echo reply: 328746582
    [SEQ/ACK analysis]
        [Bytes in flight: 5792]
Data (1448 bytes)

0000  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0010  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0020  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0030  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0040  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0050  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0060  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0070  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0080  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0090  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
00b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0100  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0110  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0120  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0130  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0140  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0150  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0160  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0170  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0180  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0190  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
01b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
01c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
01e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0200  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0210  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0220  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0230  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0240  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0250  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0260  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0270  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0280  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0290  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
02b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0300  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0310  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0320  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0330  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0340  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0350  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0360  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0370  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0380  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0390  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
03b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
03c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0400  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0410  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0420  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0430  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0440  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0450  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0460  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0470  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0480  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0490  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
04b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0500  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0510  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0520  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0530  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0540  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0550  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0560  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0570  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0580  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0590  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
05a0  30 31 32 33 34 35 36 37                           01234567
    Data: 303132333435363738393031323334353637383930313233...
    [Length: 1448]

No.     Time           Source                Destination           Protocol Length Info
   3794 5.784894000    192.168.254.52        192.168.254.1         TCP      1514   52734 > 5001 [ACK] Seq=3066889 Ack=1 Win=131760 Len=1448 TSval=1302514011 TSecr=328746582

Frame 3794: 1514 bytes on wire (12112 bits), 1514 bytes captured (12112 bits) on interface 0
    Interface id: 0
    Encapsulation type: Ethernet (1)
    Arrival Time: Jul  8, 2014 11:24:38.171581000 PDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1404843878.171581000 seconds
    [Time delta from previous captured frame: 0.000029000 seconds]
    [Time delta from previous displayed frame: 0.000029000 seconds]
    [Time since reference or first frame: 5.784894000 seconds]
    Frame Number: 3794
    Frame Length: 1514 bytes (12112 bits)
    Capture Length: 1514 bytes (12112 bits)
    [Frame is marked: True]
    [Frame is ignored: False]
    [Protocols in frame: eth:ip:tcp:data]
    [Coloring Rule Name: TCP]
    [Coloring Rule String: tcp]
Ethernet II, Src: Apple_67:24:54 (84:38:35:67:24:54), Dst: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
    Destination: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        Address: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Apple_67:24:54 (84:38:35:67:24:54)
        Address: Apple_67:24:54 (84:38:35:67:24:54)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IP (0x0800)
Internet Protocol Version 4, Src: 192.168.254.52 (192.168.254.52), Dst: 192.168.254.1 (192.168.254.1)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
        0000 00.. = Differentiated Services Codepoint: Default (0x00)
        .... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)
    Total Length: 1500
    Identification: 0xc127 (49447)
    Flags: 0x02 (Don't Fragment)
        0... .... = Reserved bit: Not set
        .1.. .... = Don't fragment: Set
        ..0. .... = More fragments: Not set
    Fragment offset: 0
    Time to live: 64
    Protocol: TCP (6)
    Header checksum: 0xf66c [correct]
        [Good: True]
        [Bad: False]
    Source: 192.168.254.52 (192.168.254.52)
    Destination: 192.168.254.1 (192.168.254.1)
    [Source GeoIP: Unknown]
    [Destination GeoIP: Unknown]
Transmission Control Protocol, Src Port: 52734 (52734), Dst Port: 5001 (5001), Seq: 3066889, Ack: 1, Len: 1448
    Source port: 52734 (52734)
    Destination port: 5001 (5001)
    [Stream index: 0]
    Sequence number: 3066889    (relative sequence number)
    [Next sequence number: 3068337    (relative sequence number)]
    Acknowledgment number: 1    (relative ack number)
    Header length: 32 bytes
    Flags: 0x010 (ACK)
        000. .... .... = Reserved: Not set
        ...0 .... .... = Nonce: Not set
        .... 0... .... = Congestion Window Reduced (CWR): Not set
        .... .0.. .... = ECN-Echo: Not set
        .... ..0. .... = Urgent: Not set
        .... ...1 .... = Acknowledgment: Set
        .... .... 0... = Push: Not set
        .... .... .0.. = Reset: Not set
        .... .... ..0. = Syn: Not set
        .... .... ...0 = Fin: Not set
    Window size value: 8235
    [Calculated window size: 131760]
    [Window size scaling factor: 16]
    Checksum: 0x13c8 [correct]
        [Good Checksum: True]
        [Bad Checksum: False]
    Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
        No-Operation (NOP)
            Type: 1
                0... .... = Copy on fragmentation: No
                .00. .... = Class: Control (0)
                ...0 0001 = Number: No-Operation (NOP) (1)
        No-Operation (NOP)
            Type: 1
                0... .... = Copy on fragmentation: No
                .00. .... = Class: Control (0)
                ...0 0001 = Number: No-Operation (NOP) (1)
        Timestamps: TSval 1302514011, TSecr 328746582
            Kind: Timestamp (8)
            Length: 10
            Timestamp value: 1302514011
            Timestamp echo reply: 328746582
    [SEQ/ACK analysis]
        [Bytes in flight: 7240]
Data (1448 bytes)

0000  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0010  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0020  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0030  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0040  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0050  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0060  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0070  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0080  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0090  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
00d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0100  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0110  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0120  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0130  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0140  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0150  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0160  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0170  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0180  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0190  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
01b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
01d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
01e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0200  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0210  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0220  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0230  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0240  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0250  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0260  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0270  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0280  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0290  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
02d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0300  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0310  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0320  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0330  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0340  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0350  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0360  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0370  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0380  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0390  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
03d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
03e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0400  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0410  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0420  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0430  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0440  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0450  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0460  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0470  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0480  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0490  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
04d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0500  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0510  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0520  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0530  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0540  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0550  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0560  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0570  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0580  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0590  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
05a0  38 39 30 31 32 33 34 35                           89012345
    Data: 383930313233343536373839303132333435363738393031...
    [Length: 1448]
-------------- next part --------------
No.     Time        Source                Destination           Protocol Length Info
   3886 4.594969    192.168.254.52        192.168.254.1         TCP      1514   [TCP Retransmission] 52734 > 5001 [ACK] Seq=3065441 Ack=1 Win=131760 [TCP CHECKSUM INCORRECT] Len=1448 TSval=1302514011 TSecr=328746582

Frame 3886: 1514 bytes on wire (12112 bits), 1514 bytes captured (12112 bits)
    Encapsulation type: Ethernet (1)
    Arrival Time: Jul  8, 2014 11:24:39.084614000 PDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1404843879.084614000 seconds
    [Time delta from previous captured frame: 0.000041000 seconds]
    [Time delta from previous displayed frame: 0.000041000 seconds]
    [Time since reference or first frame: 4.594969000 seconds]
    Frame Number: 3886
    Frame Length: 1514 bytes (12112 bits)
    Capture Length: 1514 bytes (12112 bits)
    [Frame is marked: True]
    [Frame is ignored: False]
    [Protocols in frame: eth:ip:tcp:data]
    [Coloring Rule Name: TCP]
    [Coloring Rule String: tcp]
Ethernet II, Src: Apple_67:24:54 (84:38:35:67:24:54), Dst: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
    Destination: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        Address: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Apple_67:24:54 (84:38:35:67:24:54)
        Address: Apple_67:24:54 (84:38:35:67:24:54)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IP (0x0800)
Internet Protocol Version 4, Src: 192.168.254.52 (192.168.254.52), Dst: 192.168.254.1 (192.168.254.1)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
        0000 00.. = Differentiated Services Codepoint: Default (0x00)
        .... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)
    Total Length: 1500
    Identification: 0xa03d (41021)
    Flags: 0x02 (Don't Fragment)
        0... .... = Reserved bit: Not set
        .1.. .... = Don't fragment: Set
        ..0. .... = More fragments: Not set
    Fragment offset: 0
    Time to live: 64
    Protocol: TCP (6)
    Header checksum: 0x1757 [correct]
        [Good: True]
        [Bad: False]
    Source: 192.168.254.52 (192.168.254.52)
    Destination: 192.168.254.1 (192.168.254.1)
    [Source GeoIP: Unknown]
    [Destination GeoIP: Unknown]
Transmission Control Protocol, Src Port: 52734 (52734), Dst Port: 5001 (5001), Seq: 3065441, Ack: 1, Len: 1448
    Source port: 52734 (52734)
    Destination port: 5001 (5001)
    [Stream index: 0]
    Sequence number: 3065441    (relative sequence number)
    [Next sequence number: 3066889    (relative sequence number)]
    Acknowledgment number: 1    (relative ack number)
    Header length: 32 bytes
    Flags: 0x010 (ACK)
        000. .... .... = Reserved: Not set
        ...0 .... .... = Nonce: Not set
        .... 0... .... = Congestion Window Reduced (CWR): Not set
        .... .0.. .... = ECN-Echo: Not set
        .... ..0. .... = Urgent: Not set
        .... ...1 .... = Acknowledgment: Set
        .... .... 0... = Push: Not set
        .... .... .0.. = Reset: Not set
        .... .... ..0. = Syn: Not set
        .... .... ...0 = Fin: Not set
    Window size value: 8235
    [Calculated window size: 131760]
    [Window size scaling factor: 16]
    Checksum: 0x1b72 [incorrect, should be 0x2ac9 (maybe caused by "TCP checksum offload"?)]
        [Good Checksum: False]
        [Bad Checksum: True]
            [Expert Info (Error/Checksum): Bad checksum]
                [Message: Bad checksum]
                [Severity level: Error]
                [Group: Checksum]
    Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
        No-Operation (NOP)
            Type: 1
                0... .... = Copy on fragmentation: No
                .00. .... = Class: Control (0)
                ...0 0001 = Number: No-Operation (NOP) (1)
        No-Operation (NOP)
            Type: 1
                0... .... = Copy on fragmentation: No
                .00. .... = Class: Control (0)
                ...0 0001 = Number: No-Operation (NOP) (1)
        Timestamps: TSval 1302514011, TSecr 328746582
            Kind: Timestamp (8)
            Length: 10
            Timestamp value: 1302514011
            Timestamp echo reply: 328746582
    [SEQ/ACK analysis]
        [Bytes in flight: 814161224]
        [TCP Analysis Flags]
            [This frame is a (suspected) retransmission]
                [Expert Info (Note/Sequence): Retransmission (suspected)]
                    [Message: Retransmission (suspected)]
                    [Severity level: Note]
                    [Group: Sequence]
            [The RTO for this segment was: 1.371819000 seconds]
            [RTO based on delta from frame: 1038]
Data (1448 bytes)

0000  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0010  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0020  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0030  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0040  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0050  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0060  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0070  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0080  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0090  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
00b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0100  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0110  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0120  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0130  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0140  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0150  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0160  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0170  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0180  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0190  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
01b0  32 33 34 35 36 37 38 39 9a 31 38 19 94 b7 36 37   23456789.18...67
01c0  38 39 30 31 32 33 34 35 36 37 38 39 30 91 92 b1   8901234567890...
01d0  9c 1f 36 37 38 39 30 31 32 33 34 35 36 37 38 39   ..67890123456789
01e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0200  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0210  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0220  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0230  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0240  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0250  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0260  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0270  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0280  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0290  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
02b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02e0  36 37 38 39 30 31 32 33 20 61 23 22 3c 39 30 31   67890123 a#"<901
02f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0300  38 39 30 31 32 11 36 3f 9c 3d 3a b1 38 19 9a 99   89012.6?.=:.8...
0310  34 bd 14 9d b2 b3 98 b3 38 3b 16 b7 14 9d b2 1b   4.......8;......
0320  3a 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   :123456789012345
0330  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0340  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0350  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0360  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0370  30 31 32 33 34 35 36 37 38 39 30 31 32 33 74 30   01234567890123t0
0380  32 36 38 39 30 31 32 33 34 35 36 37 38 39 30 31   2689012345678901
0390  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03a0  38 39 30 31 32 33 34 35 36 37 1a 3b 3a 9b 9a bb   8901234567.;:...
03b0  36 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   6567890123456789
03c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0400  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0410  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0420  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0430  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0440  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0450  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0460  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0470  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0480  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0490  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
04b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0500  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0510  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0520  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0530  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0540  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0550  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0560  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0570  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0580  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0590  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
05a0  30 31 32 33 34 35 36 37                           01234567
    Data: 303132333435363738393031323334353637383930313233...
    [Length: 1448]

No.     Time        Source                Destination           Protocol Length Info
   3891 4.595330    192.168.254.52        192.168.254.1         TCP      1514   [TCP Out-Of-Order] 52734 > 5001 [ACK] Seq=3065441 Ack=1 Win=131760 Len=1448 TSval=1302514011 TSecr=328746582

Frame 3891: 1514 bytes on wire (12112 bits), 1514 bytes captured (12112 bits)
    Encapsulation type: Ethernet (1)
    Arrival Time: Jul  8, 2014 11:24:39.084975000 PDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1404843879.084975000 seconds
    [Time delta from previous captured frame: 0.000006000 seconds]
    [Time delta from previous displayed frame: 0.000006000 seconds]
    [Time since reference or first frame: 4.595330000 seconds]
    Frame Number: 3891
    Frame Length: 1514 bytes (12112 bits)
    Capture Length: 1514 bytes (12112 bits)
    [Frame is marked: True]
    [Frame is ignored: False]
    [Protocols in frame: eth:ip:tcp:data]
    [Coloring Rule Name: TCP]
    [Coloring Rule String: tcp]
Ethernet II, Src: Apple_67:24:54 (84:38:35:67:24:54), Dst: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
    Destination: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        Address: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Apple_67:24:54 (84:38:35:67:24:54)
        Address: Apple_67:24:54 (84:38:35:67:24:54)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IP (0x0800)
Internet Protocol Version 4, Src: 192.168.254.52 (192.168.254.52), Dst: 192.168.254.1 (192.168.254.1)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
        0000 00.. = Differentiated Services Codepoint: Default (0x00)
        .... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)
    Total Length: 1500
    Identification: 0xa03d (41021)
    Flags: 0x02 (Don't Fragment)
        0... .... = Reserved bit: Not set
        .1.. .... = Don't fragment: Set
        ..0. .... = More fragments: Not set
    Fragment offset: 0
    Time to live: 64
    Protocol: TCP (6)
    Header checksum: 0x1757 [correct]
        [Good: True]
        [Bad: False]
    Source: 192.168.254.52 (192.168.254.52)
    Destination: 192.168.254.1 (192.168.254.1)
    [Source GeoIP: Unknown]
    [Destination GeoIP: Unknown]
Transmission Control Protocol, Src Port: 52734 (52734), Dst Port: 5001 (5001), Seq: 3065441, Ack: 1, Len: 1448
    Source port: 52734 (52734)
    Destination port: 5001 (5001)
    [Stream index: 0]
    Sequence number: 3065441    (relative sequence number)
    [Next sequence number: 3066889    (relative sequence number)]
    Acknowledgment number: 1    (relative ack number)
    Header length: 32 bytes
    Flags: 0x010 (ACK)
        000. .... .... = Reserved: Not set
        ...0 .... .... = Nonce: Not set
        .... 0... .... = Congestion Window Reduced (CWR): Not set
        .... .0.. .... = ECN-Echo: Not set
        .... ..0. .... = Urgent: Not set
        .... ...1 .... = Acknowledgment: Set
        .... .... 0... = Push: Not set
        .... .... .0.. = Reset: Not set
        .... .... ..0. = Syn: Not set
        .... .... ...0 = Fin: Not set
    Window size value: 8235
    [Calculated window size: 131760]
    [Window size scaling factor: 16]
    Checksum: 0x1b72 [correct]
        [Good Checksum: True]
        [Bad Checksum: False]
    Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
        No-Operation (NOP)
            Type: 1
                0... .... = Copy on fragmentation: No
                .00. .... = Class: Control (0)
                ...0 0001 = Number: No-Operation (NOP) (1)
        No-Operation (NOP)
            Type: 1
                0... .... = Copy on fragmentation: No
                .00. .... = Class: Control (0)
                ...0 0001 = Number: No-Operation (NOP) (1)
        Timestamps: TSval 1302514011, TSecr 328746582
            Kind: Timestamp (8)
            Length: 10
            Timestamp value: 1302514011
            Timestamp echo reply: 328746582
    [SEQ/ACK analysis]
        [TCP Analysis Flags]
            [This frame is a (suspected) out-of-order segment]
                [Expert Info (Warn/Sequence): Out-Of-Order segment]
                    [Message: Out-Of-Order segment]
                    [Severity level: Warn]
                    [Group: Sequence]
Data (1448 bytes)

0000  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0010  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0020  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0030  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0040  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0050  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0060  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0070  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0080  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0090  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
00b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0100  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0110  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0120  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0130  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0140  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0150  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0160  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0170  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0180  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0190  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
01b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
01c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
01e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0200  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0210  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0220  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0230  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0240  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0250  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0260  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0270  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0280  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0290  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
02b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0300  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0310  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0320  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0330  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0340  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0350  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0360  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0370  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0380  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0390  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
03b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
03c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0400  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0410  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0420  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0430  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0440  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0450  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0460  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0470  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0480  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0490  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
04b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0500  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0510  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0520  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0530  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0540  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0550  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0560  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0570  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0580  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0590  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
05a0  30 31 32 33 34 35 36 37                           01234567
    Data: 303132333435363738393031323334353637383930313233...
    [Length: 1448]
-------------- next part --------------
No.     Time        Source                Destination           Protocol Length Info
   5549 15.608617   192.168.254.52        192.168.254.1         TCP      3110   52734 > 5001 [ACK] Seq=3066889 Ack=1 Win=131760 [TCP CHECKSUM INCORRECT] Len=1448 TSval=1302514011 TSecr=328746582

Frame 5549: 3110 bytes on wire (24880 bits), 3110 bytes captured (24880 bits)
    Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
    Arrival Time: Jul  8, 2014 11:24:39.082371000 PDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1404843879.082371000 seconds
    [Time delta from previous captured frame: 0.000079000 seconds]
    [Time delta from previous displayed frame: 0.000079000 seconds]
    [Time since reference or first frame: 15.608617000 seconds]
    Frame Number: 5549
    Frame Length: 3110 bytes (24880 bits)
    Capture Length: 3110 bytes (24880 bits)
    [Frame is marked: True]
    [Frame is ignored: False]
    [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
    [Coloring Rule Name: TCP]
    [Coloring Rule String: tcp]
Radiotap Header v0, Length 38
    Header revision: 0
    Header pad: 0
    Header length: 38
    Present flags
        .... .... .... .... .... .... .... ...1 = TSFT: True
        .... .... .... .... .... .... .... ..1. = Flags: True
        .... .... .... .... .... .... .... .0.. = Rate: False
        .... .... .... .... .... .... .... 1... = Channel: True
        .... .... .... .... .... .... ...0 .... = FHSS: False
        .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
        .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
        .... .... .... .... .... .... 0... .... = Lock Quality: False
        .... .... .... .... .... ...0 .... .... = TX Attenuation: False
        .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
        .... .... .... .... .... .0.. .... .... = dBm TX Power: False
        .... .... .... .... .... 1... .... .... = Antenna: True
        .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
        .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
        .... .... .... .... .1.. .... .... .... = RX flags: True
        .... .... .... .0.. .... .... .... .... = Channel+: False
        .... .... .... 0... .... .... .... .... = HT information: False
        .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
        .... .... ..1. .... .... .... .... .... = VHT information: True
        ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
        ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
        .0.. .... .... .... .... .... .... .... = Vendor NS next: False
        0... .... .... .... .... .... .... .... = Ext: False
    MAC timestamp: 1395542308
    Flags: 0x40
        .... ...0 = CFP: False
        .... ..0. = Preamble: Long
        .... .0.. = WEP: False
        .... 0... = Fragmentation: False
        ...0 .... = FCS at end: False
        ..0. .... = Data Pad: False
        .1.. .... = Bad FCS: True
        0... .... = Short GI: False
    Channel frequency: 5745 [A 149]
    Channel type: 802.11a (0x0140)
        .... .... ...0 .... = Turbo: False
        .... .... ..0. .... = Complementary Code Keying (CCK): False
        .... .... .1.. .... = Orthogonal Frequency-Division Multiplexing (OFDM): True
        .... .... 0... .... = 2 GHz spectrum: False
        .... ...1 .... .... = 5 GHz spectrum: True
        .... ..0. .... .... = Passive: False
        .... .0.. .... .... = Dynamic CCK-OFDM: False
        .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
        ...0 .... .... .... = GSM (900MHz): False
        ..0. .... .... .... = Static Turbo: False
        .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
        0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
    SSI Signal: -46 dBm
    Antenna: 0
    RX flags: 0x0000
        .... .... .... .... .... ..0. = Bad PLCP: False
    VHT information
        Known VHT information: 0x44
            .... .... .... ...0 = STBC: False
            .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
            .... .... .... .1.. = Guard interval: True
            .... .... .... 0... = SGI Nsym disambiguation: False
            .... .... ...0 .... = LDPC extra OFDM symbol: False
            .... .... ..0. .... = Beamformed: False
            .... .... .1.. .... = Bandwidth: True
            .... .... 0... .... = Group ID: False
            .... ...0 .... .... = Partial AID: False
        .... .0.. = Guard interval: long (0)
        Bandwidth: 80 MHz (4)
        User 0: MCS 9
            1001 .... = MCS index 0: 9 (256-QAM 5/6)
            .... 0010 = Spatial streams 0: 2
            Space-time streams 0: 2
            Coding 0: BCC (0)
            [Data Rate: 780.0 Mb/s]
IEEE 802.11 QoS Data, Flags: .......T
    Type/Subtype: QoS Data (0x28)
    Frame Control Field: 0x8801
        .... ..00 = Version: 0
        .... 10.. = Type: Data frame (2)
        1000 .... = Subtype: 8
        Flags: 0x01
            .... ..01 = DS status: Frame from STA to DS via an AP (To DS: 1 From DS: 0) (0x01)
            .... .0.. = More Fragments: This is the last fragment
            .... 0... = Retry: Frame is not being retransmitted
            ...0 .... = PWR MGT: STA will stay up
            ..0. .... = More Data: No data buffered
            .0.. .... = Protected flag: Data is not protected
            0... .... = Order flag: Not strictly ordered
    .000 0000 0011 0000 = Duration: 48 microseconds
    Receiver address: SenaoNet_18:a7:d0 (88:dc:96:18:a7:d0)
    BSS Id: SenaoNet_18:a7:d0 (88:dc:96:18:a7:d0)
    Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
    Source address: Apple_67:24:54 (84:38:35:67:24:54)
    Destination address: SenaoNet_18:a7:d0 (88:dc:96:18:a7:d0)
    Fragment number: 0
    Sequence number: 1391
    Qos Control: 0x0080
        .... .... .... 0000 = TID: 0
        [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
        .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control field are TXOP Duration Requested
        .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
        .... .... 1... .... = Payload Type: A-MSDU
        0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
IEEE 802.11 Aggregate MSDU
    A-MSDU Subframe #1
        Destination address: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        Source address: Apple_67:24:54 (84:38:35:67:24:54)
        A-MSDU Length: 1508
        Logical-Link Control
            DSAP: SNAP (0xaa)
            IG Bit: Individual
            SSAP: SNAP (0xaa)
            CR Bit: Command
            Control field: U, func=UI (0x03)
                000. 00.. = Command: Unnumbered Information (0x00)
                .... ..11 = Frame type: Unnumbered frame (0x03)
            Organization Code: Encapsulated Ethernet (0x000000)
            Type: IP (0x0800)
        Internet Protocol Version 4, Src: 192.168.254.52 (192.168.254.52), Dst: 192.168.254.1 (192.168.254.1)
            Version: 4
            Header length: 20 bytes
            Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
                0000 00.. = Differentiated Services Codepoint: Default (0x00)
                .... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)
            Total Length: 1500
            Identification: 0xa03d (41021)
            Flags: 0x02 (Don't Fragment)
                0... .... = Reserved bit: Not set
                .1.. .... = Don't fragment: Set
                ..0. .... = More fragments: Not set
            Fragment offset: 0
            Time to live: 64
            Protocol: TCP (6)
            Header checksum: 0x1757 [correct]
                [Good: True]
                [Bad: False]
            Source: 192.168.254.52 (192.168.254.52)
            Destination: 192.168.254.1 (192.168.254.1)
            [Source GeoIP: Unknown]
            [Destination GeoIP: Unknown]
        Transmission Control Protocol, Src Port: 52734 (52734), Dst Port: 5001 (5001), Seq: 3065441, Ack: 1, Len: 1448
            Source port: 52734 (52734)
            Destination port: 5001 (5001)
            [Stream index: 0]
            Sequence number: 3065441    (relative sequence number)
            [Next sequence number: 3066889    (relative sequence number)]
            Acknowledgment number: 1    (relative ack number)
            Header length: 32 bytes
            Flags: 0x010 (ACK)
                000. .... .... = Reserved: Not set
                ...0 .... .... = Nonce: Not set
                .... 0... .... = Congestion Window Reduced (CWR): Not set
                .... .0.. .... = ECN-Echo: Not set
                .... ..0. .... = Urgent: Not set
                .... ...1 .... = Acknowledgment: Set
                .... .... 0... = Push: Not set
                .... .... .0.. = Reset: Not set
                .... .... ..0. = Syn: Not set
                .... .... ...0 = Fin: Not set
            Window size value: 8235
            [Calculated window size: 131760]
            [Window size scaling factor: 16]
            Checksum: 0x1b72 [correct]
                [Good Checksum: True]
                [Bad Checksum: False]
            Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                Timestamps: TSval 1302514011, TSecr 328746582
                    Kind: Timestamp (8)
                    Length: 10
                    Timestamp value: 1302514011
                    Timestamp echo reply: 328746582
        Data (1448 bytes)

0000  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0010  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0020  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0030  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0040  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0050  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0060  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0070  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0080  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0090  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
00b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0100  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0110  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0120  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0130  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0140  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0150  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0160  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0170  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0180  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0190  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
01b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
01c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
01e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0200  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0210  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0220  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0230  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0240  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0250  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0260  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0270  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0280  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0290  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
02b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0300  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0310  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0320  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0330  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0340  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0350  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0360  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0370  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0380  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0390  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
03b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
03c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0400  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0410  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0420  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0430  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0440  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0450  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0460  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0470  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0480  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0490  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
04b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0500  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0510  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0520  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0530  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0540  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0550  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0560  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0570  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0580  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0590  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
05a0  30 31 32 33 34 35 36 37                           01234567
            Data: 303132333435363738393031323334353637383930313233...
            [Length: 1448]
    A-MSDU Subframe #2
        Destination address: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        Source address: Apple_67:24:54 (84:38:35:67:24:54)
        A-MSDU Length: 1508
        Logical-Link Control
            DSAP: SNAP (0xaa)
            IG Bit: Individual
            SSAP: SNAP (0xaa)
            CR Bit: Command
            Control field: U, func=UI (0x03)
                000. 00.. = Command: Unnumbered Information (0x00)
                .... ..11 = Frame type: Unnumbered frame (0x03)
            Organization Code: Encapsulated Ethernet (0x000000)
            Type: IP (0x0800)
        Internet Protocol Version 4, Src: 192.168.254.52 (192.168.254.52), Dst: 192.168.254.1 (192.168.254.1)
            Version: 4
            Header length: 20 bytes
            Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
                0000 00.. = Differentiated Services Codepoint: Default (0x00)
                .... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)
            Total Length: 1500
            Identification: 0xc127 (49447)
            Flags: 0x02 (Don't Fragment)
                0... .... = Reserved bit: Not set
                .1.. .... = Don't fragment: Set
                ..0. .... = More fragments: Not set
            Fragment offset: 0
            Time to live: 64
            Protocol: TCP (6)
            Header checksum: 0xf66c [correct]
                [Good: True]
                [Bad: False]
            Source: 192.168.254.52 (192.168.254.52)
            Destination: 192.168.254.1 (192.168.254.1)
            [Source GeoIP: Unknown]
            [Destination GeoIP: Unknown]
        Transmission Control Protocol, Src Port: 52734 (52734), Dst Port: 5001 (5001), Seq: 3066889, Ack: 1, Len: 1448
            Source port: 52734 (52734)
            Destination port: 5001 (5001)
            [Stream index: 0]
            Sequence number: 3066889    (relative sequence number)
            [Next sequence number: 3068337    (relative sequence number)]
            Acknowledgment number: 1    (relative ack number)
            Header length: 32 bytes
            Flags: 0x010 (ACK)
                000. .... .... = Reserved: Not set
                ...0 .... .... = Nonce: Not set
                .... 0... .... = Congestion Window Reduced (CWR): Not set
                .... .0.. .... = ECN-Echo: Not set
                .... ..0. .... = Urgent: Not set
                .... ...1 .... = Acknowledgment: Set
                .... .... 0... = Push: Not set
                .... .... .0.. = Reset: Not set
                .... .... ..0. = Syn: Not set
                .... .... ...0 = Fin: Not set
            Window size value: 8235
            [Calculated window size: 131760]
            [Window size scaling factor: 16]
            Checksum: 0x13c8 [incorrect, should be 0xe891 (maybe caused by "TCP checksum offload"?)]
                [Good Checksum: False]
                [Bad Checksum: True]
                    [Expert Info (Error/Checksum): Bad checksum]
                        [Message: Bad checksum]
                        [Severity level: Error]
                        [Group: Checksum]
            Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                Timestamps: TSval 1302514011, TSecr 328746582
                    Kind: Timestamp (8)
                    Length: 10
                    Timestamp value: 1302514011
                    Timestamp echo reply: 328746582
        Data (1448 bytes)

0000  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0010  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0020  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0030  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0040  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0050  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0060  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0070  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0080  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0090  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
00d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0100  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0110  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0120  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0130  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0140  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0150  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0160  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0170  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0180  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0190  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
01b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
01d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
01e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0200  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0210  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0220  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0230  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0240  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0250  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0260  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0270  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0280  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0290  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
02d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0300  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0310  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0320  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0330  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0340  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0350  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0360  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0370  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0380  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0390  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
03d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
03e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0400  32 33 34 35 36 37 38 39 30 31 26 67 74 25 27 67   2345678901&gt%'g
0410  39 28 31 24 36 33 34 35 36 37 38 39 30 31 32 33   9(1$634567890123
0420  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0430  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0440  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0450  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0460  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0470  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0480  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0490  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
04d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0500  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0510  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0520  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0530  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0540  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0550  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0560  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0570  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0580  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0590  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
05a0  38 39 30 31 32 33 34 35                           89012345
            Data: 383930313233343536373839303132333435363738393031...
            [Length: 1448]

No.     Time        Source                Destination           Protocol Length Info
   5556 15.609203   192.168.254.52        192.168.254.1         TCP      3110   52734 > 5001 [ACK] Seq=3066889 Ack=1 Win=131760 Len=1448 TSval=1302514011 TSecr=328746582

Frame 5556: 3110 bytes on wire (24880 bits), 3110 bytes captured (24880 bits)
    Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
    Arrival Time: Jul  8, 2014 11:24:39.082957000 PDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1404843879.082957000 seconds
    [Time delta from previous captured frame: 0.000066000 seconds]
    [Time delta from previous displayed frame: 0.000066000 seconds]
    [Time since reference or first frame: 15.609203000 seconds]
    Frame Number: 5556
    Frame Length: 3110 bytes (24880 bits)
    Capture Length: 3110 bytes (24880 bits)
    [Frame is marked: True]
    [Frame is ignored: False]
    [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
    [Coloring Rule Name: TCP]
    [Coloring Rule String: tcp]
Radiotap Header v0, Length 38
    Header revision: 0
    Header pad: 0
    Header length: 38
    Present flags
        .... .... .... .... .... .... .... ...1 = TSFT: True
        .... .... .... .... .... .... .... ..1. = Flags: True
        .... .... .... .... .... .... .... .0.. = Rate: False
        .... .... .... .... .... .... .... 1... = Channel: True
        .... .... .... .... .... .... ...0 .... = FHSS: False
        .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
        .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
        .... .... .... .... .... .... 0... .... = Lock Quality: False
        .... .... .... .... .... ...0 .... .... = TX Attenuation: False
        .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
        .... .... .... .... .... .0.. .... .... = dBm TX Power: False
        .... .... .... .... .... 1... .... .... = Antenna: True
        .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
        .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
        .... .... .... .... .1.. .... .... .... = RX flags: True
        .... .... .... .0.. .... .... .... .... = Channel+: False
        .... .... .... 0... .... .... .... .... = HT information: False
        .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
        .... .... ..1. .... .... .... .... .... = VHT information: True
        ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
        ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
        .0.. .... .... .... .... .... .... .... = Vendor NS next: False
        0... .... .... .... .... .... .... .... = Ext: False
    MAC timestamp: 1395542664
    Flags: 0x00
        .... ...0 = CFP: False
        .... ..0. = Preamble: Long
        .... .0.. = WEP: False
        .... 0... = Fragmentation: False
        ...0 .... = FCS at end: False
        ..0. .... = Data Pad: False
        .0.. .... = Bad FCS: False
        0... .... = Short GI: False
    Channel frequency: 5745 [A 149]
    Channel type: 802.11a (0x0140)
        .... .... ...0 .... = Turbo: False
        .... .... ..0. .... = Complementary Code Keying (CCK): False
        .... .... .1.. .... = Orthogonal Frequency-Division Multiplexing (OFDM): True
        .... .... 0... .... = 2 GHz spectrum: False
        .... ...1 .... .... = 5 GHz spectrum: True
        .... ..0. .... .... = Passive: False
        .... .0.. .... .... = Dynamic CCK-OFDM: False
        .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
        ...0 .... .... .... = GSM (900MHz): False
        ..0. .... .... .... = Static Turbo: False
        .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
        0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
    SSI Signal: -46 dBm
    Antenna: 0
    RX flags: 0x0000
        .... .... .... .... .... ..0. = Bad PLCP: False
    VHT information
        Known VHT information: 0x44
            .... .... .... ...0 = STBC: False
            .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
            .... .... .... .1.. = Guard interval: True
            .... .... .... 0... = SGI Nsym disambiguation: False
            .... .... ...0 .... = LDPC extra OFDM symbol: False
            .... .... ..0. .... = Beamformed: False
            .... .... .1.. .... = Bandwidth: True
            .... .... 0... .... = Group ID: False
            .... ...0 .... .... = Partial AID: False
        .... .0.. = Guard interval: long (0)
        Bandwidth: 80 MHz (4)
        User 0: MCS 9
            1001 .... = MCS index 0: 9 (256-QAM 5/6)
            .... 0010 = Spatial streams 0: 2
            Space-time streams 0: 2
            Coding 0: BCC (0)
            [Data Rate: 780.0 Mb/s]
IEEE 802.11 QoS Data, Flags: ....R..T
    Type/Subtype: QoS Data (0x28)
    Frame Control Field: 0x8809
        .... ..00 = Version: 0
        .... 10.. = Type: Data frame (2)
        1000 .... = Subtype: 8
        Flags: 0x09
            .... ..01 = DS status: Frame from STA to DS via an AP (To DS: 1 From DS: 0) (0x01)
            .... .0.. = More Fragments: This is the last fragment
            .... 1... = Retry: Frame is being retransmitted
                [Expert Info (Note/Sequence): Retransmission (retry)]
                    [Message: Retransmission (retry)]
                    [Severity level: Note]
                    [Group: Sequence]
            ...0 .... = PWR MGT: STA will stay up
            ..0. .... = More Data: No data buffered
            .0.. .... = Protected flag: Data is not protected
            0... .... = Order flag: Not strictly ordered
    .000 0000 0011 0000 = Duration: 48 microseconds
    Receiver address: SenaoNet_18:a7:d0 (88:dc:96:18:a7:d0)
    BSS Id: SenaoNet_18:a7:d0 (88:dc:96:18:a7:d0)
    Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
    Source address: Apple_67:24:54 (84:38:35:67:24:54)
    Destination address: SenaoNet_18:a7:d0 (88:dc:96:18:a7:d0)
    Fragment number: 0
    Sequence number: 1391
    Qos Control: 0x0080
        .... .... .... 0000 = TID: 0
        [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
        .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control field are TXOP Duration Requested
        .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
        .... .... 1... .... = Payload Type: A-MSDU
        0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
IEEE 802.11 Aggregate MSDU
    A-MSDU Subframe #1
        Destination address: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        Source address: Apple_67:24:54 (84:38:35:67:24:54)
        A-MSDU Length: 1508
        Logical-Link Control
            DSAP: SNAP (0xaa)
            IG Bit: Individual
            SSAP: SNAP (0xaa)
            CR Bit: Command
            Control field: U, func=UI (0x03)
                000. 00.. = Command: Unnumbered Information (0x00)
                .... ..11 = Frame type: Unnumbered frame (0x03)
            Organization Code: Encapsulated Ethernet (0x000000)
            Type: IP (0x0800)
        Internet Protocol Version 4, Src: 192.168.254.52 (192.168.254.52), Dst: 192.168.254.1 (192.168.254.1)
            Version: 4
            Header length: 20 bytes
            Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
                0000 00.. = Differentiated Services Codepoint: Default (0x00)
                .... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)
            Total Length: 1500
            Identification: 0xa03d (41021)
            Flags: 0x02 (Don't Fragment)
                0... .... = Reserved bit: Not set
                .1.. .... = Don't fragment: Set
                ..0. .... = More fragments: Not set
            Fragment offset: 0
            Time to live: 64
            Protocol: TCP (6)
            Header checksum: 0x1757 [correct]
                [Good: True]
                [Bad: False]
            Source: 192.168.254.52 (192.168.254.52)
            Destination: 192.168.254.1 (192.168.254.1)
            [Source GeoIP: Unknown]
            [Destination GeoIP: Unknown]
        Transmission Control Protocol, Src Port: 52734 (52734), Dst Port: 5001 (5001), Seq: 3065441, Ack: 1, Len: 1448
            Source port: 52734 (52734)
            Destination port: 5001 (5001)
            [Stream index: 0]
            Sequence number: 3065441    (relative sequence number)
            [Next sequence number: 3066889    (relative sequence number)]
            Acknowledgment number: 1    (relative ack number)
            Header length: 32 bytes
            Flags: 0x010 (ACK)
                000. .... .... = Reserved: Not set
                ...0 .... .... = Nonce: Not set
                .... 0... .... = Congestion Window Reduced (CWR): Not set
                .... .0.. .... = ECN-Echo: Not set
                .... ..0. .... = Urgent: Not set
                .... ...1 .... = Acknowledgment: Set
                .... .... 0... = Push: Not set
                .... .... .0.. = Reset: Not set
                .... .... ..0. = Syn: Not set
                .... .... ...0 = Fin: Not set
            Window size value: 8235
            [Calculated window size: 131760]
            [Window size scaling factor: 16]
            Checksum: 0x1b72 [correct]
                [Good Checksum: True]
                [Bad Checksum: False]
            Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                Timestamps: TSval 1302514011, TSecr 328746582
                    Kind: Timestamp (8)
                    Length: 10
                    Timestamp value: 1302514011
                    Timestamp echo reply: 328746582
        Data (1448 bytes)

0000  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0010  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0020  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0030  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0040  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0050  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0060  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0070  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0080  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0090  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
00b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0100  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0110  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0120  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0130  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0140  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0150  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0160  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0170  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0180  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0190  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
01b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
01c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
01e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0200  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0210  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0220  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0230  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0240  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0250  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0260  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0270  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0280  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0290  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
02b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0300  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0310  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0320  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0330  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0340  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0350  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0360  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0370  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0380  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0390  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
03b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
03c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0400  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0410  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0420  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0430  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0440  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0450  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0460  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0470  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0480  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0490  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
04b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0500  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0510  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0520  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0530  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0540  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0550  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0560  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0570  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0580  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0590  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
05a0  30 31 32 33 34 35 36 37                           01234567
            Data: 303132333435363738393031323334353637383930313233...
            [Length: 1448]
    A-MSDU Subframe #2
        Destination address: Intel_5e:bd:85 (00:0e:0c:5e:bd:85)
        Source address: Apple_67:24:54 (84:38:35:67:24:54)
        A-MSDU Length: 1508
        Logical-Link Control
            DSAP: SNAP (0xaa)
            IG Bit: Individual
            SSAP: SNAP (0xaa)
            CR Bit: Command
            Control field: U, func=UI (0x03)
                000. 00.. = Command: Unnumbered Information (0x00)
                .... ..11 = Frame type: Unnumbered frame (0x03)
            Organization Code: Encapsulated Ethernet (0x000000)
            Type: IP (0x0800)
        Internet Protocol Version 4, Src: 192.168.254.52 (192.168.254.52), Dst: 192.168.254.1 (192.168.254.1)
            Version: 4
            Header length: 20 bytes
            Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
                0000 00.. = Differentiated Services Codepoint: Default (0x00)
                .... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)
            Total Length: 1500
            Identification: 0xc127 (49447)
            Flags: 0x02 (Don't Fragment)
                0... .... = Reserved bit: Not set
                .1.. .... = Don't fragment: Set
                ..0. .... = More fragments: Not set
            Fragment offset: 0
            Time to live: 64
            Protocol: TCP (6)
            Header checksum: 0xf66c [correct]
                [Good: True]
                [Bad: False]
            Source: 192.168.254.52 (192.168.254.52)
            Destination: 192.168.254.1 (192.168.254.1)
            [Source GeoIP: Unknown]
            [Destination GeoIP: Unknown]
        Transmission Control Protocol, Src Port: 52734 (52734), Dst Port: 5001 (5001), Seq: 3066889, Ack: 1, Len: 1448
            Source port: 52734 (52734)
            Destination port: 5001 (5001)
            [Stream index: 0]
            Sequence number: 3066889    (relative sequence number)
            [Next sequence number: 3068337    (relative sequence number)]
            Acknowledgment number: 1    (relative ack number)
            Header length: 32 bytes
            Flags: 0x010 (ACK)
                000. .... .... = Reserved: Not set
                ...0 .... .... = Nonce: Not set
                .... 0... .... = Congestion Window Reduced (CWR): Not set
                .... .0.. .... = ECN-Echo: Not set
                .... ..0. .... = Urgent: Not set
                .... ...1 .... = Acknowledgment: Set
                .... .... 0... = Push: Not set
                .... .... .0.. = Reset: Not set
                .... .... ..0. = Syn: Not set
                .... .... ...0 = Fin: Not set
            Window size value: 8235
            [Calculated window size: 131760]
            [Window size scaling factor: 16]
            Checksum: 0x13c8 [correct]
                [Good Checksum: True]
                [Bad Checksum: False]
            Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                No-Operation (NOP)
                    Type: 1
                        0... .... = Copy on fragmentation: No
                        .00. .... = Class: Control (0)
                        ...0 0001 = Number: No-Operation (NOP) (1)
                Timestamps: TSval 1302514011, TSecr 328746582
                    Kind: Timestamp (8)
                    Length: 10
                    Timestamp value: 1302514011
                    Timestamp echo reply: 328746582
        Data (1448 bytes)

0000  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0010  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0020  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0030  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0040  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0050  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0060  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0070  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0080  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0090  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
00b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
00c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
00d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
00e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
00f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0100  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0110  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0120  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0130  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0140  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0150  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0160  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0170  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0180  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0190  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
01b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
01c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
01d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
01e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
01f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0200  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0210  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0220  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0230  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0240  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0250  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0260  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0270  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0280  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0290  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
02b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
02c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
02d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
02e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
02f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0300  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0310  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0320  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0330  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0340  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0350  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0360  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0370  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0380  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0390  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
03b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
03c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
03d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
03e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
03f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0400  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0410  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0420  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0430  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0440  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0450  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0460  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0470  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0480  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0490  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
04b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
04c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
04d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
04e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
04f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0500  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0510  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0520  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0530  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0540  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
0550  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
0560  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
0570  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
0580  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
0590  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
05a0  38 39 30 31 32 33 34 35                           89012345
            Data: 383930313233343536373839303132333435363738393031...
            [Length: 1448]

From janusz.dziedzic at tieto.com  Wed Jul  9 00:39:21 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Wed, 9 Jul 2014 09:39:21 +0200
Subject: A-MSDU reception not working?
In-Reply-To: <CABnBrYVY_KY8mMAKhy-DV1s3+vut8oR_LohyBJX3GtW7RT=3XA@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
 <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>
 <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>
 <CALhHN=pvh8qocDzoMvK--__hJD1PVe5CrPBVriC1w=Bx1cpxpg@mail.gmail.com>
 <CABnBrYVY_KY8mMAKhy-DV1s3+vut8oR_LohyBJX3GtW7RT=3XA@mail.gmail.com>
Message-ID: <CALhHN=ozVHCzFPnz318SNE+YxgArdqKu4pTrc-Q1V88ujCz2ow@mail.gmail.com>

On 9 July 2014 08:09, Denton Gentry <denton.gentry at gmail.com> wrote:
> I ran iperf on an 802.11ac MacBook Air, through my ath10 AP, and to an
> Ubuntu system connected to the AP via Ethernet. The AP was running the
> reorder buffer patches, the patch to make A-MSDU bypass the reorder
> buffer, and the patch to make amsdu aggregation configurable via
> debugfs.
>
> http://lists.infradead.org/pipermail/ath10k/2014-June/002551.html
> http://lists.infradead.org/pipermail/ath10k/2014-June/002553.html
> http://lists.infradead.org/pipermail/ath10k/2014-July/002597.html
> http://permalink.gmane.org/gmane.linux.kernel.wireless.general/124128
>
> It was notably not running the patch from earlier in this thread to
> copy A-MSDU subframes into one skb.
>
>
> I used a second ath10k AP configured in monitor mode as a Wifi
> sniffer. I also gathered pcaps on the MacBook Air and on the Ubuntu
> system. Wireshark on the MacBook cannot gather radiotap headers nor
> put the interface into monitor mode, so we see only Ethernet frames
> and we don't see retransmissions on the Wifi link.
>
> I've attached decodes of the same two packets as captured by the
> MacBook, by the sniffer, and by the Ubuntu server.
>
> The MacBook sends two frames, TCP sequence numbers 3065441 and 3066889
> (the Wireshark "relative sequence number"). In the Wifi sniffer we see
> these being aggregated as two subframes in an A-MSDU frame. The first
> time this A-MSDU is sent it is corrupted in the air. We see the TCP
> checksum of one of the subframes is wrong, and a few bytes of the
> payload replaced with "&gt%'g9(1$".
>
> The A-MSDU is retransmitted a short time later, and the second time
> the TCP checksum of both subframes is correct.
>
> This is all fine so far.
>
> However in the pcap taken from the Ubuntu server, we see TCP sequence
> number 3065441 being delivered *twice.* The first time, the TCP
> checksum is wrong. The second time the TCP checksum is correct.
>
> To me, it looks like A-MSDU frames with bad FCS are not being
> discarded after ieee80211_rx_monitor(). The corrupted frames are being
> delivered. Delivering the corrupted frames results in sending more TCP
> Dup ACKs for the same sequence number back to the MacBook, and I think
> this is what causes the MacBook to decide there is congestion and slow
> down.
>
OK, to be sure this is the main issue we can just drop frames with wrong FCS.
Could you check this:

@@ -1267,10 +1267,10 @@ static void ath10k_htt_rx_handler(struct
ath10k_htt *htt,
                                continue;
                        }

-                       if (attention & RX_ATTENTION_FLAGS_FCS_ERR)
-                               rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-                       else
-                               rx_status->flag &= ~RX_FLAG_FAILED_FCS_CRC;
+                       if (attention & RX_ATTENTION_FLAGS_FCS_ERR) {
+                               ath10k_htt_rx_free_msdu_chain(msdu_head);
+                               continue;
+                       }

                        if (attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR)

If will help we will have to check how to handle monitor + ap case
correctly, one of idea is to not drop frames with wrong FCS only in
case of standalone monitor mode.
But, please try this patch to be sure.

BR
Janusz


> One note: the wifi sniffer does not show the same corruption to the
> same packet as the pcap from the Ubuntu system shows. I think that is
> normal: the sniffer won't see precisely the same noise, won't have
> precisely the same receive sensitivity, and its antennas are not
> pointing in the same direction as the primary AP. If I do this test
> again, I'll gather a pcap on the primary AP as well to compare to what
> we see on the Ubuntu system.
>
>
> On Tue, Jul 8, 2014 at 12:29 AM, Janusz Dziedzic
> <janusz.dziedzic at tieto.com> wrote:
>> On 8 July 2014 09:02, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>>> On 8 July 2014 08:50, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>>>> On 8 July 2014 08:43, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>> I think I know what is happening now, though I've no idea why. The
>>>>> throughput is low because we have many TCP retransmissions. We have
>>>>> retransmissions because the TCP checksum is wrong on a number of
>>>>> frames, and I do find data corruption in the payload so the checksum
>>>>> definitely should be wrong. All of the corrupted frames were
>>>>> originally one of the subframes in an A-MSDU packet.
>>>>>
>>>>> An example follows at the end of this message, as dissected by
>>>>> Wireshark. iperf sends a very regular data pattern of "0123456789..."
>>>>> over and over. Note how in subframe #2 offset 0x1e0 the bytes "32 33
>>>>> 34" have been replaced by "72 36 35"
>>>>>
>>>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>>>
>>>>> I added printks at the bottom of ath10k_htt_rx_amsdu immediately
>>>>> before the call to ath10k_process_rx. I found this same packet, and we
>>>>> see the "72 36 35" corruption in the printk. So I think it happened in
>>>>> ath10k_process_rx or before, not anything weird after passing it up to
>>>>> mac80211.
>>>>>
>>>>> [  101.863712] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>>>> [  101.863727] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>>> [  101.863742] ath10k: 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32
>>>>> [  101.863757] ath10k: 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37 38
>>>>> [  101.863773] ath10k: 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34
>>>>> [  101.863788] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>>>> [  101.863803] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>>>
>>>>>
>>>>> I've found a number of examples of similar corruption, always with
>>>>> between one and four bytes replaced.
>>>>>
>>>>> 35363738 -> e52c6e07
>>>>> 3435 -> b43f
>>>>> 3839 -> c238
>>>>> 31 -> 7f
>>>>> 3435 -> 7436
>>>>> 30 -> 50
>>>>> 3233 -> bc37
>>>>>
>>>> Seems this could be because of:
>>>>
>>>> + /* cfg80211 expect this padding */
>>>> + padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
>>>> + skb_put(skb, padding);
>>>>
>>>
>>> BTW, when AP (ath10k) send TCP ACK - are this packets also AMSDU?
>>> I see in my case AP can send 3 x A-MSDU (with total size 304 bytes)
>>> small frames aggregated. Maybe your HW have problems with that.
>>> As I remember correctly someone some time ago report problems with
>>> MacBook pro retina but I am not sure this is the same, while no one
>>> tests the fix.
>>>
>>>>>
>>>>> The packet described above, dissected by Wireshark:
>>>>>
>>>>> No.     Time        Source                Destination
>>>>> Protocol Length Info
>>>>>    2235 18.953349   192.168.144.79        192.168.144.13        TCP
>>>>>   3112   52697 > 5001 [ACK] Seq=1391553 Ack=1 Win=131760 [TCP CHECKSUM
>>>>> INCORRECT] Len=1448 TSval=1298580657 TSecr=4294947481
>>>>>
>>>>> Frame 2235: 3112 bytes on wire (24896 bits), 3112 bytes captured (24896 bits)
>>>>>     Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
>>>>>     Arrival Time: Jul  7, 2014 23:03:37.763365000 PDT
>>>>>     [Time shift for this packet: 0.000000000 seconds]
>>>>>     Epoch Time: 1404799417.763365000 seconds
>>>>>     [Time delta from previous captured frame: 0.003476000 seconds]
>>>>>     [Time delta from previous displayed frame: 0.515641000 seconds]
>>>>>     [Time since reference or first frame: 18.953349000 seconds]
>>>>>     Frame Number: 2235
>>>>>     Frame Length: 3112 bytes (24896 bits)
>>>>>     Capture Length: 3112 bytes (24896 bits)
>>>>>     [Frame is marked: False]
>>>>>     [Frame is ignored: False]
>>>>>     [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
>>>>>     [Coloring Rule Name: TCP]
>>>>>     [Coloring Rule String: tcp]
>>>>> Radiotap Header v0, Length 38
>>>>>     Header revision: 0
>>>>>     Header pad: 0
>>>>>     Header length: 38
>>>>>     Present flags
>>>>>         .... .... .... .... .... .... .... ...1 = TSFT: True
>>>>>         .... .... .... .... .... .... .... ..1. = Flags: True
>>>>>         .... .... .... .... .... .... .... .0.. = Rate: False
>>>>>         .... .... .... .... .... .... .... 1... = Channel: True
>>>>>         .... .... .... .... .... .... ...0 .... = FHSS: False
>>>>>         .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
>>>>>         .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
>>>>>         .... .... .... .... .... .... 0... .... = Lock Quality: False
>>>>>         .... .... .... .... .... ...0 .... .... = TX Attenuation: False
>>>>>         .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
>>>>>         .... .... .... .... .... .0.. .... .... = dBm TX Power: False
>>>>>         .... .... .... .... .... 1... .... .... = Antenna: True
>>>>>         .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
>>>>>         .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
>>>>>         .... .... .... .... .1.. .... .... .... = RX flags: True
>>>>>         .... .... .... .0.. .... .... .... .... = Channel+: False
>>>>>         .... .... .... 0... .... .... .... .... = HT information: False
>>>>>         .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
>>>>>         .... .... ..1. .... .... .... .... .... = VHT information: True
>>>>>         ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
>>>>>         ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
>>>>>         .0.. .... .... .... .... .... .... .... = Vendor NS next: False
>>>>>         0... .... .... .... .... .... .... .... = Ext: False
>>>>>     MAC timestamp: 78051063
>>>>>     Flags: 0x00
>>>>>         .... ...0 = CFP: False
>>>>>         .... ..0. = Preamble: Long
>>>>>         .... .0.. = WEP: False
>>>>>         .... 0... = Fragmentation: False
>>>>>         ...0 .... = FCS at end: False
>>>>>         ..0. .... = Data Pad: False
>>>>>         .0.. .... = Bad FCS: False
>>>>>         0... .... = Short GI: False
>>>>>     Channel frequency: 5745 [A 149]
>>>>>     Channel type: 802.11a (0x0140)
>>>>>         .... .... ...0 .... = Turbo: False
>>>>>         .... .... ..0. .... = Complementary Code Keying (CCK): False
>>>>>         .... .... .1.. .... = Orthogonal Frequency-Division
>>>>> Multiplexing (OFDM): True
>>>>>         .... .... 0... .... = 2 GHz spectrum: False
>>>>>         .... ...1 .... .... = 5 GHz spectrum: True
>>>>>         .... ..0. .... .... = Passive: False
>>>>>         .... .0.. .... .... = Dynamic CCK-OFDM: False
>>>>>         .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
>>>>>         ...0 .... .... .... = GSM (900MHz): False
>>>>>         ..0. .... .... .... = Static Turbo: False
>>>>>         .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
>>>>>         0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
>>>>>     SSI Signal: -53 dBm
>>>>>     Antenna: 0
>>>>>     RX flags: 0x0000
>>>>>         .... .... .... .... .... ..0. = Bad PLCP: False
>>>>>     VHT information
>>>>>         Known VHT information: 0x44
>>>>>             .... .... .... ...0 = STBC: False
>>>>>             .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
>>>>>             .... .... .... .1.. = Guard interval: True
>>>>>             .... .... .... 0... = SGI Nsym disambiguation: False
>>>>>             .... .... ...0 .... = LDPC extra OFDM symbol: False
>>>>>             .... .... ..0. .... = Beamformed: False
>>>>>             .... .... .1.. .... = Bandwidth: True
>>>>>             .... .... 0... .... = Group ID: False
>>>>>             .... ...0 .... .... = Partial AID: False
>>>>>         .... .0.. = Guard interval: long (0)
>>>>>         Bandwidth: 80 MHz (4)
>>>>>         User 0: MCS 8
>>>>>             1000 .... = MCS index 0: 8 (256-QAM 3/4)
>>>>>             .... 0010 = Spatial streams 0: 2
>>>>>             Space-time streams 0: 2
>>>>>             Coding 0: BCC (0)
>>>>>             [Data Rate: 702.0 Mb/s]
>>>>> IEEE 802.11 QoS Data, Flags: .......T
>>>>>     Type/Subtype: QoS Data (0x28)
>>>>>     Frame Control Field: 0x8801
>>>>>         .... ..00 = Version: 0
>>>>>         .... 10.. = Type: Data frame (2)
>>>>>         1000 .... = Subtype: 8
>>>>>         Flags: 0x01
>>>>>             .... ..01 = DS status: Frame from STA to DS via an AP (To
>>>>> DS: 1 From DS: 0) (0x01)
>>>>>             .... .0.. = More Fragments: This is the last fragment
>>>>>             .... 0... = Retry: Frame is not being retransmitted
>>>>>             ...0 .... = PWR MGT: STA will stay up
>>>>>             ..0. .... = More Data: No data buffered
>>>>>             .0.. .... = Protected flag: Data is not protected
>>>>>             0... .... = Order flag: Not strictly ordered
>>>>>     .000 0000 0011 0000 = Duration: 48 microseconds
>>>>>     Receiver address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>     BSS Id: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>     Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>     Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>     Destination address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>     Fragment number: 0
>>>>>     Sequence number: 1021
>>>>>     Qos Control: 0x0080
>>>>>         .... .... .... 0000 = TID: 0
>>>>>         [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
>>>>>         .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control
>>>>> field are TXOP Duration Requested
>>>>>         .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
>>>>>         .... .... 1... .... = Payload Type: A-MSDU
>>>>>         0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
>>>>> IEEE 802.11 Aggregate MSDU
>>>>>     A-MSDU Subframe #1
>>>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>         A-MSDU Length: 1510
>>>>>         Logical-Link Control
>>>>>             DSAP: SNAP (0xaa)
>>>>>             IG Bit: Individual
>>>>>             SSAP: SNAP (0xaa)
>>>>>             CR Bit: Command
>>>>>             Control field: U, func=UI (0x03)
>>>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>>>             Type: IP (0x0800)
>>>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>>>             Version: 4
>>>>>             Header length: 20 bytes
>>>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>>>> (Not ECN-Capable Transport) (0x00)
>>>>>             Total Length: 1500
>>>>>             Identification: 0xc622 (50722)
>>>>>             Flags: 0x00
>>>>>                 0... .... = Reserved bit: Not set
>>>>>                 .0.. .... = Don't fragment: Not set
>>>>>                 ..0. .... = More fragments: Not set
>>>>>             Fragment offset: 0
>>>>>             Time to live: 64
>>>>>             Protocol: TCP (6)
>>>>>             Header checksum: 0x0d4c [correct]
>>>>>                 [Good: True]
>>>>>                 [Bad: False]
>>>>>             Source: 192.168.144.79 (192.168.144.79)
>>>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>>>             [Source GeoIP: Unknown]
>>>>>             [Destination GeoIP: Unknown]
>>>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>>>> Port: 5001 (5001), Seq: 1390105, Ack: 1, Len: 1448
>>>>>             Source port: 52697 (52697)
>>>>>             Destination port: 5001 (5001)
>>>>>             [Stream index: 0]
>>>>>             Sequence number: 1390105    (relative sequence number)
>>>>>             [Next sequence number: 1391553    (relative sequence number)]
>>>>>             Acknowledgment number: 1    (relative ack number)
>>>>>             Header length: 32 bytes
>>>>>             Flags: 0x010 (ACK)
>>>>>                 000. .... .... = Reserved: Not set
>>>>>                 ...0 .... .... = Nonce: Not set
>>>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>>>                 .... .0.. .... = ECN-Echo: Not set
>>>>>                 .... ..0. .... = Urgent: Not set
>>>>>                 .... ...1 .... = Acknowledgment: Set
>>>>>                 .... .... 0... = Push: Not set
>>>>>                 .... .... .0.. = Reset: Not set
>>>>>                 .... .... ..0. = Syn: Not set
>>>>>                 .... .... ...0 = Fin: Not set
>>>>>             Window size value: 8235
>>>>>             [Calculated window size: 131760]
>>>>>             [Window size scaling factor: 16]
>>>>>             Checksum: 0xa1c0 [correct]
>>>>>                 [Good Checksum: True]
>>>>>                 [Bad Checksum: False]
>>>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>>>> (NOP), Timestamps
>>>>>                 No-Operation (NOP)
>>>>>                     Type: 1
>>>>>                         0... .... = Copy on fragmentation: No
>>>>>                         .00. .... = Class: Control (0)
>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>                 No-Operation (NOP)
>>>>>                     Type: 1
>>>>>                         0... .... = Copy on fragmentation: No
>>>>>                         .00. .... = Class: Control (0)
>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>>>                     Kind: Timestamp (8)
>>>>>                     Length: 10
>>>>>                     Timestamp value: 1298580657
>>>>>                     Timestamp echo reply: 4294947481
>>>>>         Data (1448 bytes)
>>>>>
>>>>> 0000  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0010  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0020  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0030  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0040  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0050  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0060  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0070  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0080  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0090  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 00a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 00b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 00c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 00d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 00e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 00f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0100  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0110  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0120  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0130  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0140  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0150  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0160  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0170  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0180  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0190  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 01a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 01b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 01c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 01d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 01e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 01f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0200  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0210  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0220  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0230  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0240  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0250  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0260  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0270  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0280  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0290  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 02a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 02b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 02c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 02d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 02e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 02f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0300  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0310  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0320  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0330  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0340  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0350  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0360  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0370  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0380  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0390  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 03a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 03b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 03c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 03d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 03e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 03f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0400  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0410  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0420  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0430  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0440  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0450  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0460  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0470  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0480  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0490  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 04a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 04b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 04c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 04d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 04e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 04f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0500  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0510  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0520  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0530  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0540  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0550  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0560  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0570  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0580  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0590  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 05a0  34 35 36 37 38 39 30 31                           45678901
>>>>>             Data: 343536373839303132333435363738393031323334353637...
>>>>>             [Length: 1448]
>>>>>     A-MSDU Subframe #2
>>>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>         A-MSDU Length: 1510
>>>>>         Logical-Link Control
>>>>>             DSAP: SNAP (0xaa)
>>>>>             IG Bit: Individual
>>>>>             SSAP: SNAP (0xaa)
>>>>>             CR Bit: Command
>>>>>             Control field: U, func=UI (0x03)
>>>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>>>             Type: IP (0x0800)
>>>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>>>             Version: 4
>>>>>             Header length: 20 bytes
>>>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>>>> (Not ECN-Capable Transport) (0x00)
>>>>>             Total Length: 1500
>>>>>             Identification: 0xda09 (55817)
>>>>>             Flags: 0x00
>>>>>                 0... .... = Reserved bit: Not set
>>>>>                 .0.. .... = Don't fragment: Not set
>>>>>                 ..0. .... = More fragments: Not set
>>>>>             Fragment offset: 0
>>>>>             Time to live: 64
>>>>>             Protocol: TCP (6)
>>>>>             Header checksum: 0xf964 [correct]
>>>>>                 [Good: True]
>>>>>                 [Bad: False]
>>>>>             Source: 192.168.144.79 (192.168.144.79)
>>>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>>>             [Source GeoIP: Unknown]
>>>>>             [Destination GeoIP: Unknown]
>>>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>>>> Port: 5001 (5001), Seq: 1391553, Ack: 1, Len: 1448
>>>>>             Source port: 52697 (52697)
>>>>>             Destination port: 5001 (5001)
>>>>>             [Stream index: 0]
>>>>>             Sequence number: 1391553    (relative sequence number)
>>>>>             [Next sequence number: 1393001    (relative sequence number)]
>>>>>             Acknowledgment number: 1    (relative ack number)
>>>>>             Header length: 32 bytes
>>>>>             Flags: 0x010 (ACK)
>>>>>                 000. .... .... = Reserved: Not set
>>>>>                 ...0 .... .... = Nonce: Not set
>>>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>>>                 .... .0.. .... = ECN-Echo: Not set
>>>>>                 .... ..0. .... = Urgent: Not set
>>>>>                 .... ...1 .... = Acknowledgment: Set
>>>>>                 .... .... 0... = Push: Not set
>>>>>                 .... .... .0.. = Reset: Not set
>>>>>                 .... .... ..0. = Syn: Not set
>>>>>                 .... .... ...0 = Fin: Not set
>>>>>             Window size value: 8235
>>>>>             [Calculated window size: 131760]
>>>>>             [Window size scaling factor: 16]
>>>>>             Checksum: 0x9a16 [incorrect, should be 0x5913 (maybe
>>>>> caused by "TCP checksum offload"?)]
>>
>> And yes we are using checksum offload in ath10k.
>> Best is using standalone 80211ac sniffer for that case to be sure
>> about checksum.
>>
>>>>>                 [Good Checksum: False]
>>>>>                 [Bad Checksum: True]
>>>>>                     [Expert Info (Error/Checksum): Bad checksum]
>>>>>                         [Message: Bad checksum]
>>>>>                         [Severity level: Error]
>>>>>                         [Group: Checksum]
>>>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>>>> (NOP), Timestamps
>>>>>                 No-Operation (NOP)
>>>>>                     Type: 1
>>>>>                         0... .... = Copy on fragmentation: No
>>>>>                         .00. .... = Class: Control (0)
>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>                 No-Operation (NOP)
>>>>>                     Type: 1
>>>>>                         0... .... = Copy on fragmentation: No
>>>>>                         .00. .... = Class: Control (0)
>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>>>                     Kind: Timestamp (8)
>>>>>                     Length: 10
>>>>>                     Timestamp value: 1298580657
>>>>>                     Timestamp echo reply: 4294947481
>>>>>         Data (1448 bytes)
>>>>>
>>>>> 0000  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0010  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0020  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0030  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0040  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0050  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0060  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0070  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0080  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0090  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 00a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 00b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 00c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 00d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 00e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 00f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0100  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0110  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0120  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0130  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0140  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0150  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0160  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0170  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0180  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0190  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 01a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 01b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 01c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 01d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>>> 01f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0200  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0210  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0220  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0230  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0240  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0250  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0260  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0270  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0280  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0290  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 02a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 02b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 02c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 02d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 02e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 02f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0300  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0310  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0320  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0330  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0340  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0350  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0360  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0370  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0380  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0390  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 03a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 03b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 03c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 03d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 03e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 03f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0400  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0410  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0420  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0430  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0440  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0450  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0460  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0470  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0480  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0490  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 04a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 04b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 04c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 04d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 04e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 04f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0500  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0510  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0520  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0530  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0540  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 0550  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>> 0560  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>> 0570  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>> 0580  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>> 0590  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>> 05a0  32 33 34 35 36 37 38 39                           23456789
>>>>>             Data: 323334353637383930313233343536373839303132333435...
>>>>>             [Length: 1448]
>>>>>
>>>>> On Mon, Jul 7, 2014 at 12:26 PM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>> The initial results are not promising: a MacOS 802.11ac client gets
>>>>>> between 0-2 Mbps with this change, where it was getting about 8 Mbps
>>>>>> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
>>>>>> from the receiving system shows a very large number of out of order
>>>>>> frames, likely due to TCP retransmission.
>>>>>>
>>>>>> An 802.11n MacBook gets very good throughput, only the 802.11ac
>>>>>> MacBook shows the very poor result. I'm trying to figure out why.
>>>>>>
>>>>>>
>>>>>> One specific note (and probably not related to the throughput): I
>>>>>> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
>>>>>> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
>>>>>> correctly?
>>>>>>
>>>>>>
>>>>>> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
>>>>>> <janusz.dziedzic at tieto.com> wrote:
>>>>>>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>>>>>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>>>>>>
>>>>>>>> The earlier atheros chips would just give you the AMSDU frames as
>>>>>>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>>>>>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>>>>>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>>>>>>> those sub-frames.
>>>>>>>>
>>>>>>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>>>>>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>>>>>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>>>>>>> half of one MPDU before you hit EOL, the next notification you process
>>>>>>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>>>>>>> reordering hilarity again.
>>>>>>>>
>>>>>>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>>>>>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>>>>>>> representing the current MPDU and treat the whole lot as the frame(s)
>>>>>>>> to care about. Honestly though, I'm kind of wondering whether I should
>>>>>>>> mostly just do what the Atheros reference driver does and treat it as
>>>>>>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>>>>>>> reordering is already done) and just tack on the wifi header bit via
>>>>>>>> another of the DMA rings.
>>>>>>>>
>>>>>>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> -a
>>>>>>>>
>>>>>>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>>>>>>
>>>>>>>>
>>>>>>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>>>>>>> in ieee80211_sta_manage_reorder_buf:
>>>>>>>>>
>>>>>>>>> 1. The out-of-date check:
>>>>>>>>>
>>>>>>>>>         /* frame with out of date sequence number */
>>>>>>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>>>                 goto out;
>>>>>>>>>         }
>>>>>>>>>
>>>>>>>>> As all of the subframes carry the same sequence number, the first
>>>>>>>>> subframe will be delivered and increment head_seq_num and then all
>>>>>>>>> subsequent subframes will be discarded.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> 2. The duplicates check a bit later in the routine:
>>>>>>>>>
>>>>>>>>>         /* check if we already stored this frame */
>>>>>>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>>>                 goto out;
>>>>>>>>>         }
>>>>>>>>>
>>>>>>>>> If there is enough packet loss that packets are queued in the reorder
>>>>>>>>> buffer and not immediately released, then only the first subframe will
>>>>>>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>>>>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>>>>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>>>>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>>>>>>
>>>>>>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>>>>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>>>>>>> see that it does happen, but it doesn't impact the throughput and I
>>>>>>>>> can't report the impact of fixing it.
>>>>>>>>>
>>>>>>>>> ----
>>>>>>>>>
>>>>>>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>>>>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>>>>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>>>>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>>>>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>>>>>>> match the mac80211 expectations.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>> Yes, after some more testing it does look like an unfortunate
>>>>>>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>>>>>>> subframes all carry the same sequence number. The first subframe is
>>>>>>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>>>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>>>>>>
>>>>>>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>>>>>>> head=0xb06
>>>>>>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>>>>>>> head=0xb0b
>>>>>>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>>>>>>> head=0xb10
>>>>>>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>>>>>>> head=0xb15
>>>>>>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>>>>>>> head=0xb1a
>>>>>>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>>>>>>> head=0xb1f
>>>>>>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>>>>>>> head=0xb24
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>>>>>>
>>>>>>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>>>>>>> frame makes it through.
>>>>>>>>>>>>
>>>>>>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>>>>>>
>>>>>>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>>>>>>> A-MSDU.
>>>>>>>>>>>
>>>>>>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>>>>>>
>>>>>>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>>>>>>
>>>>>>> Denton could you try attached patch: report amsdu in one big frame.
>>>>>>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>>>>>>> improve performance and reduce memcpy, while currently we have skb
>>>>>>> frames, put them in one big skb and next cfg80211 split them again
>>>>>>> into msdus and report to stack.
>>>>>>>
>>>>>>> BR
>>>>>>> Janusz


From ma86 at st-andrews.ac.uk  Wed Jul  9 07:22:09 2014
From: ma86 at st-andrews.ac.uk (Mamun Abu-Tair)
Date: Wed, 9 Jul 2014 15:22:09 +0100
Subject: Throughput is very low
Message-ID: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>


Dear all, 
I am trying to do throughput test with copmex AC cards Model (WLE900VX 7AA) .,using hostapd running on the server and  one client. 

I used Kalle sitting for the hostapd. However, the maximum throughput i can get is around 70Mbit/s which is far away from the throughput achieved by many users (UDP traffic). 

I have notice that Bit Rate keeps fixed 6 Mb/s . and it dose not responding to any commands to change it. 

The machines used: 
 Ubuntu 12.04, Kerenl 3.16 , updated regulatory to cover 80Mhz channels , and the latest  firmware 

Your help is appreciated . 
Kind regards 
Mamun



From vh.nguyen at actiasodielec.fr  Wed Jul  9 23:48:20 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Thu, 10 Jul 2014 08:48:20 +0200
Subject: Bridging problem in ath10k (STA)
In-Reply-To: <CA+BoTQnpdcBOrX32Ma7q0OZ5eaPYM31g8VV4HU==nMUqfA2Fzw@mail.gmail.com>
References: <CAEFj986inLh+Upgx-rVF0zviii+yaQZnr9cuMYOXAqEjXrVMvQ@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F109978FC@srvexch01.SODIELEC.local>
 <CAEFj986wbAp3-7y3ocpYzCWvYU=J0H6fQbrnMA3-qetRruF6RA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F109978FE@srvexch01.SODIELEC.local>
 <CAEFj986pnp2qHu8YuYyHLN66jAy2Mf+AAS=pLsuK6gdq6BU23Q@mail.gmail.com>,
 <CA+BoTQnpdcBOrX32Ma7q0OZ5eaPYM31g8VV4HU==nMUqfA2Fzw@mail.gmail.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7E0@srvexch01.SODIELEC.local>

I ran into a problem about bridging while doing test with iperf, my system is like this:
PC1 - Device 1 (AP) <= Wifi => Device 2 (STA) - PC2
My AP is set up in 802.11ac VHT 80. My STA is non-bridged and it associated with my AP directly 
on interface wlan0.
If I run iperf in the direction from AP to STA (option -c on PC1 and -s on PC2), every things work fine.
But in the opposite direction (-s on PC1 and -c on PC2), the interface wlan0.sta1 is created on my AP 
during iperf is running and I lost the connection between 2 device, though "iw wlan.sta1 station dump" 
still report the information about connection (rate, txpower, rx bytes (change very very slowly), ...)
I try to ping but not success and iperf stop running. This problem happened only when I run iperf, not
if I ping between PC1 and PC2 and inverse. 
If I delete the "wds_sta=1" in the config file of hostapd this problem is no more occurred. But I wonder
if only this parameter creates effects on this problem cause I have many STA that could associate
to my AP, some of them are bridged, other are non-bridged and I want to keep "wds_sta=1" in my config
file so that bridged STA can connect.
Any one have any ideas about this?
Thank you in advance.
 
NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE

________________________________________
De : Michal Kazior [michal.kazior at tieto.com]
Date d'envoi : lundi 9 juin 2014 13:00
? : Yeoh Chun-Yeow
Cc : Vu Hai NGUYEN; ath10k at lists.infradead.org
Objet : Re: RE : RE : Bridging problem in ath10k (STA)

On 9 June 2014 12:49, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
> Hmm, redo the testing. The FW is not crashed on STA site, but could
> not ping the AP or IP behind the AP once bridging. Only happen if the
> AP is operating at 80MHz.
>
> Any idea on what to look for?

Does this reproduce if you have non-bridged STA connected to an AP
while the STA interface is in promiscuous mode (so that monitor vdev
is running)? If it doesn't reproduce I'd look for AP configuration
issue. Does your AP have wds_sta=1? Does it create wlanX.staY
interfaces when stations connect? (I'm assuming your AP is running
hostapd).


Micha?

From janusz.dziedzic at tieto.com  Thu Jul 10 00:32:19 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Thu, 10 Jul 2014 09:32:19 +0200
Subject: Bridging problem in ath10k (STA)
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D7E0@srvexch01.SODIELEC.local>
References: <CAEFj986inLh+Upgx-rVF0zviii+yaQZnr9cuMYOXAqEjXrVMvQ@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F109978FC@srvexch01.SODIELEC.local>
 <CAEFj986wbAp3-7y3ocpYzCWvYU=J0H6fQbrnMA3-qetRruF6RA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F109978FE@srvexch01.SODIELEC.local>
 <CAEFj986pnp2qHu8YuYyHLN66jAy2Mf+AAS=pLsuK6gdq6BU23Q@mail.gmail.com>
 <CA+BoTQnpdcBOrX32Ma7q0OZ5eaPYM31g8VV4HU==nMUqfA2Fzw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7E0@srvexch01.SODIELEC.local>
Message-ID: <CALhHN=qAGsGa_+79he1R9okHEj8ZoJdEUYUC0tM4jQy0Y9ogxQ@mail.gmail.com>

On 10 July 2014 08:48, Vu Hai NGUYEN <vh.nguyen at actiasodielec.fr> wrote:
> I ran into a problem about bridging while doing test with iperf, my system is like this:
> PC1 - Device 1 (AP) <= Wifi => Device 2 (STA) - PC2
> My AP is set up in 802.11ac VHT 80. My STA is non-bridged and it associated with my AP directly
> on interface wlan0.
> If I run iperf in the direction from AP to STA (option -c on PC1 and -s on PC2), every things work fine.
> But in the opposite direction (-s on PC1 and -c on PC2), the interface wlan0.sta1 is created on my AP
Just guessing, Is wlan0.sta1 added to bridge? If not what if you will
add it manually after created?

> during iperf is running and I lost the connection between 2 device, though "iw wlan.sta1 station dump"
> still report the information about connection (rate, txpower, rx bytes (change very very slowly), ...)
> I try to ping but not success and iperf stop running. This problem happened only when I run iperf, not
> if I ping between PC1 and PC2 and inverse.
> If I delete the "wds_sta=1" in the config file of hostapd this problem is no more occurred. But I wonder
> if only this parameter creates effects on this problem cause I have many STA that could associate
> to my AP, some of them are bridged, other are non-bridged and I want to keep "wds_sta=1" in my config
> file so that bridged STA can connect.
> Any one have any ideas about this?
> Thank you in advance.
>
> NGUYEN Vu Hai
> Acita-Sodielec
> Route de Mayres - B.P. 9
> 12100 St GEORGES DE LUZENCON
> FRANCE
>
> ________________________________________
> De : Michal Kazior [michal.kazior at tieto.com]
> Date d'envoi : lundi 9 juin 2014 13:00
> ? : Yeoh Chun-Yeow
> Cc : Vu Hai NGUYEN; ath10k at lists.infradead.org
> Objet : Re: RE : RE : Bridging problem in ath10k (STA)
>
> On 9 June 2014 12:49, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
>> Hmm, redo the testing. The FW is not crashed on STA site, but could
>> not ping the AP or IP behind the AP once bridging. Only happen if the
>> AP is operating at 80MHz.
>>
>> Any idea on what to look for?
>
> Does this reproduce if you have non-bridged STA connected to an AP
> while the STA interface is in promiscuous mode (so that monitor vdev
> is running)? If it doesn't reproduce I'd look for AP configuration
> issue. Does your AP have wds_sta=1? Does it create wlanX.staY
> interfaces when stations connect? (I'm assuming your AP is running
> hostapd).
>
>
> Micha?
> _______________________________________________
> ath10k mailing list
> ath10k at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/ath10k


From janusz.dziedzic at tieto.com  Thu Jul 10 04:45:09 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Thu, 10 Jul 2014 13:45:09 +0200
Subject: [RFT/RFC 0/5] ath10k: handle/report A-MSDU as a skb list
Message-ID: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>

This is prototype, how we can handle A-MSDU as a skb list in mac80211.
No changes in mac80211 reordering code required in such case, also
we don't need to build one big frame using memcpy ...
With such prototype tid_agg_rx->reorder_buf[sn] will describe exactly
one MPDU (with included A-MSDU subframes if skb->next) and detection of duplicated
frames will work correctly. So, reordering should works correctly.

I tested this with A-MPDU and A-MSDU run together (A-MSDU frame up to 10k) - TCP STA -> AP.
I used ath10k STA with unlocked A-MSDU limit in RC in firmware.
Didn't notice any problems.

@Denton could you check this prototype in your env please

TODO:
mac80211 - release correctly A-MSDU list in case of problems (errors)
verify crypted networks + A-MSDU
introduce test code to ath10k driver that we can test mac80211 reordering implementation


Janusz Dziedzic (5):
  ath10k: amsdu rx, buid one big frame
  mac80211: add option to handle amsdu as a list of skb
  cfg80211: allow RX amsdu to be reported as a list
  ath10k: report amsdu as a skb list
  ath10k: rx, don't pass frames with invalid FCS

 drivers/net/wireless/ath/ath10k/htt_rx.c |   62 ++++++++++++++++----------
 include/net/mac80211.h                   |    4 ++
 net/mac80211/ieee80211_i.h               |    1 +
 net/mac80211/main.c                      |    2 +-
 net/mac80211/rx.c                        |   70 ++++++++++++++++++++++++++++--
 net/wireless/util.c                      |   44 +++++++++++++++++++
 6 files changed, 155 insertions(+), 28 deletions(-)

-- 
1.7.9.5



From janusz.dziedzic at tieto.com  Thu Jul 10 04:45:11 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Thu, 10 Jul 2014 13:45:11 +0200
Subject: [RFT/RFC 2/5] mac80211: add option to handle amsdu as a list of skb
In-Reply-To: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
References: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <1404992714-15690-3-git-send-email-janusz.dziedzic@tieto.com>

Initial version.
Allow to report amsdu frames as a skb list.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
---
 include/net/mac80211.h     |    4 +++
 net/mac80211/ieee80211_i.h |    1 +
 net/mac80211/main.c        |    2 +-
 net/mac80211/rx.c          |   70 +++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e7362f0..9ec8ad1 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -873,6 +873,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
  *	subframes share the same sequence number. Reported subframes can be
  *	either regular MSDU or singly A-MSDUs. Subframes must not be
  *	interleaved with other frames.
+ * @RX_FLAG_AMSDU_LIST: Some drivers report A-MSDU subframes as a skb list,
+ * 	with skb->next set. In such case we have one skb that will describe
+ *	mpdu frame. All, but last MSDU from A-MSDU should have this flag set.
  */
 enum mac80211_rx_flags {
 	RX_FLAG_MMIC_ERROR		= BIT(0),
@@ -902,6 +905,7 @@ enum mac80211_rx_flags {
 	RX_FLAG_10MHZ			= BIT(28),
 	RX_FLAG_5MHZ			= BIT(29),
 	RX_FLAG_AMSDU_MORE		= BIT(30),
+	RX_FLAG_AMSDU_LIST		= BIT(31),
 };
 
 #define RX_FLAG_STBC_SHIFT		26
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ae35bf1..3dd3133 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1862,6 +1862,7 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
 int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
 			const u8 *peer, enum nl80211_tdls_operation oper);
 
+struct sk_buff * ieee80211_dequeue_mpdu(struct sk_buff_head *frames);
 
 #ifdef CONFIG_MAC80211_NOINLINE
 #define debug_noinline noinline
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d17c26d..6ac1af4 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -222,7 +222,7 @@ static void ieee80211_tasklet_handler(unsigned long data)
 	struct ieee80211_local *local = (struct ieee80211_local *) data;
 	struct sk_buff *skb;
 
-	while ((skb = skb_dequeue(&local->skb_queue)) ||
+	while ((skb = ieee80211_dequeue_mpdu(&local->skb_queue)) ||
 	       (skb = skb_dequeue(&local->skb_queue_unreliable))) {
 		switch (skb->pkt_type) {
 		case IEEE80211_RX_MSG:
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 394e201..9034a65 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -683,6 +683,68 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 	return RX_CONTINUE;
 }
 
+static void __ieee80211_queue_mpdu(struct sk_buff_head *frames,
+				   struct sk_buff *skb)
+{
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+	struct sk_buff *next = skb->next;
+
+	__skb_queue_tail(frames, skb);
+
+	if (status->flag & RX_FLAG_AMSDU_LIST) {
+		/* Check if amsdu list and queue frames */
+		while (next) {
+			skb = next;
+			next = next->next;
+			__skb_queue_tail(frames, skb);
+		}
+	}
+}
+
+static void ieee80211_queue_mpdu(struct sk_buff_head *frames,
+				 struct sk_buff *skb)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&frames->lock, flags);
+	__ieee80211_queue_mpdu(frames, skb);
+	spin_unlock_irqrestore(&frames->lock, flags);
+}
+
+static struct sk_buff * __ieee80211_dequeue_mpdu(struct sk_buff_head *frames)
+{
+	struct sk_buff *first, *next;
+
+	first = __skb_dequeue(frames);
+
+	if (!first)
+		goto out;
+
+	next = first;
+	if (IEEE80211_SKB_RXCB(next)->flag & RX_FLAG_AMSDU_LIST) {
+		do {
+			/* Dequeue frames when amsdu list */
+			next->next = __skb_dequeue(frames);
+			next = next->next;
+		} while (next && IEEE80211_SKB_RXCB(next)->flag & RX_FLAG_AMSDU_LIST);
+	}
+
+out:
+	return first;
+}
+
+struct sk_buff * ieee80211_dequeue_mpdu(struct sk_buff_head *frames)
+{
+	struct sk_buff *mpdu;
+	unsigned long flags;
+
+	spin_lock_irqsave(&frames->lock, flags);
+	mpdu = __ieee80211_dequeue_mpdu(frames);
+	spin_unlock_irqrestore(&frames->lock, flags);
+
+	return mpdu;
+}
+
 static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
 					    struct tid_ampdu_rx *tid_agg_rx,
 					    int index,
@@ -701,7 +763,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
 	tid_agg_rx->reorder_buf[index] = NULL;
 	status = IEEE80211_SKB_RXCB(skb);
 	status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE;
-	__skb_queue_tail(frames, skb);
+	__ieee80211_queue_mpdu(frames, skb);
 
 no_frame:
 	tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num);
@@ -951,7 +1013,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
 		return;
 
  dont_reorder:
-	__skb_queue_tail(frames, skb);
+	__ieee80211_queue_mpdu(frames, skb);
 }
 
 static ieee80211_rx_result debug_noinline
@@ -2950,7 +3012,7 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
 
 	spin_lock_bh(&rx->local->rx_path_lock);
 
-	while ((skb = __skb_dequeue(frames))) {
+	while ((skb = __ieee80211_dequeue_mpdu(frames))) {
 		/*
 		 * all the other fields are valid across frames
 		 * that belong to an aMPDU since they are on the
@@ -3426,7 +3488,7 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb)
 	BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb));
 
 	skb->pkt_type = IEEE80211_RX_MSG;
-	skb_queue_tail(&local->skb_queue, skb);
+	ieee80211_queue_mpdu(&local->skb_queue, skb);
 	tasklet_schedule(&local->tasklet);
 }
 EXPORT_SYMBOL(ieee80211_rx_irqsafe);
-- 
1.7.9.5



From janusz.dziedzic at tieto.com  Thu Jul 10 04:45:12 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Thu, 10 Jul 2014 13:45:12 +0200
Subject: [RFT/RFC 3/5] cfg80211: allow RX amsdu to be reported as a list
In-Reply-To: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
References: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <1404992714-15690-4-git-send-email-janusz.dziedzic@tieto.com>

ath10k hw report amsdu frames as a separate frames.
mac80211 before this patch expect one big frame
with msdu subframes included. Next split this big
frame into smaller ethernet frames and report to
the stack.
To skip this not needed memcpy, allow driver to report
amsdu as a list of frames using skb->next.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
---
 net/wireless/util.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/net/wireless/util.c b/net/wireless/util.c
index 728f1c0..72e9ae7 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -617,6 +617,50 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
 		eth = (struct ethhdr *) skb->data;
 	}
 
+	if (skb->next) {
+		/* Seems we already get list of msdu frames */
+		do {
+			__be16 len;
+			eth = (struct ethhdr *) skb->data;
+
+			frame = skb;
+
+			memcpy(dst, eth->h_dest, ETH_ALEN);
+			memcpy(src, eth->h_source, ETH_ALEN);
+			len = eth->h_proto;
+
+			skb_pull(skb, sizeof(struct ethhdr));
+
+			skb_reset_network_header(frame);
+			frame->dev = skb->dev;
+			frame->priority = skb->priority;
+
+			payload = frame->data;
+			ethertype = (payload[6] << 8) | payload[7];
+
+			if (likely((ether_addr_equal(payload, rfc1042_header) &&
+				    ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+				   ether_addr_equal(payload, bridge_tunnel_header))) {
+				/* remove RFC1042 or Bridge-Tunnel
+				 * encapsulation and replace EtherType */
+				skb_pull(frame, 6);
+				memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
+				memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
+			} else {
+				memcpy(skb_push(frame, sizeof(__be16)), &len,
+					sizeof(__be16));
+				memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
+				memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
+			}
+
+			skb = skb->next;
+			frame->next = NULL;
+			__skb_queue_tail(list, frame);
+		} while (skb);
+
+		return;
+	}
+
 	while (skb != frame) {
 		u8 padding;
 		__be16 len = eth->h_proto;
-- 
1.7.9.5



From janusz.dziedzic at tieto.com  Thu Jul 10 04:45:10 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Thu, 10 Jul 2014 13:45:10 +0200
Subject: [RFT/RFC 1/5] ath10k: amsdu rx, buid one big frame
In-Reply-To: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
References: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <1404992714-15690-2-git-send-email-janusz.dziedzic@tieto.com>

Temporary patch, to check if will solve ampdu reordering issue.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c |   71 +++++++++++++++++++++---------
 1 file changed, 50 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 57d5a97..2a0526b 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -874,12 +874,15 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 {
 	struct htt_rx_desc *rxd;
 	struct sk_buff *skb = skb_in;
-	struct sk_buff *first;
+	struct sk_buff *first, *frame = NULL, *tmp;
 	enum rx_msdu_decap_format fmt;
 	enum htt_rx_mpdu_encrypt_type enctype;
 	struct ieee80211_hdr *hdr;
-	u8 hdr_buf[64], addr[ETH_ALEN], *qos;
+	u8 hdr_buf[64], addr[ETH_ALEN];
 	unsigned int hdr_len;
+	struct amsdu_subframe_hdr subframe_hdr;
+	unsigned int size = 0;
+	u8 padding;
 
 	rxd = (void *)skb->data - sizeof(*rxd);
 	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
@@ -890,6 +893,21 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 	memcpy(hdr_buf, hdr, hdr_len);
 	hdr = (struct ieee80211_hdr *)hdr_buf;
 
+	/* Check size we will need */
+	tmp = skb_in;
+	while (tmp) {
+		size = size + tmp->len;
+		tmp = tmp->next;
+	}
+
+	frame = dev_alloc_skb(size + skb_headroom(skb_in));
+	if (!frame) {
+		dev_kfree_skb_any(skb_in);
+		return;
+	}
+
+	skb_reserve(frame, skb_headroom(skb_in));
+
 	first = skb;
 	while (skb) {
 		void *decap_hdr;
@@ -922,19 +940,28 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 			memcpy(addr, ieee80211_get_DA(hdr), ETH_ALEN);
 			skb_pull(skb, hdr_len);
 
-			/* push original 802.11 header */
-			hdr = (struct ieee80211_hdr *)hdr_buf;
-			hdr_len = ieee80211_hdrlen(hdr->frame_control);
-			memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
+			/* cfg80211 expect this padding */
+			padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
+			skb_put(skb, padding);
 
-			/* original A-MSDU header has the bit set but we're
-			 * not including A-MSDU subframe header */
-			hdr = (struct ieee80211_hdr *)skb->data;
-			qos = ieee80211_get_qos_ctl(hdr);
-			qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+			/* build amsdu subframe header */
+			memcpy(&subframe_hdr.dst, addr, ETH_ALEN);
+			memcpy(&subframe_hdr.src, ieee80211_get_SA(hdr), ETH_ALEN);
+			subframe_hdr.len = __cpu_to_be16(skb->len) ;
 
-			/* original 802.11 header has a different DA */
-			memcpy(ieee80211_get_DA(hdr), addr, ETH_ALEN);
+			/* push back amsdu hdr */
+			memcpy(skb_push(skb, sizeof(subframe_hdr)), &subframe_hdr,
+			       sizeof(subframe_hdr));
+
+			if (skb == first) {
+				/* push back orginal 80211 header */
+				hdr = (struct ieee80211_hdr *)hdr_buf;
+				hdr_len = ieee80211_hdrlen(hdr->frame_control);
+				memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
+
+				/* original 802.11 header has a different DA */
+				memcpy(ieee80211_get_DA(hdr), addr, ETH_ALEN);
+			}
 			break;
 		case RX_MSDU_DECAP_ETHERNET2_DIX:
 			/* strip ethernet header and insert decapped 802.11
@@ -956,19 +983,21 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 		}
 
 		skb_in = skb;
-		ath10k_htt_rx_h_protected(htt, rx_status, skb_in, enctype, fmt,
-					  false);
+
+		if (skb_in == first)
+			ath10k_htt_rx_h_protected(htt, rx_status, skb_in,
+						  enctype, fmt, false);
+
+		memcpy(skb_put(frame, skb_in->len), skb_in->data, skb_in->len);
+
 		skb = skb->next;
 		skb_in->next = NULL;
 
-		if (skb)
-			rx_status->flag |= RX_FLAG_AMSDU_MORE;
-		else
-			rx_status->flag &= ~RX_FLAG_AMSDU_MORE;
-
-		ath10k_process_rx(htt->ar, rx_status, skb_in);
+		/* We don't need this skb anymore */
+		dev_kfree_skb(skb_in);
 	}
 
+	ath10k_process_rx(htt->ar, rx_status, frame);
 	/* FIXME: It might be nice to re-assemble the A-MSDU when there's a
 	 * monitor interface active for sniffing purposes. */
 }
-- 
1.7.9.5



From janusz.dziedzic at tieto.com  Thu Jul 10 04:45:13 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Thu, 10 Jul 2014 13:45:13 +0200
Subject: [RFT/RFC 4/5] ath10k: report amsdu as a skb list
In-Reply-To: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
References: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <1404992714-15690-5-git-send-email-janusz.dziedzic@tieto.com>

Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c |   48 +++++++++++-------------------
 1 file changed, 18 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 2a0526b..702653e 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -874,15 +874,14 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 {
 	struct htt_rx_desc *rxd;
 	struct sk_buff *skb = skb_in;
-	struct sk_buff *first, *frame = NULL, *tmp;
+	struct sk_buff *first;
 	enum rx_msdu_decap_format fmt;
 	enum htt_rx_mpdu_encrypt_type enctype;
 	struct ieee80211_hdr *hdr;
 	u8 hdr_buf[64], addr[ETH_ALEN];
 	unsigned int hdr_len;
 	struct amsdu_subframe_hdr subframe_hdr;
-	unsigned int size = 0;
-	u8 padding;
+	struct ieee80211_rx_status *status;
 
 	rxd = (void *)skb->data - sizeof(*rxd);
 	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
@@ -893,21 +892,6 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 	memcpy(hdr_buf, hdr, hdr_len);
 	hdr = (struct ieee80211_hdr *)hdr_buf;
 
-	/* Check size we will need */
-	tmp = skb_in;
-	while (tmp) {
-		size = size + tmp->len;
-		tmp = tmp->next;
-	}
-
-	frame = dev_alloc_skb(size + skb_headroom(skb_in));
-	if (!frame) {
-		dev_kfree_skb_any(skb_in);
-		return;
-	}
-
-	skb_reserve(frame, skb_headroom(skb_in));
-
 	first = skb;
 	while (skb) {
 		void *decap_hdr;
@@ -940,10 +924,6 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 			memcpy(addr, ieee80211_get_DA(hdr), ETH_ALEN);
 			skb_pull(skb, hdr_len);
 
-			/* cfg80211 expect this padding */
-			padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
-			skb_put(skb, padding);
-
 			/* build amsdu subframe header */
 			memcpy(&subframe_hdr.dst, addr, ETH_ALEN);
 			memcpy(&subframe_hdr.src, ieee80211_get_SA(hdr), ETH_ALEN);
@@ -984,20 +964,26 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 
 		skb_in = skb;
 
-		if (skb_in == first)
-			ath10k_htt_rx_h_protected(htt, rx_status, skb_in,
+		if (skb == first) {
+			ath10k_htt_rx_h_protected(htt, rx_status, skb,
 						  enctype, fmt, false);
+			if (skb->next)
+				rx_status->flag |= RX_FLAG_AMSDU_LIST;
+			else
+				rx_status->flag &= ~RX_FLAG_AMSDU_LIST;
+		}
 
-		memcpy(skb_put(frame, skb_in->len), skb_in->data, skb_in->len);
+		/* Setup AMSDU flag in skb->next ... subframes */
+		status = IEEE80211_SKB_RXCB(skb);
+		memset(status, 0, sizeof(*status));
 
-		skb = skb->next;
-		skb_in->next = NULL;
+		if (skb->next)
+			status->flag |= RX_FLAG_AMSDU_LIST;
 
-		/* We don't need this skb anymore */
-		dev_kfree_skb(skb_in);
+		skb = skb->next;
 	}
 
-	ath10k_process_rx(htt->ar, rx_status, frame);
+	ath10k_process_rx(htt->ar, rx_status, first);
 	/* FIXME: It might be nice to re-assemble the A-MSDU when there's a
 	 * monitor interface active for sniffing purposes. */
 }
@@ -1307,6 +1293,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
 			else
 				rx_status->flag &= ~RX_FLAG_MMIC_ERROR;
 
+			rx_status->flag &= ~RX_FLAG_AMSDU_LIST;
+
 			hdr = ath10k_htt_rx_skb_get_hdr(msdu_head);
 
 			if (ath10k_htt_rx_hdr_is_amsdu(hdr))
-- 
1.7.9.5



From janusz.dziedzic at tieto.com  Thu Jul 10 04:45:14 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Thu, 10 Jul 2014 13:45:14 +0200
Subject: [RFT/RFC 5/5] ath10k: rx, don't pass frames with invalid FCS
In-Reply-To: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
References: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <1404992714-15690-6-git-send-email-janusz.dziedzic@tieto.com>

In case of bridged network, don't pass frames with
invalid FCS to the upper layer.

TODO: pass all frames in standalone monitor mode.

Signed-off-by: Janusz Dziedzic <janusz.dziedzi at tieto.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 702653e..efcee32 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1173,8 +1173,7 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
 
 	if (status != HTT_RX_IND_MPDU_STATUS_OK &&
 	    status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR &&
-	    status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER &&
-	    !htt->ar->monitor_started) {
+	    status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER) {
 		ath10k_dbg(ATH10K_DBG_HTT,
 			   "htt rx ignoring frame w/ status %d\n",
 			   status);
-- 
1.7.9.5



From vh.nguyen at actiasodielec.fr  Thu Jul 10 04:51:36 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Thu, 10 Jul 2014 13:51:36 +0200
Subject: Bridging problem in ath10k (STA)
In-Reply-To: <CALhHN=oBttgRd2-F2+UNy9NHPpX4yGXjTD-mhXsg+8sk7Czz=w@mail.gmail.com>
References: <CAEFj986inLh+Upgx-rVF0zviii+yaQZnr9cuMYOXAqEjXrVMvQ@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F109978FC@srvexch01.SODIELEC.local>
 <CAEFj986wbAp3-7y3ocpYzCWvYU=J0H6fQbrnMA3-qetRruF6RA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F109978FE@srvexch01.SODIELEC.local>
 <CAEFj986pnp2qHu8YuYyHLN66jAy2Mf+AAS=pLsuK6gdq6BU23Q@mail.gmail.com>
 <CA+BoTQnpdcBOrX32Ma7q0OZ5eaPYM31g8VV4HU==nMUqfA2Fzw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7E0@srvexch01.SODIELEC.local>
 <CALhHN=qAGsGa_+79he1R9okHEj8ZoJdEUYUC0tM4jQy0Y9ogxQ@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7E1@srvexch01.SODIELEC.local>,
 <CALhHN=oBttgRd2-F2+UNy9NHPpX4yGXjTD-mhXsg+8sk7Czz=w@mail.gmail.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7E4@srvexch01.SODIELEC.local>

>>>Just guessing, Is wlan0.sta1 added to bridge? If not what if you will
>>>add it manually after created?

>> Sorry I don't really understand your question. My AP has the interface br0 which connects wlan0 and eth0.
>>I should run "iw dev wlan0.sta1 set 4addr on" to add it manually?
>> And can you guess why does Iperf cause the problem? That interface is created only when I run Iperf, not when
>> pinging between two devices cause my STA is non-bridged and it associate on the interface wlan0 of AP.

>try this:
>brctl addif brX wlan0.sta1

Thank you, I did it but the command returns "the interface wlan0.sta1 is already a member of the bridge, can not enslave
it to the bridge br0".  And I still lost the connection between AP and STA (pinging not success).


NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE




From denton.gentry at gmail.com  Thu Jul 10 06:40:32 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Thu, 10 Jul 2014 06:40:32 -0700
Subject: A-MSDU reception not working?
In-Reply-To: <CALhHN=ozVHCzFPnz318SNE+YxgArdqKu4pTrc-Q1V88ujCz2ow@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
 <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>
 <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>
 <CALhHN=pvh8qocDzoMvK--__hJD1PVe5CrPBVriC1w=Bx1cpxpg@mail.gmail.com>
 <CABnBrYVY_KY8mMAKhy-DV1s3+vut8oR_LohyBJX3GtW7RT=3XA@mail.gmail.com>
 <CALhHN=ozVHCzFPnz318SNE+YxgArdqKu4pTrc-Q1V88ujCz2ow@mail.gmail.com>
Message-ID: <CABnBrYXsLi3XNbBGtgW7rFhOXW7oOvh29+GapFsX+Rzx36V_QA@mail.gmail.com>

I added this check for RX_ATTENTION_FLAGS_FCS_ERR in
ath10k_htt_rx_handler, along with a printk to verify that the code was
being run.

                        if (attention & RX_ATTENTION_FLAGS_FCS_ERR) {
                                ath10k_htt_rx_free_msdu_chain(msdu_head);
                                printk(KERN_WARNING
"ath10k_htt_rx_handler: amsdu RX_ATTENTION_FLAGS_FCS_ERR");
                                continue;
                        } else
                                rx_status->flag &= ~RX_FLAG_FAILED_FCS_CRC;

I see the printk appear in dmesg, so I know some packets are hitting
it. The throughput from the MacOS 802.11ac STA does improve, from 5-20
Mbps without to 50-60 Mbps with this change. Prior to adding the
reorder buffer fix, the MacBook was getting 170 Mbps.

However, packets with incorrect TCP checksums are still being
delivered to the Ethernet connected server at the other end. I
gathered pcaps at the MacBook, at the ath10k AP, on another ath10k
device configured in monitor mode as a sniffer, and at the
Ethernet-connected Ubuntu server at the other end.


server.pcap
Captured from the Ubuntu iperf server, connected to the AP via Ethernet.

Packet #10: TCP seq 4369, IP ID 0x6373, TCP checksum incorrect
At offset 208 bytes into the data we see ?32 33 34 35? replaced by ?98 19 1e b7?

Packet #17: TCP seq 4369, IP ID 0x6373, TCP checksum correct
Packet #23: TCP seq 4369, IP ID 0xe152, TCP checksum correct


ap.pcap
Captured from the AP.

Packet #10: TCP seq 4369, IP ID 0x6373, TCP checksum incorrect
At offset 208 bytes into the data we see ?32 33 34 35? replaced by ?98 19 1e b7?
This is the same pattern we see in the Ubuntu server's trace.

Packet #14: TCP seq 4369, IP ID 0x6373, TCP checksum correct
This was a Wifi-layer retransmit, which I think means the firmware
knew that something was wrong with packet #10. In the wifisniffer
trace, packet #19 is a Block ACK from the AP which requests one packet
be retransmitted.
However it appears that RX_ATTENTION_FLAGS_FCS_ERR was not set on
packet #10, so it was forwarded to the Ethernet.

Packet #24: TCP seq 4369, IP ID 0xe152, TCP checksum correct
This is a TCP-layer retransmit from the MacBook, as the IP ID is different.


wifisniffer.pcap
A second ath10 configured in monitor mode.
Packet #17 AMSDU#1: TCP seq 4369, IP ID 0x6373, TCP checksum correct
This is packet #10 in the AP trace. Note that the sniffer did not see
?98 19 1e b7? like the AP did.

Packet #20 AMSDU#1: TCP seq 4369, IP ID 0x6373, TCP checksum correct
This is packet #14 in the AP trace.

Packet #39 AMSDU#2: TCP seq 4369, IP ID 0xe152, TCP checksum correct
This is packet #24 in the AP trace.


macbook.pcapng
56: TCP seq 4369, IP ID 0x6373, TCP checksum correct
This is the original transmission. Wireshark on MacOS cannot put the
interface into monitor mode, so we do not see the Wifi-layer
retransmission of this packet.

65: TCP seq 4369, IP ID 0xe152, TCP checksum correct
This is a TCP retransmission, triggered because it received duplicate
TCP ACKs back from the Ubuntu server.


On Wed, Jul 9, 2014 at 12:39 AM, Janusz Dziedzic
<janusz.dziedzic at tieto.com> wrote:
> On 9 July 2014 08:09, Denton Gentry <denton.gentry at gmail.com> wrote:
>> I ran iperf on an 802.11ac MacBook Air, through my ath10 AP, and to an
>> Ubuntu system connected to the AP via Ethernet. The AP was running the
>> reorder buffer patches, the patch to make A-MSDU bypass the reorder
>> buffer, and the patch to make amsdu aggregation configurable via
>> debugfs.
>>
>> http://lists.infradead.org/pipermail/ath10k/2014-June/002551.html
>> http://lists.infradead.org/pipermail/ath10k/2014-June/002553.html
>> http://lists.infradead.org/pipermail/ath10k/2014-July/002597.html
>> http://permalink.gmane.org/gmane.linux.kernel.wireless.general/124128
>>
>> It was notably not running the patch from earlier in this thread to
>> copy A-MSDU subframes into one skb.
>>
>>
>> I used a second ath10k AP configured in monitor mode as a Wifi
>> sniffer. I also gathered pcaps on the MacBook Air and on the Ubuntu
>> system. Wireshark on the MacBook cannot gather radiotap headers nor
>> put the interface into monitor mode, so we see only Ethernet frames
>> and we don't see retransmissions on the Wifi link.
>>
>> I've attached decodes of the same two packets as captured by the
>> MacBook, by the sniffer, and by the Ubuntu server.
>>
>> The MacBook sends two frames, TCP sequence numbers 3065441 and 3066889
>> (the Wireshark "relative sequence number"). In the Wifi sniffer we see
>> these being aggregated as two subframes in an A-MSDU frame. The first
>> time this A-MSDU is sent it is corrupted in the air. We see the TCP
>> checksum of one of the subframes is wrong, and a few bytes of the
>> payload replaced with "&gt%'g9(1$".
>>
>> The A-MSDU is retransmitted a short time later, and the second time
>> the TCP checksum of both subframes is correct.
>>
>> This is all fine so far.
>>
>> However in the pcap taken from the Ubuntu server, we see TCP sequence
>> number 3065441 being delivered *twice.* The first time, the TCP
>> checksum is wrong. The second time the TCP checksum is correct.
>>
>> To me, it looks like A-MSDU frames with bad FCS are not being
>> discarded after ieee80211_rx_monitor(). The corrupted frames are being
>> delivered. Delivering the corrupted frames results in sending more TCP
>> Dup ACKs for the same sequence number back to the MacBook, and I think
>> this is what causes the MacBook to decide there is congestion and slow
>> down.
>>
> OK, to be sure this is the main issue we can just drop frames with wrong FCS.
> Could you check this:
>
> @@ -1267,10 +1267,10 @@ static void ath10k_htt_rx_handler(struct
> ath10k_htt *htt,
>                                 continue;
>                         }
>
> -                       if (attention & RX_ATTENTION_FLAGS_FCS_ERR)
> -                               rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
> -                       else
> -                               rx_status->flag &= ~RX_FLAG_FAILED_FCS_CRC;
> +                       if (attention & RX_ATTENTION_FLAGS_FCS_ERR) {
> +                               ath10k_htt_rx_free_msdu_chain(msdu_head);
> +                               continue;
> +                       }
>
>                         if (attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR)
>
> If will help we will have to check how to handle monitor + ap case
> correctly, one of idea is to not drop frames with wrong FCS only in
> case of standalone monitor mode.
> But, please try this patch to be sure.
>
> BR
> Janusz
>
>
>> One note: the wifi sniffer does not show the same corruption to the
>> same packet as the pcap from the Ubuntu system shows. I think that is
>> normal: the sniffer won't see precisely the same noise, won't have
>> precisely the same receive sensitivity, and its antennas are not
>> pointing in the same direction as the primary AP. If I do this test
>> again, I'll gather a pcap on the primary AP as well to compare to what
>> we see on the Ubuntu system.
>>
>>
>> On Tue, Jul 8, 2014 at 12:29 AM, Janusz Dziedzic
>> <janusz.dziedzic at tieto.com> wrote:
>>> On 8 July 2014 09:02, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>>>> On 8 July 2014 08:50, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>>>>> On 8 July 2014 08:43, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>> I think I know what is happening now, though I've no idea why. The
>>>>>> throughput is low because we have many TCP retransmissions. We have
>>>>>> retransmissions because the TCP checksum is wrong on a number of
>>>>>> frames, and I do find data corruption in the payload so the checksum
>>>>>> definitely should be wrong. All of the corrupted frames were
>>>>>> originally one of the subframes in an A-MSDU packet.
>>>>>>
>>>>>> An example follows at the end of this message, as dissected by
>>>>>> Wireshark. iperf sends a very regular data pattern of "0123456789..."
>>>>>> over and over. Note how in subframe #2 offset 0x1e0 the bytes "32 33
>>>>>> 34" have been replaced by "72 36 35"
>>>>>>
>>>>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>>>>
>>>>>> I added printks at the bottom of ath10k_htt_rx_amsdu immediately
>>>>>> before the call to ath10k_process_rx. I found this same packet, and we
>>>>>> see the "72 36 35" corruption in the printk. So I think it happened in
>>>>>> ath10k_process_rx or before, not anything weird after passing it up to
>>>>>> mac80211.
>>>>>>
>>>>>> [  101.863712] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>>>>> [  101.863727] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>>>> [  101.863742] ath10k: 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32
>>>>>> [  101.863757] ath10k: 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37 38
>>>>>> [  101.863773] ath10k: 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34
>>>>>> [  101.863788] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>>>>> [  101.863803] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>>>>
>>>>>>
>>>>>> I've found a number of examples of similar corruption, always with
>>>>>> between one and four bytes replaced.
>>>>>>
>>>>>> 35363738 -> e52c6e07
>>>>>> 3435 -> b43f
>>>>>> 3839 -> c238
>>>>>> 31 -> 7f
>>>>>> 3435 -> 7436
>>>>>> 30 -> 50
>>>>>> 3233 -> bc37
>>>>>>
>>>>> Seems this could be because of:
>>>>>
>>>>> + /* cfg80211 expect this padding */
>>>>> + padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
>>>>> + skb_put(skb, padding);
>>>>>
>>>>
>>>> BTW, when AP (ath10k) send TCP ACK - are this packets also AMSDU?
>>>> I see in my case AP can send 3 x A-MSDU (with total size 304 bytes)
>>>> small frames aggregated. Maybe your HW have problems with that.
>>>> As I remember correctly someone some time ago report problems with
>>>> MacBook pro retina but I am not sure this is the same, while no one
>>>> tests the fix.
>>>>
>>>>>>
>>>>>> The packet described above, dissected by Wireshark:
>>>>>>
>>>>>> No.     Time        Source                Destination
>>>>>> Protocol Length Info
>>>>>>    2235 18.953349   192.168.144.79        192.168.144.13        TCP
>>>>>>   3112   52697 > 5001 [ACK] Seq=1391553 Ack=1 Win=131760 [TCP CHECKSUM
>>>>>> INCORRECT] Len=1448 TSval=1298580657 TSecr=4294947481
>>>>>>
>>>>>> Frame 2235: 3112 bytes on wire (24896 bits), 3112 bytes captured (24896 bits)
>>>>>>     Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
>>>>>>     Arrival Time: Jul  7, 2014 23:03:37.763365000 PDT
>>>>>>     [Time shift for this packet: 0.000000000 seconds]
>>>>>>     Epoch Time: 1404799417.763365000 seconds
>>>>>>     [Time delta from previous captured frame: 0.003476000 seconds]
>>>>>>     [Time delta from previous displayed frame: 0.515641000 seconds]
>>>>>>     [Time since reference or first frame: 18.953349000 seconds]
>>>>>>     Frame Number: 2235
>>>>>>     Frame Length: 3112 bytes (24896 bits)
>>>>>>     Capture Length: 3112 bytes (24896 bits)
>>>>>>     [Frame is marked: False]
>>>>>>     [Frame is ignored: False]
>>>>>>     [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
>>>>>>     [Coloring Rule Name: TCP]
>>>>>>     [Coloring Rule String: tcp]
>>>>>> Radiotap Header v0, Length 38
>>>>>>     Header revision: 0
>>>>>>     Header pad: 0
>>>>>>     Header length: 38
>>>>>>     Present flags
>>>>>>         .... .... .... .... .... .... .... ...1 = TSFT: True
>>>>>>         .... .... .... .... .... .... .... ..1. = Flags: True
>>>>>>         .... .... .... .... .... .... .... .0.. = Rate: False
>>>>>>         .... .... .... .... .... .... .... 1... = Channel: True
>>>>>>         .... .... .... .... .... .... ...0 .... = FHSS: False
>>>>>>         .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
>>>>>>         .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
>>>>>>         .... .... .... .... .... .... 0... .... = Lock Quality: False
>>>>>>         .... .... .... .... .... ...0 .... .... = TX Attenuation: False
>>>>>>         .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
>>>>>>         .... .... .... .... .... .0.. .... .... = dBm TX Power: False
>>>>>>         .... .... .... .... .... 1... .... .... = Antenna: True
>>>>>>         .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
>>>>>>         .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
>>>>>>         .... .... .... .... .1.. .... .... .... = RX flags: True
>>>>>>         .... .... .... .0.. .... .... .... .... = Channel+: False
>>>>>>         .... .... .... 0... .... .... .... .... = HT information: False
>>>>>>         .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
>>>>>>         .... .... ..1. .... .... .... .... .... = VHT information: True
>>>>>>         ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
>>>>>>         ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
>>>>>>         .0.. .... .... .... .... .... .... .... = Vendor NS next: False
>>>>>>         0... .... .... .... .... .... .... .... = Ext: False
>>>>>>     MAC timestamp: 78051063
>>>>>>     Flags: 0x00
>>>>>>         .... ...0 = CFP: False
>>>>>>         .... ..0. = Preamble: Long
>>>>>>         .... .0.. = WEP: False
>>>>>>         .... 0... = Fragmentation: False
>>>>>>         ...0 .... = FCS at end: False
>>>>>>         ..0. .... = Data Pad: False
>>>>>>         .0.. .... = Bad FCS: False
>>>>>>         0... .... = Short GI: False
>>>>>>     Channel frequency: 5745 [A 149]
>>>>>>     Channel type: 802.11a (0x0140)
>>>>>>         .... .... ...0 .... = Turbo: False
>>>>>>         .... .... ..0. .... = Complementary Code Keying (CCK): False
>>>>>>         .... .... .1.. .... = Orthogonal Frequency-Division
>>>>>> Multiplexing (OFDM): True
>>>>>>         .... .... 0... .... = 2 GHz spectrum: False
>>>>>>         .... ...1 .... .... = 5 GHz spectrum: True
>>>>>>         .... ..0. .... .... = Passive: False
>>>>>>         .... .0.. .... .... = Dynamic CCK-OFDM: False
>>>>>>         .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
>>>>>>         ...0 .... .... .... = GSM (900MHz): False
>>>>>>         ..0. .... .... .... = Static Turbo: False
>>>>>>         .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
>>>>>>         0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
>>>>>>     SSI Signal: -53 dBm
>>>>>>     Antenna: 0
>>>>>>     RX flags: 0x0000
>>>>>>         .... .... .... .... .... ..0. = Bad PLCP: False
>>>>>>     VHT information
>>>>>>         Known VHT information: 0x44
>>>>>>             .... .... .... ...0 = STBC: False
>>>>>>             .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
>>>>>>             .... .... .... .1.. = Guard interval: True
>>>>>>             .... .... .... 0... = SGI Nsym disambiguation: False
>>>>>>             .... .... ...0 .... = LDPC extra OFDM symbol: False
>>>>>>             .... .... ..0. .... = Beamformed: False
>>>>>>             .... .... .1.. .... = Bandwidth: True
>>>>>>             .... .... 0... .... = Group ID: False
>>>>>>             .... ...0 .... .... = Partial AID: False
>>>>>>         .... .0.. = Guard interval: long (0)
>>>>>>         Bandwidth: 80 MHz (4)
>>>>>>         User 0: MCS 8
>>>>>>             1000 .... = MCS index 0: 8 (256-QAM 3/4)
>>>>>>             .... 0010 = Spatial streams 0: 2
>>>>>>             Space-time streams 0: 2
>>>>>>             Coding 0: BCC (0)
>>>>>>             [Data Rate: 702.0 Mb/s]
>>>>>> IEEE 802.11 QoS Data, Flags: .......T
>>>>>>     Type/Subtype: QoS Data (0x28)
>>>>>>     Frame Control Field: 0x8801
>>>>>>         .... ..00 = Version: 0
>>>>>>         .... 10.. = Type: Data frame (2)
>>>>>>         1000 .... = Subtype: 8
>>>>>>         Flags: 0x01
>>>>>>             .... ..01 = DS status: Frame from STA to DS via an AP (To
>>>>>> DS: 1 From DS: 0) (0x01)
>>>>>>             .... .0.. = More Fragments: This is the last fragment
>>>>>>             .... 0... = Retry: Frame is not being retransmitted
>>>>>>             ...0 .... = PWR MGT: STA will stay up
>>>>>>             ..0. .... = More Data: No data buffered
>>>>>>             .0.. .... = Protected flag: Data is not protected
>>>>>>             0... .... = Order flag: Not strictly ordered
>>>>>>     .000 0000 0011 0000 = Duration: 48 microseconds
>>>>>>     Receiver address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>>     BSS Id: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>>     Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>     Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>     Destination address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>>     Fragment number: 0
>>>>>>     Sequence number: 1021
>>>>>>     Qos Control: 0x0080
>>>>>>         .... .... .... 0000 = TID: 0
>>>>>>         [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
>>>>>>         .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control
>>>>>> field are TXOP Duration Requested
>>>>>>         .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
>>>>>>         .... .... 1... .... = Payload Type: A-MSDU
>>>>>>         0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
>>>>>> IEEE 802.11 Aggregate MSDU
>>>>>>     A-MSDU Subframe #1
>>>>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>         A-MSDU Length: 1510
>>>>>>         Logical-Link Control
>>>>>>             DSAP: SNAP (0xaa)
>>>>>>             IG Bit: Individual
>>>>>>             SSAP: SNAP (0xaa)
>>>>>>             CR Bit: Command
>>>>>>             Control field: U, func=UI (0x03)
>>>>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>>>>             Type: IP (0x0800)
>>>>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>>>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>>>>             Version: 4
>>>>>>             Header length: 20 bytes
>>>>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>>>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>>>>> (Not ECN-Capable Transport) (0x00)
>>>>>>             Total Length: 1500
>>>>>>             Identification: 0xc622 (50722)
>>>>>>             Flags: 0x00
>>>>>>                 0... .... = Reserved bit: Not set
>>>>>>                 .0.. .... = Don't fragment: Not set
>>>>>>                 ..0. .... = More fragments: Not set
>>>>>>             Fragment offset: 0
>>>>>>             Time to live: 64
>>>>>>             Protocol: TCP (6)
>>>>>>             Header checksum: 0x0d4c [correct]
>>>>>>                 [Good: True]
>>>>>>                 [Bad: False]
>>>>>>             Source: 192.168.144.79 (192.168.144.79)
>>>>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>>>>             [Source GeoIP: Unknown]
>>>>>>             [Destination GeoIP: Unknown]
>>>>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>>>>> Port: 5001 (5001), Seq: 1390105, Ack: 1, Len: 1448
>>>>>>             Source port: 52697 (52697)
>>>>>>             Destination port: 5001 (5001)
>>>>>>             [Stream index: 0]
>>>>>>             Sequence number: 1390105    (relative sequence number)
>>>>>>             [Next sequence number: 1391553    (relative sequence number)]
>>>>>>             Acknowledgment number: 1    (relative ack number)
>>>>>>             Header length: 32 bytes
>>>>>>             Flags: 0x010 (ACK)
>>>>>>                 000. .... .... = Reserved: Not set
>>>>>>                 ...0 .... .... = Nonce: Not set
>>>>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>>>>                 .... .0.. .... = ECN-Echo: Not set
>>>>>>                 .... ..0. .... = Urgent: Not set
>>>>>>                 .... ...1 .... = Acknowledgment: Set
>>>>>>                 .... .... 0... = Push: Not set
>>>>>>                 .... .... .0.. = Reset: Not set
>>>>>>                 .... .... ..0. = Syn: Not set
>>>>>>                 .... .... ...0 = Fin: Not set
>>>>>>             Window size value: 8235
>>>>>>             [Calculated window size: 131760]
>>>>>>             [Window size scaling factor: 16]
>>>>>>             Checksum: 0xa1c0 [correct]
>>>>>>                 [Good Checksum: True]
>>>>>>                 [Bad Checksum: False]
>>>>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>>>>> (NOP), Timestamps
>>>>>>                 No-Operation (NOP)
>>>>>>                     Type: 1
>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>                         .00. .... = Class: Control (0)
>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>                 No-Operation (NOP)
>>>>>>                     Type: 1
>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>                         .00. .... = Class: Control (0)
>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>>>>                     Kind: Timestamp (8)
>>>>>>                     Length: 10
>>>>>>                     Timestamp value: 1298580657
>>>>>>                     Timestamp echo reply: 4294947481
>>>>>>         Data (1448 bytes)
>>>>>>
>>>>>> 0000  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0010  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0020  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0030  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0040  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0050  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0060  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0070  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0080  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0090  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 00a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 00b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 00c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 00d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 00e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 00f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0100  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0110  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0120  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0130  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0140  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0150  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0160  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0170  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0180  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0190  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 01a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 01b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 01c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 01d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 01e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 01f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0200  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0210  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0220  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0230  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0240  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0250  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0260  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0270  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0280  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0290  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 02a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 02b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 02c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 02d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 02e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 02f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0300  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0310  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0320  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0330  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0340  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0350  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0360  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0370  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0380  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0390  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 03a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 03b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 03c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 03d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 03e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 03f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0400  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0410  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0420  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0430  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0440  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0450  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0460  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0470  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0480  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0490  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 04a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 04b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 04c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 04d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 04e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 04f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0500  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0510  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0520  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0530  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0540  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0550  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0560  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0570  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0580  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0590  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 05a0  34 35 36 37 38 39 30 31                           45678901
>>>>>>             Data: 343536373839303132333435363738393031323334353637...
>>>>>>             [Length: 1448]
>>>>>>     A-MSDU Subframe #2
>>>>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>         A-MSDU Length: 1510
>>>>>>         Logical-Link Control
>>>>>>             DSAP: SNAP (0xaa)
>>>>>>             IG Bit: Individual
>>>>>>             SSAP: SNAP (0xaa)
>>>>>>             CR Bit: Command
>>>>>>             Control field: U, func=UI (0x03)
>>>>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>>>>             Type: IP (0x0800)
>>>>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>>>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>>>>             Version: 4
>>>>>>             Header length: 20 bytes
>>>>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>>>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>>>>> (Not ECN-Capable Transport) (0x00)
>>>>>>             Total Length: 1500
>>>>>>             Identification: 0xda09 (55817)
>>>>>>             Flags: 0x00
>>>>>>                 0... .... = Reserved bit: Not set
>>>>>>                 .0.. .... = Don't fragment: Not set
>>>>>>                 ..0. .... = More fragments: Not set
>>>>>>             Fragment offset: 0
>>>>>>             Time to live: 64
>>>>>>             Protocol: TCP (6)
>>>>>>             Header checksum: 0xf964 [correct]
>>>>>>                 [Good: True]
>>>>>>                 [Bad: False]
>>>>>>             Source: 192.168.144.79 (192.168.144.79)
>>>>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>>>>             [Source GeoIP: Unknown]
>>>>>>             [Destination GeoIP: Unknown]
>>>>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>>>>> Port: 5001 (5001), Seq: 1391553, Ack: 1, Len: 1448
>>>>>>             Source port: 52697 (52697)
>>>>>>             Destination port: 5001 (5001)
>>>>>>             [Stream index: 0]
>>>>>>             Sequence number: 1391553    (relative sequence number)
>>>>>>             [Next sequence number: 1393001    (relative sequence number)]
>>>>>>             Acknowledgment number: 1    (relative ack number)
>>>>>>             Header length: 32 bytes
>>>>>>             Flags: 0x010 (ACK)
>>>>>>                 000. .... .... = Reserved: Not set
>>>>>>                 ...0 .... .... = Nonce: Not set
>>>>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>>>>                 .... .0.. .... = ECN-Echo: Not set
>>>>>>                 .... ..0. .... = Urgent: Not set
>>>>>>                 .... ...1 .... = Acknowledgment: Set
>>>>>>                 .... .... 0... = Push: Not set
>>>>>>                 .... .... .0.. = Reset: Not set
>>>>>>                 .... .... ..0. = Syn: Not set
>>>>>>                 .... .... ...0 = Fin: Not set
>>>>>>             Window size value: 8235
>>>>>>             [Calculated window size: 131760]
>>>>>>             [Window size scaling factor: 16]
>>>>>>             Checksum: 0x9a16 [incorrect, should be 0x5913 (maybe
>>>>>> caused by "TCP checksum offload"?)]
>>>
>>> And yes we are using checksum offload in ath10k.
>>> Best is using standalone 80211ac sniffer for that case to be sure
>>> about checksum.
>>>
>>>>>>                 [Good Checksum: False]
>>>>>>                 [Bad Checksum: True]
>>>>>>                     [Expert Info (Error/Checksum): Bad checksum]
>>>>>>                         [Message: Bad checksum]
>>>>>>                         [Severity level: Error]
>>>>>>                         [Group: Checksum]
>>>>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>>>>> (NOP), Timestamps
>>>>>>                 No-Operation (NOP)
>>>>>>                     Type: 1
>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>                         .00. .... = Class: Control (0)
>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>                 No-Operation (NOP)
>>>>>>                     Type: 1
>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>                         .00. .... = Class: Control (0)
>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>>>>                     Kind: Timestamp (8)
>>>>>>                     Length: 10
>>>>>>                     Timestamp value: 1298580657
>>>>>>                     Timestamp echo reply: 4294947481
>>>>>>         Data (1448 bytes)
>>>>>>
>>>>>> 0000  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0010  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0020  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0030  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0040  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0050  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0060  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0070  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0080  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0090  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 00a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 00b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 00c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 00d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 00e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 00f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0100  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0110  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0120  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0130  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0140  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0150  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0160  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0170  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0180  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0190  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 01a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 01b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 01c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 01d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>>>> 01f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0200  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0210  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0220  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0230  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0240  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0250  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0260  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0270  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0280  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0290  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 02a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 02b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 02c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 02d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 02e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 02f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0300  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0310  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0320  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0330  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0340  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0350  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0360  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0370  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0380  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0390  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 03a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 03b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 03c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 03d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 03e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 03f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0400  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0410  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0420  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0430  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0440  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0450  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0460  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0470  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0480  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0490  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 04a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 04b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 04c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 04d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 04e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 04f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0500  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0510  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0520  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0530  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0540  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 0550  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>> 0560  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>> 0570  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>> 0580  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>> 0590  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>> 05a0  32 33 34 35 36 37 38 39                           23456789
>>>>>>             Data: 323334353637383930313233343536373839303132333435...
>>>>>>             [Length: 1448]
>>>>>>
>>>>>> On Mon, Jul 7, 2014 at 12:26 PM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>> The initial results are not promising: a MacOS 802.11ac client gets
>>>>>>> between 0-2 Mbps with this change, where it was getting about 8 Mbps
>>>>>>> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
>>>>>>> from the receiving system shows a very large number of out of order
>>>>>>> frames, likely due to TCP retransmission.
>>>>>>>
>>>>>>> An 802.11n MacBook gets very good throughput, only the 802.11ac
>>>>>>> MacBook shows the very poor result. I'm trying to figure out why.
>>>>>>>
>>>>>>>
>>>>>>> One specific note (and probably not related to the throughput): I
>>>>>>> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
>>>>>>> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
>>>>>>> correctly?
>>>>>>>
>>>>>>>
>>>>>>> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
>>>>>>> <janusz.dziedzic at tieto.com> wrote:
>>>>>>>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>>>>>>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>>>>>>>
>>>>>>>>> The earlier atheros chips would just give you the AMSDU frames as
>>>>>>>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>>>>>>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>>>>>>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>>>>>>>> those sub-frames.
>>>>>>>>>
>>>>>>>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>>>>>>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>>>>>>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>>>>>>>> half of one MPDU before you hit EOL, the next notification you process
>>>>>>>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>>>>>>>> reordering hilarity again.
>>>>>>>>>
>>>>>>>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>>>>>>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>>>>>>>> representing the current MPDU and treat the whole lot as the frame(s)
>>>>>>>>> to care about. Honestly though, I'm kind of wondering whether I should
>>>>>>>>> mostly just do what the Atheros reference driver does and treat it as
>>>>>>>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>>>>>>>> reordering is already done) and just tack on the wifi header bit via
>>>>>>>>> another of the DMA rings.
>>>>>>>>>
>>>>>>>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -a
>>>>>>>>>
>>>>>>>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>>>>>>>> in ieee80211_sta_manage_reorder_buf:
>>>>>>>>>>
>>>>>>>>>> 1. The out-of-date check:
>>>>>>>>>>
>>>>>>>>>>         /* frame with out of date sequence number */
>>>>>>>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>>>>                 goto out;
>>>>>>>>>>         }
>>>>>>>>>>
>>>>>>>>>> As all of the subframes carry the same sequence number, the first
>>>>>>>>>> subframe will be delivered and increment head_seq_num and then all
>>>>>>>>>> subsequent subframes will be discarded.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> 2. The duplicates check a bit later in the routine:
>>>>>>>>>>
>>>>>>>>>>         /* check if we already stored this frame */
>>>>>>>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>>>>                 goto out;
>>>>>>>>>>         }
>>>>>>>>>>
>>>>>>>>>> If there is enough packet loss that packets are queued in the reorder
>>>>>>>>>> buffer and not immediately released, then only the first subframe will
>>>>>>>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>>>>>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>>>>>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>>>>>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>>>>>>>
>>>>>>>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>>>>>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>>>>>>>> see that it does happen, but it doesn't impact the throughput and I
>>>>>>>>>> can't report the impact of fixing it.
>>>>>>>>>>
>>>>>>>>>> ----
>>>>>>>>>>
>>>>>>>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>>>>>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>>>>>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>>>>>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>>>>>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>>>>>>>> match the mac80211 expectations.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>>> Yes, after some more testing it does look like an unfortunate
>>>>>>>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>>>>>>>> subframes all carry the same sequence number. The first subframe is
>>>>>>>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>>>>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>>>>>>>
>>>>>>>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>>>>>>>> head=0xb06
>>>>>>>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>>>>>>>> head=0xb0b
>>>>>>>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>>>>>>>> head=0xb10
>>>>>>>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>>>>>>>> head=0xb15
>>>>>>>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>>>>>>>> head=0xb1a
>>>>>>>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>>>>>>>> head=0xb1f
>>>>>>>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>>>>>>>> head=0xb24
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>>>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>>>>>>>
>>>>>>>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>>>>>>>> frame makes it through.
>>>>>>>>>>>>>
>>>>>>>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>>>>>>>
>>>>>>>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>>>>>>>> A-MSDU.
>>>>>>>>>>>>
>>>>>>>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>>>>>>>
>>>>>>>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>>>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>>>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>>>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>>>>>>>
>>>>>>>> Denton could you try attached patch: report amsdu in one big frame.
>>>>>>>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>>>>>>>> improve performance and reduce memcpy, while currently we have skb
>>>>>>>> frames, put them in one big skb and next cfg80211 split them again
>>>>>>>> into msdus and report to stack.
>>>>>>>>
>>>>>>>> BR
>>>>>>>> Janusz
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ap.pcap
Type: application/octet-stream
Size: 35655 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/ath10k/attachments/20140710/2fbaf11d/attachment-0004.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: macbook.pcap
Type: application/octet-stream
Size: 39182 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/ath10k/attachments/20140710/2fbaf11d/attachment-0005.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: server.pcap
Type: application/octet-stream
Size: 24744 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/ath10k/attachments/20140710/2fbaf11d/attachment-0006.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: wifisniffer.pcap
Type: application/octet-stream
Size: 47148 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/ath10k/attachments/20140710/2fbaf11d/attachment-0007.obj>

From janusz.dziedzic at tieto.com  Thu Jul 10 11:48:15 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Thu, 10 Jul 2014 20:48:15 +0200
Subject: A-MSDU reception not working?
In-Reply-To: <CABnBrYXsLi3XNbBGtgW7rFhOXW7oOvh29+GapFsX+Rzx36V_QA@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
 <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>
 <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>
 <CALhHN=pvh8qocDzoMvK--__hJD1PVe5CrPBVriC1w=Bx1cpxpg@mail.gmail.com>
 <CABnBrYVY_KY8mMAKhy-DV1s3+vut8oR_LohyBJX3GtW7RT=3XA@mail.gmail.com>
 <CALhHN=ozVHCzFPnz318SNE+YxgArdqKu4pTrc-Q1V88ujCz2ow@mail.gmail.com>
 <CABnBrYXsLi3XNbBGtgW7rFhOXW7oOvh29+GapFsX+Rzx36V_QA@mail.gmail.com>
Message-ID: <CALhHN=qZqZVAV3_ybRL5rhip407Vg9nm53mK=h_JNwV1t0HDog@mail.gmail.com>

On 10 July 2014 15:40, Denton Gentry <denton.gentry at gmail.com> wrote:
> I added this check for RX_ATTENTION_FLAGS_FCS_ERR in
> ath10k_htt_rx_handler, along with a printk to verify that the code was
> being run.
>
>                         if (attention & RX_ATTENTION_FLAGS_FCS_ERR) {
>                                 ath10k_htt_rx_free_msdu_chain(msdu_head);
>                                 printk(KERN_WARNING
> "ath10k_htt_rx_handler: amsdu RX_ATTENTION_FLAGS_FCS_ERR");
>                                 continue;
>                         } else
>                                 rx_status->flag &= ~RX_FLAG_FAILED_FCS_CRC;
>
> I see the printk appear in dmesg, so I know some packets are hitting
> it. The throughput from the MacOS 802.11ac STA does improve, from 5-20
> Mbps without to 50-60 Mbps with this change. Prior to adding the
> reorder buffer fix, the MacBook was getting 170 Mbps.
>
> However, packets with incorrect TCP checksums are still being
> delivered to the Ethernet connected server at the other end. I
> gathered pcaps at the MacBook, at the ath10k AP, on another ath10k
> device configured in monitor mode as a sniffer, and at the
> Ethernet-connected Ubuntu server at the other end.
>
Thanks for logs.

This is strange, this suggest MPDU have correct FCS, and only data in
MSDU are incorrect.
Seems like a FW/HW bug, while FCS was correct and other sniffer see
correct frame.
Seems also like not driver issue while this incorrect data are at
offset ~0x14C. In driver we touch mostly head and  tail of the data.
FW report IP/TCP checksum - interesting what status you get for such packet.
This is line:
skb->ip_summed = ath10k_htt_rx_get_csum_state(skb);

I see also this is QAM256 (5/6) - but FCS was correct so this suggest
MPDU frame was received correctly.
Interesting issue, I am curious who and when insert this wrong data.
Will check this more tomorrow.

BTW - this patch below is wrong, when we will start reorder we will
deliver only one MSDU - last one from AMSDU - instead of all, and all
with MORE flag will go directly to stack not waiting for reorder
decision. So could introduce other problems.

+       /* not impelemented correctly when driver report separete A-MSDUs */
+        if (status->flag & RX_FLAG_AMSDU_MORE)
+               goto dont_reorder;
+

So we have 3 options in case of using mac80211 reordering:
1) use big frame (memcpy overhead)
2) report amsd as a skb list (not sure mac80211 patches will be merged
- under discussion)
3) rewrite mac80211 reordering code to support AMSDU_MORE correctly

Other option can be, put reordering code in the driver (table for each
mpdu for peer and for each tid - resources required - while we have
almost the same allocated in mac80211 already)

BR
Janusz

>
> server.pcap
> Captured from the Ubuntu iperf server, connected to the AP via Ethernet.
>
> Packet #10: TCP seq 4369, IP ID 0x6373, TCP checksum incorrect
> At offset 208 bytes into the data we see ?32 33 34 35? replaced by ?98 19 1e b7?
>
> Packet #17: TCP seq 4369, IP ID 0x6373, TCP checksum correct
> Packet #23: TCP seq 4369, IP ID 0xe152, TCP checksum correct
>
>
> ap.pcap
> Captured from the AP.
>
> Packet #10: TCP seq 4369, IP ID 0x6373, TCP checksum incorrect
> At offset 208 bytes into the data we see ?32 33 34 35? replaced by ?98 19 1e b7?
> This is the same pattern we see in the Ubuntu server's trace.
>
> Packet #14: TCP seq 4369, IP ID 0x6373, TCP checksum correct
> This was a Wifi-layer retransmit, which I think means the firmware
> knew that something was wrong with packet #10. In the wifisniffer
> trace, packet #19 is a Block ACK from the AP which requests one packet
> be retransmitted.
> However it appears that RX_ATTENTION_FLAGS_FCS_ERR was not set on
> packet #10, so it was forwarded to the Ethernet.
>
> Packet #24: TCP seq 4369, IP ID 0xe152, TCP checksum correct
> This is a TCP-layer retransmit from the MacBook, as the IP ID is different.
>
>
> wifisniffer.pcap
> A second ath10 configured in monitor mode.
> Packet #17 AMSDU#1: TCP seq 4369, IP ID 0x6373, TCP checksum correct
> This is packet #10 in the AP trace. Note that the sniffer did not see
> ?98 19 1e b7? like the AP did.
>
> Packet #20 AMSDU#1: TCP seq 4369, IP ID 0x6373, TCP checksum correct
> This is packet #14 in the AP trace.
>
> Packet #39 AMSDU#2: TCP seq 4369, IP ID 0xe152, TCP checksum correct
> This is packet #24 in the AP trace.
>
>
> macbook.pcapng
> 56: TCP seq 4369, IP ID 0x6373, TCP checksum correct
> This is the original transmission. Wireshark on MacOS cannot put the
> interface into monitor mode, so we do not see the Wifi-layer
> retransmission of this packet.
>
> 65: TCP seq 4369, IP ID 0xe152, TCP checksum correct
> This is a TCP retransmission, triggered because it received duplicate
> TCP ACKs back from the Ubuntu server.
>
>
> On Wed, Jul 9, 2014 at 12:39 AM, Janusz Dziedzic
> <janusz.dziedzic at tieto.com> wrote:
>> On 9 July 2014 08:09, Denton Gentry <denton.gentry at gmail.com> wrote:
>>> I ran iperf on an 802.11ac MacBook Air, through my ath10 AP, and to an
>>> Ubuntu system connected to the AP via Ethernet. The AP was running the
>>> reorder buffer patches, the patch to make A-MSDU bypass the reorder
>>> buffer, and the patch to make amsdu aggregation configurable via
>>> debugfs.
>>>
>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002551.html
>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002553.html
>>> http://lists.infradead.org/pipermail/ath10k/2014-July/002597.html
>>> http://permalink.gmane.org/gmane.linux.kernel.wireless.general/124128
>>>
>>> It was notably not running the patch from earlier in this thread to
>>> copy A-MSDU subframes into one skb.
>>>
>>>
>>> I used a second ath10k AP configured in monitor mode as a Wifi
>>> sniffer. I also gathered pcaps on the MacBook Air and on the Ubuntu
>>> system. Wireshark on the MacBook cannot gather radiotap headers nor
>>> put the interface into monitor mode, so we see only Ethernet frames
>>> and we don't see retransmissions on the Wifi link.
>>>
>>> I've attached decodes of the same two packets as captured by the
>>> MacBook, by the sniffer, and by the Ubuntu server.
>>>
>>> The MacBook sends two frames, TCP sequence numbers 3065441 and 3066889
>>> (the Wireshark "relative sequence number"). In the Wifi sniffer we see
>>> these being aggregated as two subframes in an A-MSDU frame. The first
>>> time this A-MSDU is sent it is corrupted in the air. We see the TCP
>>> checksum of one of the subframes is wrong, and a few bytes of the
>>> payload replaced with "&gt%'g9(1$".
>>>
>>> The A-MSDU is retransmitted a short time later, and the second time
>>> the TCP checksum of both subframes is correct.
>>>
>>> This is all fine so far.
>>>
>>> However in the pcap taken from the Ubuntu server, we see TCP sequence
>>> number 3065441 being delivered *twice.* The first time, the TCP
>>> checksum is wrong. The second time the TCP checksum is correct.
>>>
>>> To me, it looks like A-MSDU frames with bad FCS are not being
>>> discarded after ieee80211_rx_monitor(). The corrupted frames are being
>>> delivered. Delivering the corrupted frames results in sending more TCP
>>> Dup ACKs for the same sequence number back to the MacBook, and I think
>>> this is what causes the MacBook to decide there is congestion and slow
>>> down.
>>>
>> OK, to be sure this is the main issue we can just drop frames with wrong FCS.
>> Could you check this:
>>
>> @@ -1267,10 +1267,10 @@ static void ath10k_htt_rx_handler(struct
>> ath10k_htt *htt,
>>                                 continue;
>>                         }
>>
>> -                       if (attention & RX_ATTENTION_FLAGS_FCS_ERR)
>> -                               rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
>> -                       else
>> -                               rx_status->flag &= ~RX_FLAG_FAILED_FCS_CRC;
>> +                       if (attention & RX_ATTENTION_FLAGS_FCS_ERR) {
>> +                               ath10k_htt_rx_free_msdu_chain(msdu_head);
>> +                               continue;
>> +                       }
>>
>>                         if (attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR)
>>
>> If will help we will have to check how to handle monitor + ap case
>> correctly, one of idea is to not drop frames with wrong FCS only in
>> case of standalone monitor mode.
>> But, please try this patch to be sure.
>>
>> BR
>> Janusz
>>
>>
>>> One note: the wifi sniffer does not show the same corruption to the
>>> same packet as the pcap from the Ubuntu system shows. I think that is
>>> normal: the sniffer won't see precisely the same noise, won't have
>>> precisely the same receive sensitivity, and its antennas are not
>>> pointing in the same direction as the primary AP. If I do this test
>>> again, I'll gather a pcap on the primary AP as well to compare to what
>>> we see on the Ubuntu system.
>>>
>>>
>>> On Tue, Jul 8, 2014 at 12:29 AM, Janusz Dziedzic
>>> <janusz.dziedzic at tieto.com> wrote:
>>>> On 8 July 2014 09:02, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>>>>> On 8 July 2014 08:50, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>>>>>> On 8 July 2014 08:43, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>> I think I know what is happening now, though I've no idea why. The
>>>>>>> throughput is low because we have many TCP retransmissions. We have
>>>>>>> retransmissions because the TCP checksum is wrong on a number of
>>>>>>> frames, and I do find data corruption in the payload so the checksum
>>>>>>> definitely should be wrong. All of the corrupted frames were
>>>>>>> originally one of the subframes in an A-MSDU packet.
>>>>>>>
>>>>>>> An example follows at the end of this message, as dissected by
>>>>>>> Wireshark. iperf sends a very regular data pattern of "0123456789..."
>>>>>>> over and over. Note how in subframe #2 offset 0x1e0 the bytes "32 33
>>>>>>> 34" have been replaced by "72 36 35"
>>>>>>>
>>>>>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>>>>>
>>>>>>> I added printks at the bottom of ath10k_htt_rx_amsdu immediately
>>>>>>> before the call to ath10k_process_rx. I found this same packet, and we
>>>>>>> see the "72 36 35" corruption in the printk. So I think it happened in
>>>>>>> ath10k_process_rx or before, not anything weird after passing it up to
>>>>>>> mac80211.
>>>>>>>
>>>>>>> [  101.863712] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>>>>>> [  101.863727] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>>>>> [  101.863742] ath10k: 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32
>>>>>>> [  101.863757] ath10k: 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37 38
>>>>>>> [  101.863773] ath10k: 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34
>>>>>>> [  101.863788] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>>>>>> [  101.863803] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>>>>>
>>>>>>>
>>>>>>> I've found a number of examples of similar corruption, always with
>>>>>>> between one and four bytes replaced.
>>>>>>>
>>>>>>> 35363738 -> e52c6e07
>>>>>>> 3435 -> b43f
>>>>>>> 3839 -> c238
>>>>>>> 31 -> 7f
>>>>>>> 3435 -> 7436
>>>>>>> 30 -> 50
>>>>>>> 3233 -> bc37
>>>>>>>
>>>>>> Seems this could be because of:
>>>>>>
>>>>>> + /* cfg80211 expect this padding */
>>>>>> + padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
>>>>>> + skb_put(skb, padding);
>>>>>>
>>>>>
>>>>> BTW, when AP (ath10k) send TCP ACK - are this packets also AMSDU?
>>>>> I see in my case AP can send 3 x A-MSDU (with total size 304 bytes)
>>>>> small frames aggregated. Maybe your HW have problems with that.
>>>>> As I remember correctly someone some time ago report problems with
>>>>> MacBook pro retina but I am not sure this is the same, while no one
>>>>> tests the fix.
>>>>>
>>>>>>>
>>>>>>> The packet described above, dissected by Wireshark:
>>>>>>>
>>>>>>> No.     Time        Source                Destination
>>>>>>> Protocol Length Info
>>>>>>>    2235 18.953349   192.168.144.79        192.168.144.13        TCP
>>>>>>>   3112   52697 > 5001 [ACK] Seq=1391553 Ack=1 Win=131760 [TCP CHECKSUM
>>>>>>> INCORRECT] Len=1448 TSval=1298580657 TSecr=4294947481
>>>>>>>
>>>>>>> Frame 2235: 3112 bytes on wire (24896 bits), 3112 bytes captured (24896 bits)
>>>>>>>     Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
>>>>>>>     Arrival Time: Jul  7, 2014 23:03:37.763365000 PDT
>>>>>>>     [Time shift for this packet: 0.000000000 seconds]
>>>>>>>     Epoch Time: 1404799417.763365000 seconds
>>>>>>>     [Time delta from previous captured frame: 0.003476000 seconds]
>>>>>>>     [Time delta from previous displayed frame: 0.515641000 seconds]
>>>>>>>     [Time since reference or first frame: 18.953349000 seconds]
>>>>>>>     Frame Number: 2235
>>>>>>>     Frame Length: 3112 bytes (24896 bits)
>>>>>>>     Capture Length: 3112 bytes (24896 bits)
>>>>>>>     [Frame is marked: False]
>>>>>>>     [Frame is ignored: False]
>>>>>>>     [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
>>>>>>>     [Coloring Rule Name: TCP]
>>>>>>>     [Coloring Rule String: tcp]
>>>>>>> Radiotap Header v0, Length 38
>>>>>>>     Header revision: 0
>>>>>>>     Header pad: 0
>>>>>>>     Header length: 38
>>>>>>>     Present flags
>>>>>>>         .... .... .... .... .... .... .... ...1 = TSFT: True
>>>>>>>         .... .... .... .... .... .... .... ..1. = Flags: True
>>>>>>>         .... .... .... .... .... .... .... .0.. = Rate: False
>>>>>>>         .... .... .... .... .... .... .... 1... = Channel: True
>>>>>>>         .... .... .... .... .... .... ...0 .... = FHSS: False
>>>>>>>         .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
>>>>>>>         .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
>>>>>>>         .... .... .... .... .... .... 0... .... = Lock Quality: False
>>>>>>>         .... .... .... .... .... ...0 .... .... = TX Attenuation: False
>>>>>>>         .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
>>>>>>>         .... .... .... .... .... .0.. .... .... = dBm TX Power: False
>>>>>>>         .... .... .... .... .... 1... .... .... = Antenna: True
>>>>>>>         .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
>>>>>>>         .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
>>>>>>>         .... .... .... .... .1.. .... .... .... = RX flags: True
>>>>>>>         .... .... .... .0.. .... .... .... .... = Channel+: False
>>>>>>>         .... .... .... 0... .... .... .... .... = HT information: False
>>>>>>>         .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
>>>>>>>         .... .... ..1. .... .... .... .... .... = VHT information: True
>>>>>>>         ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
>>>>>>>         ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
>>>>>>>         .0.. .... .... .... .... .... .... .... = Vendor NS next: False
>>>>>>>         0... .... .... .... .... .... .... .... = Ext: False
>>>>>>>     MAC timestamp: 78051063
>>>>>>>     Flags: 0x00
>>>>>>>         .... ...0 = CFP: False
>>>>>>>         .... ..0. = Preamble: Long
>>>>>>>         .... .0.. = WEP: False
>>>>>>>         .... 0... = Fragmentation: False
>>>>>>>         ...0 .... = FCS at end: False
>>>>>>>         ..0. .... = Data Pad: False
>>>>>>>         .0.. .... = Bad FCS: False
>>>>>>>         0... .... = Short GI: False
>>>>>>>     Channel frequency: 5745 [A 149]
>>>>>>>     Channel type: 802.11a (0x0140)
>>>>>>>         .... .... ...0 .... = Turbo: False
>>>>>>>         .... .... ..0. .... = Complementary Code Keying (CCK): False
>>>>>>>         .... .... .1.. .... = Orthogonal Frequency-Division
>>>>>>> Multiplexing (OFDM): True
>>>>>>>         .... .... 0... .... = 2 GHz spectrum: False
>>>>>>>         .... ...1 .... .... = 5 GHz spectrum: True
>>>>>>>         .... ..0. .... .... = Passive: False
>>>>>>>         .... .0.. .... .... = Dynamic CCK-OFDM: False
>>>>>>>         .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
>>>>>>>         ...0 .... .... .... = GSM (900MHz): False
>>>>>>>         ..0. .... .... .... = Static Turbo: False
>>>>>>>         .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
>>>>>>>         0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
>>>>>>>     SSI Signal: -53 dBm
>>>>>>>     Antenna: 0
>>>>>>>     RX flags: 0x0000
>>>>>>>         .... .... .... .... .... ..0. = Bad PLCP: False
>>>>>>>     VHT information
>>>>>>>         Known VHT information: 0x44
>>>>>>>             .... .... .... ...0 = STBC: False
>>>>>>>             .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
>>>>>>>             .... .... .... .1.. = Guard interval: True
>>>>>>>             .... .... .... 0... = SGI Nsym disambiguation: False
>>>>>>>             .... .... ...0 .... = LDPC extra OFDM symbol: False
>>>>>>>             .... .... ..0. .... = Beamformed: False
>>>>>>>             .... .... .1.. .... = Bandwidth: True
>>>>>>>             .... .... 0... .... = Group ID: False
>>>>>>>             .... ...0 .... .... = Partial AID: False
>>>>>>>         .... .0.. = Guard interval: long (0)
>>>>>>>         Bandwidth: 80 MHz (4)
>>>>>>>         User 0: MCS 8
>>>>>>>             1000 .... = MCS index 0: 8 (256-QAM 3/4)
>>>>>>>             .... 0010 = Spatial streams 0: 2
>>>>>>>             Space-time streams 0: 2
>>>>>>>             Coding 0: BCC (0)
>>>>>>>             [Data Rate: 702.0 Mb/s]
>>>>>>> IEEE 802.11 QoS Data, Flags: .......T
>>>>>>>     Type/Subtype: QoS Data (0x28)
>>>>>>>     Frame Control Field: 0x8801
>>>>>>>         .... ..00 = Version: 0
>>>>>>>         .... 10.. = Type: Data frame (2)
>>>>>>>         1000 .... = Subtype: 8
>>>>>>>         Flags: 0x01
>>>>>>>             .... ..01 = DS status: Frame from STA to DS via an AP (To
>>>>>>> DS: 1 From DS: 0) (0x01)
>>>>>>>             .... .0.. = More Fragments: This is the last fragment
>>>>>>>             .... 0... = Retry: Frame is not being retransmitted
>>>>>>>             ...0 .... = PWR MGT: STA will stay up
>>>>>>>             ..0. .... = More Data: No data buffered
>>>>>>>             .0.. .... = Protected flag: Data is not protected
>>>>>>>             0... .... = Order flag: Not strictly ordered
>>>>>>>     .000 0000 0011 0000 = Duration: 48 microseconds
>>>>>>>     Receiver address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>>>     BSS Id: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>>>     Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>>     Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>>     Destination address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>>>     Fragment number: 0
>>>>>>>     Sequence number: 1021
>>>>>>>     Qos Control: 0x0080
>>>>>>>         .... .... .... 0000 = TID: 0
>>>>>>>         [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
>>>>>>>         .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control
>>>>>>> field are TXOP Duration Requested
>>>>>>>         .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
>>>>>>>         .... .... 1... .... = Payload Type: A-MSDU
>>>>>>>         0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
>>>>>>> IEEE 802.11 Aggregate MSDU
>>>>>>>     A-MSDU Subframe #1
>>>>>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>>>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>>         A-MSDU Length: 1510
>>>>>>>         Logical-Link Control
>>>>>>>             DSAP: SNAP (0xaa)
>>>>>>>             IG Bit: Individual
>>>>>>>             SSAP: SNAP (0xaa)
>>>>>>>             CR Bit: Command
>>>>>>>             Control field: U, func=UI (0x03)
>>>>>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>>>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>>>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>>>>>             Type: IP (0x0800)
>>>>>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>>>>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>>>>>             Version: 4
>>>>>>>             Header length: 20 bytes
>>>>>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>>>>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>>>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>>>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>>>>>> (Not ECN-Capable Transport) (0x00)
>>>>>>>             Total Length: 1500
>>>>>>>             Identification: 0xc622 (50722)
>>>>>>>             Flags: 0x00
>>>>>>>                 0... .... = Reserved bit: Not set
>>>>>>>                 .0.. .... = Don't fragment: Not set
>>>>>>>                 ..0. .... = More fragments: Not set
>>>>>>>             Fragment offset: 0
>>>>>>>             Time to live: 64
>>>>>>>             Protocol: TCP (6)
>>>>>>>             Header checksum: 0x0d4c [correct]
>>>>>>>                 [Good: True]
>>>>>>>                 [Bad: False]
>>>>>>>             Source: 192.168.144.79 (192.168.144.79)
>>>>>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>>>>>             [Source GeoIP: Unknown]
>>>>>>>             [Destination GeoIP: Unknown]
>>>>>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>>>>>> Port: 5001 (5001), Seq: 1390105, Ack: 1, Len: 1448
>>>>>>>             Source port: 52697 (52697)
>>>>>>>             Destination port: 5001 (5001)
>>>>>>>             [Stream index: 0]
>>>>>>>             Sequence number: 1390105    (relative sequence number)
>>>>>>>             [Next sequence number: 1391553    (relative sequence number)]
>>>>>>>             Acknowledgment number: 1    (relative ack number)
>>>>>>>             Header length: 32 bytes
>>>>>>>             Flags: 0x010 (ACK)
>>>>>>>                 000. .... .... = Reserved: Not set
>>>>>>>                 ...0 .... .... = Nonce: Not set
>>>>>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>>>>>                 .... .0.. .... = ECN-Echo: Not set
>>>>>>>                 .... ..0. .... = Urgent: Not set
>>>>>>>                 .... ...1 .... = Acknowledgment: Set
>>>>>>>                 .... .... 0... = Push: Not set
>>>>>>>                 .... .... .0.. = Reset: Not set
>>>>>>>                 .... .... ..0. = Syn: Not set
>>>>>>>                 .... .... ...0 = Fin: Not set
>>>>>>>             Window size value: 8235
>>>>>>>             [Calculated window size: 131760]
>>>>>>>             [Window size scaling factor: 16]
>>>>>>>             Checksum: 0xa1c0 [correct]
>>>>>>>                 [Good Checksum: True]
>>>>>>>                 [Bad Checksum: False]
>>>>>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>>>>>> (NOP), Timestamps
>>>>>>>                 No-Operation (NOP)
>>>>>>>                     Type: 1
>>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>>                         .00. .... = Class: Control (0)
>>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>>                 No-Operation (NOP)
>>>>>>>                     Type: 1
>>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>>                         .00. .... = Class: Control (0)
>>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>>>>>                     Kind: Timestamp (8)
>>>>>>>                     Length: 10
>>>>>>>                     Timestamp value: 1298580657
>>>>>>>                     Timestamp echo reply: 4294947481
>>>>>>>         Data (1448 bytes)
>>>>>>>
>>>>>>> 0000  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0010  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0020  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0030  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0040  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0050  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0060  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0070  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0080  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0090  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 00a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 00b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 00c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 00d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 00e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 00f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0100  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0110  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0120  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0130  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0140  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0150  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0160  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0170  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0180  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0190  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 01a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 01b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 01c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 01d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 01e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 01f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0200  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0210  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0220  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0230  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0240  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0250  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0260  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0270  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0280  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0290  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 02a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 02b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 02c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 02d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 02e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 02f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0300  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0310  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0320  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0330  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0340  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0350  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0360  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0370  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0380  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0390  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 03a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 03b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 03c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 03d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 03e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 03f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0400  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0410  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0420  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0430  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0440  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0450  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0460  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0470  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0480  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0490  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 04a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 04b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 04c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 04d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 04e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 04f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0500  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0510  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0520  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0530  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0540  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0550  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0560  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0570  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0580  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0590  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 05a0  34 35 36 37 38 39 30 31                           45678901
>>>>>>>             Data: 343536373839303132333435363738393031323334353637...
>>>>>>>             [Length: 1448]
>>>>>>>     A-MSDU Subframe #2
>>>>>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>>>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>>         A-MSDU Length: 1510
>>>>>>>         Logical-Link Control
>>>>>>>             DSAP: SNAP (0xaa)
>>>>>>>             IG Bit: Individual
>>>>>>>             SSAP: SNAP (0xaa)
>>>>>>>             CR Bit: Command
>>>>>>>             Control field: U, func=UI (0x03)
>>>>>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>>>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>>>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>>>>>             Type: IP (0x0800)
>>>>>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>>>>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>>>>>             Version: 4
>>>>>>>             Header length: 20 bytes
>>>>>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>>>>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>>>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>>>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>>>>>> (Not ECN-Capable Transport) (0x00)
>>>>>>>             Total Length: 1500
>>>>>>>             Identification: 0xda09 (55817)
>>>>>>>             Flags: 0x00
>>>>>>>                 0... .... = Reserved bit: Not set
>>>>>>>                 .0.. .... = Don't fragment: Not set
>>>>>>>                 ..0. .... = More fragments: Not set
>>>>>>>             Fragment offset: 0
>>>>>>>             Time to live: 64
>>>>>>>             Protocol: TCP (6)
>>>>>>>             Header checksum: 0xf964 [correct]
>>>>>>>                 [Good: True]
>>>>>>>                 [Bad: False]
>>>>>>>             Source: 192.168.144.79 (192.168.144.79)
>>>>>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>>>>>             [Source GeoIP: Unknown]
>>>>>>>             [Destination GeoIP: Unknown]
>>>>>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>>>>>> Port: 5001 (5001), Seq: 1391553, Ack: 1, Len: 1448
>>>>>>>             Source port: 52697 (52697)
>>>>>>>             Destination port: 5001 (5001)
>>>>>>>             [Stream index: 0]
>>>>>>>             Sequence number: 1391553    (relative sequence number)
>>>>>>>             [Next sequence number: 1393001    (relative sequence number)]
>>>>>>>             Acknowledgment number: 1    (relative ack number)
>>>>>>>             Header length: 32 bytes
>>>>>>>             Flags: 0x010 (ACK)
>>>>>>>                 000. .... .... = Reserved: Not set
>>>>>>>                 ...0 .... .... = Nonce: Not set
>>>>>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>>>>>                 .... .0.. .... = ECN-Echo: Not set
>>>>>>>                 .... ..0. .... = Urgent: Not set
>>>>>>>                 .... ...1 .... = Acknowledgment: Set
>>>>>>>                 .... .... 0... = Push: Not set
>>>>>>>                 .... .... .0.. = Reset: Not set
>>>>>>>                 .... .... ..0. = Syn: Not set
>>>>>>>                 .... .... ...0 = Fin: Not set
>>>>>>>             Window size value: 8235
>>>>>>>             [Calculated window size: 131760]
>>>>>>>             [Window size scaling factor: 16]
>>>>>>>             Checksum: 0x9a16 [incorrect, should be 0x5913 (maybe
>>>>>>> caused by "TCP checksum offload"?)]
>>>>
>>>> And yes we are using checksum offload in ath10k.
>>>> Best is using standalone 80211ac sniffer for that case to be sure
>>>> about checksum.
>>>>
>>>>>>>                 [Good Checksum: False]
>>>>>>>                 [Bad Checksum: True]
>>>>>>>                     [Expert Info (Error/Checksum): Bad checksum]
>>>>>>>                         [Message: Bad checksum]
>>>>>>>                         [Severity level: Error]
>>>>>>>                         [Group: Checksum]
>>>>>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>>>>>> (NOP), Timestamps
>>>>>>>                 No-Operation (NOP)
>>>>>>>                     Type: 1
>>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>>                         .00. .... = Class: Control (0)
>>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>>                 No-Operation (NOP)
>>>>>>>                     Type: 1
>>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>>                         .00. .... = Class: Control (0)
>>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>>>>>                     Kind: Timestamp (8)
>>>>>>>                     Length: 10
>>>>>>>                     Timestamp value: 1298580657
>>>>>>>                     Timestamp echo reply: 4294947481
>>>>>>>         Data (1448 bytes)
>>>>>>>
>>>>>>> 0000  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0010  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0020  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0030  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0040  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0050  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0060  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0070  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0080  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0090  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 00a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 00b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 00c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 00d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 00e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 00f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0100  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0110  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0120  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0130  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0140  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0150  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0160  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0170  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0180  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0190  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 01a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 01b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 01c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 01d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>>>>> 01f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0200  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0210  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0220  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0230  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0240  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0250  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0260  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0270  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0280  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0290  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 02a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 02b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 02c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 02d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 02e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 02f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0300  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0310  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0320  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0330  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0340  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0350  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0360  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0370  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0380  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0390  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 03a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 03b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 03c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 03d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 03e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 03f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0400  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0410  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0420  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0430  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0440  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0450  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0460  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0470  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0480  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0490  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 04a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 04b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 04c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 04d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 04e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 04f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0500  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0510  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0520  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0530  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0540  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 0550  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>> 0560  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>> 0570  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>> 0580  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>> 0590  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>> 05a0  32 33 34 35 36 37 38 39                           23456789
>>>>>>>             Data: 323334353637383930313233343536373839303132333435...
>>>>>>>             [Length: 1448]
>>>>>>>
>>>>>>> On Mon, Jul 7, 2014 at 12:26 PM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>> The initial results are not promising: a MacOS 802.11ac client gets
>>>>>>>> between 0-2 Mbps with this change, where it was getting about 8 Mbps
>>>>>>>> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
>>>>>>>> from the receiving system shows a very large number of out of order
>>>>>>>> frames, likely due to TCP retransmission.
>>>>>>>>
>>>>>>>> An 802.11n MacBook gets very good throughput, only the 802.11ac
>>>>>>>> MacBook shows the very poor result. I'm trying to figure out why.
>>>>>>>>
>>>>>>>>
>>>>>>>> One specific note (and probably not related to the throughput): I
>>>>>>>> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
>>>>>>>> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
>>>>>>>> correctly?
>>>>>>>>
>>>>>>>>
>>>>>>>> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
>>>>>>>> <janusz.dziedzic at tieto.com> wrote:
>>>>>>>>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>>>>>>>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>>>>>>>>
>>>>>>>>>> The earlier atheros chips would just give you the AMSDU frames as
>>>>>>>>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>>>>>>>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>>>>>>>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>>>>>>>>> those sub-frames.
>>>>>>>>>>
>>>>>>>>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>>>>>>>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>>>>>>>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>>>>>>>>> half of one MPDU before you hit EOL, the next notification you process
>>>>>>>>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>>>>>>>>> reordering hilarity again.
>>>>>>>>>>
>>>>>>>>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>>>>>>>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>>>>>>>>> representing the current MPDU and treat the whole lot as the frame(s)
>>>>>>>>>> to care about. Honestly though, I'm kind of wondering whether I should
>>>>>>>>>> mostly just do what the Atheros reference driver does and treat it as
>>>>>>>>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>>>>>>>>> reordering is already done) and just tack on the wifi header bit via
>>>>>>>>>> another of the DMA rings.
>>>>>>>>>>
>>>>>>>>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -a
>>>>>>>>>>
>>>>>>>>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>>>>>>>>> in ieee80211_sta_manage_reorder_buf:
>>>>>>>>>>>
>>>>>>>>>>> 1. The out-of-date check:
>>>>>>>>>>>
>>>>>>>>>>>         /* frame with out of date sequence number */
>>>>>>>>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>>>>>                 goto out;
>>>>>>>>>>>         }
>>>>>>>>>>>
>>>>>>>>>>> As all of the subframes carry the same sequence number, the first
>>>>>>>>>>> subframe will be delivered and increment head_seq_num and then all
>>>>>>>>>>> subsequent subframes will be discarded.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> 2. The duplicates check a bit later in the routine:
>>>>>>>>>>>
>>>>>>>>>>>         /* check if we already stored this frame */
>>>>>>>>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>>>>>                 goto out;
>>>>>>>>>>>         }
>>>>>>>>>>>
>>>>>>>>>>> If there is enough packet loss that packets are queued in the reorder
>>>>>>>>>>> buffer and not immediately released, then only the first subframe will
>>>>>>>>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>>>>>>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>>>>>>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>>>>>>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>>>>>>>>
>>>>>>>>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>>>>>>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>>>>>>>>> see that it does happen, but it doesn't impact the throughput and I
>>>>>>>>>>> can't report the impact of fixing it.
>>>>>>>>>>>
>>>>>>>>>>> ----
>>>>>>>>>>>
>>>>>>>>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>>>>>>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>>>>>>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>>>>>>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>>>>>>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>>>>>>>>> match the mac80211 expectations.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>>>> Yes, after some more testing it does look like an unfortunate
>>>>>>>>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>>>>>>>>> subframes all carry the same sequence number. The first subframe is
>>>>>>>>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>>>>>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>>>>>>>>
>>>>>>>>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>>>>>>>>> head=0xb06
>>>>>>>>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>>>>>>>>> head=0xb0b
>>>>>>>>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>>>>>>>>> head=0xb10
>>>>>>>>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>>>>>>>>> head=0xb15
>>>>>>>>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>>>>>>>>> head=0xb1a
>>>>>>>>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>>>>>>>>> head=0xb1f
>>>>>>>>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>>>>>>>>> head=0xb24
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>>>>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>>>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>>>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>>>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>>>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>>>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>>>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>>>>>>>>> frame makes it through.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>>>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>>>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>>>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>>>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>>>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>>>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>>>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>>>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>>>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>>>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>>>>>>>>> A-MSDU.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>>>>>>>>
>>>>>>>>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>>>>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>>>>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>>>>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>>>>>>>>
>>>>>>>>> Denton could you try attached patch: report amsdu in one big frame.
>>>>>>>>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>>>>>>>>> improve performance and reduce memcpy, while currently we have skb
>>>>>>>>> frames, put them in one big skb and next cfg80211 split them again
>>>>>>>>> into msdus and report to stack.
>>>>>>>>>
>>>>>>>>> BR
>>>>>>>>> Janusz


From janusz.dziedzic at tieto.com  Fri Jul 11 02:20:44 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Fri, 11 Jul 2014 11:20:44 +0200
Subject: A-MSDU reception not working?
In-Reply-To: <CALhHN=qZqZVAV3_ybRL5rhip407Vg9nm53mK=h_JNwV1t0HDog@mail.gmail.com>
References: <CABnBrYU3P5qXd7pE7LJ_K4JeNFLtbZnpsTgvqtpdMs07qz_gGA@mail.gmail.com>
 <CA+BoTQk_YtrHrR6Wi3mMAZxT6EHFBxdUAafp48GqfUcM=HwfZg@mail.gmail.com>
 <CABnBrYXn0T=bW45zR5VivFRhP4BqFswYY93hrjB7rx+azKX9uA@mail.gmail.com>
 <CABnBrYUTKdvUiDha3meiiu08BCqNVBuCgXb7M_Gr4DwhyON3qw@mail.gmail.com>
 <CAJ-Vmo=JKpnoU2p4swTiXeTM0Q2LYWo7-VW_-vnOLb4ufVSO5A@mail.gmail.com>
 <CALhHN=r9_3i3R45Exs59d02XRTa-07WWvBwmGY9pEKufZb3Byw@mail.gmail.com>
 <CABnBrYVANG1cwC8ixD0hGY5guaB3XTP=PAxsf4OfVuZw+iLMaA@mail.gmail.com>
 <CABnBrYUz7Wp0aKkBX8JVFUjOdoZV6gss3x2yMRVwO9WhuH26+Q@mail.gmail.com>
 <CALhHN=rHKJS_FHG1yLhdR_JiUG6_T_q8u3RT1vgtzCdJVXbARQ@mail.gmail.com>
 <CALhHN=pUG+wvvgLe+8mxJ8obE-uBGAk8WEbh0HoGpUrzxi_MpQ@mail.gmail.com>
 <CALhHN=pvh8qocDzoMvK--__hJD1PVe5CrPBVriC1w=Bx1cpxpg@mail.gmail.com>
 <CABnBrYVY_KY8mMAKhy-DV1s3+vut8oR_LohyBJX3GtW7RT=3XA@mail.gmail.com>
 <CALhHN=ozVHCzFPnz318SNE+YxgArdqKu4pTrc-Q1V88ujCz2ow@mail.gmail.com>
 <CABnBrYXsLi3XNbBGtgW7rFhOXW7oOvh29+GapFsX+Rzx36V_QA@mail.gmail.com>
 <CALhHN=qZqZVAV3_ybRL5rhip407Vg9nm53mK=h_JNwV1t0HDog@mail.gmail.com>
Message-ID: <CALhHN=p-2HVGLM0m4O8ddZYO4D6LV8UYSVW5HM3Y9a9-HJoL4w@mail.gmail.com>

On 10 July 2014 20:48, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
> On 10 July 2014 15:40, Denton Gentry <denton.gentry at gmail.com> wrote:
>> I added this check for RX_ATTENTION_FLAGS_FCS_ERR in
>> ath10k_htt_rx_handler, along with a printk to verify that the code was
>> being run.
>>
>>                         if (attention & RX_ATTENTION_FLAGS_FCS_ERR) {
>>                                 ath10k_htt_rx_free_msdu_chain(msdu_head);
>>                                 printk(KERN_WARNING
>> "ath10k_htt_rx_handler: amsdu RX_ATTENTION_FLAGS_FCS_ERR");
>>                                 continue;
>>                         } else
>>                                 rx_status->flag &= ~RX_FLAG_FAILED_FCS_CRC;
>>
>> I see the printk appear in dmesg, so I know some packets are hitting
>> it. The throughput from the MacOS 802.11ac STA does improve, from 5-20
>> Mbps without to 50-60 Mbps with this change. Prior to adding the
>> reorder buffer fix, the MacBook was getting 170 Mbps.
>>
>> However, packets with incorrect TCP checksums are still being
>> delivered to the Ethernet connected server at the other end. I
>> gathered pcaps at the MacBook, at the ath10k AP, on another ath10k
>> device configured in monitor mode as a sniffer, and at the
>> Ethernet-connected Ubuntu server at the other end.
>>
> Thanks for logs.
>
> This is strange, this suggest MPDU have correct FCS, and only data in
> MSDU are incorrect.
> Seems like a FW/HW bug, while FCS was correct and other sniffer see
> correct frame.
> Seems also like not driver issue while this incorrect data are at
> offset ~0x14C. In driver we touch mostly head and  tail of the data.
> FW report IP/TCP checksum - interesting what status you get for such packet.
> This is line:
> skb->ip_summed = ath10k_htt_rx_get_csum_state(skb);
>
> I see also this is QAM256 (5/6) - but FCS was correct so this suggest
> MPDU frame was received correctly.
> Interesting issue, I am curious who and when insert this wrong data.
> Will check this more tomorrow.
>
> BTW - this patch below is wrong, when we will start reorder we will
> deliver only one MSDU - last one from AMSDU - instead of all, and all
> with MORE flag will go directly to stack not waiting for reorder
> decision. So could introduce other problems.
>
> +       /* not impelemented correctly when driver report separete A-MSDUs */
> +        if (status->flag & RX_FLAG_AMSDU_MORE)
> +               goto dont_reorder;
> +
>
> So we have 3 options in case of using mac80211 reordering:
> 1) use big frame (memcpy overhead)
> 2) report amsd as a skb list (not sure mac80211 patches will be merged
> - under discussion)
> 3) rewrite mac80211 reordering code to support AMSDU_MORE correctly
>
> Other option can be, put reordering code in the driver (table for each
> mpdu for peer and for each tid - resources required - while we have
> almost the same allocated in mac80211 already)
>
> BR
> Janusz
>
>>
>> server.pcap
>> Captured from the Ubuntu iperf server, connected to the AP via Ethernet.
>>
>> Packet #10: TCP seq 4369, IP ID 0x6373, TCP checksum incorrect
>> At offset 208 bytes into the data we see ?32 33 34 35? replaced by ?98 19 1e b7?
>>
>> Packet #17: TCP seq 4369, IP ID 0x6373, TCP checksum correct
>> Packet #23: TCP seq 4369, IP ID 0xe152, TCP checksum correct
>>
>>
>> ap.pcap
>> Captured from the AP.
>>
>> Packet #10: TCP seq 4369, IP ID 0x6373, TCP checksum incorrect
>> At offset 208 bytes into the data we see ?32 33 34 35? replaced by ?98 19 1e b7?
>> This is the same pattern we see in the Ubuntu server's trace.
>>
>> Packet #14: TCP seq 4369, IP ID 0x6373, TCP checksum correct
>> This was a Wifi-layer retransmit, which I think means the firmware
>> knew that something was wrong with packet #10. In the wifisniffer
>> trace, packet #19 is a Block ACK from the AP which requests one packet
>> be retransmitted.
>> However it appears that RX_ATTENTION_FLAGS_FCS_ERR was not set on
>> packet #10, so it was forwarded to the Ethernet.
>>
>> Packet #24: TCP seq 4369, IP ID 0xe152, TCP checksum correct
>> This is a TCP-layer retransmit from the MacBook, as the IP ID is different.
>>
>>
>> wifisniffer.pcap
>> A second ath10 configured in monitor mode.
>> Packet #17 AMSDU#1: TCP seq 4369, IP ID 0x6373, TCP checksum correct
>> This is packet #10 in the AP trace. Note that the sniffer did not see
>> ?98 19 1e b7? like the AP did.
>>
>> Packet #20 AMSDU#1: TCP seq 4369, IP ID 0x6373, TCP checksum correct
>> This is packet #14 in the AP trace.
>>
>> Packet #39 AMSDU#2: TCP seq 4369, IP ID 0xe152, TCP checksum correct
>> This is packet #24 in the AP trace.
>>
OK, this is what I see in wifi sniffer
seq_num = 68, packet #17 - AMSDU1, AMSDU2
blockACK - missing packet 68 - this suggest AP get this frame but
probably FCS was wrong?
seq_num = 68, retransmitted, packet #20, AMSDU1, AMSDU2
blockAck OK

Seems FW report missing packet, but didn't set INVALID_FCS??


Added some logs to my test env and activate monitor interface on AP.
This is what I see in logs:

[12990.863184] ath10k: xxx mpdu 3882 fcs err 0
[12990.863187] ath10k: xxx v4 1 v6 0 tcp 1 udp 0 ip_ck_ok 1 tcp_ck_ok 0
[12990.863189] ath10k: xxx mpdu 3882 msdu 0 ip_summed 0

[12990.863205] ath10k: xxx mpdu 3883 fcs err 0
[12990.863208] ath10k: xxx v4 1 v6 0 tcp 1 udp 0 ip_ck_ok 1 tcp_ck_ok 0
[12990.863210] ath10k: xxx mpdu 3883 msdu 0 ip_summed 0
[12990.863212] ath10k: xxx v4 1 v6 0 tcp 1 udp 0 ip_ck_ok 1 tcp_ck_ok 0
[12990.863215] ath10k: xxx mpdu 3883 msdu 1 ip_summed 0
[12990.863217] ath10k: xxx v4 1 v6 0 tcp 1 udp 0 ip_ck_ok 1 tcp_ck_ok 0
[12990.863219] ath10k: xxx mpdu 3883 msdu 2 ip_summed 0

Which mean we get MPDU with 3 MSDU subframes. FCS for SN 3883 was correct!
But IP/TCP checksum in msdus subframes not.

Seems FW report FCS incorrectly in some cases.
Will check this more today.

BTW as a workaround we can skip all packets with wrong FCS and wrong
TCP/IP checksum.
Patch attached.

BR
Janusz


>>
>> macbook.pcapng
>> 56: TCP seq 4369, IP ID 0x6373, TCP checksum correct
>> This is the original transmission. Wireshark on MacOS cannot put the
>> interface into monitor mode, so we do not see the Wifi-layer
>> retransmission of this packet.
>>
>> 65: TCP seq 4369, IP ID 0xe152, TCP checksum correct
>> This is a TCP retransmission, triggered because it received duplicate
>> TCP ACKs back from the Ubuntu server.
>>
>>
>> On Wed, Jul 9, 2014 at 12:39 AM, Janusz Dziedzic
>> <janusz.dziedzic at tieto.com> wrote:
>>> On 9 July 2014 08:09, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>> I ran iperf on an 802.11ac MacBook Air, through my ath10 AP, and to an
>>>> Ubuntu system connected to the AP via Ethernet. The AP was running the
>>>> reorder buffer patches, the patch to make A-MSDU bypass the reorder
>>>> buffer, and the patch to make amsdu aggregation configurable via
>>>> debugfs.
>>>>
>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002551.html
>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002553.html
>>>> http://lists.infradead.org/pipermail/ath10k/2014-July/002597.html
>>>> http://permalink.gmane.org/gmane.linux.kernel.wireless.general/124128
>>>>
>>>> It was notably not running the patch from earlier in this thread to
>>>> copy A-MSDU subframes into one skb.
>>>>
>>>>
>>>> I used a second ath10k AP configured in monitor mode as a Wifi
>>>> sniffer. I also gathered pcaps on the MacBook Air and on the Ubuntu
>>>> system. Wireshark on the MacBook cannot gather radiotap headers nor
>>>> put the interface into monitor mode, so we see only Ethernet frames
>>>> and we don't see retransmissions on the Wifi link.
>>>>
>>>> I've attached decodes of the same two packets as captured by the
>>>> MacBook, by the sniffer, and by the Ubuntu server.
>>>>
>>>> The MacBook sends two frames, TCP sequence numbers 3065441 and 3066889
>>>> (the Wireshark "relative sequence number"). In the Wifi sniffer we see
>>>> these being aggregated as two subframes in an A-MSDU frame. The first
>>>> time this A-MSDU is sent it is corrupted in the air. We see the TCP
>>>> checksum of one of the subframes is wrong, and a few bytes of the
>>>> payload replaced with "&gt%'g9(1$".
>>>>
>>>> The A-MSDU is retransmitted a short time later, and the second time
>>>> the TCP checksum of both subframes is correct.
>>>>
>>>> This is all fine so far.
>>>>
>>>> However in the pcap taken from the Ubuntu server, we see TCP sequence
>>>> number 3065441 being delivered *twice.* The first time, the TCP
>>>> checksum is wrong. The second time the TCP checksum is correct.
>>>>
>>>> To me, it looks like A-MSDU frames with bad FCS are not being
>>>> discarded after ieee80211_rx_monitor(). The corrupted frames are being
>>>> delivered. Delivering the corrupted frames results in sending more TCP
>>>> Dup ACKs for the same sequence number back to the MacBook, and I think
>>>> this is what causes the MacBook to decide there is congestion and slow
>>>> down.
>>>>
>>> OK, to be sure this is the main issue we can just drop frames with wrong FCS.
>>> Could you check this:
>>>
>>> @@ -1267,10 +1267,10 @@ static void ath10k_htt_rx_handler(struct
>>> ath10k_htt *htt,
>>>                                 continue;
>>>                         }
>>>
>>> -                       if (attention & RX_ATTENTION_FLAGS_FCS_ERR)
>>> -                               rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
>>> -                       else
>>> -                               rx_status->flag &= ~RX_FLAG_FAILED_FCS_CRC;
>>> +                       if (attention & RX_ATTENTION_FLAGS_FCS_ERR) {
>>> +                               ath10k_htt_rx_free_msdu_chain(msdu_head);
>>> +                               continue;
>>> +                       }
>>>
>>>                         if (attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR)
>>>
>>> If will help we will have to check how to handle monitor + ap case
>>> correctly, one of idea is to not drop frames with wrong FCS only in
>>> case of standalone monitor mode.
>>> But, please try this patch to be sure.
>>>
>>> BR
>>> Janusz
>>>
>>>
>>>> One note: the wifi sniffer does not show the same corruption to the
>>>> same packet as the pcap from the Ubuntu system shows. I think that is
>>>> normal: the sniffer won't see precisely the same noise, won't have
>>>> precisely the same receive sensitivity, and its antennas are not
>>>> pointing in the same direction as the primary AP. If I do this test
>>>> again, I'll gather a pcap on the primary AP as well to compare to what
>>>> we see on the Ubuntu system.
>>>>
>>>>
>>>> On Tue, Jul 8, 2014 at 12:29 AM, Janusz Dziedzic
>>>> <janusz.dziedzic at tieto.com> wrote:
>>>>> On 8 July 2014 09:02, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>>>>>> On 8 July 2014 08:50, Janusz Dziedzic <janusz.dziedzic at tieto.com> wrote:
>>>>>>> On 8 July 2014 08:43, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>> I think I know what is happening now, though I've no idea why. The
>>>>>>>> throughput is low because we have many TCP retransmissions. We have
>>>>>>>> retransmissions because the TCP checksum is wrong on a number of
>>>>>>>> frames, and I do find data corruption in the payload so the checksum
>>>>>>>> definitely should be wrong. All of the corrupted frames were
>>>>>>>> originally one of the subframes in an A-MSDU packet.
>>>>>>>>
>>>>>>>> An example follows at the end of this message, as dissected by
>>>>>>>> Wireshark. iperf sends a very regular data pattern of "0123456789..."
>>>>>>>> over and over. Note how in subframe #2 offset 0x1e0 the bytes "32 33
>>>>>>>> 34" have been replaced by "72 36 35"
>>>>>>>>
>>>>>>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>>>>>>
>>>>>>>> I added printks at the bottom of ath10k_htt_rx_amsdu immediately
>>>>>>>> before the call to ath10k_process_rx. I found this same packet, and we
>>>>>>>> see the "72 36 35" corruption in the printk. So I think it happened in
>>>>>>>> ath10k_process_rx or before, not anything weird after passing it up to
>>>>>>>> mac80211.
>>>>>>>>
>>>>>>>> [  101.863712] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>>>>>>> [  101.863727] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>>>>>> [  101.863742] ath10k: 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32
>>>>>>>> [  101.863757] ath10k: 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37 38
>>>>>>>> [  101.863773] ath10k: 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34
>>>>>>>> [  101.863788] ath10k: 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
>>>>>>>> [  101.863803] ath10k: 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36
>>>>>>>>
>>>>>>>>
>>>>>>>> I've found a number of examples of similar corruption, always with
>>>>>>>> between one and four bytes replaced.
>>>>>>>>
>>>>>>>> 35363738 -> e52c6e07
>>>>>>>> 3435 -> b43f
>>>>>>>> 3839 -> c238
>>>>>>>> 31 -> 7f
>>>>>>>> 3435 -> 7436
>>>>>>>> 30 -> 50
>>>>>>>> 3233 -> bc37
>>>>>>>>
>>>>>>> Seems this could be because of:
>>>>>>>
>>>>>>> + /* cfg80211 expect this padding */
>>>>>>> + padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
>>>>>>> + skb_put(skb, padding);
>>>>>>>
>>>>>>
>>>>>> BTW, when AP (ath10k) send TCP ACK - are this packets also AMSDU?
>>>>>> I see in my case AP can send 3 x A-MSDU (with total size 304 bytes)
>>>>>> small frames aggregated. Maybe your HW have problems with that.
>>>>>> As I remember correctly someone some time ago report problems with
>>>>>> MacBook pro retina but I am not sure this is the same, while no one
>>>>>> tests the fix.
>>>>>>
>>>>>>>>
>>>>>>>> The packet described above, dissected by Wireshark:
>>>>>>>>
>>>>>>>> No.     Time        Source                Destination
>>>>>>>> Protocol Length Info
>>>>>>>>    2235 18.953349   192.168.144.79        192.168.144.13        TCP
>>>>>>>>   3112   52697 > 5001 [ACK] Seq=1391553 Ack=1 Win=131760 [TCP CHECKSUM
>>>>>>>> INCORRECT] Len=1448 TSval=1298580657 TSecr=4294947481
>>>>>>>>
>>>>>>>> Frame 2235: 3112 bytes on wire (24896 bits), 3112 bytes captured (24896 bits)
>>>>>>>>     Encapsulation type: IEEE 802.11 plus radiotap radio header (23)
>>>>>>>>     Arrival Time: Jul  7, 2014 23:03:37.763365000 PDT
>>>>>>>>     [Time shift for this packet: 0.000000000 seconds]
>>>>>>>>     Epoch Time: 1404799417.763365000 seconds
>>>>>>>>     [Time delta from previous captured frame: 0.003476000 seconds]
>>>>>>>>     [Time delta from previous displayed frame: 0.515641000 seconds]
>>>>>>>>     [Time since reference or first frame: 18.953349000 seconds]
>>>>>>>>     Frame Number: 2235
>>>>>>>>     Frame Length: 3112 bytes (24896 bits)
>>>>>>>>     Capture Length: 3112 bytes (24896 bits)
>>>>>>>>     [Frame is marked: False]
>>>>>>>>     [Frame is ignored: False]
>>>>>>>>     [Protocols in frame: radiotap:wlan:llc:ip:tcp:data:llc:ip:tcp:data]
>>>>>>>>     [Coloring Rule Name: TCP]
>>>>>>>>     [Coloring Rule String: tcp]
>>>>>>>> Radiotap Header v0, Length 38
>>>>>>>>     Header revision: 0
>>>>>>>>     Header pad: 0
>>>>>>>>     Header length: 38
>>>>>>>>     Present flags
>>>>>>>>         .... .... .... .... .... .... .... ...1 = TSFT: True
>>>>>>>>         .... .... .... .... .... .... .... ..1. = Flags: True
>>>>>>>>         .... .... .... .... .... .... .... .0.. = Rate: False
>>>>>>>>         .... .... .... .... .... .... .... 1... = Channel: True
>>>>>>>>         .... .... .... .... .... .... ...0 .... = FHSS: False
>>>>>>>>         .... .... .... .... .... .... ..1. .... = dBm Antenna Signal: True
>>>>>>>>         .... .... .... .... .... .... .0.. .... = dBm Antenna Noise: False
>>>>>>>>         .... .... .... .... .... .... 0... .... = Lock Quality: False
>>>>>>>>         .... .... .... .... .... ...0 .... .... = TX Attenuation: False
>>>>>>>>         .... .... .... .... .... ..0. .... .... = dB TX Attenuation: False
>>>>>>>>         .... .... .... .... .... .0.. .... .... = dBm TX Power: False
>>>>>>>>         .... .... .... .... .... 1... .... .... = Antenna: True
>>>>>>>>         .... .... .... .... ...0 .... .... .... = dB Antenna Signal: False
>>>>>>>>         .... .... .... .... ..0. .... .... .... = dB Antenna Noise: False
>>>>>>>>         .... .... .... .... .1.. .... .... .... = RX flags: True
>>>>>>>>         .... .... .... .0.. .... .... .... .... = Channel+: False
>>>>>>>>         .... .... .... 0... .... .... .... .... = HT information: False
>>>>>>>>         .... .... ...0 .... .... .... .... .... = A-MPDU Status: False
>>>>>>>>         .... .... ..1. .... .... .... .... .... = VHT information: True
>>>>>>>>         ...0 0000 00.. .... .... .... .... .... = Reserved: 0x00000000
>>>>>>>>         ..0. .... .... .... .... .... .... .... = Radiotap NS next: False
>>>>>>>>         .0.. .... .... .... .... .... .... .... = Vendor NS next: False
>>>>>>>>         0... .... .... .... .... .... .... .... = Ext: False
>>>>>>>>     MAC timestamp: 78051063
>>>>>>>>     Flags: 0x00
>>>>>>>>         .... ...0 = CFP: False
>>>>>>>>         .... ..0. = Preamble: Long
>>>>>>>>         .... .0.. = WEP: False
>>>>>>>>         .... 0... = Fragmentation: False
>>>>>>>>         ...0 .... = FCS at end: False
>>>>>>>>         ..0. .... = Data Pad: False
>>>>>>>>         .0.. .... = Bad FCS: False
>>>>>>>>         0... .... = Short GI: False
>>>>>>>>     Channel frequency: 5745 [A 149]
>>>>>>>>     Channel type: 802.11a (0x0140)
>>>>>>>>         .... .... ...0 .... = Turbo: False
>>>>>>>>         .... .... ..0. .... = Complementary Code Keying (CCK): False
>>>>>>>>         .... .... .1.. .... = Orthogonal Frequency-Division
>>>>>>>> Multiplexing (OFDM): True
>>>>>>>>         .... .... 0... .... = 2 GHz spectrum: False
>>>>>>>>         .... ...1 .... .... = 5 GHz spectrum: True
>>>>>>>>         .... ..0. .... .... = Passive: False
>>>>>>>>         .... .0.. .... .... = Dynamic CCK-OFDM: False
>>>>>>>>         .... 0... .... .... = Gaussian Frequency Shift Keying (GFSK): False
>>>>>>>>         ...0 .... .... .... = GSM (900MHz): False
>>>>>>>>         ..0. .... .... .... = Static Turbo: False
>>>>>>>>         .0.. .... .... .... = Half Rate Channel (10MHz Channel Width): False
>>>>>>>>         0... .... .... .... = Quarter Rate Channel (5MHz Channel Width): False
>>>>>>>>     SSI Signal: -53 dBm
>>>>>>>>     Antenna: 0
>>>>>>>>     RX flags: 0x0000
>>>>>>>>         .... .... .... .... .... ..0. = Bad PLCP: False
>>>>>>>>     VHT information
>>>>>>>>         Known VHT information: 0x44
>>>>>>>>             .... .... .... ...0 = STBC: False
>>>>>>>>             .... .... .... ..0. = TXOP_PS_NOT_ALLOWED: False
>>>>>>>>             .... .... .... .1.. = Guard interval: True
>>>>>>>>             .... .... .... 0... = SGI Nsym disambiguation: False
>>>>>>>>             .... .... ...0 .... = LDPC extra OFDM symbol: False
>>>>>>>>             .... .... ..0. .... = Beamformed: False
>>>>>>>>             .... .... .1.. .... = Bandwidth: True
>>>>>>>>             .... .... 0... .... = Group ID: False
>>>>>>>>             .... ...0 .... .... = Partial AID: False
>>>>>>>>         .... .0.. = Guard interval: long (0)
>>>>>>>>         Bandwidth: 80 MHz (4)
>>>>>>>>         User 0: MCS 8
>>>>>>>>             1000 .... = MCS index 0: 8 (256-QAM 3/4)
>>>>>>>>             .... 0010 = Spatial streams 0: 2
>>>>>>>>             Space-time streams 0: 2
>>>>>>>>             Coding 0: BCC (0)
>>>>>>>>             [Data Rate: 702.0 Mb/s]
>>>>>>>> IEEE 802.11 QoS Data, Flags: .......T
>>>>>>>>     Type/Subtype: QoS Data (0x28)
>>>>>>>>     Frame Control Field: 0x8801
>>>>>>>>         .... ..00 = Version: 0
>>>>>>>>         .... 10.. = Type: Data frame (2)
>>>>>>>>         1000 .... = Subtype: 8
>>>>>>>>         Flags: 0x01
>>>>>>>>             .... ..01 = DS status: Frame from STA to DS via an AP (To
>>>>>>>> DS: 1 From DS: 0) (0x01)
>>>>>>>>             .... .0.. = More Fragments: This is the last fragment
>>>>>>>>             .... 0... = Retry: Frame is not being retransmitted
>>>>>>>>             ...0 .... = PWR MGT: STA will stay up
>>>>>>>>             ..0. .... = More Data: No data buffered
>>>>>>>>             .0.. .... = Protected flag: Data is not protected
>>>>>>>>             0... .... = Order flag: Not strictly ordered
>>>>>>>>     .000 0000 0011 0000 = Duration: 48 microseconds
>>>>>>>>     Receiver address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>>>>     BSS Id: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>>>>     Transmitter address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>>>     Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>>>     Destination address: SenaoNet_18:a8:00 (88:dc:96:18:a8:00)
>>>>>>>>     Fragment number: 0
>>>>>>>>     Sequence number: 1021
>>>>>>>>     Qos Control: 0x0080
>>>>>>>>         .... .... .... 0000 = TID: 0
>>>>>>>>         [.... .... .... .000 = Priority: Best Effort (Best Effort) (0)]
>>>>>>>>         .... .... ...0 .... = QoS bit 4: Bits 8-15 of QoS Control
>>>>>>>> field are TXOP Duration Requested
>>>>>>>>         .... .... .00. .... = Ack Policy: Normal Ack (0x0000)
>>>>>>>>         .... .... 1... .... = Payload Type: A-MSDU
>>>>>>>>         0000 0000 .... .... = TXOP Duration Requested: 0 (no TXOP requested)
>>>>>>>> IEEE 802.11 Aggregate MSDU
>>>>>>>>     A-MSDU Subframe #1
>>>>>>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>>>>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>>>         A-MSDU Length: 1510
>>>>>>>>         Logical-Link Control
>>>>>>>>             DSAP: SNAP (0xaa)
>>>>>>>>             IG Bit: Individual
>>>>>>>>             SSAP: SNAP (0xaa)
>>>>>>>>             CR Bit: Command
>>>>>>>>             Control field: U, func=UI (0x03)
>>>>>>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>>>>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>>>>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>>>>>>             Type: IP (0x0800)
>>>>>>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>>>>>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>>>>>>             Version: 4
>>>>>>>>             Header length: 20 bytes
>>>>>>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>>>>>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>>>>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>>>>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>>>>>>> (Not ECN-Capable Transport) (0x00)
>>>>>>>>             Total Length: 1500
>>>>>>>>             Identification: 0xc622 (50722)
>>>>>>>>             Flags: 0x00
>>>>>>>>                 0... .... = Reserved bit: Not set
>>>>>>>>                 .0.. .... = Don't fragment: Not set
>>>>>>>>                 ..0. .... = More fragments: Not set
>>>>>>>>             Fragment offset: 0
>>>>>>>>             Time to live: 64
>>>>>>>>             Protocol: TCP (6)
>>>>>>>>             Header checksum: 0x0d4c [correct]
>>>>>>>>                 [Good: True]
>>>>>>>>                 [Bad: False]
>>>>>>>>             Source: 192.168.144.79 (192.168.144.79)
>>>>>>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>>>>>>             [Source GeoIP: Unknown]
>>>>>>>>             [Destination GeoIP: Unknown]
>>>>>>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>>>>>>> Port: 5001 (5001), Seq: 1390105, Ack: 1, Len: 1448
>>>>>>>>             Source port: 52697 (52697)
>>>>>>>>             Destination port: 5001 (5001)
>>>>>>>>             [Stream index: 0]
>>>>>>>>             Sequence number: 1390105    (relative sequence number)
>>>>>>>>             [Next sequence number: 1391553    (relative sequence number)]
>>>>>>>>             Acknowledgment number: 1    (relative ack number)
>>>>>>>>             Header length: 32 bytes
>>>>>>>>             Flags: 0x010 (ACK)
>>>>>>>>                 000. .... .... = Reserved: Not set
>>>>>>>>                 ...0 .... .... = Nonce: Not set
>>>>>>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>>>>>>                 .... .0.. .... = ECN-Echo: Not set
>>>>>>>>                 .... ..0. .... = Urgent: Not set
>>>>>>>>                 .... ...1 .... = Acknowledgment: Set
>>>>>>>>                 .... .... 0... = Push: Not set
>>>>>>>>                 .... .... .0.. = Reset: Not set
>>>>>>>>                 .... .... ..0. = Syn: Not set
>>>>>>>>                 .... .... ...0 = Fin: Not set
>>>>>>>>             Window size value: 8235
>>>>>>>>             [Calculated window size: 131760]
>>>>>>>>             [Window size scaling factor: 16]
>>>>>>>>             Checksum: 0xa1c0 [correct]
>>>>>>>>                 [Good Checksum: True]
>>>>>>>>                 [Bad Checksum: False]
>>>>>>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>>>>>>> (NOP), Timestamps
>>>>>>>>                 No-Operation (NOP)
>>>>>>>>                     Type: 1
>>>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>>>                         .00. .... = Class: Control (0)
>>>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>>>                 No-Operation (NOP)
>>>>>>>>                     Type: 1
>>>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>>>                         .00. .... = Class: Control (0)
>>>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>>>>>>                     Kind: Timestamp (8)
>>>>>>>>                     Length: 10
>>>>>>>>                     Timestamp value: 1298580657
>>>>>>>>                     Timestamp echo reply: 4294947481
>>>>>>>>         Data (1448 bytes)
>>>>>>>>
>>>>>>>> 0000  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0010  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0020  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0030  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0040  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0050  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0060  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0070  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0080  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0090  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 00a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 00b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 00c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 00d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 00e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 00f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0100  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0110  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0120  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0130  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0140  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0150  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0160  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0170  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0180  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0190  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 01a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 01b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 01c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 01d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 01e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 01f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0200  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0210  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0220  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0230  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0240  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0250  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0260  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0270  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0280  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0290  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 02a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 02b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 02c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 02d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 02e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 02f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0300  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0310  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0320  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0330  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0340  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0350  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0360  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0370  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0380  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0390  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 03a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 03b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 03c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 03d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 03e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 03f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0400  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0410  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0420  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0430  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0440  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0450  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0460  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0470  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0480  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0490  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 04a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 04b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 04c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 04d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 04e0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 04f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0500  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0510  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0520  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0530  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0540  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0550  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0560  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0570  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0580  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0590  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 05a0  34 35 36 37 38 39 30 31                           45678901
>>>>>>>>             Data: 343536373839303132333435363738393031323334353637...
>>>>>>>>             [Length: 1448]
>>>>>>>>     A-MSDU Subframe #2
>>>>>>>>         Destination address: GoogleFi_00:14:cd (f8:8f:ca:00:14:cd)
>>>>>>>>         Source address: Apple_67:24:54 (84:38:35:67:24:54)
>>>>>>>>         A-MSDU Length: 1510
>>>>>>>>         Logical-Link Control
>>>>>>>>             DSAP: SNAP (0xaa)
>>>>>>>>             IG Bit: Individual
>>>>>>>>             SSAP: SNAP (0xaa)
>>>>>>>>             CR Bit: Command
>>>>>>>>             Control field: U, func=UI (0x03)
>>>>>>>>                 000. 00.. = Command: Unnumbered Information (0x00)
>>>>>>>>                 .... ..11 = Frame type: Unnumbered frame (0x03)
>>>>>>>>             Organization Code: Encapsulated Ethernet (0x000000)
>>>>>>>>             Type: IP (0x0800)
>>>>>>>>         Internet Protocol Version 4, Src: 192.168.144.79
>>>>>>>> (192.168.144.79), Dst: 192.168.144.13 (192.168.144.13)
>>>>>>>>             Version: 4
>>>>>>>>             Header length: 20 bytes
>>>>>>>>             Differentiated Services Field: 0x00 (DSCP 0x00: Default;
>>>>>>>> ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
>>>>>>>>                 0000 00.. = Differentiated Services Codepoint: Default (0x00)
>>>>>>>>                 .... ..00 = Explicit Congestion Notification: Not-ECT
>>>>>>>> (Not ECN-Capable Transport) (0x00)
>>>>>>>>             Total Length: 1500
>>>>>>>>             Identification: 0xda09 (55817)
>>>>>>>>             Flags: 0x00
>>>>>>>>                 0... .... = Reserved bit: Not set
>>>>>>>>                 .0.. .... = Don't fragment: Not set
>>>>>>>>                 ..0. .... = More fragments: Not set
>>>>>>>>             Fragment offset: 0
>>>>>>>>             Time to live: 64
>>>>>>>>             Protocol: TCP (6)
>>>>>>>>             Header checksum: 0xf964 [correct]
>>>>>>>>                 [Good: True]
>>>>>>>>                 [Bad: False]
>>>>>>>>             Source: 192.168.144.79 (192.168.144.79)
>>>>>>>>             Destination: 192.168.144.13 (192.168.144.13)
>>>>>>>>             [Source GeoIP: Unknown]
>>>>>>>>             [Destination GeoIP: Unknown]
>>>>>>>>         Transmission Control Protocol, Src Port: 52697 (52697), Dst
>>>>>>>> Port: 5001 (5001), Seq: 1391553, Ack: 1, Len: 1448
>>>>>>>>             Source port: 52697 (52697)
>>>>>>>>             Destination port: 5001 (5001)
>>>>>>>>             [Stream index: 0]
>>>>>>>>             Sequence number: 1391553    (relative sequence number)
>>>>>>>>             [Next sequence number: 1393001    (relative sequence number)]
>>>>>>>>             Acknowledgment number: 1    (relative ack number)
>>>>>>>>             Header length: 32 bytes
>>>>>>>>             Flags: 0x010 (ACK)
>>>>>>>>                 000. .... .... = Reserved: Not set
>>>>>>>>                 ...0 .... .... = Nonce: Not set
>>>>>>>>                 .... 0... .... = Congestion Window Reduced (CWR): Not set
>>>>>>>>                 .... .0.. .... = ECN-Echo: Not set
>>>>>>>>                 .... ..0. .... = Urgent: Not set
>>>>>>>>                 .... ...1 .... = Acknowledgment: Set
>>>>>>>>                 .... .... 0... = Push: Not set
>>>>>>>>                 .... .... .0.. = Reset: Not set
>>>>>>>>                 .... .... ..0. = Syn: Not set
>>>>>>>>                 .... .... ...0 = Fin: Not set
>>>>>>>>             Window size value: 8235
>>>>>>>>             [Calculated window size: 131760]
>>>>>>>>             [Window size scaling factor: 16]
>>>>>>>>             Checksum: 0x9a16 [incorrect, should be 0x5913 (maybe
>>>>>>>> caused by "TCP checksum offload"?)]
>>>>>
>>>>> And yes we are using checksum offload in ath10k.
>>>>> Best is using standalone 80211ac sniffer for that case to be sure
>>>>> about checksum.
>>>>>
>>>>>>>>                 [Good Checksum: False]
>>>>>>>>                 [Bad Checksum: True]
>>>>>>>>                     [Expert Info (Error/Checksum): Bad checksum]
>>>>>>>>                         [Message: Bad checksum]
>>>>>>>>                         [Severity level: Error]
>>>>>>>>                         [Group: Checksum]
>>>>>>>>             Options: (12 bytes), No-Operation (NOP), No-Operation
>>>>>>>> (NOP), Timestamps
>>>>>>>>                 No-Operation (NOP)
>>>>>>>>                     Type: 1
>>>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>>>                         .00. .... = Class: Control (0)
>>>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>>>                 No-Operation (NOP)
>>>>>>>>                     Type: 1
>>>>>>>>                         0... .... = Copy on fragmentation: No
>>>>>>>>                         .00. .... = Class: Control (0)
>>>>>>>>                         ...0 0001 = Number: No-Operation (NOP) (1)
>>>>>>>>                 Timestamps: TSval 1298580657, TSecr 4294947481
>>>>>>>>                     Kind: Timestamp (8)
>>>>>>>>                     Length: 10
>>>>>>>>                     Timestamp value: 1298580657
>>>>>>>>                     Timestamp echo reply: 4294947481
>>>>>>>>         Data (1448 bytes)
>>>>>>>>
>>>>>>>> 0000  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0010  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0020  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0030  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0040  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0050  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0060  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0070  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0080  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0090  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 00a0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 00b0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 00c0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 00d0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 00e0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 00f0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0100  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0110  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0120  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0130  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0140  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0150  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0160  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0170  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0180  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0190  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 01a0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 01b0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 01c0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 01d0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 01e0  32 33 34 35 36 37 38 39 30 31 72 36 35 35 36 37   2345678901r65567
>>>>>>>> 01f0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0200  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0210  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0220  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0230  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0240  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0250  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0260  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0270  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0280  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0290  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 02a0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 02b0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 02c0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 02d0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 02e0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 02f0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0300  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0310  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0320  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0330  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0340  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0350  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0360  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0370  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0380  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0390  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 03a0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 03b0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 03c0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 03d0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 03e0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 03f0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0400  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0410  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0420  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0430  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0440  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0450  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0460  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0470  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0480  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0490  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 04a0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 04b0  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 04c0  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 04d0  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 04e0  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 04f0  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0500  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0510  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0520  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0530  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0540  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 0550  32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37   2345678901234567
>>>>>>>> 0560  38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33   8901234567890123
>>>>>>>> 0570  34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39   4567890123456789
>>>>>>>> 0580  30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35   0123456789012345
>>>>>>>> 0590  36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31   6789012345678901
>>>>>>>> 05a0  32 33 34 35 36 37 38 39                           23456789
>>>>>>>>             Data: 323334353637383930313233343536373839303132333435...
>>>>>>>>             [Length: 1448]
>>>>>>>>
>>>>>>>> On Mon, Jul 7, 2014 at 12:26 PM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>> The initial results are not promising: a MacOS 802.11ac client gets
>>>>>>>>> between 0-2 Mbps with this change, where it was getting about 8 Mbps
>>>>>>>>> prior to this change and ~170 Mbps prior to the reordering fix. A pcap
>>>>>>>>> from the receiving system shows a very large number of out of order
>>>>>>>>> frames, likely due to TCP retransmission.
>>>>>>>>>
>>>>>>>>> An 802.11n MacBook gets very good throughput, only the 802.11ac
>>>>>>>>> MacBook shows the very poor result. I'm trying to figure out why.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> One specific note (and probably not related to the throughput): I
>>>>>>>>> believe ath10k_htt_rx_amsdu runs in the tasklet, which means it would
>>>>>>>>> need to use GFP_ATOMIC instead of GFP_KERNEL. Do I understand it
>>>>>>>>> correctly?
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Mon, Jul 7, 2014 at 1:30 AM, Janusz Dziedzic
>>>>>>>>> <janusz.dziedzic at tieto.com> wrote:
>>>>>>>>>> On 6 July 2014 04:27, Adrian Chadd <adrian at freebsd.org> wrote:
>>>>>>>>>>> I think you may have to tell mac80211 that it's okay and not to drop the frames.
>>>>>>>>>>>
>>>>>>>>>>> The earlier atheros chips would just give you the AMSDU frames as
>>>>>>>>>>> deaggregated A-MPDU sub-frames - you'd just pass the A-MSDU up to
>>>>>>>>>>> net80211 and it'd ull it apart. But if the driver is doing it (or,
>>>>>>>>>>> well, the chip is doing it) then mac80211 needs to know not to drop
>>>>>>>>>>> those sub-frames.
>>>>>>>>>>>
>>>>>>>>>>> I wonder if you'll ever get notified before the complete A-MPDU has
>>>>>>>>>>> been received. That happens on previous chips. eg, you have an A-MPDU
>>>>>>>>>>> of 16 frames with 4 MSDUs in each MPDU. If you get notified and handle
>>>>>>>>>>> half of one MPDU before you hit EOL, the next notification you process
>>>>>>>>>>> will be the next MSDU in the same MPDU - and then you'll hit the
>>>>>>>>>>> reordering hilarity again.
>>>>>>>>>>>
>>>>>>>>>>> So hm, i will face the same issue in FreeBSD at some point, so I'd
>>>>>>>>>>> likely do what you're thinking of doing - pass up a chain of mbufs
>>>>>>>>>>> representing the current MPDU and treat the whole lot as the frame(s)
>>>>>>>>>>> to care about. Honestly though, I'm kind of wondering whether I should
>>>>>>>>>>> mostly just do what the Atheros reference driver does and treat it as
>>>>>>>>>>> ethernet payload frames (ie, it's already de-encapsulated and the
>>>>>>>>>>> reordering is already done) and just tack on the wifi header bit via
>>>>>>>>>>> another of the DMA rings.
>>>>>>>>>>>
>>>>>>>>>>> Ugh, I really should sit down and write the FreeBSD version of this.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -a
>>>>>>>>>>>
>>>>>>>>>>> (I'm still having flashbacks from working on this firmware at QCA. Aiee.)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On 5 July 2014 06:55, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>>>> There are two issues in handling the dis-aggregated A-MSDU subframes
>>>>>>>>>>>> in ieee80211_sta_manage_reorder_buf:
>>>>>>>>>>>>
>>>>>>>>>>>> 1. The out-of-date check:
>>>>>>>>>>>>
>>>>>>>>>>>>         /* frame with out of date sequence number */
>>>>>>>>>>>>         if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
>>>>>>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>>>>>>                 goto out;
>>>>>>>>>>>>         }
>>>>>>>>>>>>
>>>>>>>>>>>> As all of the subframes carry the same sequence number, the first
>>>>>>>>>>>> subframe will be delivered and increment head_seq_num and then all
>>>>>>>>>>>> subsequent subframes will be discarded.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> 2. The duplicates check a bit later in the routine:
>>>>>>>>>>>>
>>>>>>>>>>>>         /* check if we already stored this frame */
>>>>>>>>>>>>         if (tid_agg_rx->reorder_buf[index]) {
>>>>>>>>>>>>                 dev_kfree_skb(skb);
>>>>>>>>>>>>                 goto out;
>>>>>>>>>>>>         }
>>>>>>>>>>>>
>>>>>>>>>>>> If there is enough packet loss that packets are queued in the reorder
>>>>>>>>>>>> buffer and not immediately released, then only the first subframe will
>>>>>>>>>>>> be stored. Subsequent subframes will be discarded as duplicates.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> An 802.11ac MacBook is able to get about 170 Mbps with iperf prior to
>>>>>>>>>>>> the reordering buffer changes, and dropped to about 8 Mbps with the
>>>>>>>>>>>> reorder buffer. Hacking around the out-of-date sequence number check
>>>>>>>>>>>> to allow all subframes to egress restores it to 170 Mbps.
>>>>>>>>>>>>
>>>>>>>>>>>> In the area where I'm testing there isn't enough 5 GHz noise to make
>>>>>>>>>>>> the duplicates-check issue happen very often. By adding a printk I can
>>>>>>>>>>>> see that it does happen, but it doesn't impact the throughput and I
>>>>>>>>>>>> can't report the impact of fixing it.
>>>>>>>>>>>>
>>>>>>>>>>>> ----
>>>>>>>>>>>>
>>>>>>>>>>>> I do wonder if both of these are symptoms of dis-aggregating the
>>>>>>>>>>>> A-MSDU too early. mac80211 expects to be dealing with the whole MPDU
>>>>>>>>>>>> at a time, and the ath10k A-MSDU case is sending it subframes instead.
>>>>>>>>>>>> Trying to make the ath10k code send up all of the subframes as a chain
>>>>>>>>>>>> of skbs didn't immediately work, but I do wonder if that would better
>>>>>>>>>>>> match the mac80211 expectations.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On Fri, Jul 4, 2014 at 11:58 AM, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>>>>> Yes, after some more testing it does look like an unfortunate
>>>>>>>>>>>>> interaction between the reorder buffer and A-MSDU. The disaggregated
>>>>>>>>>>>>> subframes all carry the same sequence number. The first subframe is
>>>>>>>>>>>>> released from the reorder buffer and increments the head_seq_num.
>>>>>>>>>>>>> Subsequent subframes are all discarded as being out of date.
>>>>>>>>>>>>>
>>>>>>>>>>>>> [  308.514021] ieee80211_sta_manage_reorder_buf: out of date seq=0xb05
>>>>>>>>>>>>> head=0xb06
>>>>>>>>>>>>> [  308.520577] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0a
>>>>>>>>>>>>> head=0xb0b
>>>>>>>>>>>>> [  308.527198] ieee80211_sta_manage_reorder_buf: out of date seq=0xb0f
>>>>>>>>>>>>> head=0xb10
>>>>>>>>>>>>> [  308.533857] ieee80211_sta_manage_reorder_buf: out of date seq=0xb14
>>>>>>>>>>>>> head=0xb15
>>>>>>>>>>>>> [  308.540480] ieee80211_sta_manage_reorder_buf: out of date seq=0xb19
>>>>>>>>>>>>> head=0xb1a
>>>>>>>>>>>>> [  308.547730] ieee80211_sta_manage_reorder_buf: out of date seq=0xb1e
>>>>>>>>>>>>> head=0xb1f
>>>>>>>>>>>>> [  308.554069] ieee80211_sta_manage_reorder_buf: out of date seq=0xb23
>>>>>>>>>>>>> head=0xb24
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Wed, Jul 2, 2014 at 9:49 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>>>>>>>>>>>>> On 30 June 2014 22:15, Denton Gentry <denton.gentry at gmail.com> wrote:
>>>>>>>>>>>>>>> In iperf tests using a MacBook STA bridging through an ath10k AP to an
>>>>>>>>>>>>>>> Ethernet server, I'm noticing very selective packet loss. The second
>>>>>>>>>>>>>>> and subsequent frames in an A-MSDU packet appear to be dropped.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> The AP sets the A-MSDU size to 3839 bytes, and the MacBook frequently
>>>>>>>>>>>>>>> sends A-MSDU packets containing two TCP frames. So far as I can tell,
>>>>>>>>>>>>>>> the first TCP frame from an A-MSDU aggregate is delivered and the
>>>>>>>>>>>>>>> second is consistently lost. The MacBook generally retransmits the
>>>>>>>>>>>>>>> lost frame as a singleton with no aggregation, and the retransmitted
>>>>>>>>>>>>>>> frame makes it through.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> This became more noticeable after the reordering fixes in
>>>>>>>>>>>>>>> http://lists.infradead.org/pipermail/ath10k/2014-June/002552.html
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I see this A-MSDU packet loss behavior both with and without the
>>>>>>>>>>>>>>> reordering fixes, the first packet in an A-MSDU is delivered while the
>>>>>>>>>>>>>>> second is dropped. However, *without* the reordering fixes (and
>>>>>>>>>>>>>>> therefore with packets delivered out of order) the MacBook sends
>>>>>>>>>>>>>>> relatively few A-MSDU frames. *With* the reordering fixes, so all
>>>>>>>>>>>>>>> packets are delivered in order, the MacBook keeps sending A-MSDU and
>>>>>>>>>>>>>>> therefore has to deal with more packet loss. I suspect it is an
>>>>>>>>>>>>>>> interaction with the MacOS TCP congestion window which I'm likely
>>>>>>>>>>>>>>> never going to fully understand, its stuck in a region of the
>>>>>>>>>>>>>>> congestion window where the Wifi driver keeps choosing to using
>>>>>>>>>>>>>>> A-MSDU.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I was actually worried about A-MSDU once A-MPDU re-ordering issue was raised.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> ath10k fw reports A-MSDU subframes separately. To avoid memory
>>>>>>>>>>>>>> copying/allocation overhead each subframe is reported as a singly
>>>>>>>>>>>>>> A-MSDU MSDU to mac80211 with an extra rx_flag AMSDU_MORE. Perhaps
>>>>>>>>>>>>>> A-MPDU reordering intereferes with A-MSDU now?
>>>>>>>>>>>>>>
>>>>>>>>>> Denton could you try attached patch: report amsdu in one big frame.
>>>>>>>>>> If help, we can add amsdu skb list support to mac80211/cfg80211 - to
>>>>>>>>>> improve performance and reduce memcpy, while currently we have skb
>>>>>>>>>> frames, put them in one big skb and next cfg80211 split them again
>>>>>>>>>> into msdus and report to stack.
>>>>>>>>>>
>>>>>>>>>> BR
>>>>>>>>>> Janusz
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-ath10k-skip-frames-with-tcp-ip-checksum.patch
Type: text/x-diff
Size: 2513 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/ath10k/attachments/20140711/263fef45/attachment-0001.bin>

From janusz.dziedzic at tieto.com  Mon Jul 14 05:47:21 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Mon, 14 Jul 2014 14:47:21 +0200
Subject: [PATCH] ath10k: handle attention flags correctly when A-MSDU
Message-ID: <1405342041-7114-1-git-send-email-janusz.dziedzic@tieto.com>

In case of A-MSDU RX we should check flags for all
MSDU subframes to be sure we have correct FCS status.

Before we check attention flags only for first frame
where we didn't have correct info about FCS status in
case of A-MSDU. Next didn't mark RX_FLAG_FAILED_FCS_CRC
for skb. As a side efect we see big TP drop when TCP used.
This was easy to reproduce when AP interface was used
and added monitor interface run in promiscuous mode.

Reported-by: Denton Gentry <denton.gentry at gmail.com>
Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c |   23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 6c102b1..9f704fe 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -307,7 +307,8 @@ static void ath10k_htt_rx_free_msdu_chain(struct sk_buff *skb)
 static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
 				   u8 **fw_desc, int *fw_desc_len,
 				   struct sk_buff **head_msdu,
-				   struct sk_buff **tail_msdu)
+				   struct sk_buff **tail_msdu,
+				   u32 *attention)
 {
 	int msdu_len, msdu_chaining = 0;
 	struct sk_buff *msdu;
@@ -358,6 +359,11 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
 			break;
 		}
 
+		*attention |= __le32_to_cpu(rx_desc->attention.flags) &
+					    (RX_ATTENTION_FLAGS_TKIP_MIC_ERR |
+					     RX_ATTENTION_FLAGS_DECRYPT_ERR |
+					     RX_ATTENTION_FLAGS_FCS_ERR |
+					     RX_ATTENTION_FLAGS_MGMT_TYPE);
 		/*
 		 * Copy the FW rx descriptor for this MSDU from the rx
 		 * indication message into the MSDU's netbuf. HL uses the
@@ -1233,13 +1239,15 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
 		for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) {
 			struct sk_buff *msdu_head, *msdu_tail;
 
+			attention = 0;
 			msdu_head = NULL;
 			msdu_tail = NULL;
 			ret = ath10k_htt_rx_amsdu_pop(htt,
 						      &fw_desc,
 						      &fw_desc_len,
 						      &msdu_head,
-						      &msdu_tail);
+						      &msdu_tail,
+						      &attention);
 
 			if (ret < 0) {
 				ath10k_warn("failed to pop amsdu from htt rx ring %d\n",
@@ -1251,7 +1259,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
 			rxd = container_of((void *)msdu_head->data,
 					   struct htt_rx_desc,
 					   msdu_payload);
-			attention = __le32_to_cpu(rxd->attention.flags);
 
 			if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head,
 							 status,
@@ -1304,6 +1311,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
 	u8 *fw_desc;
 	int fw_desc_len, hdrlen, paramlen;
 	int trim;
+	u32 attention = 0;
 
 	fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes);
 	fw_desc = (u8 *)frag->fw_msdu_rx_desc;
@@ -1313,7 +1321,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
 
 	spin_lock_bh(&htt->rx_ring.lock);
 	ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
-				      &msdu_head, &msdu_tail);
+				      &msdu_head, &msdu_tail,
+				      &attention);
 	spin_unlock_bh(&htt->rx_ring.lock);
 
 	ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
@@ -1330,10 +1339,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
 
 	hdr = (struct ieee80211_hdr *)msdu_head->data;
 	rxd = (void *)msdu_head->data - sizeof(*rxd);
-	tkip_mic_err = !!(__le32_to_cpu(rxd->attention.flags) &
-				RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
-	decrypt_err = !!(__le32_to_cpu(rxd->attention.flags) &
-				RX_ATTENTION_FLAGS_DECRYPT_ERR);
+	tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
+	decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
 	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
 			RX_MSDU_START_INFO1_DECAP_FORMAT);
 
-- 
1.7.9.5



From kvalo at qca.qualcomm.com  Mon Jul 14 05:48:40 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 14 Jul 2014 15:48:40 +0300
Subject: [PATCH v2] ath10k: add implementation for configure max amsdu,
 ampdu
In-Reply-To: <1401438255-7349-1-git-send-email-janusz.dziedzic@tieto.com>
 (Janusz Dziedzic's message of "Fri, 30 May 2014 10:24:15 +0200")
References: <1401438255-7349-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <87lhrwm7h3.fsf@kamboji.qca.qualcomm.com>

Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:

> Allow to setup maximum subframes for AMSDU and AMPDU aggregation
> via debugfs htt_max_amsdu_ampdu file.
>
> Eg.
> echo "2 64" > htt_max_amsdu_ampdu
> will setup maximum amsdu subframes equal 2 and
> maximum ampdu subframes equal to 64.
>
> Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From michal.kazior at tieto.com  Mon Jul 14 06:18:05 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 14 Jul 2014 15:18:05 +0200
Subject: [RFC/RFT 1/2] mac80211: add support for Rx reordering offloading
In-Reply-To: <1404803407.4419.3.camel@jlt4.sipsolutions.net>
References: <1403860015-31601-1-git-send-email-michal.kazior@tieto.com>
 <1403860015-31601-2-git-send-email-michal.kazior@tieto.com>
 <1404803407.4419.3.camel@jlt4.sipsolutions.net>
Message-ID: <CA+BoTQ=8UU+S8F_OhALShkoD5jT7Lj-m2oZ=B5HhmSwEuDyxpw@mail.gmail.com>

On 8 July 2014 09:10, Johannes Berg <johannes at sipsolutions.net> wrote:
> On Fri, 2014-06-27 at 11:06 +0200, Michal Kazior wrote:
>
>> +/**
>> + * ieee80211_start_rx_ba_session_offl - start a Rx BA session
>> + *
>> + * Some device drivers may offload part of the Rx aggregation flow including
>> + * AddBa/DelBa negotiation but may otherwise be incapable of full Rx
>> + * reordering.
>> + *
>> + * Create structures responsible for reordering so device drivers may call here
>> + * when they complete AddBa negotiation.
>> + *
>> + * @vif: &struct ieee80211_vif pointer from the add_interface callback
>> + * @addr: station mac address
>> + * @dialog_token:
>> + * @timeout: session timeout (in TU)
>
> Why would you need the dialog token (and why no docs?) and timeout?

Good point. I'll remove both.


>> + * @start_seq_num: starting frame sequence number
>> + * @tid: the rx tid
>
>> + * @buf_size: max number of frames in reorder buffer
>
> The buf_size also isn't really needed, is it? We are allowed to use a
> bigger buffer, I believe?

Good point. I'll use the max buffer size macro.


>> +void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
>> +                                     const u8 *addr, u8 dialog_token,
>> +                                     u16 timeout, u16 start_seq_num,
>> +                                     u16 tid, u16 buf_size)
>> +{
>> +     struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
>> +     struct ieee80211_local *local = sdata->local;
>> +     struct ieee80211_rx_agg *rx_agg;
>> +     struct sk_buff *skb = dev_alloc_skb(0);
>> +
>> +     if (unlikely(!skb))
>> +             return;
>> +
>> +     rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
>> +     memcpy(&rx_agg->addr, addr, ETH_ALEN);
>> +     rx_agg->dialog_token = dialog_token;
>> +     rx_agg->timeout = timeout;
>> +     rx_agg->start_seq_num = start_seq_num;
>> +     rx_agg->ba_policy = 1;
>> +     rx_agg->tid = tid;
>> +     rx_agg->buf_size = buf_size;
>> +
>> +     skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START;
>> +     skb_queue_tail(&sdata->skb_queue, skb);
>> +     ieee80211_queue_work(&local->hw, &sdata->work);
>
> This seems problematic, since packets might be received immediately.
>
> On the teardown path it should probably also be invalidated immediately,
> no?
>
> Then again, we have the same problem already? Hmm.

Yeah. You have to go through the iface worker so you can race with
data frames coming in in ieee80211_rx() either way.

You'd have to make ampdu_action() atomic, replace sta->ampdu_mlme.mtx
with a spinlock and move some del_timer_sync() around - at least
that's what I've found after taking a quick look.


Micha?


From kvalo at qca.qualcomm.com  Mon Jul 14 06:20:08 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 14 Jul 2014 16:20:08 +0300
Subject: [PATCH 2/2] ath10k: sanitize tx ring index access properly
In-Reply-To: <1401954520-3365-3-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 5 Jun 2014 09:48:40 +0200")
References: <1401954520-3365-1-git-send-email-michal.kazior@tieto.com>
 <1401954520-3365-3-git-send-email-michal.kazior@tieto.com>
Message-ID: <87vbr0krg7.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> The tx ring index was immediately trimmed with a
> bitmask. This discarded the 0xFFFFFFFF error case
> (which theoretically can happen when a device is
> abruptly disconnected) and led to using an invalid
> tx ring index. This could lead to memory
> corruption.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
> ---
>  drivers/net/wireless/ath/ath10k/ce.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
> index d185dc0..7c6c7d5 100644
> --- a/drivers/net/wireless/ath/ath10k/ce.c
> +++ b/drivers/net/wireless/ath/ath10k/ce.c
> @@ -603,16 +603,19 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
>  		if (ret)
>  			return ret;
>  
> -		src_ring->hw_index =
> -			ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
> -		src_ring->hw_index &= nentries_mask;
> +		read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
> +		if (read_index == 0xFFFFFFFF)
> +			return -ENODEV;

I changed this to lower case, as it was before. Let's use lower case hex
values in ath10k.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Jul 14 06:25:11 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 14 Jul 2014 16:25:11 +0300
Subject: [PATCH] ath10k: fix unregister deadlock when fw probe fails
In-Reply-To: <1404120720-14649-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Mon, 30 Jun 2014 11:32:00 +0200")
References: <1404120720-14649-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87r41okr7s.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> If firmware probing worker failed it called
> device_release_driver() which synchronously called
> remove() pci callback. The callback in turn waited
> for the worker that called it to finish resulting
> in a deadlock.
>
> Waiting for a completion instead of a worker, like
> some other drivers do, doesn't seem like the best
> idea either:
>
>   Syscall                 Worker
>
>                           probe_fw()
>   rmmod
>   dev_lock()
>   pci->remove()
>   wait_for_completion()
>                           complete_all()
>                           device_release_driver()
>                           dev_lock()
>                           [sleep]
>   free(ar)
>   dev_unlock()
>                           [resume]
>
> There's no guarantee that Worker upon resuming can
> still access any data/code of the module.
>
> Leaving device bound to a driver is not as harmful
> as deadlocking so remove the call to
> device_release_driver() while a proper solution is
> figured out.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Jul 15 01:22:41 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 15 Jul 2014 11:22:41 +0300
Subject: [PATCH 0/2] ath10k: pci fixes 2014-06-05
In-Reply-To: <1401954520-3365-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 5 Jun 2014 09:48:38 +0200")
References: <1401954520-3365-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87d2d7ghf2.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> I've found a few issues while I was testing ath10k
> in QEMU/KVM with PCI passthrough. The second patch
> is something that I've found while analysing the
> bmi race and I don't think anyone experienced
> problems associated with it.
>
> There's still a weird synchronization issue with
> (what I think is) iomap write propagation. The
> initial fw bootup interrupt doesn't come in and
> it seems CE interrupts are unmasked with a lag
> because explicit polling after ctl_resp timeout
> seems to be sufficient to work around it. I
> suspect this might be a virtualization problem
> rather than ath10k. Ideas, anyone?

No ideas, but it would be great to get ath10k working in KVM. If we
cannot find a better solution, could we add the explicit polling anyway?
(With an approriate comment why such a hack is needed, of course)

> Michal Kazior (2):
>   ath10k: fix bmi exchange tx/rx race
>   ath10k: sanitize tx ring index access properly

Thanks, both patches applied.

-- 
Kalle Valo


From sw at simonwunderlich.de  Tue Jul 15 09:32:44 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Tue, 15 Jul 2014 18:32:44 +0200
Subject: [RFC 0/2] ath10k spectral scan support
Message-ID: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>

This is the first patchset iteration for review to implement the ath10k
spectral scan feature. The patchset is still experimental, but we were
able to detect our analogue 5.8 GHz TV repeater in the sample data. :)

As for ath9k, a proof of concept data plotter has been implemented, and
is currently available for ath10k in its own branch of FFT_eval [1].

There are a few open questions, and any help or pointers would be
appreciated:

 * so far, we could only enable endless mode (samples are sent
   endlessly). To prevent relayfs buffers overflowing because they are
   not read from userspace, it would be great to set a "count" to limit
   the number of samples sent after a trigger. That was possible in
   ath9k as well. However, if we set the "scan_count" parameter in the
   WMI command to something else than 0 (default), we don't get any
   samples at all. Is there any other configuration which needs to be
   done to get a limited number of samples?
 * So far, we always get 64 bins of fft data in the samples, even if we
   are in HT40 or VHT80 mode. That doesn't seem right, as there should
   be more bins for wider channels (e.g. 128 or 256 bins). Is there any
   parameter to change in the configuration to get the output from
   multiple channels / higher bandwidth?

Kudos to Kalle and Michal for their help to get this started. :)

Cheers,
     Simon

[1] https://github.com/simonwunderlich/FFT_eval/tree/ath10k_wip

Sven Eckelmann (2):
  ath: Move spectral debugfs structs to shared header
  ath10k: add spectral scan feature

 drivers/net/wireless/ath/ath10k/Kconfig    |   1 +
 drivers/net/wireless/ath/ath10k/Makefile   |   3 +-
 drivers/net/wireless/ath/ath10k/core.h     |   6 +
 drivers/net/wireless/ath/ath10k/debug.c    |   3 +
 drivers/net/wireless/ath/ath10k/spectral.c | 368 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |  66 ++++++
 drivers/net/wireless/ath/ath10k/wmi.c      |  98 +++++++-
 drivers/net/wireless/ath/ath10k/wmi.h      |  80 +++++++
 drivers/net/wireless/ath/ath9k/spectral.h  |  71 +-----
 drivers/net/wireless/ath/spectral_common.h | 108 +++++++++
 10 files changed, 733 insertions(+), 71 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h
 create mode 100644 drivers/net/wireless/ath/spectral_common.h

-- 
1.9.1



From sw at simonwunderlich.de  Tue Jul 15 09:32:45 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Tue, 15 Jul 2014 18:32:45 +0200
Subject: [RFC 1/2] ath: Move spectral debugfs structs to shared header
In-Reply-To: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
References: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <1405441966-32681-2-git-send-email-sw@simonwunderlich.de>

From: Sven Eckelmann <sven at narfation.org>

The ath9k and ath10k will share the definitions of the debugfs spectral
structures and enums. Having them in the same place helps to avoid conflicts.

Signed-off-by: Sven Eckelmann <sven at narfation.org>
Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
---
 drivers/net/wireless/ath/ath9k/spectral.h  | 71 +-----------------------
 drivers/net/wireless/ath/spectral_common.h | 88 ++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 69 deletions(-)
 create mode 100644 drivers/net/wireless/ath/spectral_common.h

diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h
index ead6341..7b410c6 100644
--- a/drivers/net/wireless/ath/ath9k/spectral.h
+++ b/drivers/net/wireless/ath/ath9k/spectral.h
@@ -17,6 +17,8 @@
 #ifndef SPECTRAL_H
 #define SPECTRAL_H
 
+#include "../spectral_common.h"
+
 /* enum spectral_mode:
  *
  * @SPECTRAL_DISABLED: spectral mode is disabled
@@ -54,8 +56,6 @@ struct ath_ht20_mag_info {
 	u8 max_exp;
 } __packed;
 
-#define SPECTRAL_HT20_NUM_BINS		56
-
 /* WARNING: don't actually use this struct! MAC may vary the amount of
  * data by -1/+2. This struct is for reference only.
  */
@@ -83,8 +83,6 @@ struct ath_ht20_40_mag_info {
 	u8 max_exp;
 } __packed;
 
-#define SPECTRAL_HT20_40_NUM_BINS		128
-
 /* WARNING: don't actually use this struct! MAC may vary the amount of
  * data. This struct is for reference only.
  */
@@ -125,71 +123,6 @@ static inline u8 spectral_bitmap_weight(u8 *bins)
 	return bins[0] & 0x3f;
 }
 
-/* FFT sample format given to userspace via debugfs.
- *
- * Please keep the type/length at the front position and change
- * other fields after adding another sample type
- *
- * TODO: this might need rework when switching to nl80211-based
- * interface.
- */
-enum ath_fft_sample_type {
-	ATH_FFT_SAMPLE_HT20 = 1,
-	ATH_FFT_SAMPLE_HT20_40,
-};
-
-struct fft_sample_tlv {
-	u8 type;	/* see ath_fft_sample */
-	__be16 length;
-	/* type dependent data follows */
-} __packed;
-
-struct fft_sample_ht20 {
-	struct fft_sample_tlv tlv;
-
-	u8 max_exp;
-
-	__be16 freq;
-	s8 rssi;
-	s8 noise;
-
-	__be16 max_magnitude;
-	u8 max_index;
-	u8 bitmap_weight;
-
-	__be64 tsf;
-
-	u8 data[SPECTRAL_HT20_NUM_BINS];
-} __packed;
-
-struct fft_sample_ht20_40 {
-	struct fft_sample_tlv tlv;
-
-	u8 channel_type;
-	__be16 freq;
-
-	s8 lower_rssi;
-	s8 upper_rssi;
-
-	__be64 tsf;
-
-	s8 lower_noise;
-	s8 upper_noise;
-
-	__be16 lower_max_magnitude;
-	__be16 upper_max_magnitude;
-
-	u8 lower_max_index;
-	u8 upper_max_index;
-
-	u8 lower_bitmap_weight;
-	u8 upper_bitmap_weight;
-
-	u8 max_exp;
-
-	u8 data[SPECTRAL_HT20_40_NUM_BINS];
-} __packed;
-
 void ath9k_spectral_init_debug(struct ath_softc *sc);
 void ath9k_spectral_deinit_debug(struct ath_softc *sc);
 
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
new file mode 100644
index 0000000..b9ab722
--- /dev/null
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_COMMON_H
+#define SPECTRAL_COMMON_H
+
+#define SPECTRAL_HT20_NUM_BINS		56
+#define SPECTRAL_HT20_40_NUM_BINS		128
+
+/* FFT sample format given to userspace via debugfs.
+ *
+ * Please keep the type/length at the front position and change
+ * other fields after adding another sample type
+ *
+ * TODO: this might need rework when switching to nl80211-based
+ * interface.
+ */
+enum ath_fft_sample_type {
+	ATH_FFT_SAMPLE_HT20 = 1,
+	ATH_FFT_SAMPLE_HT20_40,
+};
+
+struct fft_sample_tlv {
+	u8 type;	/* see ath_fft_sample */
+	__be16 length;
+	/* type dependent data follows */
+} __packed;
+
+struct fft_sample_ht20 {
+	struct fft_sample_tlv tlv;
+
+	u8 max_exp;
+
+	__be16 freq;
+	s8 rssi;
+	s8 noise;
+
+	__be16 max_magnitude;
+	u8 max_index;
+	u8 bitmap_weight;
+
+	__be64 tsf;
+
+	u8 data[SPECTRAL_HT20_NUM_BINS];
+} __packed;
+
+struct fft_sample_ht20_40 {
+	struct fft_sample_tlv tlv;
+
+	u8 channel_type;
+	__be16 freq;
+
+	s8 lower_rssi;
+	s8 upper_rssi;
+
+	__be64 tsf;
+
+	s8 lower_noise;
+	s8 upper_noise;
+
+	__be16 lower_max_magnitude;
+	__be16 upper_max_magnitude;
+
+	u8 lower_max_index;
+	u8 upper_max_index;
+
+	u8 lower_bitmap_weight;
+	u8 upper_bitmap_weight;
+
+	u8 max_exp;
+
+	u8 data[SPECTRAL_HT20_40_NUM_BINS];
+} __packed;
+
+#endif /* SPECTRAL_COMMON_H */
-- 
1.9.1



From sw at simonwunderlich.de  Tue Jul 15 09:32:46 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Tue, 15 Jul 2014 18:32:46 +0200
Subject: [RFC 2/2] ath10k: add spectral scan feature
In-Reply-To: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
References: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <1405441966-32681-3-git-send-email-sw@simonwunderlich.de>

From: Sven Eckelmann <sven at narfation.org>

Adds the spectral scan feature for ath10k. The spectral scan is triggered by
configuring a mode through a debugfs control file. Samples can be gathered via
another relay debugfs file.

Essentially, to try it out:

ip link dev wlan0 set up
echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
iw dev wlan0 scan
echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples

This feature is still experimental.

Signed-off-by: Sven Eckelmann <sven at narfation.org>
Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
---
 drivers/net/wireless/ath/ath10k/Kconfig    |   1 +
 drivers/net/wireless/ath/ath10k/Makefile   |   3 +-
 drivers/net/wireless/ath/ath10k/core.h     |   6 +
 drivers/net/wireless/ath/ath10k/debug.c    |   3 +
 drivers/net/wireless/ath/ath10k/spectral.c | 368 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |  66 ++++++
 drivers/net/wireless/ath/ath10k/wmi.c      |  98 +++++++-
 drivers/net/wireless/ath/ath10k/wmi.h      |  80 +++++++
 drivers/net/wireless/ath/spectral_common.h |  20 ++
 9 files changed, 643 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h

diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index a6f5285..1053bb5 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -25,6 +25,7 @@ config ATH10K_DEBUG
 config ATH10K_DEBUGFS
 	bool "Atheros ath10k debugfs support"
 	depends on ATH10K
+	select RELAY
 	---help---
 	  Enabled debugfs support
 
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index a4179f4..2a1e9a3 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -8,7 +8,8 @@ ath10k_core-y += mac.o \
 		 htt_tx.o \
 		 txrx.o \
 		 wmi.o \
-		 bmi.o
+		 bmi.o \
+		 spectral.o
 
 ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
 
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 83a5fa9..4af7f59 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -31,6 +31,7 @@
 #include "../ath.h"
 #include "../regd.h"
 #include "../dfs_pattern_detector.h"
+#include "spectral.h"
 
 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -494,6 +495,11 @@ struct ath10k {
 #ifdef CONFIG_ATH10K_DEBUGFS
 	struct ath10k_debug debug;
 #endif
+
+	/* relay(fs) channel for spectral scan */
+	struct rchan *rfs_chan_spec_scan;
+	enum spectral_mode spectral_mode;
+	struct ath_spec_scan spec_config;
 };
 
 struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 3030158..42cb448 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -957,12 +957,15 @@ int ath10k_debug_create(struct ath10k *ar)
 				    &fops_dfs_stats);
 	}
 
+	ath10k_spectral_init_debug(ar);
+
 	return 0;
 }
 
 void ath10k_debug_destroy(struct ath10k *ar)
 {
 	cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
+	ath10k_spectral_deinit_debug(ar);
 }
 
 #endif /* CONFIG_ATH10K_DEBUGFS */
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
new file mode 100644
index 0000000..20f7037
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/relay.h>
+#include "core.h"
+
+static void ath_debug_send_fft_sample(struct ath10k *ar,
+				      struct fft_sample_tlv *fft_sample_tlv)
+{
+	int length;
+
+	if (!ar->rfs_chan_spec_scan)
+		return;
+
+	length = __be16_to_cpu(fft_sample_tlv->length) +
+		 sizeof(*fft_sample_tlv);
+	relay_write(ar->rfs_chan_spec_scan, fft_sample_tlv, length);
+}
+
+int ath10k_process_fft(struct ath10k *ar,
+		       struct wmi_single_phyerr_rx_event *event,
+		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
+{
+	struct fft_sample_ath10k_ht20 fft_sample;
+	u32 reg0, reg1;
+	u16 peak_mag;
+	u8 *bins;
+	u16 freq1;
+	u16 freq2;
+	u16 total_gain_db;
+	u16 base_pwr_db;
+	u8 chain_idx;
+	u32 nf_list1;
+	u32 nf_list2;
+	u16 length;
+
+	if (bin_len != SPECTRAL_ATH10K_HT20_NUM_BINS)
+		return 0;
+
+	reg0 = __le32_to_cpu(fftr->reg0);
+	reg1 = __le32_to_cpu(fftr->reg1);
+
+	length = sizeof(fft_sample) - sizeof(struct fft_sample_tlv);
+	fft_sample.tlv.type = ATH_FFT_SAMPLE_ATH10K_HT20;
+	fft_sample.tlv.length = __cpu_to_be16(length);
+
+	fft_sample.mhz = event->hdr.chan_width_mhz;
+	fft_sample.relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
+	fft_sample.avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
+
+	peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
+	fft_sample.max_magnitude = __cpu_to_be16(peak_mag);
+	fft_sample.max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
+	fft_sample.rssi = event->hdr.rssi_combined;
+
+	total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
+	base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
+	fft_sample.total_gain_db = __cpu_to_be16(total_gain_db);
+	fft_sample.base_pwr_db = __cpu_to_be16(base_pwr_db);
+
+	freq1 = __le16_to_cpu(event->hdr.freq1);
+	freq2 = __le16_to_cpu(event->hdr.freq2);
+	fft_sample.freq1 = __cpu_to_be16(freq1);
+	fft_sample.freq2 = __cpu_to_be16(freq2);
+
+	nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
+	nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
+	chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
+	switch (chain_idx) {
+	case 0:
+		fft_sample.noise = __cpu_to_be16(nf_list1 & 0xffffu);
+		break;
+	case 1:
+		fft_sample.noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
+		break;
+	case 2:
+		fft_sample.noise = __cpu_to_be16(nf_list2 & 0xffffu);
+		break;
+	case 3:
+		fft_sample.noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
+		break;
+	}
+
+	fft_sample.tsf = __cpu_to_be64(tsf);
+
+	bins = (u8 *)fftr;
+	bins += sizeof(*fftr);
+	memcpy(fft_sample.data, bins, SPECTRAL_ATH10K_HT20_NUM_BINS);
+
+	ath_debug_send_fft_sample(ar, &fft_sample.tlv);
+
+	return 1;
+}
+
+static int ath_get_spectral_vdevid(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+
+	if (list_empty(&ar->arvifs))
+		return -ENODEV;
+
+	arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list);
+	return arvif->vdev_id;
+}
+
+int ath10k_spectral_scan_trigger(struct ath10k *ar)
+{
+	int ret;
+	int vdev_id;
+
+	vdev_id = ath_get_spectral_vdevid(ar);
+	if (vdev_id < 0)
+		return vdev_id;
+
+	if (ar->spectral_mode == SPECTRAL_DISABLED)
+		return 0;
+
+	ret = ath10k_vdev_spectral_enable(ar, vdev_id,
+					  WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					  WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (ret < 0)
+		return ret;
+
+	ret = ath10k_vdev_spectral_enable(ar, vdev_id,
+					  WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
+					  WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int ath10k_spectral_scan_config(struct ath10k *ar, enum spectral_mode mode)
+{
+	int count, ret;
+	struct wmi_vdev_spectral_configure_arg arg;
+	int vdev_id;
+
+	vdev_id = ath_get_spectral_vdevid(ar);
+	if (vdev_id < 0)
+		return vdev_id;
+
+	ar->spectral_mode = mode;
+
+	ath10k_vdev_spectral_enable(ar, vdev_id,
+				    WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+				    WMI_SPECTRAL_ENABLE_CMD_DISABLE);
+	if (mode == SPECTRAL_DISABLED)
+		return 0;
+
+	if (mode == SPECTRAL_BACKGROUND)
+		count = WMI_SPECTRAL_COUNT_DEFAULT;
+	else
+		count = max_t(u8, 1, ar->spec_config.count);
+
+	arg.vdev_id              = vdev_id;
+	arg.scan_count           = count;
+	arg.scan_period          = WMI_SPECTRAL_PERIOD_DEFAULT;
+	arg.scan_priority        = WMI_SPECTRAL_PRIORITY_DEFAULT;
+	arg.scan_fft_size        = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
+	arg.scan_gc_ena          = WMI_SPECTRAL_GC_ENA_DEFAULT;
+	arg.scan_restart_ena     = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
+	arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
+	arg.scan_init_delay      = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
+	arg.scan_nb_tone_thr     = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
+	arg.scan_str_bin_thr     = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
+	arg.scan_wb_rpt_mode     = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
+	arg.scan_rssi_rpt_mode   = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
+	arg.scan_rssi_thr        = WMI_SPECTRAL_RSSI_THR_DEFAULT;
+	arg.scan_pwr_format      = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
+	arg.scan_rpt_mode        = WMI_SPECTRAL_RPT_MODE_DEFAULT;
+	arg.scan_bin_scale       = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	arg.scan_dBm_adj         = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
+	arg.scan_chn_mask        = WMI_SPECTRAL_CHN_MASK_DEFAULT;
+
+	ret = ath10k_vdev_spectral_configure(ar, &arg);
+	if (ret < 0)
+		return ret;
+
+	if (mode == SPECTRAL_BACKGROUND)
+		ath10k_spectral_scan_trigger(ar);
+
+	return 0;
+}
+
+/*********************/
+/* spectral_scan_ctl */
+/*********************/
+
+static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char *mode = "";
+	unsigned int len;
+
+	switch (ar->spectral_mode) {
+	case SPECTRAL_DISABLED:
+		mode = "disable";
+		break;
+	case SPECTRAL_BACKGROUND:
+		mode = "background";
+		break;
+	case SPECTRAL_MANUAL:
+		mode = "manual";
+		break;
+	}
+
+	len = strlen(mode);
+	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
+}
+
+static ssize_t write_file_spec_scan_ctl(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+
+	if (strncmp("trigger", buf, 7) == 0) {
+		if (ar->spectral_mode == SPECTRAL_MANUAL)
+			ath10k_spectral_scan_trigger(ar);
+	} else if (strncmp("background", buf, 9) == 0) {
+		ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
+	} else if (strncmp("manual", buf, 6) == 0) {
+		ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
+	} else if (strncmp("disable", buf, 7) == 0) {
+		ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
+	} else {
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static const struct file_operations fops_spec_scan_ctl = {
+	.read = read_file_spec_scan_ctl,
+	.write = write_file_spec_scan_ctl,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+/******************/
+/* spectral_count */
+/******************/
+
+static ssize_t read_file_spectral_count(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len;
+
+	len = sprintf(buf, "%d\n", ar->spec_config.count);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_count(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 0 || val > 255)
+		return -EINVAL;
+
+	ar->spec_config.count = val;
+	return count;
+}
+
+static const struct file_operations fops_spectral_count = {
+	.read = read_file_spectral_count,
+	.write = write_file_spectral_count,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+/*******************/
+/* Relay interface */
+/*******************/
+
+static struct dentry *create_buf_file_handler(const char *filename,
+					      struct dentry *parent,
+					      umode_t mode,
+					      struct rchan_buf *buf,
+					      int *is_global)
+{
+	struct dentry *buf_file;
+
+	buf_file = debugfs_create_file(filename, mode, parent, buf,
+				       &relay_file_operations);
+	*is_global = 1;
+	return buf_file;
+}
+
+static int remove_buf_file_handler(struct dentry *dentry)
+{
+	debugfs_remove(dentry);
+
+	return 0;
+}
+
+static struct rchan_callbacks rfs_spec_scan_cb = {
+	.create_buf_file = create_buf_file_handler,
+	.remove_buf_file = remove_buf_file_handler,
+};
+
+/*********************/
+/* Debug Init/Deinit */
+/*********************/
+
+void ath10k_spectral_deinit_debug(struct ath10k *ar)
+{
+	if (config_enabled(CONFIG_ATH10K_DEBUGFS) && ar->rfs_chan_spec_scan) {
+		relay_close(ar->rfs_chan_spec_scan);
+		ar->rfs_chan_spec_scan = NULL;
+	}
+}
+
+void ath10k_spectral_init_debug(struct ath10k *ar)
+{
+	ar->rfs_chan_spec_scan = relay_open("spectral_scan",
+					    ar->debug.debugfs_phy,
+					    1024, 256, &rfs_spec_scan_cb,
+					    NULL);
+	debugfs_create_file("spectral_scan_ctl",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spec_scan_ctl);
+	debugfs_create_file("spectral_count",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_count);
+}
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
new file mode 100644
index 0000000..288672e
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_H
+#define SPECTRAL_H
+
+#include "../spectral_common.h"
+
+/**
+ * struct ath_spec_scan - parameters for Atheros spectral scan
+ *
+ * @count: number of scan results requested for manual mode
+ */
+struct ath_spec_scan {
+	u8 count;
+};
+
+/* enum spectral_mode:
+ *
+ * @SPECTRAL_DISABLED: spectral mode is disabled
+ * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
+ *	something else.
+ * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
+ *	is performed manually.
+ */
+enum spectral_mode {
+	SPECTRAL_DISABLED = 0,
+	SPECTRAL_BACKGROUND,
+	SPECTRAL_MANUAL,
+};
+
+void ath10k_spectral_init_debug(struct ath10k *ar);
+void ath10k_spectral_deinit_debug(struct ath10k *ar);
+
+int ath10k_spectral_scan_trigger(struct ath10k *ar);
+int ath10k_spectral_scan_config(struct ath10k *ar,
+				enum spectral_mode spectral_mode);
+
+#ifdef CONFIG_ATH10K_DEBUGFS
+int ath10k_process_fft(struct ath10k *ar,
+		       struct wmi_single_phyerr_rx_event *event,
+		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf);
+#else
+static inline int
+ath10k_process_fft(struct ath10k *ar,
+		   struct wmi_single_phyerr_rx_event *event,
+		   struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
+{
+	return 0;
+}
+#endif /* CONFIG_ATH10K_DEBUGFS */
+
+#endif /* SPECTRAL_H */
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 6f83cae..7ad9c71 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1659,7 +1659,47 @@ static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
 				struct wmi_single_phyerr_rx_event *event,
 				u64 tsf)
 {
-	ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n");
+	int buf_len, tlv_len, res, i = 0;
+	struct phyerr_tlv *tlv;
+	u8 *tlv_buf;
+	struct phyerr_fft_report *fftr;
+	size_t fftr_len;
+
+	buf_len = __le32_to_cpu(event->hdr.buf_len);
+
+	while (i < buf_len) {
+		if (i + sizeof(*tlv) > buf_len) {
+			ath10k_warn("too short buf for tlv header (%d)\n", i);
+			return;
+		}
+
+		tlv = (struct phyerr_tlv *)&event->bufp[i];
+		tlv_len = __le16_to_cpu(tlv->len);
+		tlv_buf = &event->bufp[i + sizeof(*tlv)];
+
+		if (i + sizeof(*tlv) + tlv_len > buf_len) {
+			ath10k_warn("too short buf for tlv (%d)\n", i);
+			return;
+		}
+
+		switch (tlv->tag) {
+		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
+			if (sizeof(*fftr) > tlv_len) {
+				ath10k_warn("too short fft report (%d)\n", i);
+				return;
+			}
+
+			fftr_len = tlv_len - sizeof(*fftr);
+			fftr = (struct phyerr_fft_report *)tlv_buf;
+			res = ath10k_process_fft(ar, event, fftr, fftr_len,
+						 tsf);
+			if (res)
+				return;
+			break;
+		}
+
+		i += sizeof(*tlv) + tlv_len;
+	}
 }
 
 static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
@@ -3236,6 +3276,62 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				   ar->wmi.cmd->vdev_install_key_cmdid);
 }
 
+int ath10k_vdev_spectral_configure(struct ath10k *ar,
+			      const struct wmi_vdev_spectral_configure_arg *arg)
+{
+	struct wmi_vdev_spectral_configure_cmd *cmd;
+	struct sk_buff *skb;
+	__le32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_configure_cmd *)skb->data;
+	cmd->vdev_id              = __cpu_to_le32(arg->vdev_id);
+	cmd->scan_count           = __cpu_to_le32(arg->scan_count);
+	cmd->scan_period          = __cpu_to_le32(arg->scan_period);
+	cmd->scan_priority        = __cpu_to_le32(arg->scan_priority);
+	cmd->scan_fft_size        = __cpu_to_le32(arg->scan_fft_size);
+	cmd->scan_gc_ena          = __cpu_to_le32(arg->scan_gc_ena);
+	cmd->scan_restart_ena     = __cpu_to_le32(arg->scan_restart_ena);
+	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
+	cmd->scan_init_delay      = __cpu_to_le32(arg->scan_init_delay);
+	cmd->scan_nb_tone_thr     = __cpu_to_le32(arg->scan_nb_tone_thr);
+	cmd->scan_str_bin_thr     = __cpu_to_le32(arg->scan_str_bin_thr);
+	cmd->scan_wb_rpt_mode     = __cpu_to_le32(arg->scan_wb_rpt_mode);
+	cmd->scan_rssi_rpt_mode   = __cpu_to_le32(arg->scan_rssi_rpt_mode);
+	cmd->scan_rssi_thr        = __cpu_to_le32(arg->scan_rssi_thr);
+	cmd->scan_pwr_format      = __cpu_to_le32(arg->scan_pwr_format);
+	cmd->scan_rpt_mode        = __cpu_to_le32(arg->scan_rpt_mode);
+	cmd->scan_bin_scale       = __cpu_to_le32(arg->scan_bin_scale);
+	cmd->scan_dBm_adj         = __cpu_to_le32(arg->scan_dBm_adj);
+	cmd->scan_chn_mask        = __cpu_to_le32(arg->scan_chn_mask);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_configure_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
+int ath10k_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				u32 enable)
+{
+	struct wmi_vdev_spectral_enable_cmd *cmd;
+	struct sk_buff *skb;
+	__le32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_enable_cmd *)skb->data;
+	cmd->vdev_id     = __cpu_to_le32(vdev_id);
+	cmd->trigger_cmd = __cpu_to_le32(trigger);
+	cmd->enable_cmd  = __cpu_to_le32(enable);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_enable_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 			   const u8 peer_addr[ETH_ALEN])
 {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index e93df2c..1020851 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2067,6 +2067,7 @@ struct wmi_comb_phyerr_rx_event {
 #define PHYERR_TLV_SIG				0xBB
 #define PHYERR_TLV_TAG_SEARCH_FFT_REPORT	0xFB
 #define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY	0xF8
+#define PHYERR_TLV_TAG_SPECTRAL_SUMMARY_REPORT	0xF9
 
 struct phyerr_radar_report {
 	__le32 reg0; /* RADAR_REPORT_REG0_* */
@@ -3444,6 +3445,81 @@ struct wmi_vdev_simple_event {
 /* unsupported VDEV combination */
 #define WMI_INIFIED_VDEV_START_RESPONSE_NOT_SUPPORTED	0x2
 
+struct wmi_vdev_spectral_configure_cmd {
+	__le32 vdev_id;
+	__le32 scan_count;
+	__le32 scan_period;
+	__le32 scan_priority;
+	__le32 scan_fft_size;
+	__le32 scan_gc_ena;
+	__le32 scan_restart_ena;
+	__le32 scan_noise_floor_ref;
+	__le32 scan_init_delay;
+	__le32 scan_nb_tone_thr;
+	__le32 scan_str_bin_thr;
+	__le32 scan_wb_rpt_mode;
+	__le32 scan_rssi_rpt_mode;
+	__le32 scan_rssi_thr;
+	__le32 scan_pwr_format;
+	__le32 scan_rpt_mode;
+	__le32 scan_bin_scale;
+	__le32 scan_dBm_adj;
+	__le32 scan_chn_mask;
+} __packed;
+
+struct wmi_vdev_spectral_configure_arg {
+	u32 vdev_id;
+	u32 scan_count;
+	u32 scan_period;
+	u32 scan_priority;
+	u32 scan_fft_size;
+	u32 scan_gc_ena;
+	u32 scan_restart_ena;
+	u32 scan_noise_floor_ref;
+	u32 scan_init_delay;
+	u32 scan_nb_tone_thr;
+	u32 scan_str_bin_thr;
+	u32 scan_wb_rpt_mode;
+	u32 scan_rssi_rpt_mode;
+	u32 scan_rssi_thr;
+	u32 scan_pwr_format;
+	u32 scan_rpt_mode;
+	u32 scan_bin_scale;
+	u32 scan_dBm_adj;
+	u32 scan_chn_mask;
+};
+
+#define WMI_SPECTRAL_ENABLE_DEFAULT              0
+#define WMI_SPECTRAL_COUNT_DEFAULT               0
+#define WMI_SPECTRAL_PERIOD_DEFAULT             35
+#define WMI_SPECTRAL_PRIORITY_DEFAULT            1
+#define WMI_SPECTRAL_FFT_SIZE_DEFAULT            7
+#define WMI_SPECTRAL_GC_ENA_DEFAULT              1
+#define WMI_SPECTRAL_RESTART_ENA_DEFAULT         0
+#define WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT   -96
+#define WMI_SPECTRAL_INIT_DELAY_DEFAULT         80
+#define WMI_SPECTRAL_NB_TONE_THR_DEFAULT        12
+#define WMI_SPECTRAL_STR_BIN_THR_DEFAULT         8
+#define WMI_SPECTRAL_WB_RPT_MODE_DEFAULT         0
+#define WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT       0
+#define WMI_SPECTRAL_RSSI_THR_DEFAULT         0xf0
+#define WMI_SPECTRAL_PWR_FORMAT_DEFAULT          0
+#define WMI_SPECTRAL_RPT_MODE_DEFAULT            2
+#define WMI_SPECTRAL_BIN_SCALE_DEFAULT           1
+#define WMI_SPECTRAL_DBM_ADJ_DEFAULT             1
+#define WMI_SPECTRAL_CHN_MASK_DEFAULT            1
+
+struct wmi_vdev_spectral_enable_cmd {
+	__le32 vdev_id;
+	__le32 trigger_cmd;
+	__le32 enable_cmd;
+} __packed;
+
+#define WMI_SPECTRAL_TRIGGER_CMD_TRIGGER  1
+#define WMI_SPECTRAL_TRIGGER_CMD_CLEAR    2
+#define WMI_SPECTRAL_ENABLE_CMD_ENABLE    1
+#define WMI_SPECTRAL_ENABLE_CMD_DISABLE   2
+
 /* Beacon processing related command and event structures */
 struct wmi_bcn_tx_hdr {
 	__le32 vdev_id;
@@ -4290,6 +4366,10 @@ int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id,
 			      u32 param_id, u32 param_value);
 int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				const struct wmi_vdev_install_key_arg *arg);
+int ath10k_vdev_spectral_configure(struct ath10k *ar,
+			     const struct wmi_vdev_spectral_configure_arg *arg);
+int ath10k_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				u32 enable);
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 		    const u8 peer_addr[ETH_ALEN]);
 int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
index b9ab722..fa01b9f 100644
--- a/drivers/net/wireless/ath/spectral_common.h
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -19,6 +19,7 @@
 
 #define SPECTRAL_HT20_NUM_BINS		56
 #define SPECTRAL_HT20_40_NUM_BINS		128
+#define SPECTRAL_ATH10K_HT20_NUM_BINS		64
 
 /* FFT sample format given to userspace via debugfs.
  *
@@ -31,6 +32,7 @@
 enum ath_fft_sample_type {
 	ATH_FFT_SAMPLE_HT20 = 1,
 	ATH_FFT_SAMPLE_HT20_40,
+	ATH_FFT_SAMPLE_ATH10K_HT20,
 };
 
 struct fft_sample_tlv {
@@ -85,4 +87,22 @@ struct fft_sample_ht20_40 {
 	u8 data[SPECTRAL_HT20_40_NUM_BINS];
 } __packed;
 
+struct fft_sample_ath10k_ht20 {
+	struct fft_sample_tlv tlv;
+	u8 mhz;
+	__be16 freq1;
+	__be16 freq2;
+	__be16 noise;
+	__be16 max_magnitude;
+	__be16 total_gain_db;
+	__be16 base_pwr_db;
+	__be64 tsf;
+	s8 max_index;
+	u8 rssi;
+	u8 relpwr_db;
+	u8 avgpwr_db;
+
+	u8 data[SPECTRAL_ATH10K_HT20_NUM_BINS];
+} __packed;
+
 #endif /* SPECTRAL_COMMON_H */
-- 
1.9.1



From avalentin at marcant.net  Tue Jul 15 14:16:18 2014
From: avalentin at marcant.net (Andre Valentin)
Date: Tue, 15 Jul 2014 23:16:18 +0200
Subject: ath10k OTP loading issues
In-Reply-To: <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>
References: <53AD2EEE.4040704@marcant.net>	<87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>
Message-ID: <53C59A22.6000505@marcant.net>

Hi!

Somehow I did not see this message. Sorry.
 >>> If I remove OTP loading the card initializes fine, but I think I will
>>> not have a good performance. So bad idea.
>>
>> All that was changed recently was that we now check the error code
>> coming from otp.bin. So you have had this issue all along, it was just
>> hidden before.
>
> Same issue here.
>
> Is it correct that board.bin should contain the calibration data of
> the actual board?
> I tried copying it from the APs ART partition but still no luck.
>
> Any hint on how to debug further why the otp calibration fails?

I have no idea except disabling the error return inside of ath10k_pci.
Would that make sense as a temporary workaround? It seems I have normal
performance without enfording otp loading.

Andr?



From michal.kazior at tieto.com  Tue Jul 15 23:24:58 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 08:24:58 +0200
Subject: [RFC 0/2] ath10k spectral scan support
In-Reply-To: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
References: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <CA+BoTQmNJuwYpSiXqF8OUuXQULLSdUW+PO4Sz5oNKyaduHMKPg@mail.gmail.com>

On 15 July 2014 18:32, Simon Wunderlich <sw at simonwunderlich.de> wrote:
> This is the first patchset iteration for review to implement the ath10k
> spectral scan feature. The patchset is still experimental, but we were
> able to detect our analogue 5.8 GHz TV repeater in the sample data. :)

Awesome!


[...]
>  * So far, we always get 64 bins of fft data in the samples, even if we
>    are in HT40 or VHT80 mode. That doesn't seem right, as there should
>    be more bins for wider channels (e.g. 128 or 256 bins). Is there any
>    parameter to change in the configuration to get the output from
>    multiple channels / higher bandwidth?

Hmm.. I suspect this may be because you use scan command. Scanning
uses channel list which is programmed with legacy modes a and g
(implying 20Mhz). Perhaps that's the limiting factor now. Using other
(wider) modes breaks scan from what I remember but it might be worth
checking out if it impacts fft bin sizes.


Micha?


From sven at narfation.org  Wed Jul 16 01:25:23 2014
From: sven at narfation.org (Sven Eckelmann)
Date: Wed, 16 Jul 2014 10:25:23 +0200
Subject: [RFC 0/2] ath10k spectral scan support
In-Reply-To: <CA+BoTQmNJuwYpSiXqF8OUuXQULLSdUW+PO4Sz5oNKyaduHMKPg@mail.gmail.com>
References: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
 <CA+BoTQmNJuwYpSiXqF8OUuXQULLSdUW+PO4Sz5oNKyaduHMKPg@mail.gmail.com>
Message-ID: <4111404.UJkIUxkzQm@bentobox>

On Wednesday 16 July 2014 08:24:58 Michal Kazior wrote:
> >  * So far, we always get 64 bins of fft data in the samples, even if we
> >  
> >    are in HT40 or VHT80 mode. That doesn't seem right, as there should
> >    be more bins for wider channels (e.g. 128 or 256 bins). Is there any
> >    parameter to change in the configuration to get the output from
> >    multiple channels / higher bandwidth?
> 
> Hmm.. I suspect this may be because you use scan command. Scanning
> uses channel list which is programmed with legacy modes a and g
> (implying 20Mhz). Perhaps that's the limiting factor now. Using other
> (wider) modes breaks scan from what I remember but it might be worth
> checking out if it impacts fft bin sizes.

I did the HT80 and HT40 stuff on a single channel in the spectral "background" 
mode. They reports from the firmware (10.1) still only had 64 bins. The HT80 
stuff wasn't tested with the "main" firmware because it refused to switch to 
HT80 mode as AP/Sta.

Kind regards,
	Sven


From sw at simonwunderlich.de  Wed Jul 16 01:38:09 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Wed, 16 Jul 2014 10:38:09 +0200
Subject: [RFC 0/2] ath10k spectral scan support
In-Reply-To: <4111404.UJkIUxkzQm@bentobox>
References: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
 <CA+BoTQmNJuwYpSiXqF8OUuXQULLSdUW+PO4Sz5oNKyaduHMKPg@mail.gmail.com>
 <4111404.UJkIUxkzQm@bentobox>
Message-ID: <201407161038.10130.sw@simonwunderlich.de>


> On Wednesday 16 July 2014 08:24:58 Michal Kazior wrote:
> > >  * So far, we always get 64 bins of fft data in the samples, even if we
> > >  
> > >    are in HT40 or VHT80 mode. That doesn't seem right, as there should
> > >    be more bins for wider channels (e.g. 128 or 256 bins). Is there any
> > >    parameter to change in the configuration to get the output from
> > >    multiple channels / higher bandwidth?
> > 
> > Hmm.. I suspect this may be because you use scan command. Scanning
> > uses channel list which is programmed with legacy modes a and g
> > (implying 20Mhz). Perhaps that's the limiting factor now. Using other
> > (wider) modes breaks scan from what I remember but it might be worth
> > checking out if it impacts fft bin sizes.
> 
> I did the HT80 and HT40 stuff on a single channel in the spectral
> "background" mode. They reports from the firmware (10.1) still only had 64
> bins. The HT80 stuff wasn't tested with the "main" firmware because it
> refused to switch to HT80 mode as AP/Sta.

Just to clarify this a little more, we tried AP (running hostapd) as well a 
STA in 40 and 80 MHz modes. We always got 64 bins returned.

Cheers,
    Simon


From michal.kazior at tieto.com  Wed Jul 16 01:56:16 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 10:56:16 +0200
Subject: [RFC 0/2] ath10k spectral scan support
In-Reply-To: <201407161038.10130.sw@simonwunderlich.de>
References: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
 <CA+BoTQmNJuwYpSiXqF8OUuXQULLSdUW+PO4Sz5oNKyaduHMKPg@mail.gmail.com>
 <4111404.UJkIUxkzQm@bentobox>
 <201407161038.10130.sw@simonwunderlich.de>
Message-ID: <CA+BoTQm_pbtiT+ujRypZ6DuoqfFkYM-OfzvtaC+q9qurnMwpaA@mail.gmail.com>

On 16 July 2014 10:38, Simon Wunderlich <sw at simonwunderlich.de> wrote:
>
>> On Wednesday 16 July 2014 08:24:58 Michal Kazior wrote:
>> > >  * So far, we always get 64 bins of fft data in the samples, even if we
>> > >
>> > >    are in HT40 or VHT80 mode. That doesn't seem right, as there should
>> > >    be more bins for wider channels (e.g. 128 or 256 bins). Is there any
>> > >    parameter to change in the configuration to get the output from
>> > >    multiple channels / higher bandwidth?
>> >
>> > Hmm.. I suspect this may be because you use scan command. Scanning
>> > uses channel list which is programmed with legacy modes a and g
>> > (implying 20Mhz). Perhaps that's the limiting factor now. Using other
>> > (wider) modes breaks scan from what I remember but it might be worth
>> > checking out if it impacts fft bin sizes.
>>
>> I did the HT80 and HT40 stuff on a single channel in the spectral
>> "background" mode. They reports from the firmware (10.1) still only had 64
>> bins. The HT80 stuff wasn't tested with the "main" firmware because it
>> refused to switch to HT80 mode as AP/Sta.
>
> Just to clarify this a little more, we tried AP (running hostapd) as well a
> STA in 40 and 80 MHz modes. We always got 64 bins returned.

It seems the number of bins is 2^ (fft_size - bin_scale) = 2^(7-1) =
64. Changing fft_size to 9 yields 256 bins.

Perhaps fft reports are (implicitly) relative to the mode the hw is in
at a given time and if you want a reasonable bin resolution for, e.g.
VHT80 you need to increase fft_size?


Micha?


From michal.kazior at tieto.com  Wed Jul 16 02:30:12 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 11:30:12 +0200
Subject: [RFC 2/2] ath10k: add spectral scan feature
In-Reply-To: <1405441966-32681-3-git-send-email-sw@simonwunderlich.de>
References: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
 <1405441966-32681-3-git-send-email-sw@simonwunderlich.de>
Message-ID: <CA+BoTQm1i2UoTtPBf7Z3QLQDBs_1uXwdG8gYOkP556+a7AqcpQ@mail.gmail.com>

On 15 July 2014 18:32, Simon Wunderlich <sw at simonwunderlich.de> wrote:
> From: Sven Eckelmann <sven at narfation.org>
>
> Adds the spectral scan feature for ath10k. The spectral scan is triggered by
> configuring a mode through a debugfs control file. Samples can be gathered via
> another relay debugfs file.
>
> Essentially, to try it out:
>
> ip link dev wlan0 set up
> echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> iw dev wlan0 scan
> echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples
>
> This feature is still experimental.
>
> Signed-off-by: Sven Eckelmann <sven at narfation.org>
> Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
> Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
> ---
>  drivers/net/wireless/ath/ath10k/Kconfig    |   1 +
>  drivers/net/wireless/ath/ath10k/Makefile   |   3 +-
>  drivers/net/wireless/ath/ath10k/core.h     |   6 +
>  drivers/net/wireless/ath/ath10k/debug.c    |   3 +
>  drivers/net/wireless/ath/ath10k/spectral.c | 368 +++++++++++++++++++++++++++++
>  drivers/net/wireless/ath/ath10k/spectral.h |  66 ++++++
>  drivers/net/wireless/ath/ath10k/wmi.c      |  98 +++++++-
>  drivers/net/wireless/ath/ath10k/wmi.h      |  80 +++++++
>  drivers/net/wireless/ath/spectral_common.h |  20 ++
>  9 files changed, 643 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
>  create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h
>
[...]
> +static void ath_debug_send_fft_sample(struct ath10k *ar,
> +                                     struct fft_sample_tlv *fft_sample_tlv)
> +{

Why ath_debug_... instead of ath10k_debug_.. ?


[...]
> +static int ath_get_spectral_vdevid(struct ath10k *ar)

ath_get_..? Shouldn't this be ath10k_get?


> +{
> +       struct ath10k_vif *arvif;
> +
> +       if (list_empty(&ar->arvifs))
> +               return -ENODEV;
> +
> +       arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list);
> +       return arvif->vdev_id;
> +}

No locks? Access to arvifs must be protected with conf_mutex.

What happens when an interface is removed without spectral scan being stopped?


> +int ath10k_spectral_scan_trigger(struct ath10k *ar)
> +{
> +       int ret;
> +       int vdev_id;
> +
> +       vdev_id = ath_get_spectral_vdevid(ar);
> +       if (vdev_id < 0)
> +               return vdev_id;
> +
> +       if (ar->spectral_mode == SPECTRAL_DISABLED)
> +               return 0;
> +
> +       ret = ath10k_vdev_spectral_enable(ar, vdev_id,
> +                                         WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
> +                                         WMI_SPECTRAL_ENABLE_CMD_ENABLE);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = ath10k_vdev_spectral_enable(ar, vdev_id,
> +                                         WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
> +                                         WMI_SPECTRAL_ENABLE_CMD_ENABLE);
> +       if (ret < 0)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +int ath10k_spectral_scan_config(struct ath10k *ar, enum spectral_mode mode)
> +{
> +       int count, ret;

We tend to use `res` in ath10k.


> +       struct wmi_vdev_spectral_configure_arg arg;
> +       int vdev_id;
> +
> +       vdev_id = ath_get_spectral_vdevid(ar);
> +       if (vdev_id < 0)
> +               return vdev_id;
> +
> +       ar->spectral_mode = mode;
> +
> +       ath10k_vdev_spectral_enable(ar, vdev_id,
> +                                   WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
> +                                   WMI_SPECTRAL_ENABLE_CMD_DISABLE);
> +       if (mode == SPECTRAL_DISABLED)
> +               return 0;
> +
> +       if (mode == SPECTRAL_BACKGROUND)
> +               count = WMI_SPECTRAL_COUNT_DEFAULT;
> +       else
> +               count = max_t(u8, 1, ar->spec_config.count);
> +
> +       arg.vdev_id              = vdev_id;
> +       arg.scan_count           = count;
> +       arg.scan_period          = WMI_SPECTRAL_PERIOD_DEFAULT;
> +       arg.scan_priority        = WMI_SPECTRAL_PRIORITY_DEFAULT;
> +       arg.scan_fft_size        = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
> +       arg.scan_gc_ena          = WMI_SPECTRAL_GC_ENA_DEFAULT;
> +       arg.scan_restart_ena     = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
> +       arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
> +       arg.scan_init_delay      = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
> +       arg.scan_nb_tone_thr     = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
> +       arg.scan_str_bin_thr     = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
> +       arg.scan_wb_rpt_mode     = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
> +       arg.scan_rssi_rpt_mode   = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
> +       arg.scan_rssi_thr        = WMI_SPECTRAL_RSSI_THR_DEFAULT;
> +       arg.scan_pwr_format      = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
> +       arg.scan_rpt_mode        = WMI_SPECTRAL_RPT_MODE_DEFAULT;
> +       arg.scan_bin_scale       = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
> +       arg.scan_dBm_adj         = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
> +       arg.scan_chn_mask        = WMI_SPECTRAL_CHN_MASK_DEFAULT;
> +
> +       ret = ath10k_vdev_spectral_configure(ar, &arg);
> +       if (ret < 0)

+ ath10k_warn("failed to configure spectral scan: %d\n", ret);


> +               return ret;
> +
> +       if (mode == SPECTRAL_BACKGROUND)
> +               ath10k_spectral_scan_trigger(ar);

Why isn't ath10k_spectral_scan_trigger() return value not checked?
Also +ath10k_warn.


[...]
> diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
> index 6f83cae..7ad9c71 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi.c
> +++ b/drivers/net/wireless/ath/ath10k/wmi.c
> @@ -1659,7 +1659,47 @@ static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
>                                 struct wmi_single_phyerr_rx_event *event,
>                                 u64 tsf)
>  {
> -       ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n");
> +       int buf_len, tlv_len, res, i = 0;
> +       struct phyerr_tlv *tlv;
> +       u8 *tlv_buf;
> +       struct phyerr_fft_report *fftr;
> +       size_t fftr_len;
> +
> +       buf_len = __le32_to_cpu(event->hdr.buf_len);
> +
> +       while (i < buf_len) {
> +               if (i + sizeof(*tlv) > buf_len) {
> +                       ath10k_warn("too short buf for tlv header (%d)\n", i);

"failed to parse phyerr tlv header at byte %d\n", i


> +                       return;
> +               }
> +
> +               tlv = (struct phyerr_tlv *)&event->bufp[i];
> +               tlv_len = __le16_to_cpu(tlv->len);
> +               tlv_buf = &event->bufp[i + sizeof(*tlv)];
> +
> +               if (i + sizeof(*tlv) + tlv_len > buf_len) {
> +                       ath10k_warn("too short buf for tlv (%d)\n", i);

"failed to parse phyerr tlv payload at byte %d\n", i


> +                       return;
> +               }
> +
> +               switch (tlv->tag) {
> +               case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
> +                       if (sizeof(*fftr) > tlv_len) {
> +                               ath10k_warn("too short fft report (%d)\n", i);

"failed to parse fft report at byte %d\n", i


> +                               return;
> +                       }
> +
> +                       fftr_len = tlv_len - sizeof(*fftr);
> +                       fftr = (struct phyerr_fft_report *)tlv_buf;
> +                       res = ath10k_process_fft(ar, event, fftr, fftr_len,
> +                                                tsf);
> +                       if (res)

+ ath10k_warn("failed to process fft report: %d\n", res)


[...]
> +int ath10k_vdev_spectral_configure(struct ath10k *ar,
> +                             const struct wmi_vdev_spectral_configure_arg *arg)

ath10k_wmi_vdev_spectral_configure


[...]
> +int ath10k_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
> +                               u32 enable)

ath10k_wmi_vdev_spectral_enable


[...]
> +struct wmi_vdev_spectral_configure_arg {
> +       u32 vdev_id;
> +       u32 scan_count;
> +       u32 scan_period;
> +       u32 scan_priority;
> +       u32 scan_fft_size;
> +       u32 scan_gc_ena;
> +       u32 scan_restart_ena;
> +       u32 scan_noise_floor_ref;
> +       u32 scan_init_delay;
> +       u32 scan_nb_tone_thr;
> +       u32 scan_str_bin_thr;
> +       u32 scan_wb_rpt_mode;
> +       u32 scan_rssi_rpt_mode;
> +       u32 scan_rssi_thr;
> +       u32 scan_pwr_format;
> +       u32 scan_rpt_mode;
> +       u32 scan_bin_scale;
> +       u32 scan_dBm_adj;
> +       u32 scan_chn_mask;

Some stuff isn't self-explanatory. I'd love to see some of these
fields documented to account for possible values (wb_rpt_mode?) and
units (init_delay?).


[...]
> +struct fft_sample_ath10k_ht20 {
> +       struct fft_sample_tlv tlv;
> +       u8 mhz;

A more suitable name would be "chan_width_mhz" I guess?


> +       __be16 freq1;
> +       __be16 freq2;
> +       __be16 noise;
> +       __be16 max_magnitude;
> +       __be16 total_gain_db;
> +       __be16 base_pwr_db;
> +       __be64 tsf;
> +       s8 max_index;
> +       u8 rssi;
> +       u8 relpwr_db;
> +       u8 avgpwr_db;
> +
> +       u8 data[SPECTRAL_ATH10K_HT20_NUM_BINS];

And as pointed out the size/count of bins is most likely not
bandwidth-dependant. It's just a matter of resolution configured with
fft_size + bin_scale. Maybe this should be a variable-sized array?


Generally this seems to be missing locking (does debugfs guarantee
serialized read/write calls?).


Micha?


From michal.kazior at tieto.com  Wed Jul 16 03:17:35 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 12:17:35 +0200
Subject: [PATCH v2] ath10k: fix Rx aggregation reordering
Message-ID: <1405505855-13741-1-git-send-email-michal.kazior@tieto.com>

Firmware doesn't perform Rx reordering so it is
left to the host driver to do that.

Use mac80211 to perform reordering instead of
re-inventing the wheel.

This fixes TCP throughput issues in some
environments.

Reported-by: Denton Gentry <denton.gentry at gmail.com>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
This depends on:

 * mac80211: fix Rx reordering with RX_FLAG_AMSDU_MORE
 * mac80211: add support for Rx reordering offloading

I'm still seeing some issues with TCP traffic.
Apparently firmware/hardware sometimes stalls Rx
for ~100ms and misses some aggregate frames. I
wasn't able to pinpoint what the problem is. The
more parallel TCP streams (iperf) the more often
stalls happen. UDP doesn't seem to trigger the Rx
stalls at all.


Notes:
    v2:
     * split addba/delba handling into separate functions [Kalle]
     * extend ampdu_action debug print (+vdev_id, +sta addr, +tid)

 drivers/net/wireless/ath/ath10k/htt_rx.c | 94 +++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/mac.c    | 33 +++++++++++
 drivers/net/wireless/ath/ath10k/txrx.c   |  3 +-
 drivers/net/wireless/ath/ath10k/txrx.h   |  1 +
 4 files changed, 127 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index eebc860..966bd4a 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -21,6 +21,7 @@
 #include "txrx.h"
 #include "debug.h"
 #include "trace.h"
+#include "mac.h"
 
 #include <linux/log2.h>
 
@@ -1422,6 +1423,86 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
 	}
 }
 
+static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
+{
+	struct htt_rx_addba *ev = &resp->rx_addba;
+	struct ath10k_peer *peer;
+	struct ath10k_vif *arvif;
+	u16 info0, tid, peer_id;
+
+	info0 = __le32_to_cpu(ev->info0);
+	tid = MS(info0, HTT_RX_BA_INFO0_TID);
+	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx addba tid %hu peer_id %hu size %hhu\n",
+		   tid, peer_id, ev->window_size);
+
+	spin_lock_bh(&ar->data_lock);
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer) {
+		ath10k_warn("received addba event for invalid peer_id: %hu\n",
+			    peer_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	arvif = ath10k_get_arvif(ar, peer->vdev_id);
+	if (!arvif) {
+		ath10k_warn("received addba event for invalid vdev_id: %u\n",
+			    peer->vdev_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx start rx ba session sta %pM tid %hu size %hhu\n",
+		   peer->addr, tid, ev->window_size);
+
+	ieee80211_start_rx_ba_session_offl(arvif->vif, peer->addr, tid);
+	spin_unlock_bh(&ar->data_lock);
+}
+
+static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
+{
+	struct htt_rx_addba *ev = &resp->rx_addba;
+	struct ath10k_peer *peer;
+	struct ath10k_vif *arvif;
+	u16 info0, tid, peer_id;
+
+	info0 = __le32_to_cpu(ev->info0);
+	tid = MS(info0, HTT_RX_BA_INFO0_TID);
+	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx delba tid %hu peer_id %hu\n",
+		   tid, peer_id);
+
+	spin_lock_bh(&ar->data_lock);
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer) {
+		ath10k_warn("received addba event for invalid peer_id: %hu\n",
+			    peer_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	arvif = ath10k_get_arvif(ar, peer->vdev_id);
+	if (!arvif) {
+		ath10k_warn("received addba event for invalid vdev_id: %u\n",
+			    peer->vdev_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx stop rx ba session sta %pM tid %hu\n",
+		   peer->addr, tid);
+
+	ieee80211_stop_rx_ba_session_offl(arvif->vif, peer->addr, tid);
+	spin_unlock_bh(&ar->data_lock);
+}
+
 void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct ath10k_htt *htt = &ar->htt;
@@ -1515,10 +1596,19 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 	case HTT_T2H_MSG_TYPE_STATS_CONF:
 		trace_ath10k_htt_stats(skb->data, skb->len);
 		break;
-	case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
 	case HTT_T2H_MSG_TYPE_RX_ADDBA:
+		ath10k_htt_rx_addba(ar, resp);
+		break;
 	case HTT_T2H_MSG_TYPE_RX_DELBA:
-	case HTT_T2H_MSG_TYPE_RX_FLUSH:
+		ath10k_htt_rx_delba(ar, resp);
+		break;
+	case HTT_T2H_MSG_TYPE_RX_FLUSH: {
+		/* Ignore this event because mac80211 takes care of Rx
+		 * aggregation reordering.
+		 */
+		break;
+	}
+	case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
 	default:
 		ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n",
 			   resp->hdr.msg_type);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b8314a5..24d5ac0 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4331,6 +4331,38 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	return 0;
 }
 
+int ath10k_ampdu_action(struct ieee80211_hw *hw,
+			struct ieee80211_vif *vif,
+			enum ieee80211_ampdu_mlme_action action,
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			u8 buf_size)
+{
+	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+
+	ath10k_dbg(ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
+		   arvif->vdev_id, sta->addr, tid, action);
+
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+	case IEEE80211_AMPDU_RX_STOP:
+		/* HTT AddBa/DelBa events trigger mac80211 Rx BA session
+		 * creation/removal. Do we need to verify this?
+		 */
+		return 0;
+	case IEEE80211_AMPDU_TX_START:
+	case IEEE80211_AMPDU_TX_STOP_CONT:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		/* Firmware offloads Tx aggregation entirely so deny mac80211
+		 * Tx aggregation requests.
+		 */
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
 static const struct ieee80211_ops ath10k_ops = {
 	.tx				= ath10k_tx,
 	.start				= ath10k_start,
@@ -4358,6 +4390,7 @@ static const struct ieee80211_ops ath10k_ops = {
 	.set_bitrate_mask		= ath10k_set_bitrate_mask,
 	.sta_rc_update			= ath10k_sta_rc_update,
 	.get_tsf			= ath10k_get_tsf,
+	.ampdu_action			= ath10k_ampdu_action,
 #ifdef CONFIG_PM
 	.suspend			= ath10k_suspend,
 	.resume				= ath10k_resume,
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 82669a7..f4fa22d 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -119,8 +119,7 @@ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
 	return NULL;
 }
 
-static struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar,
-						  int peer_id)
+struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
 {
 	struct ath10k_peer *peer;
 
diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h
index aee3e20..a90e09f 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.h
+++ b/drivers/net/wireless/ath/ath10k/txrx.h
@@ -24,6 +24,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
 
 struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
 				     const u8 *addr);
+struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id);
 int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id,
 				 const u8 *addr);
 int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id,
-- 
1.8.5.3



From michal.kazior at tieto.com  Wed Jul 16 04:19:00 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 13:19:00 +0200
Subject: [PATCH v3] ath10k: fix Rx aggregation reordering
In-Reply-To: <1405505855-13741-1-git-send-email-michal.kazior@tieto.com>
References: <1405505855-13741-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>

Firmware doesn't perform Rx reordering so it is
left to the host driver to do that.

Use mac80211 to perform reordering instead of
re-inventing the wheel.

This fixes TCP throughput issues in some
environments.

Reported-by: Denton Gentry <denton.gentry at gmail.com>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
This depends on:

 * mac80211: fix Rx reordering with RX_FLAG_AMSDU_MORE
 * mac80211: add support for Rx reordering offloading

I'm still seeing some issues with TCP traffic.
Apparently firmware/hardware sometimes stalls Rx
for ~100ms and misses some aggregate frames. I
wasn't able to pinpoint what the problem is. The
more parallel TCP streams (iperf) the more often
stalls happen. UDP doesn't seem to trigger the Rx
stalls at all.


Notes:
    v3:
     * make ath10k_ampdu_action() static
    
    v2:
     * split addba/delba handling into separate functions [Kalle]
     * extend ampdu_action debug print (+vdev_id, +sta addr, +tid)

 drivers/net/wireless/ath/ath10k/htt_rx.c | 94 +++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/mac.c    | 33 +++++++++++
 drivers/net/wireless/ath/ath10k/txrx.c   |  3 +-
 drivers/net/wireless/ath/ath10k/txrx.h   |  1 +
 4 files changed, 127 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index eebc860..966bd4a 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -21,6 +21,7 @@
 #include "txrx.h"
 #include "debug.h"
 #include "trace.h"
+#include "mac.h"
 
 #include <linux/log2.h>
 
@@ -1422,6 +1423,86 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
 	}
 }
 
+static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
+{
+	struct htt_rx_addba *ev = &resp->rx_addba;
+	struct ath10k_peer *peer;
+	struct ath10k_vif *arvif;
+	u16 info0, tid, peer_id;
+
+	info0 = __le32_to_cpu(ev->info0);
+	tid = MS(info0, HTT_RX_BA_INFO0_TID);
+	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx addba tid %hu peer_id %hu size %hhu\n",
+		   tid, peer_id, ev->window_size);
+
+	spin_lock_bh(&ar->data_lock);
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer) {
+		ath10k_warn("received addba event for invalid peer_id: %hu\n",
+			    peer_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	arvif = ath10k_get_arvif(ar, peer->vdev_id);
+	if (!arvif) {
+		ath10k_warn("received addba event for invalid vdev_id: %u\n",
+			    peer->vdev_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx start rx ba session sta %pM tid %hu size %hhu\n",
+		   peer->addr, tid, ev->window_size);
+
+	ieee80211_start_rx_ba_session_offl(arvif->vif, peer->addr, tid);
+	spin_unlock_bh(&ar->data_lock);
+}
+
+static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
+{
+	struct htt_rx_addba *ev = &resp->rx_addba;
+	struct ath10k_peer *peer;
+	struct ath10k_vif *arvif;
+	u16 info0, tid, peer_id;
+
+	info0 = __le32_to_cpu(ev->info0);
+	tid = MS(info0, HTT_RX_BA_INFO0_TID);
+	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx delba tid %hu peer_id %hu\n",
+		   tid, peer_id);
+
+	spin_lock_bh(&ar->data_lock);
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer) {
+		ath10k_warn("received addba event for invalid peer_id: %hu\n",
+			    peer_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	arvif = ath10k_get_arvif(ar, peer->vdev_id);
+	if (!arvif) {
+		ath10k_warn("received addba event for invalid vdev_id: %u\n",
+			    peer->vdev_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx stop rx ba session sta %pM tid %hu\n",
+		   peer->addr, tid);
+
+	ieee80211_stop_rx_ba_session_offl(arvif->vif, peer->addr, tid);
+	spin_unlock_bh(&ar->data_lock);
+}
+
 void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct ath10k_htt *htt = &ar->htt;
@@ -1515,10 +1596,19 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 	case HTT_T2H_MSG_TYPE_STATS_CONF:
 		trace_ath10k_htt_stats(skb->data, skb->len);
 		break;
-	case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
 	case HTT_T2H_MSG_TYPE_RX_ADDBA:
+		ath10k_htt_rx_addba(ar, resp);
+		break;
 	case HTT_T2H_MSG_TYPE_RX_DELBA:
-	case HTT_T2H_MSG_TYPE_RX_FLUSH:
+		ath10k_htt_rx_delba(ar, resp);
+		break;
+	case HTT_T2H_MSG_TYPE_RX_FLUSH: {
+		/* Ignore this event because mac80211 takes care of Rx
+		 * aggregation reordering.
+		 */
+		break;
+	}
+	case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
 	default:
 		ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n",
 			   resp->hdr.msg_type);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b8314a5..67bf8ed 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4331,6 +4331,38 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	return 0;
 }
 
+static int ath10k_ampdu_action(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       enum ieee80211_ampdu_mlme_action action,
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size)
+{
+	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+
+	ath10k_dbg(ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
+		   arvif->vdev_id, sta->addr, tid, action);
+
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+	case IEEE80211_AMPDU_RX_STOP:
+		/* HTT AddBa/DelBa events trigger mac80211 Rx BA session
+		 * creation/removal. Do we need to verify this?
+		 */
+		return 0;
+	case IEEE80211_AMPDU_TX_START:
+	case IEEE80211_AMPDU_TX_STOP_CONT:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		/* Firmware offloads Tx aggregation entirely so deny mac80211
+		 * Tx aggregation requests.
+		 */
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
 static const struct ieee80211_ops ath10k_ops = {
 	.tx				= ath10k_tx,
 	.start				= ath10k_start,
@@ -4358,6 +4390,7 @@ static const struct ieee80211_ops ath10k_ops = {
 	.set_bitrate_mask		= ath10k_set_bitrate_mask,
 	.sta_rc_update			= ath10k_sta_rc_update,
 	.get_tsf			= ath10k_get_tsf,
+	.ampdu_action			= ath10k_ampdu_action,
 #ifdef CONFIG_PM
 	.suspend			= ath10k_suspend,
 	.resume				= ath10k_resume,
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 82669a7..f4fa22d 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -119,8 +119,7 @@ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
 	return NULL;
 }
 
-static struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar,
-						  int peer_id)
+struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
 {
 	struct ath10k_peer *peer;
 
diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h
index aee3e20..a90e09f 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.h
+++ b/drivers/net/wireless/ath/ath10k/txrx.h
@@ -24,6 +24,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
 
 struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
 				     const u8 *addr);
+struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id);
 int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id,
 				 const u8 *addr);
 int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id,
-- 
1.8.5.3



From varkabhadram at gmail.com  Wed Jul 16 04:38:10 2014
From: varkabhadram at gmail.com (Varka Bhadram)
Date: Wed, 16 Jul 2014 17:08:10 +0530
Subject: [PATCH v3] ath10k: fix Rx aggregation reordering
In-Reply-To: <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
References: <1405505855-13741-1-git-send-email-michal.kazior@tieto.com>
 <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <53C66422.10702@gmail.com>

On 07/16/2014 04:49 PM, Michal Kazior wrote:

(...)

> +static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
> +{
> +	struct htt_rx_addba *ev = &resp->rx_addba;
> +	struct ath10k_peer *peer;
> +	struct ath10k_vif *arvif;
> +	u16 info0, tid, peer_id;
> +
> +	info0 = __le32_to_cpu(ev->info0);
> +	tid = MS(info0, HTT_RX_BA_INFO0_TID);
> +	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
> +
> +	ath10k_dbg(ATH10K_DBG_HTT,
> +		   "htt rx addba tid %hu peer_id %hu size %hhu\n",
> +		   tid, peer_id, ev->window_size);
> +
> +	spin_lock_bh(&ar->data_lock);
> +	peer = ath10k_peer_find_by_id(ar, peer_id);
> +	if (!peer) {
> +		ath10k_warn("received addba event for invalid peer_id: %hu\n",
> +			    peer_id);
> +		spin_unlock_bh(&ar->data_lock);
> +		return;
> +	}

Here my concern in amount of time holding the lock...

spin_lock_bh(&ar->data_lock);
peer = ath10k_peer_find_by_id(ar, peer_id);
if (!peer) {
	spin_unlock_bh(&ar->data_lock);
	ath10k_warn("received addba event for invalid peer_id: %hu\n",
		    peer_id);
	return;
}

No need to of putting the debug message inside the critical region...  :-)

> +
> +	arvif = ath10k_get_arvif(ar, peer->vdev_id);
> +	if (!arvif) {
> +		ath10k_warn("received addba event for invalid vdev_id: %u\n",
> +			    peer->vdev_id);
> +		spin_unlock_bh(&ar->data_lock);

Ditto

> +		return;
> +	}
> +
> +	ath10k_dbg(ATH10K_DBG_HTT,
> +		   "htt rx start rx ba session sta %pM tid %hu size %hhu\n",
> +		   peer->addr, tid, ev->window_size);
> +
> +	ieee80211_start_rx_ba_session_offl(arvif->vif, peer->addr, tid);
> +	spin_unlock_bh(&ar->data_lock);
> +}
> +
> +static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
> +{
> +	struct htt_rx_addba *ev = &resp->rx_addba;
> +	struct ath10k_peer *peer;
> +	struct ath10k_vif *arvif;
> +	u16 info0, tid, peer_id;
> +
> +	info0 = __le32_to_cpu(ev->info0);
> +	tid = MS(info0, HTT_RX_BA_INFO0_TID);
> +	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
> +
> +	ath10k_dbg(ATH10K_DBG_HTT,
> +		   "htt rx delba tid %hu peer_id %hu\n",
> +		   tid, peer_id);
> +
> +	spin_lock_bh(&ar->data_lock);
> +	peer = ath10k_peer_find_by_id(ar, peer_id);
> +	if (!peer) {
> +		ath10k_warn("received addba event for invalid peer_id: %hu\n",
> +			    peer_id);
> +		spin_unlock_bh(&ar->data_lock);
> +		return;

Ditto..

> +	}
> +
> +	arvif = ath10k_get_arvif(ar, peer->vdev_id);
> +	if (!arvif) {
> +		ath10k_warn("received addba event for invalid vdev_id: %u\n",
> +			    peer->vdev_id);
> +		spin_unlock_bh(&ar->data_lock);
> +		return;
> +	}
> +
> +	ath10k_dbg(ATH10K_DBG_HTT,
> +		   "htt rx stop rx ba session sta %pM tid %hu\n",
> +		   peer->addr, tid);
> +
> +	ieee80211_stop_rx_ba_session_offl(arvif->vif, peer->addr, tid);
> +	spin_unlock_bh(&ar->data_lock);
> +}
> +
>   void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
>   {
>   	struct ath10k_htt *htt = &ar->htt;
> @@ -1515,10 +1596,19 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
>   	case HTT_T2H_MSG_TYPE_STATS_CONF:
>   		trace_ath10k_htt_stats(skb->data, skb->len);
>   		break;
> -	case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
>   	case HTT_T2H_MSG_TYPE_RX_ADDBA:
> +		ath10k_htt_rx_addba(ar, resp);
> +		break;
>   	case HTT_T2H_MSG_TYPE_RX_DELBA:
> -	case HTT_T2H_MSG_TYPE_RX_FLUSH:
> +		ath10k_htt_rx_delba(ar, resp);
> +		break;
> +	case HTT_T2H_MSG_TYPE_RX_FLUSH: {
> +		/* Ignore this event because mac80211 takes care of Rx
> +		 * aggregation reordering.
> +		 */
> +		break;
> +	}
> +	case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
>   	default:
>   		ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n",
>   			   resp->hdr.msg_type);
> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
> index b8314a5..67bf8ed 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -4331,6 +4331,38 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
>   	return 0;
>   }
>   
> +static int ath10k_ampdu_action(struct ieee80211_hw *hw,
> +			       struct ieee80211_vif *vif,
> +			       enum ieee80211_ampdu_mlme_action action,
> +			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
> +			       u8 buf_size)
> +{
> +	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
> +
> +	ath10k_dbg(ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
> +		   arvif->vdev_id, sta->addr, tid, action);
> +
> +	switch (action) {
> +	case IEEE80211_AMPDU_RX_START:
> +	case IEEE80211_AMPDU_RX_STOP:
> +		/* HTT AddBa/DelBa events trigger mac80211 Rx BA session
> +		 * creation/removal. Do we need to verify this?
> +		 */
> +		return 0;
> +	case IEEE80211_AMPDU_TX_START:
> +	case IEEE80211_AMPDU_TX_STOP_CONT:
> +	case IEEE80211_AMPDU_TX_STOP_FLUSH:
> +	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
> +	case IEEE80211_AMPDU_TX_OPERATIONAL:
> +		/* Firmware offloads Tx aggregation entirely so deny mac80211
> +		 * Tx aggregation requests.
> +		 */
> +		break;

Instead of break here we can directly do: return -EOPNOTSUPP;

> +	}
> +
> +	return -EOPNOTSUPP;
> +}
> +

-- 
Regards,
Varka Bhadram.



From michal.kazior at tieto.com  Wed Jul 16 05:35:41 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 14:35:41 +0200
Subject: [PATCH v3] ath10k: fix Rx aggregation reordering
In-Reply-To: <53C66422.10702@gmail.com>
References: <1405505855-13741-1-git-send-email-michal.kazior@tieto.com>
 <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
 <53C66422.10702@gmail.com>
Message-ID: <CA+BoTQn8TYX4vDx=K4P5rE+LBXrrUL2q1E7GsiOpBj82QgRKsw@mail.gmail.com>

On 16 July 2014 13:38, Varka Bhadram <varkabhadram at gmail.com> wrote:
> On 07/16/2014 04:49 PM, Michal Kazior wrote:
>
> (...)
>
>
>> +static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
>> +{
>> +       struct htt_rx_addba *ev = &resp->rx_addba;
>> +       struct ath10k_peer *peer;
>> +       struct ath10k_vif *arvif;
>> +       u16 info0, tid, peer_id;
>> +
>> +       info0 = __le32_to_cpu(ev->info0);
>> +       tid = MS(info0, HTT_RX_BA_INFO0_TID);
>> +       peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
>> +
>> +       ath10k_dbg(ATH10K_DBG_HTT,
>> +                  "htt rx addba tid %hu peer_id %hu size %hhu\n",
>> +                  tid, peer_id, ev->window_size);
>> +
>> +       spin_lock_bh(&ar->data_lock);
>> +       peer = ath10k_peer_find_by_id(ar, peer_id);
>> +       if (!peer) {
>> +               ath10k_warn("received addba event for invalid peer_id:
>> %hu\n",
>> +                           peer_id);
>> +               spin_unlock_bh(&ar->data_lock);
>> +               return;
>> +       }
>
>
> Here my concern in amount of time holding the lock...
>
> spin_lock_bh(&ar->data_lock);
> peer = ath10k_peer_find_by_id(ar, peer_id);
> if (!peer) {
>         spin_unlock_bh(&ar->data_lock);
>
>         ath10k_warn("received addba event for invalid peer_id: %hu\n",
>                     peer_id);
>         return;
> }
>
> No need to of putting the debug message inside the critical region...  :-)

Sounds reasonable in this case as I'm not printing spinlock-protected values.


[...]
>>   +static int ath10k_ampdu_action(struct ieee80211_hw *hw,
>> +                              struct ieee80211_vif *vif,
>> +                              enum ieee80211_ampdu_mlme_action action,
>> +                              struct ieee80211_sta *sta, u16 tid, u16
>> *ssn,
>> +                              u8 buf_size)
>> +{
>> +       struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
>> +
>> +       ath10k_dbg(ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu
>> action %d\n",
>> +                  arvif->vdev_id, sta->addr, tid, action);
>> +
>> +       switch (action) {
>> +       case IEEE80211_AMPDU_RX_START:
>> +       case IEEE80211_AMPDU_RX_STOP:
>> +               /* HTT AddBa/DelBa events trigger mac80211 Rx BA session
>> +                * creation/removal. Do we need to verify this?
>> +                */
>> +               return 0;
>> +       case IEEE80211_AMPDU_TX_START:
>> +       case IEEE80211_AMPDU_TX_STOP_CONT:
>> +       case IEEE80211_AMPDU_TX_STOP_FLUSH:
>> +       case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
>> +       case IEEE80211_AMPDU_TX_OPERATIONAL:
>> +               /* Firmware offloads Tx aggregation entirely so deny
>> mac80211
>> +                * Tx aggregation requests.
>> +                */
>> +               break;
>
>
> Instead of break here we can directly do: return -EOPNOTSUPP;

True.


Thanks for review. I'll wait a bit more before I re-post v4 (although
there's no rush since the patch needs mac80211 patches to be applied
first).


Micha?


From michal.kazior at tieto.com  Wed Jul 16 05:41:27 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 14:41:27 +0200
Subject: [PATCH v3] ath10k: fix Rx aggregation reordering
In-Reply-To: <CA+BoTQn8TYX4vDx=K4P5rE+LBXrrUL2q1E7GsiOpBj82QgRKsw@mail.gmail.com>
References: <1405505855-13741-1-git-send-email-michal.kazior@tieto.com>
 <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
 <53C66422.10702@gmail.com>
 <CA+BoTQn8TYX4vDx=K4P5rE+LBXrrUL2q1E7GsiOpBj82QgRKsw@mail.gmail.com>
Message-ID: <CA+BoTQkk5oYS4JZ5a6W02rZ62AgxcHE76knS7QA2VfZDxYi2Jg@mail.gmail.com>

On 16 July 2014 14:35, Michal Kazior <michal.kazior at tieto.com> wrote:
> On 16 July 2014 13:38, Varka Bhadram <varkabhadram at gmail.com> wrote:
>> On 07/16/2014 04:49 PM, Michal Kazior wrote:
>>
>> (...)
>>
>>
>>> +static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
>>> +{
>>> +       struct htt_rx_addba *ev = &resp->rx_addba;
>>> +       struct ath10k_peer *peer;
>>> +       struct ath10k_vif *arvif;
>>> +       u16 info0, tid, peer_id;
>>> +
>>> +       info0 = __le32_to_cpu(ev->info0);
>>> +       tid = MS(info0, HTT_RX_BA_INFO0_TID);
>>> +       peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
>>> +
>>> +       ath10k_dbg(ATH10K_DBG_HTT,
>>> +                  "htt rx addba tid %hu peer_id %hu size %hhu\n",
>>> +                  tid, peer_id, ev->window_size);
>>> +
>>> +       spin_lock_bh(&ar->data_lock);
>>> +       peer = ath10k_peer_find_by_id(ar, peer_id);
>>> +       if (!peer) {
>>> +               ath10k_warn("received addba event for invalid peer_id:
>>> %hu\n",
>>> +                           peer_id);
>>> +               spin_unlock_bh(&ar->data_lock);
>>> +               return;
>>> +       }
>>
>>
>> Here my concern in amount of time holding the lock...
>>
>> spin_lock_bh(&ar->data_lock);
>> peer = ath10k_peer_find_by_id(ar, peer_id);
>> if (!peer) {
>>         spin_unlock_bh(&ar->data_lock);
>>
>>         ath10k_warn("received addba event for invalid peer_id: %hu\n",
>>                     peer_id);
>>         return;
>> }
>>
>> No need to of putting the debug message inside the critical region...  :-)
>
> Sounds reasonable in this case as I'm not printing spinlock-protected values.

..and I realized this isn't true upon hitting the send button.

The other print uses peer->vdev_id. The peer was acquired under a lock
and must not be used after the lock is released. It'll just look
confusing if I mix ordering of unlock/print in some cases so I'll
leave it as is.

(sorry for the noise)


Micha?


From michal.kazior at tieto.com  Wed Jul 16 06:01:39 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 15:01:39 +0200
Subject: [PATCH] ath10k: workaround boot issues with KVM/PCI-passthrough
Message-ID: <1405515699-32452-1-git-send-email-michal.kazior@tieto.com>

Apparently iomap writes that unmask CE irqs aren't
propagated properly sometimes. Before failing try
to poll for the control response message as it may
have been delivered without an interrupt.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/htc.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index e493db4..5fdc40d 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -546,7 +546,7 @@ static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc,
 
 int ath10k_htc_wait_target(struct ath10k_htc *htc)
 {
-	int status = 0;
+	int i, status = 0;
 	struct ath10k_htc_svc_conn_req conn_req;
 	struct ath10k_htc_svc_conn_resp conn_resp;
 	struct ath10k_htc_msg *msg;
@@ -556,10 +556,26 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 
 	status = wait_for_completion_timeout(&htc->ctl_resp,
 					     ATH10K_HTC_WAIT_TIMEOUT_HZ);
-	if (status <= 0) {
+	if (status == 0) {
+		/* Workaround: In some cases the PCI HIF doesn't
+		 * receive interrupt for the control response message
+		 * even if the buffer was completed. It is suspected
+		 * iomap writes unmasking PCI CE irqs aren't propagated
+		 * properly in KVM PCI-passthrough sometimes.
+		 */
+		ath10k_warn("failed to receive control response completion, polling..\n");
+
+		for (i = 0; i < CE_COUNT; i++)
+			ath10k_hif_send_complete_check(htc->ar, i, 1);
+
+		status = wait_for_completion_timeout(&htc->ctl_resp,
+					ATH10K_HTC_WAIT_TIMEOUT_HZ);
+
 		if (status == 0)
 			status = -ETIMEDOUT;
+	}
 
+	if (status < 0) {
 		ath10k_err("ctl_resp never came in (%d)\n", status);
 		return status;
 	}
-- 
1.8.5.3



From michal.kazior at tieto.com  Wed Jul 16 06:21:13 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 15:21:13 +0200
Subject: [RFC/RFT 2/2] ath10k: don't start monitor vdev for promisc
In-Reply-To: <1405516873-26411-1-git-send-email-michal.kazior@tieto.com>
References: <1405516873-26411-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1405516873-26411-2-git-send-email-michal.kazior@tieto.com>

ath10k doesn't apply any extra rx filters so
there's no need to start monitor vdev for
promiscuous mode.

This fixes crashes with 4addr station interface
bridging and some very rare crashes of AP
interfaces with bridging as well.

Reported-by: Sven Schnelle <svens at stackframe.org>
Reported-by: Vu Hai NGUYEN <vh.nguyen at actiasodielec.fr>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h | 1 -
 drivers/net/wireless/ath/ath10k/mac.c  | 9 +--------
 2 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 83a5fa9..d5cba97 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -432,7 +432,6 @@ struct ath10k {
 	struct cfg80211_chan_def chandef;
 
 	int free_vdev_map;
-	bool promisc;
 	bool monitor;
 	int monitor_vdev_id;
 	bool monitor_started;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 2a1c710..f9ab878 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -688,7 +688,7 @@ static int ath10k_monitor_recalc(struct ath10k *ar)
 {
 	bool should_start;
 
-	should_start = ar->promisc || ar->monitor ||
+	should_start = ar->monitor ||
 		       test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
 
 	ath10k_dbg(ATH10K_DBG_MAC,
@@ -2308,7 +2308,6 @@ void ath10k_halt(struct ath10k *ar)
 	lockdep_assert_held(&ar->conf_mutex);
 
 	clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-	ar->promisc = false;
 	ar->monitor = false;
 
 	if (ar->monitor_started)
@@ -2917,7 +2916,6 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
 				    u64 multicast)
 {
 	struct ath10k *ar = hw->priv;
-	int ret;
 
 	mutex_lock(&ar->conf_mutex);
 
@@ -2925,11 +2923,6 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
 	*total_flags &= SUPPORTED_FILTERS;
 	ar->filter_flags = *total_flags;
 
-	ar->promisc = !!(ar->filter_flags & FIF_PROMISC_IN_BSS);
-	ret = ath10k_monitor_recalc(ar);
-	if (ret)
-		ath10k_warn("failed to recalc montior: %d\n", ret);
-
 	mutex_unlock(&ar->conf_mutex);
 }
 
-- 
1.8.5.3



From michal.kazior at tieto.com  Wed Jul 16 06:21:12 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 15:21:12 +0200
Subject: [RFC/RFT 1/2] ath10k: fix monitor start/stop sequences
Message-ID: <1405516873-26411-1-git-send-email-michal.kazior@tieto.com>

Fix some cases where monitor start failure left
the driver in a confused state.

This also makes the monitor code simpler.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 117 +++++++++++++---------------------
 1 file changed, 45 insertions(+), 72 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b8314a5..2a1c710 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -492,19 +492,6 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
 	return 0;
 }
 
-static bool ath10k_monitor_is_enabled(struct ath10k *ar)
-{
-	lockdep_assert_held(&ar->conf_mutex);
-
-	ath10k_dbg(ATH10K_DBG_MAC,
-		   "mac monitor refs: promisc %d monitor %d cac %d\n",
-		   ar->promisc, ar->monitor,
-		   test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags));
-
-	return ar->promisc || ar->monitor ||
-	       test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-}
-
 static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
 {
 	struct cfg80211_chan_def *chandef = &ar->chandef;
@@ -654,16 +641,6 @@ static int ath10k_monitor_start(struct ath10k *ar)
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	if (!ath10k_monitor_is_enabled(ar)) {
-		ath10k_warn("trying to start monitor with no references\n");
-		return 0;
-	}
-
-	if (ar->monitor_started) {
-		ath10k_dbg(ATH10K_DBG_MAC, "mac monitor already started\n");
-		return 0;
-	}
-
 	ret = ath10k_monitor_vdev_create(ar);
 	if (ret) {
 		ath10k_warn("failed to create monitor vdev: %d\n", ret);
@@ -683,34 +660,48 @@ static int ath10k_monitor_start(struct ath10k *ar)
 	return 0;
 }
 
-static void ath10k_monitor_stop(struct ath10k *ar)
+static int ath10k_monitor_stop(struct ath10k *ar)
 {
 	int ret;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	if (ath10k_monitor_is_enabled(ar)) {
-		ath10k_dbg(ATH10K_DBG_MAC,
-			   "mac monitor will be stopped later\n");
-		return;
-	}
-
-	if (!ar->monitor_started) {
-		ath10k_dbg(ATH10K_DBG_MAC,
-			   "mac monitor probably failed to start earlier\n");
-		return;
-	}
-
 	ret = ath10k_monitor_vdev_stop(ar);
-	if (ret)
+	if (ret) {
 		ath10k_warn("failed to stop monitor vdev: %d\n", ret);
+		return ret;
+	}
 
 	ret = ath10k_monitor_vdev_delete(ar);
-	if (ret)
+	if (ret) {
 		ath10k_warn("failed to delete monitor vdev: %d\n", ret);
+		return ret;
+	}
 
 	ar->monitor_started = false;
 	ath10k_dbg(ATH10K_DBG_MAC, "mac monitor stopped\n");
+
+	return 0;
+}
+
+static int ath10k_monitor_recalc(struct ath10k *ar)
+{
+	bool should_start;
+
+	should_start = ar->promisc || ar->monitor ||
+		       test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+
+	ath10k_dbg(ATH10K_DBG_MAC,
+		   "mac monitor recalc started? %d should? %d\n",
+		   ar->monitor_started, should_start);
+
+	if (should_start == ar->monitor_started)
+		return 0;
+
+	if (should_start)
+		return ath10k_monitor_start(ar);
+	else
+		return ath10k_monitor_stop(ar);
 }
 
 static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
@@ -741,7 +732,7 @@ static int ath10k_start_cac(struct ath10k *ar)
 
 	set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
 
-	ret = ath10k_monitor_start(ar);
+	ret = ath10k_monitor_recalc(ar);
 	if (ret) {
 		ath10k_warn("failed to start monitor (cac): %d\n", ret);
 		clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
@@ -2316,12 +2307,12 @@ void ath10k_halt(struct ath10k *ar)
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	if (ath10k_monitor_is_enabled(ar)) {
-		clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-		ar->promisc = false;
-		ar->monitor = false;
+	clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+	ar->promisc = false;
+	ar->monitor = false;
+
+	if (ar->monitor_started)
 		ath10k_monitor_stop(ar);
-	}
 
 	del_timer_sync(&ar->scan.timeout);
 	ath10k_reset_scan((unsigned long)ar);
@@ -2574,7 +2565,7 @@ static void ath10k_config_chan(struct ath10k *ar)
 	/* First stop monitor interface. Some FW versions crash if there's a
 	 * lone monitor interface. */
 	if (ar->monitor_started)
-		ath10k_monitor_vdev_stop(ar);
+		ath10k_monitor_stop(ar);
 
 	list_for_each_entry(arvif, &ar->arvifs, list) {
 		if (!arvif->is_started)
@@ -2619,8 +2610,7 @@ static void ath10k_config_chan(struct ath10k *ar)
 		}
 	}
 
-	if (ath10k_monitor_is_enabled(ar))
-		ath10k_monitor_vdev_start(ar, ar->monitor_vdev_id);
+	ath10k_monitor_recalc(ar);
 }
 
 static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
@@ -2675,19 +2665,10 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
 		ath10k_config_ps(ar);
 
 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
-		if (conf->flags & IEEE80211_CONF_MONITOR && !ar->monitor) {
-			ar->monitor = true;
-			ret = ath10k_monitor_start(ar);
-			if (ret) {
-				ath10k_warn("failed to start monitor (config): %d\n",
-					    ret);
-				ar->monitor = false;
-			}
-		} else if (!(conf->flags & IEEE80211_CONF_MONITOR) &&
-			   ar->monitor) {
-			ar->monitor = false;
-			ath10k_monitor_stop(ar);
-		}
+		ar->monitor = conf->flags & IEEE80211_CONF_MONITOR;
+		ret = ath10k_monitor_recalc(ar);
+		if (ret)
+			ath10k_warn("failed to recalc monitor: %d\n", ret);
 	}
 
 	mutex_unlock(&ar->conf_mutex);
@@ -2944,18 +2925,10 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
 	*total_flags &= SUPPORTED_FILTERS;
 	ar->filter_flags = *total_flags;
 
-	if (ar->filter_flags & FIF_PROMISC_IN_BSS && !ar->promisc) {
-		ar->promisc = true;
-		ret = ath10k_monitor_start(ar);
-		if (ret) {
-			ath10k_warn("failed to start monitor (promisc): %d\n",
-				    ret);
-			ar->promisc = false;
-		}
-	} else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) && ar->promisc) {
-		ar->promisc = false;
-		ath10k_monitor_stop(ar);
-	}
+	ar->promisc = !!(ar->filter_flags & FIF_PROMISC_IN_BSS);
+	ret = ath10k_monitor_recalc(ar);
+	if (ret)
+		ath10k_warn("failed to recalc montior: %d\n", ret);
 
 	mutex_unlock(&ar->conf_mutex);
 }
-- 
1.8.5.3



From michal.kazior at tieto.com  Wed Jul 16 06:41:13 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 16 Jul 2014 15:41:13 +0200
Subject: [PATCH] ath10k: prevent some tx flushing failures
Message-ID: <1405518073-14513-1-git-send-email-michal.kazior@tieto.com>

Firmware could request inspection of some
submitted tx requests. Since the callback wasn't
implemented it was possible to bleed tx msdu_ids
which could translate to tx flushing timeouts.

There's nothing ath10k can do to help firmware
with tx processing now so just report all tx
frames as already inspected to prevent firmware
from sending up inspection events and force it to
report regular tx completion indications with
discard status.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 7 +++++++
 drivers/net/wireless/ath/ath10k/htt_tx.c | 6 ++++++
 2 files changed, 13 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index eebc860..318efc3 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1516,6 +1516,13 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 		trace_ath10k_htt_stats(skb->data, skb->len);
 		break;
 	case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
+		/* Firmware can return tx frames if it's unable to fully
+		 * process them and suspects host may be able to fix it. ath10k
+		 * sends all tx frames as already inspected so this shouldn't
+		 * happen unless fw has a bug.
+		 */
+		ath10k_warn("received an unexpected htt tx inspect event\n");
+		break;
 	case HTT_T2H_MSG_TYPE_RX_ADDBA:
 	case HTT_T2H_MSG_TYPE_RX_DELBA:
 	case HTT_T2H_MSG_TYPE_RX_FLUSH:
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index accb6b4..8b27bfc 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -531,6 +531,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
 	flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
 	flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
 
+	/* Prevent firmware from sending up tx inspection requests. There's
+	 * nothing ath10k can do with frames requested for inspection so force
+	 * it to simply rely a regular tx completion with discard status.
+	 */
+	flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;
+
 	skb_cb->htt.txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
 	skb_cb->htt.txbuf->cmd_tx.flags0 = flags0;
 	skb_cb->htt.txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
-- 
1.8.5.3



From sven at narfation.org  Wed Jul 16 07:35:41 2014
From: sven at narfation.org (Sven Eckelmann)
Date: Wed, 16 Jul 2014 16:35:41 +0200
Subject: [RFC 2/2] ath10k: add spectral scan feature
In-Reply-To: <CA+BoTQm1i2UoTtPBf7Z3QLQDBs_1uXwdG8gYOkP556+a7AqcpQ@mail.gmail.com>
References: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
 <1405441966-32681-3-git-send-email-sw@simonwunderlich.de>
 <CA+BoTQm1i2UoTtPBf7Z3QLQDBs_1uXwdG8gYOkP556+a7AqcpQ@mail.gmail.com>
Message-ID: <3551054.tVFpeBPdYt@bentobox>

On Wednesday 16 July 2014 11:30:12 Michal Kazior wrote:
> > +static void ath_debug_send_fft_sample(struct ath10k *ar,
> > +                                     struct fft_sample_tlv
> > *fft_sample_tlv) +{
> 
> Why ath_debug_... instead of ath10k_debug_.. ?
> 
> 
> [...]

Will be modified.

> 
> > +static int ath_get_spectral_vdevid(struct ath10k *ar)
> 
> ath_get_..? Shouldn't this be ath10k_get?
> 
> > +{
> > +       struct ath10k_vif *arvif;
> > +
> > +       if (list_empty(&ar->arvifs))
> > +               return -ENODEV;
> > +
> > +       arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list);
> > +       return arvif->vdev_id;
> > +}
> 
> No locks? Access to arvifs must be protected with conf_mutex.

Will be handled by the caller and lockdep_assert will be added to this 
function

> 
> What happens when an interface is removed without spectral scan being
> stopped?

This is a question for the QCA firmware guys.

> > +int ath10k_spectral_scan_config(struct ath10k *ar, enum spectral_mode
> > mode) +{
> > +       int count, ret;
> 
> We tend to use `res` in ath10k.

Thanks, will be changed. But actually, I found a lot of ret stuff in the 
ath10k code.

[...]
> + ath10k_warn("failed to configure spectral scan: %d\n", ret);
[...]
> "failed to parse phyerr tlv header at byte %d\n", i
[...]
> "failed to parse phyerr tlv payload at byte %d\n", i
[...]
> "failed to parse fft report at byte %d\n", i
[...]
> + ath10k_warn("failed to process fft report: %d\n", res)

Ok, warning messages will be modified.

> > +int ath10k_vdev_spectral_configure(struct ath10k *ar,
> > +                             const struct wmi_vdev_spectral_configure_arg
> > *arg)
> ath10k_wmi_vdev_spectral_configure
[...]
> > +int ath10k_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32
> > trigger, +                               u32 enable)
> 
> ath10k_wmi_vdev_spectral_enable

Ok, will be renamed.

> [...]
> > +struct wmi_vdev_spectral_configure_arg {
> > +       u32 vdev_id;
> > +       u32 scan_count;
> > +       u32 scan_period;
> > +       u32 scan_priority;
> > +       u32 scan_fft_size;
> > +       u32 scan_gc_ena;
> > +       u32 scan_restart_ena;
> > +       u32 scan_noise_floor_ref;
> > +       u32 scan_init_delay;
> > +       u32 scan_nb_tone_thr;
> > +       u32 scan_str_bin_thr;
> > +       u32 scan_wb_rpt_mode;
> > +       u32 scan_rssi_rpt_mode;
> > +       u32 scan_rssi_thr;
> > +       u32 scan_pwr_format;
> > +       u32 scan_rpt_mode;
> > +       u32 scan_bin_scale;
> > +       u32 scan_dBm_adj;
> > +       u32 scan_chn_mask;
> 
> Some stuff isn't self-explanatory. I'd love to see some of these
> fields documented to account for possible values (wb_rpt_mode?) and
> units (init_delay?).

Sorry, I got no documentation to anything. So I cannot provide one to you. 
Maybe you can get it easier than me.

> [...]
> 
> > +struct fft_sample_ath10k_ht20 {
> > +       struct fft_sample_tlv tlv;
> > +       u8 mhz;
> 
> A more suitable name would be "chan_width_mhz" I guess?

Ok,

> > +       __be16 freq1;
> > +       __be16 freq2;
> > +       __be16 noise;
> > +       __be16 max_magnitude;
> > +       __be16 total_gain_db;
> > +       __be16 base_pwr_db;
> > +       __be64 tsf;
> > +       s8 max_index;
> > +       u8 rssi;
> > +       u8 relpwr_db;
> > +       u8 avgpwr_db;
> > +
> > +       u8 data[SPECTRAL_ATH10K_HT20_NUM_BINS];
> 
> And as pointed out the size/count of bins is most likely not
> bandwidth-dependant. It's just a matter of resolution configured with
> fft_size + bin_scale. Maybe this should be a variable-sized array?

Ok, bin_scale didn't make a difference in my tests (I've just repeated them). 
But 2 ** (fft_size - 1) seems to be relevant. We have to change the format 
accordingly.

But currently we don't see any change in the bandwidth (20MHz/40MHz) for the 
different bin numbers. This has to be checked later in detail.

Kind regards,
	Sven


From greearb at candelatech.com  Wed Jul 16 08:28:50 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 16 Jul 2014 08:28:50 -0700
Subject: [RFC/RFT 2/2] ath10k: don't start monitor vdev for promisc
In-Reply-To: <1405516873-26411-2-git-send-email-michal.kazior@tieto.com>
References: <1405516873-26411-1-git-send-email-michal.kazior@tieto.com>
 <1405516873-26411-2-git-send-email-michal.kazior@tieto.com>
Message-ID: <53C69A32.3090305@candelatech.com>

On 07/16/2014 06:21 AM, Michal Kazior wrote:
> ath10k doesn't apply any extra rx filters so
> there's no need to start monitor vdev for
> promiscuous mode.
>
> This fixes crashes with 4addr station interface
> bridging and some very rare crashes of AP
> interfaces with bridging as well.

Ahh, I was just working on some related hack-arounds to make sure
I left a vdev slot open for the monitor interface in case some poor
person started a sniffer on an interface and made it go promisc...

With this patch, I can be sure monitor interfaces will not
be automatically created without explicit user request?

Any idea if it will be a problem to apply this to what is
effectively a 3.15 kernel?

Thanks,
Ben

-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From Bart.Jooris at intec.ugent.be  Wed Jul 16 09:01:11 2014
From: Bart.Jooris at intec.ugent.be (Bart Jooris)
Date: Wed, 16 Jul 2014 18:01:11 +0200
Subject: Throughput is very low
In-Reply-To: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
Message-ID: <53C6A1C7.5060004@intec.ugent.be>

Dear Mamum,

On 07/09/2014 04:22 PM, Mamun Abu-Tair wrote:
> Dear all,
> I am trying to do throughput test with copmex AC cards Model (WLE900VX 7AA) .,using hostapd running on the server and  one client.
I have some cards with the same label. Hostapd on the server, on the 
station we use wpa_supplicant.
>
> I used Kalle sitting for the hostapd. However, the maximum throughput i can get is around 70Mbit/s which is far away from the throughput achieved by many users (UDP traffic).
In a setup with those cards we can observe a UDP throughput of approx. 
640Mbps.

>
> I have notice that Bit Rate keeps fixed 6 Mb/s . and it dose not responding to any commands to change it.
While running iperf client on the station I can also retrieve the Tx 
bitrate of 6Mbps with both iwconfig and 'iw wlanX station dump'. Version 
of iw has some impact on the output too, I have version 3.15.  I don't 
know a tool which shows the right info on the transmitting node...
But a third node which is configured as a sniffer shows Tx bitrate of 
1299.99Mbps :-)

>
> The machines used:
>   Ubuntu 12.04, Kerenl 3.16 , updated regulatory to cover 80Mhz channels , and the latest  firmware
Our nodes are also running 12.04 but still with the default kernel 
3.11.0-15-generic.
dmesg | grep qca98 shows
[    4.594975] ath10k: qca988x hw2.0 (0x4100016c) fw 10.1.467.2-1 api 2 
htt 2.1
Further, as Kalle suggested, we installed the ath10k driver from 
backports-3.15.1-1.

Best regards,

Bart

-- 
Bart Jooris
Department of Information Technology
Internet Based Communication Networks and Services (IBCN)
Ghent University - iMinds
Gaston Crommenlaan 8 (Bus 201), B-9050 Gent, Belgium
E-mail: bart.jooris at intec.UGent.be
M: +32 474 59 53 42
Tel. +32 9 33 14900
Fax +32 9 33 14899



From michal.kazior at tieto.com  Wed Jul 16 22:15:07 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 17 Jul 2014 07:15:07 +0200
Subject: [RFC/RFT 2/2] ath10k: don't start monitor vdev for promisc
In-Reply-To: <53C69A32.3090305@candelatech.com>
References: <1405516873-26411-1-git-send-email-michal.kazior@tieto.com>
 <1405516873-26411-2-git-send-email-michal.kazior@tieto.com>
 <53C69A32.3090305@candelatech.com>
Message-ID: <CA+BoTQ=X6GZLYmztehWp=gi6JHWZAJrOnvtB-HjbTqGfwUR4eA@mail.gmail.com>

On 16 July 2014 17:28, Ben Greear <greearb at candelatech.com> wrote:
> On 07/16/2014 06:21 AM, Michal Kazior wrote:
>>
>> ath10k doesn't apply any extra rx filters so
>> there's no need to start monitor vdev for
>> promiscuous mode.
>>
>> This fixes crashes with 4addr station interface
>> bridging and some very rare crashes of AP
>> interfaces with bridging as well.
>
>
> Ahh, I was just working on some related hack-arounds to make sure
> I left a vdev slot open for the monitor interface in case some poor
> person started a sniffer on an interface and made it go promisc...
>
> With this patch, I can be sure monitor interfaces will not
> be automatically created without explicit user request?

I'm not sure if I understand you correctly, but:

With this patch monitor vdev will be created and started only if there
is at least one monitor interface up and running or CAC is in
progress. Promiscuous mode does not change driver state at all. IOW if
you start tcpdump on a wlan0 (station iftype) or add wlan0 (ap iftype,
sta iftype) to a bridge then monitor vdev will not be created. You
have to iw wlan0 interface add mon type monitor && ip link set mon up
to start monitor vdev. From then on you can tcpdump or tcpdump -p on
mon to sniff everything that the card sees on the air.


> Any idea if it will be a problem to apply this to what is
> effectively a 3.15 kernel?

Hmm.. I guess it should apply. This depends on some earlier monitor
clean up patches but I can't remember when those were merged.


Micha?


From michal.kazior at tieto.com  Wed Jul 16 22:21:21 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 17 Jul 2014 07:21:21 +0200
Subject: Throughput is very low
In-Reply-To: <53C6A1C7.5060004@intec.ugent.be>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
Message-ID: <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>

On 16 July 2014 18:01, Bart Jooris <Bart.Jooris at intec.ugent.be> wrote:
> On 07/09/2014 04:22 PM, Mamun Abu-Tair wrote:
[...]
>> I have notice that Bit Rate keeps fixed 6 Mb/s . and it dose not
>> responding to any commands to change it.
>
> While running iperf client on the station I can also retrieve the Tx bitrate
> of 6Mbps with both iwconfig and 'iw wlanX station dump'. Version of iw has
> some impact on the output too, I have version 3.15.  I don't know a tool
> which shows the right info on the transmitting node...
> But a third node which is configured as a sniffer shows Tx bitrate of
> 1299.99Mbps :-)

The 6mbps tx rate reporting is due to firmware limitation.

You might want to check
/sys/kernel/debug/ieee80211/phyX/ath10k/fw_stats (replace phyX with
according phy of your ath10k device) instead.


Micha?


From michal.kazior at tieto.com  Wed Jul 16 22:34:05 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 17 Jul 2014 07:34:05 +0200
Subject: [RFC 2/2] ath10k: add spectral scan feature
In-Reply-To: <3551054.tVFpeBPdYt@bentobox>
References: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
 <1405441966-32681-3-git-send-email-sw@simonwunderlich.de>
 <CA+BoTQm1i2UoTtPBf7Z3QLQDBs_1uXwdG8gYOkP556+a7AqcpQ@mail.gmail.com>
 <3551054.tVFpeBPdYt@bentobox>
Message-ID: <CA+BoTQkmG2t1HkF=C6BZC18XjJzuwF3EpxEh-tiNct_BnyP62A@mail.gmail.com>

On 16 July 2014 16:35, Sven Eckelmann <sven at narfation.org> wrote:
> On Wednesday 16 July 2014 11:30:12 Michal Kazior wrote:
[...]
>>
>> What happens when an interface is removed without spectral scan being
>> stopped?
>
> This is a question for the QCA firmware guys.

Not really. My problems is this:
 - have 2 interfaces (vdev 0 and vdev 1)
 - start spectral (using vdev 0 which happens to be the first one)
 - remove 1 interface (vdev 0)

Now spectral scan on vdev 0 is not stopped and if you request to stop
it you effectively call spectral commands with vdev 1 (the other
interface which is the only one left). Yuck. I don't even want to know
how firmware (or different versions and branches of it) handle this
clumsiness.


>> > +int ath10k_spectral_scan_config(struct ath10k *ar, enum spectral_mode
>> > mode) +{
>> > +       int count, ret;
>>
>> We tend to use `res` in ath10k.
>
> Thanks, will be changed. But actually, I found a lot of ret stuff in the
> ath10k code.

Ah, sorry. You're right. I had a brain fart. `ret` is good.


[...]
>> > +       __be16 freq1;
>> > +       __be16 freq2;
>> > +       __be16 noise;
>> > +       __be16 max_magnitude;
>> > +       __be16 total_gain_db;
>> > +       __be16 base_pwr_db;
>> > +       __be64 tsf;
>> > +       s8 max_index;
>> > +       u8 rssi;
>> > +       u8 relpwr_db;
>> > +       u8 avgpwr_db;
>> > +
>> > +       u8 data[SPECTRAL_ATH10K_HT20_NUM_BINS];
>>
>> And as pointed out the size/count of bins is most likely not
>> bandwidth-dependant. It's just a matter of resolution configured with
>> fft_size + bin_scale. Maybe this should be a variable-sized array?
>
> Ok, bin_scale didn't make a difference in my tests (I've just repeated them).
> But 2 ** (fft_size - 1) seems to be relevant. We have to change the format
> accordingly.
>
> But currently we don't see any change in the bandwidth (20MHz/40MHz) for the
> different bin numbers. This has to be checked later in detail.

Yes. Apparently number of bins does *not* change with bandwidth but in
that case I'm guessing bin data does refer to the given bandwidth
which implies different bandwidths end up with different bin data
*resolution*.


Micha?


From vh.nguyen at actiasodielec.fr  Thu Jul 17 03:40:01 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Thu, 17 Jul 2014 12:40:01 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>,
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>

Hi all,
I'm using ath10k with official firmware (10.1, 467-2-1), my module of wifi is Compex WLE900VX.
In theory MCS9 should give better rate than MCS 7.
But when running test with Iperf, I notice that if I force rate (using command "iw") to MCS9 or MCS8, 
the rate result from iperf are always lower than MCS 7 (even NSS1,2 or 3). 
Though I check RX rate report from "iw station dump" and it matches with the rate that I want to force.
You can see in the attached file a report of my test.
Any one has done the test and get better rate in MCS9 than in MCS7 with this wifi module ???

PS: The rate increases normally from MCS1 to MCS6.
Thanks,
NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE

-------------- next part --------------
A non-text attachment was scrubbed...
Name: Selection_004.png
Type: image/png
Size: 15261 bytes
Desc: Selection_004.png
URL: <http://lists.infradead.org/pipermail/ath10k/attachments/20140717/7bb15faa/attachment-0001.png>

From bartosz.markowski at tieto.com  Thu Jul 17 03:53:46 2014
From: bartosz.markowski at tieto.com (Bartosz Markowski)
Date: Thu, 17 Jul 2014 12:53:46 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
Message-ID: <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>

On 17 July 2014 12:40, Vu Hai NGUYEN <vh.nguyen at actiasodielec.fr> wrote:
> Hi all,
> I'm using ath10k with official firmware (10.1, 467-2-1), my module of wifi is Compex WLE900VX.
> In theory MCS9 should give better rate than MCS 7.
> But when running test with Iperf, I notice that if I force rate (using command "iw") to MCS9 or MCS8,
> the rate result from iperf are always lower than MCS 7 (even NSS1,2 or 3).
> Though I check RX rate report from "iw station dump" and it matches with the rate that I want to force.
> You can see in the attached file a report of my test.
> Any one has done the test and get better rate in MCS9 than in MCS7 with this wifi module ???

Did you use cables or measured OTA? What platform it is? Did you use
hostapd? Is it AP mode (bridge)?
(You did not provide basically any details on what exacly you've measured).

In open AP mode (bridge), CUS223 HW (not WLE900VX however) and on
AP135 platform (customized openwrt SW + bleeding edge of
ath10k/wireless subsystem souces - private backports tarball).. for
UDP (last time I measured) I have around 820Mpbs for UCP both ways and
720Mbps TCP.

-Bartosz


From michal.kazior at tieto.com  Thu Jul 17 03:57:09 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 17 Jul 2014 12:57:09 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
Message-ID: <CA+BoTQmENGOcdWTGDU6By-4sXu2o9WNzTuizD=+_bDK14miWqg@mail.gmail.com>

On 17 July 2014 12:40, Vu Hai NGUYEN <vh.nguyen at actiasodielec.fr> wrote:
> Hi all,

Hi,


> I'm using ath10k with official firmware (10.1, 467-2-1), my module of wifi is Compex WLE900VX.
> In theory MCS9 should give better rate than MCS 7.
> But when running test with Iperf, I notice that if I force rate (using command "iw") to MCS9 or MCS8,
> the rate result from iperf are always lower than MCS 7 (even NSS1,2 or 3).
> Though I check RX rate report from "iw station dump" and it matches with the rate that I want to force.
> You can see in the attached file a report of my test.
> Any one has done the test and get better rate in MCS9 than in MCS7 with this wifi module ???

The higher the MCS rate the more symbols are packed up per baud which
means it is more susceptible to interference and corruption.

You probably don't have an environment clean enough to pull off MCS8
and MCS9 and you end up with a lot of retransmissions.

If you're sure you have a clean environment then try putting your
devices (or them antenna) at different angles against each other and
different distances.


Micha?


From ma86 at st-andrews.ac.uk  Thu Jul 17 04:34:41 2014
From: ma86 at st-andrews.ac.uk (Mamun Abu-Tair)
Date: Thu, 17 Jul 2014 12:34:41 +0100
Subject: Fwd: Throughput is very low
References: <2E79DF84-6D1A-4EEB-88AA-19A6F1860289@st-andrews.ac.uk>
Message-ID: <22BBE3DA-7977-455A-B97D-AD24773B67C3@st-andrews.ac.uk>

Sorry forget to CC the ath10k mailing list
Begin forwarded message:

> From: Mamun Abu-Tair <ma86 at st-andrews.ac.uk>
> Subject: Re: Throughput is very low
> Date: 17 July 2014 12:21:27 BST
> To: Bart.Jooris at intec.ugent.be
> 
> Dear Bart, 
> Many thanks for your reply. 
> 
> On 16 Jul 2014, at 17:01, Bart Jooris <Bart.Jooris at intec.ugent.be> wrote:
> 
>> Dear Mamum,
>> 
>> On 07/09/2014 04:22 PM, Mamun Abu-Tair wrote:
>>> Dear all,
>>> I am trying to do throughput test with copmex AC cards Model (WLE900VX 7AA) .,using hostapd running on the server and  one client.
>> I have some cards with the same label. Hostapd on the server, on the station we use wpa_supplicant.
> 
> which version of hostapd you are using ?
> 
> 
>>> 
>>> I used Kalle sitting for the hostapd. However, the maximum throughput i can get is around 70Mbit/s which is far away from the throughput achieved by many users (UDP traffic).
>> In a setup with those cards we can observe a UDP throughput of approx. 640Mbps.
>> 
>>> 
>>> I have notice that Bit Rate keeps fixed 6 Mb/s . and it dose not responding to any commands to change it.
>> While running iperf client on the station I can also retrieve the Tx bitrate of 6Mbps with both iwconfig and 'iw wlanX station dump'. Version of iw has some impact on the output too, I have version 3.15.  I don't know a tool which shows the right info on the transmitting node...
>> But a third node which is configured as a sniffer shows Tx bitrate of 1299.99Mbps :-)
>> 
>>> 
>>> The machines used:
>>> Ubuntu 12.04, Kerenl 3.16 , updated regulatory to cover 80Mhz channels , and the latest  firmware
>> Our nodes are also running 12.04 but still with the default kernel 3.11.0-15-generic.
>> dmesg | grep qca98 shows
>> [    4.594975] ath10k: qca988x hw2.0 (0x4100016c) fw 10.1.467.2-1 api 2 htt 2.1
> mine show as follow 
> 
> [   13.846597] ath10k: firmware 10.1.467.2-1 booted
> [   13.856533] ath10k: htt target version 2.1
> 
> Dose this make any difference ?!!! 
> 
> kind regards 
> Mamun
> 
> 
>> Further, as Kalle suggested, we in=stalled the ath10k driver from backports-3.15.1-1.
>> 
>> Best regards,
>> 
>> Bart
>> 
>> -- 
>> Bart Jooris
>> Department of Information Technology
>> Internet Based Communication Networks and Services (IBCN)
>> Ghent University - iMinds
>> Gaston Crommenlaan 8 (Bus 201), B-9050 Gent, Belgium
>> E-mail: bart.jooris at intec.UGent.be
>> M: +32 474 59 53 42
>> Tel. +32 9 33 14900
>> Fax +32 9 33 14899
>> 
> 



From ma86 at st-andrews.ac.uk  Thu Jul 17 04:37:28 2014
From: ma86 at st-andrews.ac.uk (Mamun Abu-Tair)
Date: Thu, 17 Jul 2014 12:37:28 +0100
Subject: Throughput is very low
References: <7771CBBE-70F2-44FF-AAC8-C35987A83D67@st-andrews.ac.uk>
Message-ID: <6EC6CD88-590A-4BA4-996D-405A46CB1988@st-andrews.ac.uk>


Begin forwarded message:

> From: Mamun Abu-Tair <ma86 at st-andrews.ac.uk>
> Subject: Re: Throughput is very low
> Date: 17 July 2014 12:22:46 BST
> To: Michal Kazior <michal.kazior at tieto.com>
> 
> Many thanks Michale, 
> 
> On 17 Jul 2014, at 06:21, Michal Kazior <michal.kazior at tieto.com> wrote:
> 
>> On 16 July 2014 18:01, Bart Jooris <Bart.Jooris at intec.ugent.be> wrote:
>>> On 07/09/2014 04:22 PM, Mamun Abu-Tair wrote:
>> [...]
>>>> I have notice that Bit Rate keeps fixed 6 Mb/s . and it dose not
>>>> responding to any commands to change it.
>>> 
>>> While running iperf client on the station I can also retrieve the Tx bitrate
>>> of 6Mbps with both iwconfig and 'iw wlanX station dump'. Version of iw has
>>> some impact on the output too, I have version 3.15.  I don't know a tool
>>> which shows the right info on the transmitting node...
>>> But a third node which is configured as a sniffer shows Tx bitrate of
>>> 1299.99Mbps :-)
>> 
>> The 6mbps tx rate reporting is due to firmware limitation.
>> 
>> You might want to check
>> /sys/kernel/debug/ieee80211/phyX/ath10k/fw_stats (replace phyX with
>> according phy of your ath10k device) instead.
> 
> I have checked the file and it has nothing on it. Is this normal ?!!!
> Kind regards 
> Mamun
> 
>> 
>> 
>> Micha?



From michal.kazior at tieto.com  Thu Jul 17 04:38:01 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 17 Jul 2014 13:38:01 +0200
Subject: Throughput is very low
In-Reply-To: <830E6887-0C19-4FE3-B264-E07B2427697D@st-andrews.ac.uk>
References: <7771CBBE-70F2-44FF-AAC8-C35987A83D67@st-andrews.ac.uk>
 <830E6887-0C19-4FE3-B264-E07B2427697D@st-andrews.ac.uk>
Message-ID: <CA+BoTQkxnxwHCimjcPBJbMxiJjX-UnG-5P-11skGKAs9Dh3Wfw@mail.gmail.com>

On 17 July 2014 13:35, Mamun Abu-Tair <ma86 at st-andrews.ac.uk> wrote:
> Sorry forget to CC the ath10k mailing list
>
> Begin forwarded message:
>
> From: Mamun Abu-Tair <ma86 at st-andrews.ac.uk>
> Subject: Re: Throughput is very low
> Date: 17 July 2014 12:22:46 BST
> To: Michal Kazior <michal.kazior at tieto.com>
>
> Many thanks Micjhale,
>
> On 17 Jul 2014, at 06:21, Michal Kazior <michal.kazior at tieto.com> wrote:
>
> On 16 July 2014 18:01, Bart Jooris <Bart.Jooris at intec.ugent.be> wrote:
>
> On 07/09/2014 04:22 PM, Mamun Abu-Tair wrote:
>
> [...]
>
> I have notice that Bit Rate keeps fixed 6 Mb/s . and it dose not
> responding to any commands to change it.
>
>
> While running iperf client on the station I can also retrieve the Tx bitrate
> of 6Mbps with both iwconfig and 'iw wlanX station dump'. Version of iw has
> some impact on the output too, I have version 3.15.  I don't know a tool
> which shows the right info on the transmitting node...
> But a third node which is configured as a sniffer shows Tx bitrate of
> 1299.99Mbps :-)
>
>
> The 6mbps tx rate reporting is due to firmware limitation.
>
> You might want to check
> /sys/kernel/debug/ieee80211/phyX/ath10k/fw_stats (replace phyX with
> according phy of your ath10k device) instead.
>
>
> I have checked the file and it has nothing on it. Is this normal ?!!!

If no ath10k interface is running (connected/associated) then fw_stats
is empty. Run hostapd or connect to an AP and then check the file. If
it's still empty make sure you update the driver (i.e. using
backports).


Micha?


From vh.nguyen at actiasodielec.fr  Thu Jul 17 05:22:06 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Thu, 17 Jul 2014 14:22:06 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>,
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>

>Did you use cables or measured OTA?

My system is like this: 
PC1 - Device 1 (AP) <= Wifi => Device 2 (STA) - PC2
Each PC connects to the device by a Gigabit Ethernet  cable. 


>What platform it is? 
My platform is a PC built with an ARMv7 1.2GHz. 

> Did you use hostapd? Is it AP mode (bridge)?
I'm using hostapd for AP and wpa_supplicant for STA. AP is in mode bridge 
but STA isn't (the official firmware crashed in bridge mode, I can set up bridged STA 
using the firmware of Candelatech but the rate is slower a little bit when I do iperf test.

>(You did not provide basically any details on what exacly you've measured).
Sorry, please feel free to ask me more details.
I obtained that result table  when I did iperf test in TCP, option -w256K and 10 streams (-P10)
If I did the test in UDP, with the same bandwidth (option -b),  I lost more packets 
in MCS 8 and 9 compared to MCS7, which also means that MCS7 has better performance.


>In open AP mode (bridge), CUS223 HW (not WLE900VX however) and on
>AP135 platform (customized openwrt SW + bleeding edge of
>ath10k/wireless subsystem souces - private backports tarball).. for
>UDP (last time I measured) I have around 820Mpbs for UCP both ways and
>720Mbps TCP.

This is in NSS3 -MCS9? Did you get better or worse rate if you clear the mask
(iw wlanX set bitrates) cause if I don't config rate, from AP to STA I have the best rate
(ie same as MCS7) but from STA to AP my rate is much lower than MCS7 (240 Mbps 
vs 370 Mbps in TCP).

NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE



From vh.nguyen at actiasodielec.fr  Thu Jul 17 05:42:40 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Thu, 17 Jul 2014 14:42:40 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <CA+BoTQmENGOcdWTGDU6By-4sXu2o9WNzTuizD=+_bDK14miWqg@mail.gmail.com>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>,
 <CA+BoTQmENGOcdWTGDU6By-4sXu2o9WNzTuizD=+_bDK14miWqg@mail.gmail.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7ED@srvexch01.SODIELEC.local>

>The higher the MCS rate the more symbols are packed up per baud which
>means it is more susceptible to interference and corruption.

>You probably don't have an environment clean enough to pull off MCS8
>and MCS9 and you end up with a lot of retransmissions.

>If you're sure you have a clean environment then try putting your
>devices (or them antenna) at different angles against each other and
>different distances.

What did you mean by clean environment? (There's no other 5Ghz wifi in the room,
no radar or device that emit in 5Ghz frequency? I may have other 2.4Ghz wifi in my room, 
hope that it doesn't create any effects)
I'm using an Omnidirectional antennas of PCTEL so I guess it doesn't change anything 
if I change the angle.
One more thing, my processor is already exhausted (0-1% idle) when I obtain 410Mbps in NSS3 -MCS7,
so if I force it to MCS8 or 9, is it possible that a reverse effects is created? The processor gets a lot of work 
to do and then I end up with retransmissions like you said? 
I hope not cause even in VHT40 or VHT20 my processor is not exhausted and MCS9 is still lower than MCS 8 or 7. 

NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE




From bartosz.markowski at tieto.com  Thu Jul 17 05:42:52 2014
From: bartosz.markowski at tieto.com (Bartosz Markowski)
Date: Thu, 17 Jul 2014 14:42:52 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
Message-ID: <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>

On 17 July 2014 14:22, Vu Hai NGUYEN <vh.nguyen at actiasodielec.fr> wrote:
>>Did you use cables or measured OTA?
>
> My system is like this:
> PC1 - Device 1 (AP) <= Wifi => Device 2 (STA) - PC2
> Each PC connects to the device by a Gigabit Ethernet  cable.

I ment RF cables and attenuation to get around 30dBm signal lvl.

PC    ---(eth)---   [AP135 - APUT]ath10k    - - - (RF cable) - - -
[AP135]Station    ---(eth)---    PC

>>What platform it is?
> My platform is a PC built with an ARMv7 1.2GHz.
>
>> Did you use hostapd? Is it AP mode (bridge)?
> I'm using hostapd for AP and wpa_supplicant for STA. AP is in mode bridge
> but STA isn't (the official firmware crashed in bridge mode, I can set up bridged STA
> using the firmware of Candelatech but the rate is slower a little bit when I do iperf test.
>
>>(You did not provide basically any details on what exacly you've measured).
> Sorry, please feel free to ask me more details.
> I obtained that result table  when I did iperf test in TCP, option -w256K and 10 streams (-P10)
> If I did the test in UDP, with the same bandwidth (option -b),  I lost more packets
> in MCS 8 and 9 compared to MCS7, which also means that MCS7 has better performance.

So probably the air condition you have forces the rate control to pick
MCS7 as the most suitable rates.

>>In open AP mode (bridge), CUS223 HW (not WLE900VX however) and on
>>AP135 platform (customized openwrt SW + bleeding edge of
>>ath10k/wireless subsystem souces - private backports tarball).. for
>>UDP (last time I measured) I have around 820Mpbs for UCP both ways and
>>720Mbps TCP.
>
> This is in NSS3 -MCS9? Did you get better or worse rate if you clear the mask
> (iw wlanX set bitrates) cause if I don't config rate, from AP to STA I have the best rate
> (ie same as MCS7) but from STA to AP my rate is much lower than MCS7 (240 Mbps
> vs 370 Mbps in TCP).

Yes, NSS-3; Over the RF-cables I'm easily able to get MCS9 rates
transmitions without any forced settings (the rate control is picking
the highest rates).

-- 
Bartosz


From michal.kazior at tieto.com  Thu Jul 17 05:45:21 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 17 Jul 2014 14:45:21 +0200
Subject: [PATCH 1/2] ath10k: simplify tx helpers
Message-ID: <1405601122-29726-1-git-send-email-michal.kazior@tieto.com>

It always bugged me how tid is computed and stored
in a temporary var before written to the control
buffer. It was confusing and it made it difficult
to work with tx helpers.

While at it rename the qos workaround function as
it was misleading - it's not a workaround but
preparation for nwifi tx mode.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 49 ++++++++++++++---------------------
 drivers/net/wireless/ath/ath10k/mac.h |  4 +--
 drivers/net/wireless/ath/ath10k/wmi.c |  2 +-
 3 files changed, 23 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b8314a5..bbce3a0 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1865,13 +1865,10 @@ static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar,
 	return 0;
 }
 
-/*
- * Frames sent to the FW have to be in "Native Wifi" format.
- * Strip the QoS field from the 802.11 header.
+/* HTT Tx uses Native Wifi tx mode which expects 802.11 frames without QoS
+ * Control in the header.
  */
-static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw,
-				       struct ieee80211_tx_control *control,
-				       struct sk_buff *skb)
+static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	u8 *qos_ctl;
@@ -1919,14 +1916,13 @@ unlock:
 	mutex_unlock(&arvif->ar->conf_mutex);
 }
 
-static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
+static void ath10k_tx_h_update_wep_key(struct ieee80211_vif *vif,
+				       struct ieee80211_key_conf *key,
+				       struct sk_buff *skb)
 {
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_vif *vif = info->control.vif;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	struct ath10k *ar = arvif->ar;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_key_conf *key = info->control.hw_key;
 
 	if (!ieee80211_has_protected(hdr->frame_control))
 		return;
@@ -1948,11 +1944,11 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
 	ieee80211_queue_work(ar->hw, &arvif->wep_key_work);
 }
 
-static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb)
+static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
+				       struct ieee80211_vif *vif,
+				       struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_vif *vif = info->control.vif;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 
 	/* This is case only for P2P_GO */
@@ -2254,33 +2250,28 @@ static void ath10k_tx(struct ieee80211_hw *hw,
 		      struct ieee80211_tx_control *control,
 		      struct sk_buff *skb)
 {
+	struct ath10k *ar = hw->priv;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_vif *vif = info->control.vif;
+	struct ieee80211_key_conf *key = info->control.hw_key;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ath10k *ar = hw->priv;
-	u8 tid, vdev_id;
 
 	/* We should disable CCK RATE due to P2P */
 	if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
 		ath10k_dbg(ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
 
-	/* we must calculate tid before we apply qos workaround
-	 * as we'd lose the qos control field */
-	tid = ath10k_tx_h_get_tid(hdr);
-	vdev_id = ath10k_tx_h_get_vdev_id(ar, info);
+	ATH10K_SKB_CB(skb)->htt.is_offchan = false;
+	ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
+	ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, info);
 
 	/* it makes no sense to process injected frames like that */
-	if (info->control.vif &&
-	    info->control.vif->type != NL80211_IFTYPE_MONITOR) {
-		ath10k_tx_h_qos_workaround(hw, control, skb);
-		ath10k_tx_h_update_wep_key(skb);
-		ath10k_tx_h_add_p2p_noa_ie(ar, skb);
-		ath10k_tx_h_seq_no(skb);
+	if (vif && vif->type != NL80211_IFTYPE_MONITOR) {
+		ath10k_tx_h_nwifi(hw, skb);
+		ath10k_tx_h_update_wep_key(vif, key, skb);
+		ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb);
+		ath10k_tx_h_seq_no(vif, skb);
 	}
 
-	ATH10K_SKB_CB(skb)->vdev_id = vdev_id;
-	ATH10K_SKB_CB(skb)->htt.is_offchan = false;
-	ATH10K_SKB_CB(skb)->htt.tid = tid;
-
 	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
 		spin_lock_bh(&ar->data_lock);
 		ATH10K_SKB_CB(skb)->htt.is_offchan = true;
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index ba10219..ef4f843 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -43,11 +43,11 @@ static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
 	return (struct ath10k_vif *)vif->drv_priv;
 }
 
-static inline void ath10k_tx_h_seq_no(struct sk_buff *skb)
+static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif,
+				      struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_vif *vif = info->control.vif;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 
 	if (info->flags  & IEEE80211_TX_CTL_ASSIGN_SEQ) {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 6f83cae..c2c87c9 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1432,7 +1432,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
 			continue;
 		}
 
-		ath10k_tx_h_seq_no(bcn);
+		ath10k_tx_h_seq_no(arvif->vif, bcn);
 		ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info);
 		ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info);
 
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Jul 17 05:45:22 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 17 Jul 2014 14:45:22 +0200
Subject: [PATCH 2/2] ath10k: workaround qos nullfunc bug
In-Reply-To: <1405601122-29726-1-git-send-email-michal.kazior@tieto.com>
References: <1405601122-29726-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1405601122-29726-2-git-send-email-michal.kazior@tieto.com>

Apparently fw/hw generates a corrupted QoS Control
Field in Qos NullFunc frames. The only way to
workaround this is to downgrade frames to
NullFunc. This should be okay since powersave is
done by fw/hw and these frames are only used for
CQM purposes (e.g. from hostapd to check if
station is still connected).

This doesn't fix any user visible bug that I know
of. It just prevents from sending out funky frames
on the air.

Reported-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index bbce3a0..3f9afaa 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1871,6 +1871,7 @@ static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar,
 static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr = (void *)skb->data;
+	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
 	u8 *qos_ctl;
 
 	if (!ieee80211_is_data_qos(hdr->frame_control))
@@ -1880,6 +1881,16 @@ static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb)
 	memmove(skb->data + IEEE80211_QOS_CTL_LEN,
 		skb->data, (void *)qos_ctl - (void *)skb->data);
 	skb_pull(skb, IEEE80211_QOS_CTL_LEN);
+
+	/* Fw/Hw generates a corrupted QoS Control Field for QoS NullFunc
+	 * frames. Powersave is handled by the fw/hw so QoS NyllFunc frames are
+	 * used only for CQM purposes (e.g. hostapd station keepalive ping) so
+	 * it is safe to downgrade to NullFunc.
+	 */
+	if (ieee80211_is_qos_nullfunc(hdr->frame_control)) {
+		hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
+		cb->htt.tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
+	}
 }
 
 static void ath10k_tx_wep_key_work(struct work_struct *work)
-- 
1.8.5.3



From vh.nguyen at actiasodielec.fr  Thu Jul 17 06:19:11 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Thu, 17 Jul 2014 15:19:11 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>,
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>

>So probably the air condition you have forces the rate control to pick
>MCS7 as the most suitable rates.

What could I do to improve this? (Change the air conditioner LOL?)

NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE



From ma86 at st-andrews.ac.uk  Thu Jul 17 06:37:07 2014
From: ma86 at st-andrews.ac.uk (Mamun Abu-Tair)
Date: Thu, 17 Jul 2014 14:37:07 +0100
Subject: Throughput is very low
In-Reply-To: <CA+BoTQkxnxwHCimjcPBJbMxiJjX-UnG-5P-11skGKAs9Dh3Wfw@mail.gmail.com>
References: <7771CBBE-70F2-44FF-AAC8-C35987A83D67@st-andrews.ac.uk>
 <830E6887-0C19-4FE3-B264-E07B2427697D@st-andrews.ac.uk>
 <CA+BoTQkxnxwHCimjcPBJbMxiJjX-UnG-5P-11skGKAs9Dh3Wfw@mail.gmail.com>
Message-ID: <2D8D7F08-9E64-4D53-8D47-0A825E9CE626@st-andrews.ac.uk>


On 17 Jul 2014, at 12:38, Michal Kazior <michal.kazior at tieto.com> wrote:

> On 17 July 2014 13:35, Mamun Abu-Tair <ma86 at st-andrews.ac.uk> wrote:
>> Sorry forget to CC the ath10k mailing list
>> 
>> Begin forwarded message:
>> 
>> From: Mamun Abu-Tair <ma86 at st-andrews.ac.uk>
>> Subject: Re: Throughput is very low
>> Date: 17 July 2014 12:22:46 BST
>> To: Michal Kazior <michal.kazior at tieto.com>
>> 
>> Many thanks Micjhale,
>> 
>> On 17 Jul 2014, at 06:21, Michal Kazior <michal.kazior at tieto.com> wrote:
>> 
>> On 16 July 2014 18:01, Bart Jooris <Bart.Jooris at intec.ugent.be> wrote:
>> 
>> On 07/09/2014 04:22 PM, Mamun Abu-Tair wrote:
>> 
>> [...]
>> 
>> I have notice that Bit Rate keeps fixed 6 Mb/s . and it dose not
>> responding to any commands to change it.
>> 
>> 
>> While running iperf client on the station I can also retrieve the Tx bitrate
>> of 6Mbps with both iwconfig and 'iw wlanX station dump'. Version of iw has
>> some impact on the output too, I have version 3.15.  I don't know a tool
>> which shows the right info on the transmitting node...
>> But a third node which is configured as a sniffer shows Tx bitrate of
>> 1299.99Mbps :-)
>> 
>> 
>> The 6mbps tx rate reporting is due to firmware limitation.
>> 
>> You might want to check
>> /sys/kernel/debug/ieee80211/phyX/ath10k/fw_stats (replace phyX with
>> according phy of your ath10k device) instead.
>> 
>> 
>> I have checked the file and it has nothing on it. Is this normal ?!!!
> 
> If no ath10k interface is running (connected/associated) then fw_stats
> is empty. Run hostapd or connect to an AP and then check the file. If
> it's still empty make sure you update the driver (i.e. using
> backports).
> 
Well ,the fw_stats is still empty . After upgrading the driver the throughput dropped down from 180Mbit/s tp 60 Mbit/s :-(. 
the following is a new message I have got: 
[  509.831850] ath10k: peer-unmap-event: unknown peer id 2
Many thanks for your help. 


> 
> Micha?



From helmut.schaa at googlemail.com  Thu Jul 17 07:12:35 2014
From: helmut.schaa at googlemail.com (Helmut Schaa)
Date: Thu, 17 Jul 2014 16:12:35 +0200
Subject: ath10k OTP loading issues
In-Reply-To: <53C59A22.6000505@marcant.net>
References: <53AD2EEE.4040704@marcant.net>
 <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>
 <53C59A22.6000505@marcant.net>
Message-ID: <CAGXE3d8KZ=BG6a2PBhY_ZAhf71admtrnCF01LNoyA2tnLNJcAA@mail.gmail.com>

Hey,

On Tue, Jul 15, 2014 at 11:16 PM, Andre Valentin <avalentin at marcant.net> wrote:
> Hi!
>
> Somehow I did not see this message. Sorry.

No problem.

>>>> If I remove OTP loading the card initializes fine, but I think I will
>>>>
>>>> not have a good performance. So bad idea.
>>>
>>>
>>> All that was changed recently was that we now check the error code
>>> coming from otp.bin. So you have had this issue all along, it was just
>>> hidden before.
>>
>>
>> Same issue here.
>>
>> Is it correct that board.bin should contain the calibration data of
>> the actual board?
>> I tried copying it from the APs ART partition but still no luck.
>>
>> Any hint on how to debug further why the otp calibration fails?
>
>
> I have no idea except disabling the error return inside of ath10k_pci.
> Would that make sense as a temporary workaround? It seems I have normal
> performance without enfording otp loading.

Sure, but it is a workaround and I'd like to find out why it fails if I use the
calibration data from the original firmware.

Thanks,
Helmut


From kvalo at qca.qualcomm.com  Thu Jul 17 08:03:52 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 17 Jul 2014 18:03:52 +0300
Subject: ath10k OTP loading issues
In-Reply-To: <CAGXE3d8KZ=BG6a2PBhY_ZAhf71admtrnCF01LNoyA2tnLNJcAA@mail.gmail.com>
 (Helmut Schaa's message of "Thu, 17 Jul 2014 16:12:35 +0200")
References: <53AD2EEE.4040704@marcant.net>
 <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>
 <53C59A22.6000505@marcant.net>
 <CAGXE3d8KZ=BG6a2PBhY_ZAhf71admtrnCF01LNoyA2tnLNJcAA@mail.gmail.com>
Message-ID: <87wqbc6n8n.fsf@kamboji.qca.qualcomm.com>

Helmut Schaa <helmut.schaa at googlemail.com> writes:

>>> Is it correct that board.bin should contain the calibration data of
>>> the actual board? I tried copying it from the APs ART partition but
>>> still no luck.
>>>
>>> Any hint on how to debug further why the otp calibration fails?
>>
>> I have no idea except disabling the error return inside of ath10k_pci.
>> Would that make sense as a temporary workaround? It seems I have normal
>> performance without enfording otp loading.
>
> Sure, but it is a workaround and I'd like to find out why it fails if I use the
> calibration data from the original firmware.

Let me clarify. There are two ways to store the calibration data:

1) to the OTP area within the QCA9880 chip

2) to the host, for example to an MTD partition

otp.bin is used with method 1). It reads the OTP area and provides the
calibration data to the firmware.

But in method 2) otp.bin will fail as there's no data in the OTP area.
This is expected and that's why we should not run otp.bin at all with
method 2).

-- 
Kalle Valo


From helmut.schaa at googlemail.com  Thu Jul 17 08:45:46 2014
From: helmut.schaa at googlemail.com (Helmut Schaa)
Date: Thu, 17 Jul 2014 17:45:46 +0200
Subject: ath10k OTP loading issues
In-Reply-To: <87wqbc6n8n.fsf@kamboji.qca.qualcomm.com>
References: <53AD2EEE.4040704@marcant.net>
 <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>
 <53C59A22.6000505@marcant.net>
 <CAGXE3d8KZ=BG6a2PBhY_ZAhf71admtrnCF01LNoyA2tnLNJcAA@mail.gmail.com>
 <87wqbc6n8n.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CAGXE3d_FQvvmkGajQ1ioU5mEL04xVzUQ1k9-uXSLjoDFX+Z-Cg@mail.gmail.com>

On Thu, Jul 17, 2014 at 5:03 PM, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Helmut Schaa <helmut.schaa at googlemail.com> writes:
>
>>>> Is it correct that board.bin should contain the calibration data of
>>>> the actual board? I tried copying it from the APs ART partition but
>>>> still no luck.
>>>>
>>>> Any hint on how to debug further why the otp calibration fails?
>>>
>>> I have no idea except disabling the error return inside of ath10k_pci.
>>> Would that make sense as a temporary workaround? It seems I have normal
>>> performance without enfording otp loading.
>>
>> Sure, but it is a workaround and I'd like to find out why it fails if I use the
>> calibration data from the original firmware.
>
> Let me clarify. There are two ways to store the calibration data:
>
> 1) to the OTP area within the QCA9880 chip
>
> 2) to the host, for example to an MTD partition
>
> otp.bin is used with method 1). It reads the OTP area and provides the
> calibration data to the firmware.
>
> But in method 2) otp.bin will fail as there's no data in the OTP area.
> This is expected and that's why we should not run otp.bin at all with
> method 2).

Thanks for clarification Kalle!
So, method 2 requires only a board.bin?

Helmut


From kvalo at qca.qualcomm.com  Thu Jul 17 08:50:36 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 17 Jul 2014 18:50:36 +0300
Subject: ath10k OTP loading issues
In-Reply-To: <CAGXE3d_FQvvmkGajQ1ioU5mEL04xVzUQ1k9-uXSLjoDFX+Z-Cg@mail.gmail.com>
 (Helmut Schaa's message of "Thu, 17 Jul 2014 17:45:46 +0200")
References: <53AD2EEE.4040704@marcant.net>
 <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>
 <53C59A22.6000505@marcant.net>
 <CAGXE3d8KZ=BG6a2PBhY_ZAhf71admtrnCF01LNoyA2tnLNJcAA@mail.gmail.com>
 <87wqbc6n8n.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d_FQvvmkGajQ1ioU5mEL04xVzUQ1k9-uXSLjoDFX+Z-Cg@mail.gmail.com>
Message-ID: <87lhrs6l2r.fsf@kamboji.qca.qualcomm.com>

Helmut Schaa <helmut.schaa at googlemail.com> writes:

>> But in method 2) otp.bin will fail as there's no data in the OTP area.
>> This is expected and that's why we should not run otp.bin at all with
>> method 2).
>
> Thanks for clarification Kalle! So, method 2 requires only a
> board.bin?

Yes. You need to extract the board file from the MTD partition and
provide it to ath10k.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Thu Jul 17 08:54:33 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 17 Jul 2014 18:54:33 +0300
Subject: Pull request: ath 20140717
Message-ID: <87k37c6kw6.fsf@kamboji.qca.qualcomm.com>

Hi John,

here's new pull request for 3.17. Major changes are:

For ath6kl me and Jessica added support for ar6004 hw3.0, our latest
version of ar6004.

For ath10k Janusz added a printout so that it's easier to check what
ath10k kconfig options are enabled. He also added a debugfs file to
configure maximum amsdu and ampdu values. Also we had few fixes as
usual.

Please let me know if there are any problems.

Kalle

The following changes since commit a715c7ddd65a1a3b2839b8ebd759bb2d361f7675:

  wil6210: improve debug for WMI receive (2014-05-30 13:49:34 -0400)

are available in the git repository at:

  git://github.com/kvalo/ath.git tags/for-linville-20140717

for you to fetch changes up to 993619443774f7ef4df3b98655df4c3bf298548c:

  ath10k: sanitize tx ring index access properly (2014-07-15 11:19:45 +0300)

----------------------------------------------------------------
Frederic Danis (1):
      ath6kl: Fix ath6kl_bmi_read_hi32 macro

Janusz Dziedzic (2):
      ath10k: print Kconfig options
      ath10k: add implementation for configure max amsdu, ampdu

Jessica Wu (3):
      ath6kl: implement rx flush for htc pipe
      ath6kl: add support wmi rate tables with mcs15
      ath6kl: add support for ar6004 hw3.0

Kalle Valo (3):
      ath10k: remove unused len variables from wmi process rx functions
      ath6kl: convert ar6004 hardware flags to firmware feature flags
      ath6kl: don't set hi_refclk_hz if hardware version doesn't need it

Michal Kazior (3):
      ath10k: fix unregister deadlock when fw probe fails
      ath10k: fix bmi exchange tx/rx race
      ath10k: sanitize tx ring index access properly

 drivers/net/wireless/ath/ath10k/ce.c       |   11 ++--
 drivers/net/wireless/ath/ath10k/core.c     |   12 +++-
 drivers/net/wireless/ath/ath10k/core.h     |    3 +
 drivers/net/wireless/ath/ath10k/debug.c    |   73 ++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/htt.h      |   13 ++--
 drivers/net/wireless/ath/ath10k/htt_tx.c   |   46 ++++++++++++++
 drivers/net/wireless/ath/ath10k/pci.c      |   11 +---
 drivers/net/wireless/ath/ath10k/pci.h      |    3 +-
 drivers/net/wireless/ath/ath10k/wmi.c      |    6 --
 drivers/net/wireless/ath/ath6kl/bmi.h      |    3 +-
 drivers/net/wireless/ath/ath6kl/cfg80211.c |    6 +-
 drivers/net/wireless/ath/ath6kl/core.c     |   16 +++++
 drivers/net/wireless/ath/ath6kl/core.h     |   36 +++++++++--
 drivers/net/wireless/ath/ath6kl/htc_pipe.c |   32 +++++++++-
 drivers/net/wireless/ath/ath6kl/init.c     |   90 ++++++++++++++++++++++------
 drivers/net/wireless/ath/ath6kl/main.c     |   17 ++++--
 drivers/net/wireless/ath/ath6kl/usb.c      |    7 ++-
 drivers/net/wireless/ath/ath6kl/wmi.c      |   72 ++++++++++++++++++++--
 drivers/net/wireless/ath/ath6kl/wmi.h      |    2 +-
 19 files changed, 388 insertions(+), 71 deletions(-)

-- 
Kalle Valo


From avalentin at marcant.net  Thu Jul 17 08:54:54 2014
From: avalentin at marcant.net (Andre Valentin)
Date: Thu, 17 Jul 2014 17:54:54 +0200
Subject: ath10k OTP loading issues
In-Reply-To: <87lhrs6l2r.fsf@kamboji.qca.qualcomm.com>
References: <53AD2EEE.4040704@marcant.net>	<87tx70p4e0.fsf@kamboji.qca.qualcomm.com>	<CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>	<53C59A22.6000505@marcant.net>	<CAGXE3d8KZ=BG6a2PBhY_ZAhf71admtrnCF01LNoyA2tnLNJcAA@mail.gmail.com>	<87wqbc6n8n.fsf@kamboji.qca.qualcomm.com>	<CAGXE3d_FQvvmkGajQ1ioU5mEL04xVzUQ1k9-uXSLjoDFX+Z-Cg@mail.gmail.com>
 <87lhrs6l2r.fsf@kamboji.qca.qualcomm.com>
Message-ID: <53C7F1CE.3060501@marcant.net>

Hi!

On 17.07.2014 17:50, Kalle Valo wrote:
> Helmut Schaa <helmut.schaa at googlemail.com> writes:
>
>>> But in method 2) otp.bin will fail as there's no data in the OTP area.
>>> This is expected and that's why we should not run otp.bin at all with
>>> method 2).
>>
>> Thanks for clarification Kalle! So, method 2 requires only a
>> board.bin?
>
> Yes. You need to extract the board file from the MTD partition and
> provide it to ath10k.
>
So the question is why does in this case fail the otp.bin loading process or why is it started.
How can I prevent it. I provided the correspondig board.bin. If needed, I could run
a debug on the ath10k loading.

Kind regards,

Andr?



From kvalo at qca.qualcomm.com  Thu Jul 17 08:59:47 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 17 Jul 2014 18:59:47 +0300
Subject: ath10k OTP loading issues
In-Reply-To: <53C7F1CE.3060501@marcant.net> (Andre Valentin's message of "Thu, 
 17 Jul 2014 17:54:54 +0200")
References: <53AD2EEE.4040704@marcant.net>
 <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>
 <53C59A22.6000505@marcant.net>
 <CAGXE3d8KZ=BG6a2PBhY_ZAhf71admtrnCF01LNoyA2tnLNJcAA@mail.gmail.com>
 <87wqbc6n8n.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d_FQvvmkGajQ1ioU5mEL04xVzUQ1k9-uXSLjoDFX+Z-Cg@mail.gmail.com>
 <87lhrs6l2r.fsf@kamboji.qca.qualcomm.com>
 <53C7F1CE.3060501@marcant.net>
Message-ID: <87fvi06kng.fsf@kamboji.qca.qualcomm.com>

Andre Valentin <avalentin at marcant.net> writes:

> Hi!
>
> On 17.07.2014 17:50, Kalle Valo wrote:
>> Helmut Schaa <helmut.schaa at googlemail.com> writes:
>>
>>>> But in method 2) otp.bin will fail as there's no data in the OTP area.
>>>> This is expected and that's why we should not run otp.bin at all with
>>>> method 2).
>>>
>>> Thanks for clarification Kalle! So, method 2 requires only a
>>> board.bin?
>>
>> Yes. You need to extract the board file from the MTD partition and
>> provide it to ath10k.
>
> So the question is why does in this case fail the otp.bin loading
> process or why is it started. How can I prevent it. I provided the
> correspondig board.bin. If needed, I could run a debug on the ath10k
> loading.

Because ath10k does not support method 2) yet. We only support method 1)
right now, ie. the calibration data stored in OTP area.

Patches more than welcome to fix the situation :)

-- 
Kalle Valo


From adrian at freebsd.org  Thu Jul 17 12:18:46 2014
From: adrian at freebsd.org (Adrian Chadd)
Date: Thu, 17 Jul 2014 12:18:46 -0700
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>
Message-ID: <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>

On 17 July 2014 06:19, Vu Hai NGUYEN <vh.nguyen at actiasodielec.fr> wrote:
>>So probably the air condition you have forces the rate control to pick
>>MCS7 as the most suitable rates.
>
> What could I do to improve this? (Change the air conditioner LOL?)
>

Heh, he meant the RF environment in the location you are. :)

And ugh - this is why we need an open source ART already.



-a


From helmut.schaa at googlemail.com  Thu Jul 17 14:44:08 2014
From: helmut.schaa at googlemail.com (Helmut Schaa)
Date: Thu, 17 Jul 2014 23:44:08 +0200
Subject: ath10k OTP loading issues
In-Reply-To: <87lhrs6l2r.fsf@kamboji.qca.qualcomm.com>
References: <53AD2EEE.4040704@marcant.net>
 <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>
 <53C59A22.6000505@marcant.net>
 <CAGXE3d8KZ=BG6a2PBhY_ZAhf71admtrnCF01LNoyA2tnLNJcAA@mail.gmail.com>
 <87wqbc6n8n.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d_FQvvmkGajQ1ioU5mEL04xVzUQ1k9-uXSLjoDFX+Z-Cg@mail.gmail.com>
 <87lhrs6l2r.fsf@kamboji.qca.qualcomm.com>
Message-ID: <63dce1c7-0142-4592-b8a1-2b09dce63af3@email.android.com>



On 17. Juli 2014 17:50:36 MESZ, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>Helmut Schaa <helmut.schaa at googlemail.com> writes:
>
>>> But in method 2) otp.bin will fail as there's no data in the OTP
>area.
>>> This is expected and that's why we should not run otp.bin at all
>with
>>> method 2).
>>
>> Thanks for clarification Kalle! So, method 2 requires only a
>> board.bin?
>
>Yes. You need to extract the board file from the MTD partition and
>provide it to ath10k.

Understood. Will give it a try soon ...
Helmut


From Bart.Jooris at intec.ugent.be  Fri Jul 18 00:39:10 2014
From: Bart.Jooris at intec.ugent.be (Bart Jooris)
Date: Fri, 18 Jul 2014 09:39:10 +0200
Subject: Fwd: Throughput is very low
In-Reply-To: <22BBE3DA-7977-455A-B97D-AD24773B67C3@st-andrews.ac.uk>
References: <2E79DF84-6D1A-4EEB-88AA-19A6F1860289@st-andrews.ac.uk>
 <22BBE3DA-7977-455A-B97D-AD24773B67C3@st-andrews.ac.uk>
Message-ID: <53C8CF1E.8080300@intec.ugent.be>

Dear Mamun,

On 07/17/2014 01:34 PM, Mamun Abu-Tair wrote:
> which version of hostapd you are using ? 

     ./hostap/hostapd/hostapd -v
     hostapd v2.3-devel
     User space daemon for IEEE 802.11 AP management,
     IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
     Copyright (c) 2002-2014, Jouni Malinen <j at w1.fi> and contributors

I followed these instructions:
http://wireless.kernel.org/en/users/Documentation/hostapd#Download_and_compile_hostapd
> mine show as follow
>
> [   13.846597] ath10k: firmware 10.1.467.2-1 booted
> [   13.856533] ath10k: htt target version 2.1
>
> Dose this make any difference ?!!!
Difference in output is probably related to your driver version?
I have:

	modinfo ath10k_pci
	filename:       /lib/modules/3.11.0-24-generic/updates/drivers/net/wireless/ath/ath10k/ath10k_pci.ko
	firmware:       ath10k/QCA988X/hw2.0/board.bin
	firmware:       ath10k/QCA988X/hw2.0/otp.bin
	firmware:       ath10k/QCA988X/hw2.0/firmware.bin
	license:        Dual BSD/GPL
	description:    Driver support for Atheros QCA988X PCIe devices
	author:         Qualcomm Atheros
	version:        backported from Linux (v3.15.1-0-g41b67d8) using backports v3.15.1-1-0-gfcc5f19
	srcversion:     2F02C56BB696ECC1D986D19
	alias:          pci:v0000168Cd0000003Csv*sd*bc*sc*i*
	depends:        ath10k_core,compat
	vermagic:       3.11.0-24-generic SMP mod_unload modversions
	parm:           ath10k_target_ps:Enable ath10k Target (SoC) PS option (uint)
	parm:           irq_mode:0: auto, 1: legacy, 2: msi (default: 0) (uint)
  
and also

	dmesg | grep backport
	[    3.595614] Loading modules backported from Linux version v3.15.1-0-g41b67d8
	[    3.595617] Backport generated by backports.git v3.15.1-1-0-gfcc5f19

see

	http://wireless.kernel.org/en/users/Drivers/ath10k/backports#ath10k_backports_releases

Best regards,

Bart

-- 
Bart Jooris
Department of Information Technology
Internet Based Communication Networks and Services (IBCN)
Ghent University - iMinds
Gaston Crommenlaan 8 (Bus 201), B-9050 Gent, Belgium



From janusz.dziedzic at tieto.com  Fri Jul 18 01:34:31 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Fri, 18 Jul 2014 10:34:31 +0200
Subject: [PATCH] ath10k: extend debug code for RX path
Message-ID: <1405672472-16302-1-git-send-email-janusz.dziedzic@tieto.com>

Print sequence number, AMSDU_MORE flag and AC when additional
debug enabled in RX path. This is usefull for debugging purpose.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c |   32 ++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 6db0e49..04140e3 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -819,19 +819,46 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
 	return true;
 }
 
+static char *tid_to_ac[] = {
+	"BE(0)",
+	"BK(1)",
+	"BK(2)",
+	"BE(3)",
+	"VI(4)",
+	"VI(5)",
+	"VO(6)",
+	"VO(7)",
+	"tid(8)",
+	"tid(9)",
+	"tid(10)",
+	"tid(11)",
+	"tid(12)",
+	"tid(13)",
+	"tid(14)",
+	"tid(15)",
+};
+
 static void ath10k_process_rx(struct ath10k *ar,
 			      struct ieee80211_rx_status *rx_status,
 			      struct sk_buff *skb)
 {
 	struct ieee80211_rx_status *status;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
 	status = IEEE80211_SKB_RXCB(skb);
 	*status = *rx_status;
 
 	ath10k_dbg(ATH10K_DBG_DATA,
-		   "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %imic-err %i\n",
+		   "rx skb %p len %u peer %pM %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
 		   skb,
 		   skb->len,
+		   ieee80211_get_SA(hdr),
+		   ieee80211_is_data_qos(hdr->frame_control) ?
+			(tid_to_ac[*(ieee80211_get_qos_ctl(hdr)) &
+				   IEEE80211_QOS_CTL_TID_MASK]) :
+			(is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
+				"mcast" : "ucast"),
+		   (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4,
 		   status->flag == 0 ? "legacy" : "",
 		   status->flag & RX_FLAG_HT ? "ht" : "",
 		   status->flag & RX_FLAG_VHT ? "vht" : "",
@@ -843,7 +870,8 @@ static void ath10k_process_rx(struct ath10k *ar,
 		   status->freq,
 		   status->band, status->flag,
 		   !!(status->flag & RX_FLAG_FAILED_FCS_CRC),
-		   !!(status->flag & RX_FLAG_MMIC_ERROR));
+		   !!(status->flag & RX_FLAG_MMIC_ERROR),
+		   !!(status->flag & RX_FLAG_AMSDU_MORE));
 	ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
 			skb->data, skb->len);
 
-- 
1.7.9.5



From janusz.dziedzic at tieto.com  Fri Jul 18 03:26:33 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Fri, 18 Jul 2014 12:26:33 +0200
Subject: [RFC 0/2] ath10k spectral scan support
In-Reply-To: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
References: <1405441966-32681-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <CALhHN=q_EapV6wTpicByf_Ga+qfpFe0edAsdufLSkwLRmhm2-Q@mail.gmail.com>

On 15 July 2014 18:32, Simon Wunderlich <sw at simonwunderlich.de> wrote:
> This is the first patchset iteration for review to implement the ath10k
> spectral scan feature. The patchset is still experimental, but we were
> able to detect our analogue 5.8 GHz TV repeater in the sample data. :)
>
> As for ath9k, a proof of concept data plotter has been implemented, and
> is currently available for ath10k in its own branch of FFT_eval [1].
>
Tested this with fft_eval, seems works quite good.
There is small problem with scan timeout, when spectral scan activated
and channels with high load checked, I often hit scan timeout.
Seems we should increase scan timeout in ath10k_start_scan() when
spectral activated.

BR
Janusz


From kvalo at qca.qualcomm.com  Fri Jul 18 05:32:18 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 18 Jul 2014 15:32:18 +0300
Subject: [RFT/RFC 0/5] ath10k: handle/report A-MSDU as a skb list
In-Reply-To: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
 (Janusz Dziedzic's message of "Thu, 10 Jul 2014 13:45:09 +0200")
References: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <871tti3l0t.fsf@kamboji.qca.qualcomm.com>

Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:

> This is prototype, how we can handle A-MSDU as a skb list in mac80211.
> No changes in mac80211 reordering code required in such case, also we
> don't need to build one big frame using memcpy ...
>
> With such prototype tid_agg_rx->reorder_buf[sn] will describe exactly
> one MPDU (with included A-MSDU subframes if skb->next) and detection of
> duplicated frames will work correctly. So, reordering should works
> correctly.
>
> I tested this with A-MPDU and A-MSDU run together (A-MSDU frame up to
> 10k) - TCP STA -> AP. I used ath10k STA with unlocked A-MSDU limit in
> RC in firmware. Didn't notice any problems.

So what are you exactly fixing here? It would be nice to get some
background and motivations for the changes in the cover letter.

Also we have so many reordering patches that I'm confused now. For
example, how is this related to patch "ath10k: handle attention flags
correctly when A-MSDU"?

-- 
Kalle Valo


From janusz.dziedzic at tieto.com  Fri Jul 18 05:40:15 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Fri, 18 Jul 2014 14:40:15 +0200
Subject: [RFT/RFC 0/5] ath10k: handle/report A-MSDU as a skb list
In-Reply-To: <871tti3l0t.fsf@kamboji.qca.qualcomm.com>
References: <1404992714-15690-1-git-send-email-janusz.dziedzic@tieto.com>
 <871tti3l0t.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CALhHN=rwv1uVmrnErypGBTEu50JfmNSFFiHub2bZD4MBoQbpaQ@mail.gmail.com>

On 18 July 2014 14:32, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:
>
>> This is prototype, how we can handle A-MSDU as a skb list in mac80211.
>> No changes in mac80211 reordering code required in such case, also we
>> don't need to build one big frame using memcpy ...
>>
>> With such prototype tid_agg_rx->reorder_buf[sn] will describe exactly
>> one MPDU (with included A-MSDU subframes if skb->next) and detection of
>> duplicated frames will work correctly. So, reordering should works
>> correctly.
>>
>> I tested this with A-MPDU and A-MSDU run together (A-MSDU frame up to
>> 10k) - TCP STA -> AP. I used ath10k STA with unlocked A-MSDU limit in
>> RC in firmware. Didn't notice any problems.
>
> So what are you exactly fixing here? It would be nice to get some
> background and motivations for the changes in the cover letter.
>
> Also we have so many reordering patches that I'm confused now. For
> example, how is this related to patch "ath10k: handle attention flags
> correctly when A-MSDU"?
>
We should skip this patchset, while we decide to change reordering
code in mac80211 instead of passing skb list.

ath10k: handle attention flags correctly when A-MSDU  is required
while fix generic FCS reporting issue.

BR
Janusz


From kvalo at qca.qualcomm.com  Fri Jul 18 05:41:07 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 18 Jul 2014 15:41:07 +0300
Subject: [PATCH v3] ath10k: fix Rx aggregation reordering
In-Reply-To: <CA+BoTQkk5oYS4JZ5a6W02rZ62AgxcHE76knS7QA2VfZDxYi2Jg@mail.gmail.com>
 (Michal Kazior's message of "Wed, 16 Jul 2014 14:41:27 +0200")
References: <1405505855-13741-1-git-send-email-michal.kazior@tieto.com>
 <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
 <53C66422.10702@gmail.com>
 <CA+BoTQn8TYX4vDx=K4P5rE+LBXrrUL2q1E7GsiOpBj82QgRKsw@mail.gmail.com>
 <CA+BoTQkk5oYS4JZ5a6W02rZ62AgxcHE76knS7QA2VfZDxYi2Jg@mail.gmail.com>
Message-ID: <87tx6e261o.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

>>> Here my concern in amount of time holding the lock...
>>>
>>> spin_lock_bh(&ar->data_lock);
>>> peer = ath10k_peer_find_by_id(ar, peer_id);
>>> if (!peer) {
>>>         spin_unlock_bh(&ar->data_lock);
>>>
>>>         ath10k_warn("received addba event for invalid peer_id: %hu\n",
>>>                     peer_id);
>>>         return;
>>> }
>>>
>>> No need to of putting the debug message inside the critical region...  :-)
>>
>> Sounds reasonable in this case as I'm not printing spinlock-protected values.
>
> ..and I realized this isn't true upon hitting the send button.
>
> The other print uses peer->vdev_id. The peer was acquired under a lock
> and must not be used after the lock is released. It'll just look
> confusing if I mix ordering of unlock/print in some cases so I'll
> leave it as is.

I actually prefer also the original form of "warn(); unlock(); return;",
somehow it feels more natural for me. And this is on error path where
efficiency is not really a priority.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Fri Jul 18 05:50:05 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 18 Jul 2014 15:50:05 +0300
Subject: [PATCH] ath10k: handle attention flags correctly when A-MSDU
In-Reply-To: <1405342041-7114-1-git-send-email-janusz.dziedzic@tieto.com>
 (Janusz Dziedzic's message of "Mon, 14 Jul 2014 14:47:21 +0200")
References: <1405342041-7114-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <87pph225mq.fsf@kamboji.qca.qualcomm.com>

Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:

> In case of A-MSDU RX we should check flags for all
> MSDU subframes to be sure we have correct FCS status.
>
> Before we check attention flags only for first frame
> where we didn't have correct info about FCS status in
> case of A-MSDU. Next didn't mark RX_FLAG_FAILED_FCS_CRC
> for skb. As a side efect we see big TP drop when TCP used.
> This was easy to reproduce when AP interface was used
> and added monitor interface run in promiscuous mode.
>
> Reported-by: Denton Gentry <denton.gentry at gmail.com>
> Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>

I'm having a hard time to understand the commit log. I think it would
make it easier to read if you first clearly describe the bug you are
fixing and then, in a separate paragraph, tell how you fix it.

So what is the bug Denton reported? "we see big TP drop when TCP used"
implies that this happens with all TCP traffic, but that can't be right.
Or did it happen with one of the reorder patches?

-- 
Kalle Valo


From michal.kazior at tieto.com  Fri Jul 18 05:45:01 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Fri, 18 Jul 2014 14:45:01 +0200
Subject: [PATCH] ath10k: prevent endless pci rx loop
Message-ID: <1405687501-25917-1-git-send-email-michal.kazior@tieto.com>

It was possible to enter an endless loop while
processing a single pci copy engine pipe. This
could effectively render ath10k incapable of
responding to any requests.

An example case when this could happen is when
firmware generates a lot of events, e.g. spectral
scan phyerr via WMI.

Reported-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
Janusz was testing spectral scan when he found
ath10k would sometimes stop responding while
flooding dmesg with phyerr prints.

There's another bug he found related to scan code
but we still need to test some stuff before I can
post the fix.

 drivers/net/wireless/ath/ath10k/pci.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 06840d1..0ffff20 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -726,18 +726,12 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
 	unsigned int nbytes, max_nbytes;
 	unsigned int transfer_id;
 	unsigned int flags;
-	int err;
+	int err, num_replenish = 0;
 
 	while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
 					     &ce_data, &nbytes, &transfer_id,
 					     &flags) == 0) {
-		err = ath10k_pci_post_rx_pipe(pipe_info, 1);
-		if (unlikely(err)) {
-			/* FIXME: retry */
-			ath10k_warn("failed to replenish CE rx ring %d: %d\n",
-				    pipe_info->pipe_num, err);
-		}
-
+		num_replenish++;
 		skb = transfer_context;
 		max_nbytes = skb->len + skb_tailroom(skb);
 		dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
@@ -753,6 +747,13 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
 		skb_put(skb, nbytes);
 		cb->rx_completion(ar, skb, pipe_info->pipe_num);
 	}
+
+	err = ath10k_pci_post_rx_pipe(pipe_info, num_replenish);
+	if (unlikely(err)) {
+		/* FIXME: retry */
+		ath10k_warn("failed to replenish CE rx ring %d (%d bufs): %d\n",
+			    pipe_info->pipe_num, num_replenish, err);
+	}
 }
 
 static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
-- 
1.8.5.3



From sw at simonwunderlich.de  Fri Jul 18 06:26:30 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Fri, 18 Jul 2014 15:26:30 +0200
Subject: [PATCH 0/2] ath10k spectral scan support
Message-ID: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>

This is the first "PATCH" patchset iteration for the ath10k spectral
scan feature. The feature is still experimental, but we made quite
some progress.

The fft_eval tool has also been updated based on the new patchset, and
now supports both ath9k and ath10k sample formats in the same branch,
which has been merged into master [1].

The bin issue has been solved thanks to the valuable input of Michal and
Kathy! In my tests, most modes seem to support 64, 128 or 256 bins, and
an option to configure that has been added. 512 bins should be possible
as well under some circumstances according to Kathys mail, but I couldn't
get that working. Also HT80/64 bin reports look bogus, so these are
disabled for now. FFT_eval includes some data samples in case you are
interested.

The count issue is still open: Even when a count is specified, the
hardware seems to send endless samples. It seems to work most of the
time in VHT80 mode though, but in HT20 and HT40 the count value seems
to be ignored. To reproduce this, start hostapd with the desired
channel width and do:

echo 8 > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_count
echo manual > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
echo trigger > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 >> /tmp/fft.dump

Repeating the last line and checking the filesize will easily show
whether ath10k still sends samples or not. We would expect 8 samples in
this configuration.

See the patch for more information on the changes.

Thanks again to Michal, Kathy, Kalle and Sven for their support!

Cheers,
	Simon

[1] https://github.com/simonwunderlich/FFT_eval

Simon Wunderlich (1):
  ath10k: add spectral scan feature

Sven Eckelmann (1):
  ath: Move spectral debugfs structs to shared header

 drivers/net/wireless/ath/ath10k/Kconfig    |   1 +
 drivers/net/wireless/ath/ath10k/Makefile   |   3 +-
 drivers/net/wireless/ath/ath10k/core.c     |   4 +
 drivers/net/wireless/ath/ath10k/core.h     |   7 +
 drivers/net/wireless/ath/ath10k/debug.c    |   3 +
 drivers/net/wireless/ath/ath10k/mac.c      |   8 +
 drivers/net/wireless/ath/ath10k/spectral.c | 558 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |  64 ++++
 drivers/net/wireless/ath/ath10k/wmi.c      | 104 +++++-
 drivers/net/wireless/ath/ath10k/wmi.h      |  94 +++++
 drivers/net/wireless/ath/ath9k/spectral.h  |  71 +---
 drivers/net/wireless/ath/spectral_common.h | 112 ++++++
 12 files changed, 958 insertions(+), 71 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h
 create mode 100644 drivers/net/wireless/ath/spectral_common.h

-- 
1.9.1



From sw at simonwunderlich.de  Fri Jul 18 06:26:31 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Fri, 18 Jul 2014 15:26:31 +0200
Subject: [PATCH 1/2] ath: Move spectral debugfs structs to shared header
In-Reply-To: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
References: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <1405689992-8538-2-git-send-email-sw@simonwunderlich.de>

From: Sven Eckelmann <sven at narfation.org>

The ath9k and ath10k will share the definitions of the debugfs spectral
structures and enums. Having them in the same place helps to avoid conflicts.

Signed-off-by: Sven Eckelmann <sven at narfation.org>
Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
---
 drivers/net/wireless/ath/ath9k/spectral.h  | 71 +-----------------------
 drivers/net/wireless/ath/spectral_common.h | 88 ++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 69 deletions(-)
 create mode 100644 drivers/net/wireless/ath/spectral_common.h

diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h
index 137e2e6..0b9465e 100644
--- a/drivers/net/wireless/ath/ath9k/spectral.h
+++ b/drivers/net/wireless/ath/ath9k/spectral.h
@@ -17,6 +17,8 @@
 #ifndef SPECTRAL_H
 #define SPECTRAL_H
 
+#include "../spectral_common.h"
+
 /* enum spectral_mode:
  *
  * @SPECTRAL_DISABLED: spectral mode is disabled
@@ -54,8 +56,6 @@ struct ath_ht20_mag_info {
 	u8 max_exp;
 } __packed;
 
-#define SPECTRAL_HT20_NUM_BINS		56
-
 /* WARNING: don't actually use this struct! MAC may vary the amount of
  * data by -1/+2. This struct is for reference only.
  */
@@ -83,8 +83,6 @@ struct ath_ht20_40_mag_info {
 	u8 max_exp;
 } __packed;
 
-#define SPECTRAL_HT20_40_NUM_BINS		128
-
 /* WARNING: don't actually use this struct! MAC may vary the amount of
  * data. This struct is for reference only.
  */
@@ -125,71 +123,6 @@ static inline u8 spectral_bitmap_weight(u8 *bins)
 	return bins[0] & 0x3f;
 }
 
-/* FFT sample format given to userspace via debugfs.
- *
- * Please keep the type/length at the front position and change
- * other fields after adding another sample type
- *
- * TODO: this might need rework when switching to nl80211-based
- * interface.
- */
-enum ath_fft_sample_type {
-	ATH_FFT_SAMPLE_HT20 = 1,
-	ATH_FFT_SAMPLE_HT20_40,
-};
-
-struct fft_sample_tlv {
-	u8 type;	/* see ath_fft_sample */
-	__be16 length;
-	/* type dependent data follows */
-} __packed;
-
-struct fft_sample_ht20 {
-	struct fft_sample_tlv tlv;
-
-	u8 max_exp;
-
-	__be16 freq;
-	s8 rssi;
-	s8 noise;
-
-	__be16 max_magnitude;
-	u8 max_index;
-	u8 bitmap_weight;
-
-	__be64 tsf;
-
-	u8 data[SPECTRAL_HT20_NUM_BINS];
-} __packed;
-
-struct fft_sample_ht20_40 {
-	struct fft_sample_tlv tlv;
-
-	u8 channel_type;
-	__be16 freq;
-
-	s8 lower_rssi;
-	s8 upper_rssi;
-
-	__be64 tsf;
-
-	s8 lower_noise;
-	s8 upper_noise;
-
-	__be16 lower_max_magnitude;
-	__be16 upper_max_magnitude;
-
-	u8 lower_max_index;
-	u8 upper_max_index;
-
-	u8 lower_bitmap_weight;
-	u8 upper_bitmap_weight;
-
-	u8 max_exp;
-
-	u8 data[SPECTRAL_HT20_40_NUM_BINS];
-} __packed;
-
 void ath9k_spectral_init_debug(struct ath_softc *sc);
 void ath9k_spectral_deinit_debug(struct ath_softc *sc);
 
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
new file mode 100644
index 0000000..b9ab722
--- /dev/null
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_COMMON_H
+#define SPECTRAL_COMMON_H
+
+#define SPECTRAL_HT20_NUM_BINS		56
+#define SPECTRAL_HT20_40_NUM_BINS		128
+
+/* FFT sample format given to userspace via debugfs.
+ *
+ * Please keep the type/length at the front position and change
+ * other fields after adding another sample type
+ *
+ * TODO: this might need rework when switching to nl80211-based
+ * interface.
+ */
+enum ath_fft_sample_type {
+	ATH_FFT_SAMPLE_HT20 = 1,
+	ATH_FFT_SAMPLE_HT20_40,
+};
+
+struct fft_sample_tlv {
+	u8 type;	/* see ath_fft_sample */
+	__be16 length;
+	/* type dependent data follows */
+} __packed;
+
+struct fft_sample_ht20 {
+	struct fft_sample_tlv tlv;
+
+	u8 max_exp;
+
+	__be16 freq;
+	s8 rssi;
+	s8 noise;
+
+	__be16 max_magnitude;
+	u8 max_index;
+	u8 bitmap_weight;
+
+	__be64 tsf;
+
+	u8 data[SPECTRAL_HT20_NUM_BINS];
+} __packed;
+
+struct fft_sample_ht20_40 {
+	struct fft_sample_tlv tlv;
+
+	u8 channel_type;
+	__be16 freq;
+
+	s8 lower_rssi;
+	s8 upper_rssi;
+
+	__be64 tsf;
+
+	s8 lower_noise;
+	s8 upper_noise;
+
+	__be16 lower_max_magnitude;
+	__be16 upper_max_magnitude;
+
+	u8 lower_max_index;
+	u8 upper_max_index;
+
+	u8 lower_bitmap_weight;
+	u8 upper_bitmap_weight;
+
+	u8 max_exp;
+
+	u8 data[SPECTRAL_HT20_40_NUM_BINS];
+} __packed;
+
+#endif /* SPECTRAL_COMMON_H */
-- 
1.9.1



From sw at simonwunderlich.de  Fri Jul 18 06:26:32 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Fri, 18 Jul 2014 15:26:32 +0200
Subject: [PATCH 2/2] ath10k: add spectral scan feature
In-Reply-To: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
References: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <1405689992-8538-3-git-send-email-sw@simonwunderlich.de>

Adds the spectral scan feature for ath10k. The spectral scan is triggered by
configuring a mode through a debugfs control file. Samples can be gathered via
another relay debugfs file.

Essentially, to try it out:

ip link dev wlan0 set up
echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
iw dev wlan0 scan
echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples

This feature is still experimental. Based on the original RFC patch of
Sven Eckelmann.

Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
--
PATCH:
 * change the tlv format to a variable-length format, depending on the
   number of bins
 * perform dc interpolation and max_exp calculation in the driver (as
   for ath9k)
 * make fft_size configurable
 * background scan will only start after beeing trigger, like in ath9k
 * document at least some spectral configuration members (thanks Kathy)
 * fix sparse problems
 * sample bandwidth appears to be 110% of what is reported by the
   hardware according to the plotter (e.g. 20->22, 40->44 MHz etc),
   so fix that in the driver.
 * disable spectral for a vif when it's beeing deleted and still active
   (Michals comment)
 * modify ath_ prefix of function/struct/enum to ath10k_ (Michal)
 * changed variable ret to res (Michal)
 * added ath10k_warn messages (Michal)
 * renamed wmi functions (Michal)
 * use ar->conf_mutex for locking (Michal)
 * renamed mhz to chan_width_mhz (Michal)
 * only enable spectral scan files when ATH10K_DEBUGFS is enabled
---
 drivers/net/wireless/ath/ath10k/Kconfig    |   1 +
 drivers/net/wireless/ath/ath10k/Makefile   |   3 +-
 drivers/net/wireless/ath/ath10k/core.c     |   4 +
 drivers/net/wireless/ath/ath10k/core.h     |   7 +
 drivers/net/wireless/ath/ath10k/debug.c    |   3 +
 drivers/net/wireless/ath/ath10k/mac.c      |   8 +
 drivers/net/wireless/ath/ath10k/spectral.c | 558 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |  64 ++++
 drivers/net/wireless/ath/ath10k/wmi.c      | 104 +++++-
 drivers/net/wireless/ath/ath10k/wmi.h      |  94 +++++
 drivers/net/wireless/ath/spectral_common.h |  24 ++
 11 files changed, 868 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h

diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index 489bf8b..095dcaf 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -27,6 +27,7 @@ config ATH10K_DEBUG
 config ATH10K_DEBUGFS
 	bool "Atheros ath10k debugfs support"
 	depends on ATH10K
+	select RELAY
 	---help---
 	  Enabled debugfs support
 
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index 2110a5c..e1dcefd 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -8,7 +8,8 @@ ath10k_core-y += mac.o \
 		 htt_tx.o \
 		 txrx.o \
 		 wmi.o \
-		 bmi.o
+		 bmi.o \
+		 spectral.o
 
 ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
 
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index ebc5fc2..3a113fb 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -699,6 +699,10 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 	ar->hif.priv = hif_priv;
 	ar->hif.ops = hif_ops;
 
+	ar->spectral_mode = SPECTRAL_DISABLED;
+	ar->spec_config.count = WMI_SPECTRAL_COUNT_DEFAULT;
+	ar->spec_config.fft_size = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
+
 	init_completion(&ar->scan.started);
 	init_completion(&ar->scan.completed);
 	init_completion(&ar->scan.on_channel);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 80aa5a4..5fc7ff5 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -31,6 +31,7 @@
 #include "../ath.h"
 #include "../regd.h"
 #include "../dfs_pattern_detector.h"
+#include "spectral.h"
 
 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -230,6 +231,7 @@ struct ath10k_vif {
 
 	bool is_started;
 	bool is_up;
+	bool spectral_enabled;
 	u32 aid;
 	u8 bssid[ETH_ALEN];
 
@@ -469,6 +471,11 @@ struct ath10k {
 #ifdef CONFIG_ATH10K_DEBUGFS
 	struct ath10k_debug debug;
 #endif
+
+	/* relay(fs) channel for spectral scan */
+	struct rchan *rfs_chan_spec_scan;
+	enum ath10k_spectral_mode spectral_mode;
+	struct ath10k_spec_scan spec_config;
 };
 
 struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index a84691e..e39aa96 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -827,12 +827,15 @@ int ath10k_debug_create(struct ath10k *ar)
 				    &fops_dfs_stats);
 	}
 
+	ath10k_spectral_init_debug(ar);
+
 	return 0;
 }
 
 void ath10k_debug_destroy(struct ath10k *ar)
 {
 	cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
+	ath10k_spectral_deinit_debug(ar);
 }
 
 #endif /* CONFIG_ATH10K_DEBUGFS */
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 348a639..c369ac1 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2671,8 +2671,16 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 		dev_kfree_skb_any(arvif->beacon);
 		arvif->beacon = NULL;
 	}
+
 	spin_unlock_bh(&ar->data_lock);
 
+	if (arvif->spectral_enabled) {
+		ret = ath10k_interface_disable_spectral(arvif);
+		if (ret)
+			ath10k_warn("spectral disable for vdev %i failed\n",
+				    arvif->vdev_id);
+	}
+
 	ar->free_vdev_map |= 1 << (arvif->vdev_id);
 	list_del(&arvif->list);
 
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
new file mode 100644
index 0000000..a7a74f7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -0,0 +1,558 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/relay.h>
+#include "core.h"
+#include "debug.h"
+
+static void ath10k_debug_send_fft_sample(struct ath10k *ar,
+					 struct fft_sample_tlv *fft_sample_tlv)
+{
+	int length;
+
+	if (!ar->rfs_chan_spec_scan)
+		return;
+
+	length = __be16_to_cpu(fft_sample_tlv->length) +
+		 sizeof(*fft_sample_tlv);
+	relay_write(ar->rfs_chan_spec_scan, fft_sample_tlv, length);
+}
+
+static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
+			   u8 *data)
+{
+	int dc_pos;
+	u8 max_exp;
+
+	dc_pos = bin_len / 2;
+	/* peak index outside of bins */
+	if (dc_pos < max_index || -dc_pos >= max_index)
+		return 0;
+
+	for (max_exp = 0; max_exp < 8; max_exp++) {
+		if (data[dc_pos + max_index] == (max_magnitude >> max_exp))
+			break;
+	}
+
+	/* max_exp not found */
+	if (data[dc_pos + max_index] != (max_magnitude >> max_exp))
+		return 0;
+
+	return max_exp;
+}
+
+int ath10k_process_fft(struct ath10k *ar,
+		       struct wmi_single_phyerr_rx_event *event,
+		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
+{
+	struct fft_sample_ath10k *fft_sample;
+	u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
+	int dc_pos;
+	u32 reg0, reg1;
+	u16 peak_mag;
+	u8 *bins;
+	u16 freq1;
+	u16 freq2;
+	u16 total_gain_db;
+	u16 base_pwr_db;
+	u8 chain_idx;
+	u32 nf_list1;
+	u32 nf_list2;
+	u16 length;
+
+	fft_sample = (struct fft_sample_ath10k *)&buf;
+
+	if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
+		return -EINVAL;
+
+	reg0 = __le32_to_cpu(fftr->reg0);
+	reg1 = __le32_to_cpu(fftr->reg1);
+
+	length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + bin_len;
+	fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH10K;
+	fft_sample->tlv.length = __cpu_to_be16(length);
+
+	/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
+	 * but the results/plots suggest that its actually 22/44/88 MHz.
+	 */
+	switch (event->hdr.chan_width_mhz) {
+	case 20:
+		fft_sample->chan_width_mhz = 22;
+		break;
+	case 40:
+		fft_sample->chan_width_mhz = 44;
+		break;
+	case 80:
+		/* TODO: As experiments with an analogue sender and various
+		 * configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
+		 * show, the particular configuration of 80 MHz/64 bins does
+		 * not match with the other smaples at all. Until the reason
+		 * for that is found, don't report these samples.
+		 */
+		if (bin_len == 64)
+			return -EINVAL;
+		fft_sample->chan_width_mhz = 88;
+		break;
+	default:
+		fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
+	}
+	fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
+	fft_sample->avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
+
+	peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
+	fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
+	fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
+	fft_sample->rssi = event->hdr.rssi_combined;
+
+	total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
+	base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
+	fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
+	fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
+
+	freq1 = __le16_to_cpu(event->hdr.freq1);
+	freq2 = __le16_to_cpu(event->hdr.freq2);
+	fft_sample->freq1 = __cpu_to_be16(freq1);
+	fft_sample->freq2 = __cpu_to_be16(freq2);
+
+	nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
+	nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
+	chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
+	switch (chain_idx) {
+	case 0:
+		fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
+		break;
+	case 1:
+		fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
+		break;
+	case 2:
+		fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
+		break;
+	case 3:
+		fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
+		break;
+	}
+
+	bins = (u8 *)fftr;
+	bins += sizeof(*fftr);
+
+	fft_sample->tsf = __cpu_to_be64(tsf);
+	/* max_exp has been directly reported by previous hardware (ath9k),
+	 * maybe its possible to get it by other means?
+	 */
+	fft_sample->max_exp = get_max_exp(fft_sample->max_index, peak_mag,
+					  bin_len, bins);
+
+	memcpy(fft_sample->data, bins, bin_len);
+
+	/* DC value (value in the middle) is the blind spot of the spectral
+	 * sample and invalid, interpolate it.
+	 */
+	dc_pos = bin_len / 2;
+	fft_sample->data[dc_pos] = (fft_sample->data[dc_pos + 1] +
+				    fft_sample->data[dc_pos - 1]) / 2;
+
+	ath10k_debug_send_fft_sample(ar, &fft_sample->tlv);
+
+	return 0;
+}
+
+static struct ath10k_vif *ath10k_get_spectral_vdev(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	if (list_empty(&ar->arvifs))
+		return NULL;
+
+	/* if there already is a vif doing spectral, return that. */
+	list_for_each_entry(arvif, &ar->arvifs, list)
+		if (arvif->spectral_enabled)
+			return arvif;
+
+	/* otherwise, return the first vif. */
+	return list_first_entry(&ar->arvifs, typeof(*arvif), list);
+}
+
+static int ath10k_spectral_scan_trigger(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+	int res;
+	int vdev_id;
+
+	arvif = ath10k_get_spectral_vdev(ar);
+	if (!arvif)
+		return -ENODEV;
+	vdev_id = arvif->vdev_id;
+
+	if (ar->spectral_mode == SPECTRAL_DISABLED)
+		return 0;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (res < 0)
+		return res;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
+					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (res < 0)
+		return res;
+
+	return 0;
+}
+
+static int ath10k_spectral_scan_config(struct ath10k *ar,
+				       enum ath10k_spectral_mode mode)
+{
+	struct wmi_vdev_spectral_conf_arg arg;
+	struct ath10k_vif *arvif;
+	int vdev_id, count, res = 0;
+
+	arvif = ath10k_get_spectral_vdev(ar);
+	if (!arvif)
+		return -ENODEV;
+
+	vdev_id = arvif->vdev_id;
+
+	arvif->spectral_enabled = (mode != SPECTRAL_DISABLED);
+	ar->spectral_mode = mode;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					      WMI_SPECTRAL_ENABLE_CMD_DISABLE);
+	if (res < 0) {
+		ath10k_warn("failed to enable spectral scan: %d\n", res);
+		return res;
+	}
+
+	if (mode == SPECTRAL_DISABLED)
+		return 0;
+
+	if (mode == SPECTRAL_BACKGROUND)
+		count = WMI_SPECTRAL_COUNT_DEFAULT;
+	else
+		count = max_t(u8, 1, ar->spec_config.count);
+
+	arg.vdev_id              = vdev_id;
+	arg.scan_count           = count;
+	arg.scan_period          = WMI_SPECTRAL_PERIOD_DEFAULT;
+	arg.scan_priority        = WMI_SPECTRAL_PRIORITY_DEFAULT;
+	arg.scan_fft_size        = ar->spec_config.fft_size;
+	arg.scan_gc_ena          = WMI_SPECTRAL_GC_ENA_DEFAULT;
+	arg.scan_restart_ena     = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
+	arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
+	arg.scan_init_delay      = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
+	arg.scan_nb_tone_thr     = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
+	arg.scan_str_bin_thr     = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
+	arg.scan_wb_rpt_mode     = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
+	arg.scan_rssi_rpt_mode   = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
+	arg.scan_rssi_thr        = WMI_SPECTRAL_RSSI_THR_DEFAULT;
+	arg.scan_pwr_format      = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
+	arg.scan_rpt_mode        = WMI_SPECTRAL_RPT_MODE_DEFAULT;
+	arg.scan_bin_scale       = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	arg.scan_dbm_adj         = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
+	arg.scan_chn_mask        = WMI_SPECTRAL_CHN_MASK_DEFAULT;
+
+	res = ath10k_wmi_vdev_spectral_conf(ar, &arg);
+	if (res < 0) {
+		ath10k_warn("failed to configure spectral scan: %d\n", res);
+		return res;
+	}
+
+	return 0;
+}
+
+int ath10k_interface_disable_spectral(struct ath10k_vif *arvif)
+{
+	return ath10k_spectral_scan_config(arvif->ar, SPECTRAL_DISABLED);
+}
+
+/*********************/
+/* spectral_scan_ctl */
+/*********************/
+
+static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char *mode = "";
+	unsigned int len;
+	enum ath10k_spectral_mode spectral_mode;
+
+	mutex_lock(&ar->conf_mutex);
+	spectral_mode = ar->spectral_mode;
+	mutex_unlock(&ar->conf_mutex);
+
+	switch (spectral_mode) {
+	case SPECTRAL_DISABLED:
+		mode = "disable";
+		break;
+	case SPECTRAL_BACKGROUND:
+		mode = "background";
+		break;
+	case SPECTRAL_MANUAL:
+		mode = "manual";
+		break;
+	}
+
+	len = strlen(mode);
+	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
+}
+
+static ssize_t write_file_spec_scan_ctl(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	ssize_t len;
+	int res;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (strncmp("trigger", buf, 7) == 0) {
+		if (ar->spectral_mode == SPECTRAL_MANUAL ||
+		    ar->spectral_mode == SPECTRAL_BACKGROUND) {
+			/* reset the configuration to adopt possibly changed
+			 * debugfs parameters
+			 */
+			res = ath10k_spectral_scan_config(ar,
+							  ar->spectral_mode);
+			if (res < 0) {
+				ath10k_warn("failed to reconfigure spectral scan: %d\n",
+					    res);
+			}
+			res = ath10k_spectral_scan_trigger(ar);
+			if (res < 0) {
+				ath10k_warn("failed to trigger spectral scan: %d\n",
+					    res);
+			}
+		} else {
+			res = -EINVAL;
+		}
+	} else if (strncmp("background", buf, 9) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
+	} else if (strncmp("manual", buf, 6) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
+	} else if (strncmp("disable", buf, 7) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
+	} else {
+		res = -EINVAL;
+	}
+
+	mutex_unlock(&ar->conf_mutex);
+
+	if (res < 0)
+		return res;
+
+	return count;
+}
+
+static const struct file_operations fops_spec_scan_ctl = {
+	.read = read_file_spec_scan_ctl,
+	.write = write_file_spec_scan_ctl,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+/******************/
+/* spectral_count */
+/******************/
+
+static ssize_t read_file_spectral_count(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len;
+	u8 spectral_count;
+
+	mutex_lock(&ar->conf_mutex);
+	spectral_count = ar->spec_config.count;
+	mutex_unlock(&ar->conf_mutex);
+
+	len = sprintf(buf, "%d\n", spectral_count);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_count(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 0 || val > 255)
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+	ar->spec_config.count = val;
+	mutex_unlock(&ar->conf_mutex);
+
+	return count;
+}
+
+static const struct file_operations fops_spectral_count = {
+	.read = read_file_spectral_count,
+	.write = write_file_spectral_count,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+/*****************/
+/* spectral_bins */
+/*****************/
+
+static ssize_t read_file_spectral_bins(struct file *file,
+				       char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len;
+	unsigned int bins;
+
+	mutex_lock(&ar->conf_mutex);
+	bins = 1 << (ar->spec_config.fft_size - WMI_SPECTRAL_BIN_SCALE_DEFAULT);
+	mutex_unlock(&ar->conf_mutex);
+
+	len = sprintf(buf, "%d\n", bins);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_bins(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
+		return -EINVAL;
+
+	if (!is_power_of_2(val))
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+	ar->spec_config.fft_size = ilog2(val);
+	ar->spec_config.fft_size += WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	mutex_unlock(&ar->conf_mutex);
+
+	return count;
+}
+
+static const struct file_operations fops_spectral_bins = {
+	.read = read_file_spectral_bins,
+	.write = write_file_spectral_bins,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+/*******************/
+/* Relay interface */
+/*******************/
+
+static struct dentry *create_buf_file_handler(const char *filename,
+					      struct dentry *parent,
+					      umode_t mode,
+					      struct rchan_buf *buf,
+					      int *is_global)
+{
+	struct dentry *buf_file;
+
+	buf_file = debugfs_create_file(filename, mode, parent, buf,
+				       &relay_file_operations);
+	*is_global = 1;
+	return buf_file;
+}
+
+static int remove_buf_file_handler(struct dentry *dentry)
+{
+	debugfs_remove(dentry);
+
+	return 0;
+}
+
+static struct rchan_callbacks rfs_spec_scan_cb = {
+	.create_buf_file = create_buf_file_handler,
+	.remove_buf_file = remove_buf_file_handler,
+};
+
+/*********************/
+/* Debug Init/Deinit */
+/*********************/
+
+void ath10k_spectral_deinit_debug(struct ath10k *ar)
+{
+	if (config_enabled(CONFIG_ATH10K_DEBUGFS) && ar->rfs_chan_spec_scan) {
+		relay_close(ar->rfs_chan_spec_scan);
+		ar->rfs_chan_spec_scan = NULL;
+	}
+}
+
+void ath10k_spectral_init_debug(struct ath10k *ar)
+{
+#ifdef CONFIG_ATH10K_DEBUGFS
+	ar->rfs_chan_spec_scan = relay_open("spectral_scan",
+					    ar->debug.debugfs_phy,
+					    1024, 256, &rfs_spec_scan_cb,
+					    NULL);
+	debugfs_create_file("spectral_scan_ctl",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spec_scan_ctl);
+	debugfs_create_file("spectral_count",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_count);
+	debugfs_create_file("spectral_bins",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_bins);
+#endif
+}
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
new file mode 100644
index 0000000..40c0718
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_H
+#define SPECTRAL_H
+
+#include "../spectral_common.h"
+
+/**
+ * struct ath10k_spec_scan - parameters for Atheros spectral scan
+ *
+ * @count: number of scan results requested for manual mode
+ */
+struct ath10k_spec_scan {
+	u8 count;
+	u8 fft_size;
+};
+
+/* enum ath10k_spectral_mode:
+ *
+ * @SPECTRAL_DISABLED: spectral mode is disabled
+ * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
+ *	something else.
+ * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
+ *	is performed manually.
+ */
+enum ath10k_spectral_mode {
+	SPECTRAL_DISABLED = 0,
+	SPECTRAL_BACKGROUND,
+	SPECTRAL_MANUAL,
+};
+
+void ath10k_spectral_init_debug(struct ath10k *ar);
+void ath10k_spectral_deinit_debug(struct ath10k *ar);
+int ath10k_interface_disable_spectral(struct ath10k_vif *arvif);
+
+#ifdef CONFIG_ATH10K_DEBUGFS
+int ath10k_process_fft(struct ath10k *ar,
+		       struct wmi_single_phyerr_rx_event *event,
+		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf);
+#else
+static inline int
+ath10k_process_fft(struct ath10k *ar,
+		   struct wmi_single_phyerr_rx_event *event,
+		   struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
+{
+	return 0;
+}
+#endif /* CONFIG_ATH10K_DEBUGFS */
+
+#endif /* SPECTRAL_H */
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index beac30d..1422296 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1649,7 +1649,53 @@ static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
 				struct wmi_single_phyerr_rx_event *event,
 				u64 tsf)
 {
-	ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n");
+	int buf_len, tlv_len, res, i = 0;
+	struct phyerr_tlv *tlv;
+	u8 *tlv_buf;
+	struct phyerr_fft_report *fftr;
+	size_t fftr_len;
+
+	buf_len = __le32_to_cpu(event->hdr.buf_len);
+
+	while (i < buf_len) {
+		if (i + sizeof(*tlv) > buf_len) {
+			ath10k_warn("failed to parse phyerr tlv header at byte %d\n",
+				    i);
+			return;
+		}
+
+		tlv = (struct phyerr_tlv *)&event->bufp[i];
+		tlv_len = __le16_to_cpu(tlv->len);
+		tlv_buf = &event->bufp[i + sizeof(*tlv)];
+
+		if (i + sizeof(*tlv) + tlv_len > buf_len) {
+			ath10k_warn("failed to parse phyerr tlv payload at byte %d\n",
+				    i);
+			return;
+		}
+
+		switch (tlv->tag) {
+		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
+			if (sizeof(*fftr) > tlv_len) {
+				ath10k_warn("failed to parse fft report at byte %d\n",
+					    i);
+				return;
+			}
+
+			fftr_len = tlv_len - sizeof(*fftr);
+			fftr = (struct phyerr_fft_report *)tlv_buf;
+			res = ath10k_process_fft(ar, event, fftr, fftr_len,
+						 tsf);
+			if (res < 0) {
+				ath10k_warn("failed to process fft report: %d\n",
+					    res);
+				return;
+			}
+			break;
+		}
+
+		i += sizeof(*tlv) + tlv_len;
+	}
 }
 
 static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
@@ -3191,6 +3237,62 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				   ar->wmi.cmd->vdev_install_key_cmdid);
 }
 
+int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
+				  const struct wmi_vdev_spectral_conf_arg *arg)
+{
+	struct wmi_vdev_spectral_conf_cmd *cmd;
+	struct sk_buff *skb;
+	u32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_conf_cmd *)skb->data;
+	cmd->vdev_id              = __cpu_to_le32(arg->vdev_id);
+	cmd->scan_count           = __cpu_to_le32(arg->scan_count);
+	cmd->scan_period          = __cpu_to_le32(arg->scan_period);
+	cmd->scan_priority        = __cpu_to_le32(arg->scan_priority);
+	cmd->scan_fft_size        = __cpu_to_le32(arg->scan_fft_size);
+	cmd->scan_gc_ena          = __cpu_to_le32(arg->scan_gc_ena);
+	cmd->scan_restart_ena     = __cpu_to_le32(arg->scan_restart_ena);
+	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
+	cmd->scan_init_delay      = __cpu_to_le32(arg->scan_init_delay);
+	cmd->scan_nb_tone_thr     = __cpu_to_le32(arg->scan_nb_tone_thr);
+	cmd->scan_str_bin_thr     = __cpu_to_le32(arg->scan_str_bin_thr);
+	cmd->scan_wb_rpt_mode     = __cpu_to_le32(arg->scan_wb_rpt_mode);
+	cmd->scan_rssi_rpt_mode   = __cpu_to_le32(arg->scan_rssi_rpt_mode);
+	cmd->scan_rssi_thr        = __cpu_to_le32(arg->scan_rssi_thr);
+	cmd->scan_pwr_format      = __cpu_to_le32(arg->scan_pwr_format);
+	cmd->scan_rpt_mode        = __cpu_to_le32(arg->scan_rpt_mode);
+	cmd->scan_bin_scale       = __cpu_to_le32(arg->scan_bin_scale);
+	cmd->scan_dbm_adj         = __cpu_to_le32(arg->scan_dbm_adj);
+	cmd->scan_chn_mask        = __cpu_to_le32(arg->scan_chn_mask);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_configure_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
+int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				    u32 enable)
+{
+	struct wmi_vdev_spectral_enable_cmd *cmd;
+	struct sk_buff *skb;
+	u32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_enable_cmd *)skb->data;
+	cmd->vdev_id     = __cpu_to_le32(vdev_id);
+	cmd->trigger_cmd = __cpu_to_le32(trigger);
+	cmd->enable_cmd  = __cpu_to_le32(enable);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_enable_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 			   const u8 peer_addr[ETH_ALEN])
 {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 4fcc96a..da5cbda 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2077,6 +2077,7 @@ struct wmi_comb_phyerr_rx_event {
 #define PHYERR_TLV_SIG				0xBB
 #define PHYERR_TLV_TAG_SEARCH_FFT_REPORT	0xFB
 #define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY	0xF8
+#define PHYERR_TLV_TAG_SPECTRAL_SUMMARY_REPORT	0xF9
 
 struct phyerr_radar_report {
 	__le32 reg0; /* RADAR_REPORT_REG0_* */
@@ -3381,6 +3382,95 @@ struct wmi_vdev_simple_event {
 /* unsupported VDEV combination */
 #define WMI_INIFIED_VDEV_START_RESPONSE_NOT_SUPPORTED	0x2
 
+/* TODO: please add more comments if you have in-depth information */
+struct wmi_vdev_spectral_conf_cmd {
+	__le32 vdev_id;
+	/* number of fft samples to send (0 for infinite) */
+	__le32 scan_count;
+	__le32 scan_period;
+	__le32 scan_priority;
+	/* number of bins in the FFT: 2^(fft_size - bin_scale) */
+	__le32 scan_fft_size;
+	__le32 scan_gc_ena;
+	__le32 scan_restart_ena;
+	__le32 scan_noise_floor_ref;
+	__le32 scan_init_delay;
+	__le32 scan_nb_tone_thr;
+	__le32 scan_str_bin_thr;
+	__le32 scan_wb_rpt_mode;
+	__le32 scan_rssi_rpt_mode;
+	__le32 scan_rssi_thr;
+	__le32 scan_pwr_format;
+	/* rpt_mode: Format of FFT report to software for spectral scan
+	 * triggered FFTs:
+	 *	0: No FFT report (only spectral scan summary report)
+	 *	1: 2-dword summary of metrics for each completed FFT + spectral
+	 *	   scan	summary report
+	 *	2: 2-dword summary of metrics for each completed FFT +
+	 *	   1x- oversampled bins(in-band) per FFT + spectral scan summary
+	 *	   report
+	 *	3: 2-dword summary of metrics for each completed FFT +
+	 *	   2x- oversampled bins	(all) per FFT + spectral scan summary
+	 */
+	__le32 scan_rpt_mode;
+	__le32 scan_bin_scale;
+	__le32 scan_dbm_adj;
+	__le32 scan_chn_mask;
+} __packed;
+
+struct wmi_vdev_spectral_conf_arg {
+	u32 vdev_id;
+	u32 scan_count;
+	u32 scan_period;
+	u32 scan_priority;
+	u32 scan_fft_size;
+	u32 scan_gc_ena;
+	u32 scan_restart_ena;
+	u32 scan_noise_floor_ref;
+	u32 scan_init_delay;
+	u32 scan_nb_tone_thr;
+	u32 scan_str_bin_thr;
+	u32 scan_wb_rpt_mode;
+	u32 scan_rssi_rpt_mode;
+	u32 scan_rssi_thr;
+	u32 scan_pwr_format;
+	u32 scan_rpt_mode;
+	u32 scan_bin_scale;
+	u32 scan_dbm_adj;
+	u32 scan_chn_mask;
+};
+
+#define WMI_SPECTRAL_ENABLE_DEFAULT              0
+#define WMI_SPECTRAL_COUNT_DEFAULT               0
+#define WMI_SPECTRAL_PERIOD_DEFAULT             35
+#define WMI_SPECTRAL_PRIORITY_DEFAULT            1
+#define WMI_SPECTRAL_FFT_SIZE_DEFAULT            7
+#define WMI_SPECTRAL_GC_ENA_DEFAULT              1
+#define WMI_SPECTRAL_RESTART_ENA_DEFAULT         0
+#define WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT   -96
+#define WMI_SPECTRAL_INIT_DELAY_DEFAULT         80
+#define WMI_SPECTRAL_NB_TONE_THR_DEFAULT        12
+#define WMI_SPECTRAL_STR_BIN_THR_DEFAULT         8
+#define WMI_SPECTRAL_WB_RPT_MODE_DEFAULT         0
+#define WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT       0
+#define WMI_SPECTRAL_RSSI_THR_DEFAULT         0xf0
+#define WMI_SPECTRAL_PWR_FORMAT_DEFAULT          0
+#define WMI_SPECTRAL_RPT_MODE_DEFAULT            2
+#define WMI_SPECTRAL_BIN_SCALE_DEFAULT           1
+#define WMI_SPECTRAL_DBM_ADJ_DEFAULT             1
+#define WMI_SPECTRAL_CHN_MASK_DEFAULT            1
+
+struct wmi_vdev_spectral_enable_cmd {
+	__le32 vdev_id;
+	__le32 trigger_cmd;
+	__le32 enable_cmd;
+} __packed;
+
+#define WMI_SPECTRAL_TRIGGER_CMD_TRIGGER  1
+#define WMI_SPECTRAL_TRIGGER_CMD_CLEAR    2
+#define WMI_SPECTRAL_ENABLE_CMD_ENABLE    1
+#define WMI_SPECTRAL_ENABLE_CMD_DISABLE   2
+
 /* Beacon processing related command and event structures */
 struct wmi_bcn_tx_hdr {
 	__le32 vdev_id;
@@ -4226,6 +4316,10 @@ int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id,
 			      u32 param_id, u32 param_value);
 int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				const struct wmi_vdev_install_key_arg *arg);
+int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
+				  const struct wmi_vdev_spectral_conf_arg *arg);
+int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				    u32 enable);
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 		    const u8 peer_addr[ETH_ALEN]);
 int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
index b9ab722..0827cb7 100644
--- a/drivers/net/wireless/ath/spectral_common.h
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -19,6 +19,10 @@
 
 #define SPECTRAL_HT20_NUM_BINS		56
 #define SPECTRAL_HT20_40_NUM_BINS		128
+/* TODO: could possibly be 512, but no samples this large
+ * could be acquired so far.
+ */
+#define SPECTRAL_ATH10K_MAX_NUM_BINS		256
 
 /* FFT sample format given to userspace via debugfs.
  *
@@ -31,6 +35,7 @@
 enum ath_fft_sample_type {
 	ATH_FFT_SAMPLE_HT20 = 1,
 	ATH_FFT_SAMPLE_HT20_40,
+	ATH_FFT_SAMPLE_ATH10K,
 };
 
 struct fft_sample_tlv {
@@ -85,4 +90,23 @@ struct fft_sample_ht20_40 {
 	u8 data[SPECTRAL_HT20_40_NUM_BINS];
 } __packed;
 
+struct fft_sample_ath10k {
+	struct fft_sample_tlv tlv;
+	u8 chan_width_mhz;
+	__be16 freq1;
+	__be16 freq2;
+	__be16 noise;
+	__be16 max_magnitude;
+	__be16 total_gain_db;
+	__be16 base_pwr_db;
+	__be64 tsf;
+	s8 max_index;
+	u8 rssi;
+	u8 relpwr_db;
+	u8 avgpwr_db;
+	u8 max_exp;
+
+	u8 data[0];
+} __packed;
+
 #endif /* SPECTRAL_COMMON_H */
-- 
1.9.1



From linville at tuxdriver.com  Fri Jul 18 10:45:15 2014
From: linville at tuxdriver.com (John W. Linville)
Date: Fri, 18 Jul 2014 13:45:15 -0400
Subject: Pull request: ath 20140717
In-Reply-To: <87k37c6kw6.fsf@kamboji.qca.qualcomm.com>
References: <87k37c6kw6.fsf@kamboji.qca.qualcomm.com>
Message-ID: <20140718174515.GF31114@tuxdriver.com>

On Thu, Jul 17, 2014 at 06:54:33PM +0300, Kalle Valo wrote:
> Hi John,
> 
> here's new pull request for 3.17. Major changes are:
> 
> For ath6kl me and Jessica added support for ar6004 hw3.0, our latest
> version of ar6004.
> 
> For ath10k Janusz added a printout so that it's easier to check what
> ath10k kconfig options are enabled. He also added a debugfs file to
> configure maximum amsdu and ampdu values. Also we had few fixes as
> usual.
> 
> Please let me know if there are any problems.
> 
> Kalle
> 
> The following changes since commit a715c7ddd65a1a3b2839b8ebd759bb2d361f7675:
> 
>   wil6210: improve debug for WMI receive (2014-05-30 13:49:34 -0400)
> 
> are available in the git repository at:
> 
>   git://github.com/kvalo/ath.git tags/for-linville-20140717
> 
> for you to fetch changes up to 993619443774f7ef4df3b98655df4c3bf298548c:
> 
>   ath10k: sanitize tx ring index access properly (2014-07-15 11:19:45 +0300)

Pulling now...

-- 
John W. Linville		Someday the world will need a hero, and you
linville at tuxdriver.com			might be all we have.  Be ready.


From avalentin at marcant.net  Sat Jul 19 16:46:24 2014
From: avalentin at marcant.net (Andre Valentin)
Date: Sun, 20 Jul 2014 01:46:24 +0200
Subject: ath10k OTP loading issues
In-Reply-To: <63dce1c7-0142-4592-b8a1-2b09dce63af3@email.android.com>
References: <53AD2EEE.4040704@marcant.net>
 <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>
 <53C59A22.6000505@marcant.net>
 <CAGXE3d8KZ=BG6a2PBhY_ZAhf71admtrnCF01LNoyA2tnLNJcAA@mail.gmail.com>
 <87wqbc6n8n.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d_FQvvmkGajQ1ioU5mEL04xVzUQ1k9-uXSLjoDFX+Z-Cg@mail.gmail.com>
 <87lhrs6l2r.fsf@kamboji.qca.qualcomm.com>
 <63dce1c7-0142-4592-b8a1-2b09dce63af3@email.android.com>
Message-ID: <53CB0350.2060506@marcant.net>

Hi!

I noticed that OTP loading works on some ZyXEL NBG6716 devices and some not. I made a diff between both
boot (working non-working) logs. Please take a look at the cpu intr cause:

8c8
< ath10k: boot target cpu intr cause: 0x00000000
---
> ath10k: boot target cpu intr cause: 0x00000008
10c10
< ath10k: boot target cpu intr cause: 0x00000000
---
> ath10k: boot target cpu intr cause: 0x00000008
13,19c13,19
< ath10k: boot init ce src ring id 0 entries 16 base_addr ae4dd000
< ath10k: boot ce dest ring id 1 entries 512 base_addr aef52000
< ath10k: boot ce dest ring id 2 entries 32 base_addr ae4d8000
< ath10k: boot init ce src ring id 3 entries 32 base_addr ae28a000
< ath10k: boot init ce src ring id 4 entries 4096 base_addr ae4e0000
< ath10k: boot init ce src ring id 7 entries 2 base_addr ae4d9000
< ath10k: boot ce dest ring id 7 entries 2 base_addr ae4dc000
---
> ath10k: boot init ce src ring id 0 entries 16 base_addr aef3e000
> ath10k: boot ce dest ring id 1 entries 512 base_addr aeedc000
> ath10k: boot ce dest ring id 2 entries 32 base_addr ae0d1000
> ath10k: boot init ce src ring id 3 entries 32 base_addr aed7d000
> ath10k: boot init ce src ring id 4 entries 4096 base_addr ae7a0000
> ath10k: boot init ce src ring id 7 entries 2 base_addr ae0c2000
> ath10k: boot ce dest ring id 7 entries 2 base_addr ae730000
45c45,48
< ath10k: boot otp execute result 0
---
> ath10k: boot otp execute result 2
> ath10k: otp calibration failed: 2
> ath10k: failed to run otp: -22
> ath10k: Ignoring otp execution failure: -22
66c69
< ath10k: boot target cpu intr cause: 0x00001000
---
> ath10k: boot target cpu intr cause: 0x00001008
68c71
< ath10k: boot target cpu intr cause: 0x00000000
---
> ath10k: boot target cpu intr cause: 0x00000008
74c77
< ath10k: boot target cpu intr cause: 0x00000000
---
> ath10k: boot target cpu intr cause: 0x00000008
76c79
< ath10k: boot target cpu intr cause: 0x00000000
---
> ath10k: boot target cpu intr cause: 0x00000008


And with a cold reset (hacked the code) instead:

6,19c4,12
< ath10k: boot warm reset
< ath10k: boot host cpu intr cause: 0x00000000
< ath10k: boot target cpu intr cause: 0x00000000
< ath10k: boot host cpu intr cause: 0x00000000
< ath10k: boot target cpu intr cause: 0x00000000
< ath10k: boot target reset state: 0x00000800
< ath10k: boot warm reset complete
< ath10k: boot init ce src ring id 0 entries 16 base_addr ae4dd000
< ath10k: boot ce dest ring id 1 entries 512 base_addr aef52000
< ath10k: boot ce dest ring id 2 entries 32 base_addr ae4d8000
< ath10k: boot init ce src ring id 3 entries 32 base_addr ae28a000
< ath10k: boot init ce src ring id 4 entries 4096 base_addr ae4e0000
< ath10k: boot init ce src ring id 7 entries 2 base_addr ae4d9000
< ath10k: boot ce dest ring id 7 entries 2 base_addr ae4dc000
---
> ath10k: boot cold reset
> ath10k: boot cold reset complete
> ath10k: boot init ce src ring id 0 entries 16 base_addr aeed5000
> ath10k: boot ce dest ring id 1 entries 512 base_addr ae112000
> ath10k: boot ce dest ring id 2 entries 32 base_addr aeedf000
> ath10k: boot init ce src ring id 3 entries 32 base_addr ae453000
> ath10k: boot init ce src ring id 4 entries 4096 base_addr ad0c0000
> ath10k: boot init ce src ring id 7 entries 2 base_addr ae49f000
> ath10k: boot ce dest ring id 7 entries 2 base_addr ae258000
25,27d17
< ath10k: boot target indicator 0
< ath10k: boot target indicator 0
< ath10k: boot target indicator 0
45c35,36
< ath10k: boot otp execute result 0
---
> ath10k: boot otp execute result 2
> ath10k: otp stream is empty, using board.bin contents

Do you have an idea?

Andr?

On 17.07.2014 23:44, Helmut Schaa wrote:
>
> On 17. Juli 2014 17:50:36 MESZ, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> Helmut Schaa <helmut.schaa at googlemail.com> writes:
>>
>>>> But in method 2) otp.bin will fail as there's no data in the OTP
>> area.
>>>> This is expected and that's why we should not run otp.bin at all
>> with
>>>> method 2).
>>> Thanks for clarification Kalle! So, method 2 requires only a
>>> board.bin?
>> Yes. You need to extract the board file from the MTD partition and
>> provide it to ath10k.
> Understood. Will give it a try soon ...
> Helmut



From avalentin at marcant.net  Sat Jul 19 16:57:54 2014
From: avalentin at marcant.net (Andre Valentin)
Date: Sun, 20 Jul 2014 01:57:54 +0200
Subject: ath10k OTP loading issues
In-Reply-To: <53CB0350.2060506@marcant.net>
References: <53AD2EEE.4040704@marcant.net>
 <87tx70p4e0.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d-i1Cf93cTuM=gSPttOBsCrP1c_Hb0=XDi8mXsZBm-MUQ@mail.gmail.com>
 <53C59A22.6000505@marcant.net>
 <CAGXE3d8KZ=BG6a2PBhY_ZAhf71admtrnCF01LNoyA2tnLNJcAA@mail.gmail.com>
 <87wqbc6n8n.fsf@kamboji.qca.qualcomm.com>
 <CAGXE3d_FQvvmkGajQ1ioU5mEL04xVzUQ1k9-uXSLjoDFX+Z-Cg@mail.gmail.com>
 <87lhrs6l2r.fsf@kamboji.qca.qualcomm.com>
 <63dce1c7-0142-4592-b8a1-2b09dce63af3@email.android.com>
 <53CB0350.2060506@marcant.net>
Message-ID: <53CB0602.8070307@marcant.net>

Hi!

And here is the working log just in case :-(

ath10k: boot pci_mem 0xb2000000
ath10k: boot chip_id 0x043202ff hw_revision 0x2
ath10k: boot hif power up
ath10k: boot warm reset
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x00000000
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x00000000
ath10k: boot target reset state: 0x00000800
ath10k: boot warm reset complete
ath10k: boot init ce src ring id 0 entries 16 base_addr ae4dd000
ath10k: boot ce dest ring id 1 entries 512 base_addr aef52000
ath10k: boot ce dest ring id 2 entries 32 base_addr ae4d8000
ath10k: boot init ce src ring id 3 entries 32 base_addr ae28a000
ath10k: boot init ce src ring id 4 entries 4096 base_addr ae4e0000
ath10k: boot init ce src ring id 7 entries 2 base_addr ae4d9000
ath10k: boot ce dest ring id 7 entries 2 base_addr ae4dc000
ath10k: boot waiting target to initialise
ath10k: boot target indicator 0
ath10k: boot target indicator 0
ath10k: boot target indicator 0
ath10k: boot target indicator 0
ath10k: boot target indicator 0
ath10k: boot target indicator 0
ath10k: boot target indicator 0
ath10k: boot target indicator 2
ath10k: boot target initialised
ath10k: pci irq legacy irq_mode 0 reset_mode 0
ath10k: Hardware name qca988x hw2.0 version 0x4100016c
ath10k: trying fw api 2
ath10k: found fw version 10.1.467.2-1
ath10k: found fw timestamp 1391440175
ath10k: found otp image ie (6917 B)
ath10k: found fw image ie (190250 B)
ath10k: found firmware features ie (1 B)
ath10k: Enabling feature bit: 1
ath10k: Enabling feature bit: 2
ath10k: features
00000000: 00 00 00 06                                      ....
ath10k: using fw api 2
ath10k: boot push board extended data addr 0x0
ath10k: boot upload otp to 0x1234 len 6917
ath10k: boot otp execute result 0
ath10k: boot hif start
ath10k: boot htc service 'Control' ul pipe 0 dl pipe 1 eid 0 ready
ath10k: boot htc ep 0 ul polled 0 dl polled 0
ath10k: boot htc service 'Control' eid 0 TX flow control disabled
ath10k: boot htc service HTT Data does not allocate target credits
ath10k: boot htc service 'HTT Data' ul pipe 4 dl pipe 1 eid 1 ready
ath10k: boot htc ep 1 ul polled 1 dl polled 0
ath10k: boot htc service 'HTT Data' eid 1 TX flow control disabled
ath10k: htt tx max num pending tx 1424
ath10k: htt rx ring size 1024 fill_level 1000
ath10k: boot htc service 'WMI' ul pipe 3 dl pipe 2 eid 2 ready
ath10k: boot htc ep 2 ul polled 0 dl polled 0
ath10k: boot wmi ready
ath10k: firmware 10.1.467.2-1 booted
ath10k: htt target version 2.1
ath10k: qca988x hw2.0 (0x4100016c, 0x043202ff) fw 10.1.467.2-1 api 2 htt 2.1
ath10k: boot suspend complete
ath10k: boot hif stop
ath10k: boot warm reset
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x00001000
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x00000000
ath10k: boot target reset state: 0x00000804
ath10k: boot warm reset complete
ath10k: boot hif power down
ath10k: boot warm reset
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x00000000
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x00000000
ath10k: boot target reset state: 0x00000800
ath10k: boot warm reset complete

Andr?


On 20.07.2014 01:46, Andre Valentin wrote:
> Hi!
>
> I noticed that OTP loading works on some ZyXEL NBG6716 devices and some not. I made a diff between both
> boot (working non-working) logs. Please take a look at the cpu intr cause:
>
> 8c8
> < ath10k: boot target cpu intr cause: 0x00000000
> ---
>> ath10k: boot target cpu intr cause: 0x00000008
> 10c10
> < ath10k: boot target cpu intr cause: 0x00000000
> ---
>> ath10k: boot target cpu intr cause: 0x00000008
> 13,19c13,19
> < ath10k: boot init ce src ring id 0 entries 16 base_addr ae4dd000
> < ath10k: boot ce dest ring id 1 entries 512 base_addr aef52000
> < ath10k: boot ce dest ring id 2 entries 32 base_addr ae4d8000
> < ath10k: boot init ce src ring id 3 entries 32 base_addr ae28a000
> < ath10k: boot init ce src ring id 4 entries 4096 base_addr ae4e0000
> < ath10k: boot init ce src ring id 7 entries 2 base_addr ae4d9000
> < ath10k: boot ce dest ring id 7 entries 2 base_addr ae4dc000
> ---
>> ath10k: boot init ce src ring id 0 entries 16 base_addr aef3e000
>> ath10k: boot ce dest ring id 1 entries 512 base_addr aeedc000
>> ath10k: boot ce dest ring id 2 entries 32 base_addr ae0d1000
>> ath10k: boot init ce src ring id 3 entries 32 base_addr aed7d000
>> ath10k: boot init ce src ring id 4 entries 4096 base_addr ae7a0000
>> ath10k: boot init ce src ring id 7 entries 2 base_addr ae0c2000
>> ath10k: boot ce dest ring id 7 entries 2 base_addr ae730000
> 45c45,48
> < ath10k: boot otp execute result 0
> ---
>> ath10k: boot otp execute result 2
>> ath10k: otp calibration failed: 2
>> ath10k: failed to run otp: -22
>> ath10k: Ignoring otp execution failure: -22
> 66c69
> < ath10k: boot target cpu intr cause: 0x00001000
> ---
>> ath10k: boot target cpu intr cause: 0x00001008
> 68c71
> < ath10k: boot target cpu intr cause: 0x00000000
> ---
>> ath10k: boot target cpu intr cause: 0x00000008
> 74c77
> < ath10k: boot target cpu intr cause: 0x00000000
> ---
>> ath10k: boot target cpu intr cause: 0x00000008
> 76c79
> < ath10k: boot target cpu intr cause: 0x00000000
> ---
>> ath10k: boot target cpu intr cause: 0x00000008
>
>
> And with a cold reset (hacked the code) instead:
>
> 6,19c4,12
> < ath10k: boot warm reset
> < ath10k: boot host cpu intr cause: 0x00000000
> < ath10k: boot target cpu intr cause: 0x00000000
> < ath10k: boot host cpu intr cause: 0x00000000
> < ath10k: boot target cpu intr cause: 0x00000000
> < ath10k: boot target reset state: 0x00000800
> < ath10k: boot warm reset complete
> < ath10k: boot init ce src ring id 0 entries 16 base_addr ae4dd000
> < ath10k: boot ce dest ring id 1 entries 512 base_addr aef52000
> < ath10k: boot ce dest ring id 2 entries 32 base_addr ae4d8000
> < ath10k: boot init ce src ring id 3 entries 32 base_addr ae28a000
> < ath10k: boot init ce src ring id 4 entries 4096 base_addr ae4e0000
> < ath10k: boot init ce src ring id 7 entries 2 base_addr ae4d9000
> < ath10k: boot ce dest ring id 7 entries 2 base_addr ae4dc000
> ---
>> ath10k: boot cold reset
>> ath10k: boot cold reset complete
>> ath10k: boot init ce src ring id 0 entries 16 base_addr aeed5000
>> ath10k: boot ce dest ring id 1 entries 512 base_addr ae112000
>> ath10k: boot ce dest ring id 2 entries 32 base_addr aeedf000
>> ath10k: boot init ce src ring id 3 entries 32 base_addr ae453000
>> ath10k: boot init ce src ring id 4 entries 4096 base_addr ad0c0000
>> ath10k: boot init ce src ring id 7 entries 2 base_addr ae49f000
>> ath10k: boot ce dest ring id 7 entries 2 base_addr ae258000
> 25,27d17
> < ath10k: boot target indicator 0
> < ath10k: boot target indicator 0
> < ath10k: boot target indicator 0
> 45c35,36
> < ath10k: boot otp execute result 0
> ---
>> ath10k: boot otp execute result 2
>> ath10k: otp stream is empty, using board.bin contents
>
> Do you have an idea?
>
> Andr?
>
> On 17.07.2014 23:44, Helmut Schaa wrote:
>>
>> On 17. Juli 2014 17:50:36 MESZ, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>>> Helmut Schaa <helmut.schaa at googlemail.com> writes:
>>>
>>>>> But in method 2) otp.bin will fail as there's no data in the OTP
>>> area.
>>>>> This is expected and that's why we should not run otp.bin at all
>>> with
>>>>> method 2).
>>>> Thanks for clarification Kalle! So, method 2 requires only a
>>>> board.bin?
>>> Yes. You need to extract the board file from the MTD partition and
>>> provide it to ath10k.
>> Understood. Will give it a try soon ...
>> Helmut
>


-- 
Mit freundlichen Gr??en,
Andr? Valentin
Projektkoordination / Systemadministration

MarcanT GmbH, Ravensberger Str. 10 G, D - 33602 Bielefeld
Fon: +49 (521) 95945-0 | Fax -18
URL: http://www.marcant.net | http://www.global-m2m.com

Gesch?ftsf?hrer: Thorsten Hojas
Handelsregister: AG Bielefeld, HRB 35827 USt-ID Nr.: DE 190203238
___________________________________________________________
CONFIDENTIALITY NOTICE
The contents of this email are confidential to the ordinary user of the
email address to which it was addressed and may also be privileged. If
you are not the addressee of this email you may not copy, forward,
disclose or otherwise use it or any part of it in any form whatsoever.
If you have received this email in error please email the sender by
replying to this message.



From yeohchunyeow at gmail.com  Sun Jul 20 21:15:33 2014
From: yeohchunyeow at gmail.com (Yeoh Chun-Yeow)
Date: Mon, 21 Jul 2014 12:15:33 +0800
Subject: [PATCH 2/2] ath10k: add spectral scan feature
In-Reply-To: <1405689992-8538-3-git-send-email-sw@simonwunderlich.de>
References: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
 <1405689992-8538-3-git-send-email-sw@simonwunderlich.de>
Message-ID: <CAEFj986Vruig8wCP+RLS_gQf8utAirmTDCKwmMGyfj7B2vH9pw@mail.gmail.com>

On Fri, Jul 18, 2014 at 9:26 PM, Simon Wunderlich <sw at simonwunderlich.de> wrote:
> Adds the spectral scan feature for ath10k. The spectral scan is triggered by
> configuring a mode through a debugfs control file. Samples can be gathered via
> another relay debugfs file.
>
> Essentially, to try it out:
>
> ip link dev wlan0 set up

It should be "ip link set dev wlan0 up", right?

I have tried to capture the samples on ath10k and open it using fft_eval.

But found the following errors in my samples "invalid bin length 63".

I will send the samples in separate email.

---
Chun-Yeow


From michal.kazior at tieto.com  Sun Jul 20 23:56:09 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 21 Jul 2014 08:56:09 +0200
Subject: [PATCH 2/2] ath10k: add spectral scan feature
In-Reply-To: <1405689992-8538-3-git-send-email-sw@simonwunderlich.de>
References: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
 <1405689992-8538-3-git-send-email-sw@simonwunderlich.de>
Message-ID: <CA+BoTQmrn0ddGe=p_d9+vCpMUMQ6dKhL+DmZ76OicacmxoYVMA@mail.gmail.com>

On 18 July 2014 15:26, Simon Wunderlich <sw at simonwunderlich.de> wrote:
> Adds the spectral scan feature for ath10k. The spectral scan is triggered by
> configuring a mode through a debugfs control file. Samples can be gathered via
> another relay debugfs file.
[...]
> diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
> index 80aa5a4..5fc7ff5 100644
> --- a/drivers/net/wireless/ath/ath10k/core.h
> +++ b/drivers/net/wireless/ath/ath10k/core.h
> @@ -31,6 +31,7 @@
>  #include "../ath.h"
>  #include "../regd.h"
>  #include "../dfs_pattern_detector.h"
> +#include "spectral.h"
>
>  #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
>  #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
> @@ -230,6 +231,7 @@ struct ath10k_vif {
>
>         bool is_started;
>         bool is_up;
> +       bool spectral_enabled;
>         u32 aid;
>         u8 bssid[ETH_ALEN];
>
> @@ -469,6 +471,11 @@ struct ath10k {
>  #ifdef CONFIG_ATH10K_DEBUGFS
>         struct ath10k_debug debug;
>  #endif
> +
> +       /* relay(fs) channel for spectral scan */
> +       struct rchan *rfs_chan_spec_scan;
> +       enum ath10k_spectral_mode spectral_mode;
> +       struct ath10k_spec_scan spec_config;

It's probably a good idea to add a comment stating that spectral_mode
and spec_config are conf_mutex protected.


>  };
>
>  struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
> diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
> index a84691e..e39aa96 100644
> --- a/drivers/net/wireless/ath/ath10k/debug.c
> +++ b/drivers/net/wireless/ath/ath10k/debug.c
> @@ -827,12 +827,15 @@ int ath10k_debug_create(struct ath10k *ar)
>                                     &fops_dfs_stats);
>         }
>
> +       ath10k_spectral_init_debug(ar);
> +
>         return 0;
>  }
>
>  void ath10k_debug_destroy(struct ath10k *ar)
>  {
>         cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
> +       ath10k_spectral_deinit_debug(ar);
>  }
>
>  #endif /* CONFIG_ATH10K_DEBUGFS */
> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
> index 348a639..c369ac1 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -2671,8 +2671,16 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
>                 dev_kfree_skb_any(arvif->beacon);
>                 arvif->beacon = NULL;
>         }
> +
>         spin_unlock_bh(&ar->data_lock);
>
> +       if (arvif->spectral_enabled) {
> +               ret = ath10k_interface_disable_spectral(arvif);
> +               if (ret)
> +                       ath10k_warn("spectral disable for vdev %i failed\n",
> +                                   arvif->vdev_id);

We tend to put verbs first, e.g. "failed to disable spectral scan for
vdev %i: %d\n". Also, your warning is missing "ret" here.


[...]
> +#include <linux/relay.h>
> +#include "core.h"
> +#include "debug.h"
> +
> +static void ath10k_debug_send_fft_sample(struct ath10k *ar,
> +                                        struct fft_sample_tlv *fft_sample_tlv)

I guess fft_sample_tlv could be const. Other functions could also have
const arguments. But I'm just being picky now :-)


> +int ath10k_process_fft(struct ath10k *ar,
> +                      struct wmi_single_phyerr_rx_event *event,
> +                      struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
> +{
[...]
> +       nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
> +       nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
> +       chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
> +       switch (chain_idx) {
> +       case 0:
> +               fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);

Are you sure you want to & nf_list1 itself *before* the byte swap? You
probably won't see a difference with an intel host system which is
little-endian just like the target device.


> +               break;
> +       case 1:
> +               fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
> +               break;
> +       case 2:
> +               fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
> +               break;
> +       case 3:
> +               fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
> +               break;
> +       }

Ditto for the above.


> +static int ath10k_spectral_scan_trigger(struct ath10k *ar)
> +{
> +       struct ath10k_vif *arvif;
> +       int res;
> +       int vdev_id;
> +

You access ar->spectral_mode here which requires conf_mutex to be
held. I suggest lockdep_assert_held() to be put here.


> +       arvif = ath10k_get_spectral_vdev(ar);
> +       if (!arvif)
> +               return -ENODEV;
> +       vdev_id = arvif->vdev_id;
> +
> +       if (ar->spectral_mode == SPECTRAL_DISABLED)
> +               return 0;
> +
> +       res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
> +                                             WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
> +                                             WMI_SPECTRAL_ENABLE_CMD_ENABLE);
> +       if (res < 0)
> +               return res;
> +
> +       res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
> +                                             WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
> +                                             WMI_SPECTRAL_ENABLE_CMD_ENABLE);
> +       if (res < 0)
> +               return res;
> +
> +       return 0;
> +}
> +static int ath10k_spectral_scan_config(struct ath10k *ar,
> +                                      enum ath10k_spectral_mode mode)
> +{
> +       struct wmi_vdev_spectral_conf_arg arg;
> +       struct ath10k_vif *arvif;
> +       int vdev_id, count, res = 0;
> +

Ditto. lockdep_assert_held().


> +       arvif = ath10k_get_spectral_vdev(ar);
> +       if (!arvif)
> +               return -ENODEV;
> +
> +       vdev_id = arvif->vdev_id;
> +
> +       arvif->spectral_enabled = (mode != SPECTRAL_DISABLED);
> +       ar->spectral_mode = mode;
> +
> +       res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
> +                                             WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
> +                                             WMI_SPECTRAL_ENABLE_CMD_DISABLE);
> +       if (res < 0) {
> +               ath10k_warn("failed to enable spectral scan: %d\n", res);
> +               return res;
> +       }
> +
> +       if (mode == SPECTRAL_DISABLED)
> +               return 0;
> +
> +       if (mode == SPECTRAL_BACKGROUND)
> +               count = WMI_SPECTRAL_COUNT_DEFAULT;
> +       else
> +               count = max_t(u8, 1, ar->spec_config.count);
> +
> +       arg.vdev_id              = vdev_id;
> +       arg.scan_count           = count;
> +       arg.scan_period          = WMI_SPECTRAL_PERIOD_DEFAULT;
> +       arg.scan_priority        = WMI_SPECTRAL_PRIORITY_DEFAULT;
> +       arg.scan_fft_size        = ar->spec_config.fft_size;
> +       arg.scan_gc_ena          = WMI_SPECTRAL_GC_ENA_DEFAULT;
> +       arg.scan_restart_ena     = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
> +       arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
> +       arg.scan_init_delay      = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
> +       arg.scan_nb_tone_thr     = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
> +       arg.scan_str_bin_thr     = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
> +       arg.scan_wb_rpt_mode     = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
> +       arg.scan_rssi_rpt_mode   = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
> +       arg.scan_rssi_thr        = WMI_SPECTRAL_RSSI_THR_DEFAULT;
> +       arg.scan_pwr_format      = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
> +       arg.scan_rpt_mode        = WMI_SPECTRAL_RPT_MODE_DEFAULT;
> +       arg.scan_bin_scale       = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
> +       arg.scan_dbm_adj         = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
> +       arg.scan_chn_mask        = WMI_SPECTRAL_CHN_MASK_DEFAULT;
> +
> +       res = ath10k_wmi_vdev_spectral_conf(ar, &arg);
> +       if (res < 0) {
> +               ath10k_warn("failed to configure spectral scan: %d\n", res);
> +               return res;
> +       }
> +
> +       return 0;
> +}


Did you test this against a firmware crash while spectral scan is
enabled? ar->spectral_mode will be left as-is when restart is
performed but no spectral scan will be actually configured. You either
need to restart spectral scan (better from user perspective) or clear
out the old mode (easier to code, but bad from user perspective
because suddenly spectral scan would be stopped implicitly by device
crash).


Micha?


From janusz.dziedzic at tieto.com  Mon Jul 21 01:53:16 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Mon, 21 Jul 2014 10:53:16 +0200
Subject: [PATCH] ath10k: handle attention flags correctly when A-MSDU
In-Reply-To: <87pph225mq.fsf@kamboji.qca.qualcomm.com>
References: <1405342041-7114-1-git-send-email-janusz.dziedzic@tieto.com>
 <87pph225mq.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CALhHN=q2XcvPiLpeDgw_DksU1xzQLvJtxjzk8iZte-VMd+viLg@mail.gmail.com>

On 18 July 2014 14:50, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:
>
>> In case of A-MSDU RX we should check flags for all
>> MSDU subframes to be sure we have correct FCS status.
>>
>> Before we check attention flags only for first frame
>> where we didn't have correct info about FCS status in
>> case of A-MSDU. Next didn't mark RX_FLAG_FAILED_FCS_CRC
>> for skb. As a side efect we see big TP drop when TCP used.
>> This was easy to reproduce when AP interface was used
>> and added monitor interface run in promiscuous mode.
>>
>> Reported-by: Denton Gentry <denton.gentry at gmail.com>
>> Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
>
> I'm having a hard time to understand the commit log. I think it would
> make it easier to read if you first clearly describe the bug you are
> fixing and then, in a separate paragraph, tell how you fix it.
>
Will change that.

> So what is the bug Denton reported? "we see big TP drop when TCP used"
> implies that this happens with all TCP traffic, but that can't be right.
> Or did it happen with one of the reorder patches?
>
TP drop is seen with/without reordering patches when TCP STA --> AP and:
- used ath10k STA
- I force to use AMSDU (7 frames) on STA
- not using cables and other traffic on the channel (often FCS errors)
- monitor iface used on AP

Without a patch we report AMSDU packets with wrong FCS as a correct to
the stack, next there is a lot of DUP ACK packets from AP --> STA.
TP drop depends on FCS errors for AMSDU.


This is example what I see without patch (without reordering patch):

echo "1 64" > htt_max_amsdu_ampdu
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 5.0 sec  56.6 MBytes  95.0 Mbits/sec
[  3]  5.0-10.0 sec  60.4 MBytes   101 Mbits/sec
[  3] 10.0-15.0 sec  60.2 MBytes   101 Mbits/sec
[  3] 15.0-20.0 sec  60.2 MBytes   101 Mbits/sec
[  3] 20.0-25.0 sec  63.8 MBytes   107 Mbits/sec
[  3] 25.0-30.0 sec  64.9 MBytes   109 Mbits/sec

echo "7 64" > htt_max_amsdu_ampdu  // lot of DUP ACK from AP --> STA seen
[  3] 30.0-35.0 sec  40.0 MBytes  67.1 Mbits/sec
[  3] 35.0-40.0 sec  35.9 MBytes  60.2 Mbits/sec
[  3] 40.0-45.0 sec  36.9 MBytes  61.9 Mbits/sec
[  3] 45.0-50.0 sec  37.9 MBytes  63.5 Mbits/sec
[  3] 50.0-55.0 sec  34.5 MBytes  57.9 Mbits/sec
[  3] 55.0-60.0 sec  25.4 MBytes  42.6 Mbits/sec
[  3] 60.0-65.0 sec  48.2 MBytes  81.0 Mbits/sec
[  3] 65.0-70.0 sec  28.8 MBytes  48.2 Mbits/sec
[  3] 70.0-75.0 sec  29.2 MBytes  49.1 Mbits/sec
[  3] 75.0-80.0 sec  22.9 MBytes  38.4 Mbits/sec
[  3] 80.0-85.0 sec  26.4 MBytes  44.2 Mbits/sec
[  3] 85.0-90.0 sec  31.5 MBytes  52.8 Mbits/sec


With patch:

echo "1 64" > htt_max_amsdu_ampdu
[  3] local 192.168.12.2 port 57512 connected with 192.168.12.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 5.0 sec  60.8 MBytes   102 Mbits/sec
[  3]  5.0-10.0 sec  62.2 MBytes   104 Mbits/sec
[  3] 10.0-15.0 sec  60.9 MBytes   102 Mbits/sec

echo "7 64" > htt_max_amsdu_ampdu  // none DUP ACK form AP --> STA seen
[  3] 15.0-20.0 sec  68.1 MBytes   114 Mbits/sec
[  3] 20.0-25.0 sec  80.5 MBytes   135 Mbits/sec
[  3] 25.0-30.0 sec  83.0 MBytes   139 Mbits/sec
[  3] 30.0-35.0 sec  79.1 MBytes   133 Mbits/sec
[  3] 35.0-40.0 sec  77.1 MBytes   129 Mbits/sec
[  3] 40.0-45.0 sec  77.4 MBytes   130 Mbits/sec


BR
Janusz


From benoit.taine at lip6.fr  Fri Jul 18 08:26:47 2014
From: benoit.taine at lip6.fr (Benoit Taine)
Date: Fri, 18 Jul 2014 17:26:47 +0200
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
Message-ID: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>

We should prefer `const struct pci_device_id` over
`DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
This issue was reported by checkpatch.

A simplified version of the semantic patch that makes this change is as
follows (http://coccinelle.lip6.fr/):

// <smpl>

@@
identifier i;
declarer name DEFINE_PCI_DEVICE_TABLE;
initializer z;
@@

- DEFINE_PCI_DEVICE_TABLE(i)
+ const struct pci_device_id i[]
= z;

// </smpl>

I have 103 patches ready, and will only send a few for you to judge if
it is useful enough, and to prevent from spamming too much.

Thanks.


From James.Bottomley at HansenPartnership.com  Fri Jul 18 09:28:54 2014
From: James.Bottomley at HansenPartnership.com (James Bottomley)
Date: Fri, 18 Jul 2014 09:28:54 -0700
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
Message-ID: <1405700934.605.31.camel@jarvis.lan>

On Fri, 2014-07-18 at 17:26 +0200, Benoit Taine wrote:
> We should prefer `const struct pci_device_id` over
> `DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
> This issue was reported by checkpatch.

What kernel coding style?  checkpatch isn't the arbiter of style, if
that's the only problem.

The DEFINE_PCI macro was a well reasoned addition when it was added in
2008.  The problem was most people were getting the definition wrong.
When we converted away from CONFIG_HOTPLUG, having this DEFINE_ meant
that only one place needed changing instead of hundreds for PCI tables.

The reason people were getting the PCI table wrong was mostly the init
section specifiers which are now gone, but it has enough underlying
utility (mostly constification) that I don't think we'd want to churn
the kernel hugely to make a change to struct pci_table and then have to
start detecting and fixing misuses.

James




From linville at tuxdriver.com  Fri Jul 18 09:22:13 2014
From: linville at tuxdriver.com (John W. Linville)
Date: Fri, 18 Jul 2014 12:22:13 -0400
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
Message-ID: <20140718162213.GC31114@tuxdriver.com>

On Fri, Jul 18, 2014 at 05:26:47PM +0200, Benoit Taine wrote:
> We should prefer `const struct pci_device_id` over
> `DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
> This issue was reported by checkpatch.

Honestly, I prefer the macro -- it stands-out more.  Maybe the style
guidelines and/or checkpatch should change instead?

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville at tuxdriver.com			might be all we have.  Be ready.


From jacob.e.keller at intel.com  Fri Jul 18 09:33:16 2014
From: jacob.e.keller at intel.com (Keller, Jacob E)
Date: Fri, 18 Jul 2014 16:33:16 +0000
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <1405700934.605.31.camel@jarvis.lan>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
 <1405700934.605.31.camel@jarvis.lan>
Message-ID: <1405701196.21801.3.camel@jekeller-desk1.amr.corp.intel.com>

On Fri, 2014-07-18 at 09:28 -0700, James Bottomley wrote:
> On Fri, 2014-07-18 at 17:26 +0200, Benoit Taine wrote:
> > We should prefer `const struct pci_device_id` over
> > `DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
> > This issue was reported by checkpatch.
> 
> What kernel coding style?  checkpatch isn't the arbiter of style, if
> that's the only problem.
> 
> The DEFINE_PCI macro was a well reasoned addition when it was added in
> 2008.  The problem was most people were getting the definition wrong.
> When we converted away from CONFIG_HOTPLUG, having this DEFINE_ meant
> that only one place needed changing instead of hundreds for PCI tables.
> 
> The reason people were getting the PCI table wrong was mostly the init
> section specifiers which are now gone, but it has enough underlying
> utility (mostly constification) that I don't think we'd want to churn
> the kernel hugely to make a change to struct pci_table and then have to
> start detecting and fixing misuses.
> 
> James
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

I would rather fix the misuses of the macro, than remove it. Could we
possibly make checkpatch smart enough to tell when the macro is misused?

Thanks,
Jake

From greg at kroah.com  Fri Jul 18 09:43:40 2014
From: greg at kroah.com (Greg KH)
Date: Fri, 18 Jul 2014 09:43:40 -0700
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <20140718162213.GC31114@tuxdriver.com>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
 <20140718162213.GC31114@tuxdriver.com>
Message-ID: <20140718164340.GA24960@kroah.com>

On Fri, Jul 18, 2014 at 12:22:13PM -0400, John W. Linville wrote:
> On Fri, Jul 18, 2014 at 05:26:47PM +0200, Benoit Taine wrote:
> > We should prefer `const struct pci_device_id` over
> > `DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
> > This issue was reported by checkpatch.
> 
> Honestly, I prefer the macro -- it stands-out more.  Maybe the style
> guidelines and/or checkpatch should change instead?

The macro is horrid, no other bus has this type of thing just to save a
few characters in typing, so why should PCI be "special" in this regard
anymore?

thanks,

greg k-h


From James.Bottomley at HansenPartnership.com  Fri Jul 18 09:54:32 2014
From: James.Bottomley at HansenPartnership.com (James Bottomley)
Date: Fri, 18 Jul 2014 09:54:32 -0700
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <20140718164340.GA24960@kroah.com>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
 <20140718162213.GC31114@tuxdriver.com> <20140718164340.GA24960@kroah.com>
Message-ID: <1405702472.30262.1.camel@dabdike.int.hansenpartnership.com>

On Fri, 2014-07-18 at 09:43 -0700, Greg KH wrote:
> On Fri, Jul 18, 2014 at 12:22:13PM -0400, John W. Linville wrote:
> > On Fri, Jul 18, 2014 at 05:26:47PM +0200, Benoit Taine wrote:
> > > We should prefer `const struct pci_device_id` over
> > > `DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
> > > This issue was reported by checkpatch.
> > 
> > Honestly, I prefer the macro -- it stands-out more.  Maybe the style
> > guidelines and/or checkpatch should change instead?
> 
> The macro is horrid, no other bus has this type of thing just to save a
> few characters in typing

OK, so this is the macro:

#define DEFINE_PCI_DEVICE_TABLE(_table) \
	const struct pci_device_id _table[]

Could you explain what's so horrible?

The reason it's useful today is that people forget the const (and
sometimes the [] making it a true table instead of a pointer).  If you
use the DEFINE_PCI_DEVICE_TABLE macro, the compile breaks if you use it
wrongly (good) and you automatically get the correct annotations.

> , so why should PCI be "special" in this regard
> anymore?

I think the PCI usage dwarfs most other bus types now, so you could turn
the question around.  However, I don't think majority voting is a good
guide to best practise; lets debate the merits for their own sake.

James




From joe at perches.com  Fri Jul 18 11:05:39 2014
From: joe at perches.com (Joe Perches)
Date: Fri, 18 Jul 2014 11:05:39 -0700
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <20140718164340.GA24960@kroah.com>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
 <20140718162213.GC31114@tuxdriver.com> <20140718164340.GA24960@kroah.com>
Message-ID: <1405706739.14358.68.camel@joe-AO725>

On Fri, 2014-07-18 at 09:43 -0700, Greg KH wrote:
> On Fri, Jul 18, 2014 at 12:22:13PM -0400, John W. Linville wrote:
> > On Fri, Jul 18, 2014 at 05:26:47PM +0200, Benoit Taine wrote:
> > > We should prefer `const struct pci_device_id` over
> > > `DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
> > > This issue was reported by checkpatch.
> >  scripts/checkpatch.pl | 4 ++--
> > Honestly, I prefer the macro -- it stands-out more.  Maybe the style
> > guidelines and/or checkpatch should change instead?
> 
> The macro is horrid, no other bus has this type of thing just to save a
> few characters in typing, so why should PCI be "special" in this regard
> anymore?

I think it doesn't matter much.

The PCI_DEVICE and PCI_VDEVICE macro uses are somewhat similar
and are frequently used with PCI_DEVICE_TABLE, so there's some
commonality there.

The checkpatch message could be made --strict/CHK instead of
WARN so most people would never see it.

Of course it could be removed altogether too.  I don't care.
---
(suggested patch is for -next)

 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index dc72a9b..754fbf2 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -3018,8 +3018,8 @@ sub process {
 
 # check for uses of DEFINE_PCI_DEVICE_TABLE
 		if ($line =~ /\bDEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=/) {
-			if (WARN("DEFINE_PCI_DEVICE_TABLE",
-				 "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) &&
+			if (CHK("DEFINE_PCI_DEVICE_TABLE",
+				"Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) &&
 			    $fix) {
 				$fixed[$fixlinenr] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /;
 			}




From greg at kroah.com  Fri Jul 18 11:17:59 2014
From: greg at kroah.com (Greg KH)
Date: Fri, 18 Jul 2014 11:17:59 -0700
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <1405702472.30262.1.camel@dabdike.int.hansenpartnership.com>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
 <20140718162213.GC31114@tuxdriver.com>
 <20140718164340.GA24960@kroah.com>
 <1405702472.30262.1.camel@dabdike.int.hansenpartnership.com>
Message-ID: <20140718181759.GB2193@kroah.com>

On Fri, Jul 18, 2014 at 09:54:32AM -0700, James Bottomley wrote:
> On Fri, 2014-07-18 at 09:43 -0700, Greg KH wrote:
> > On Fri, Jul 18, 2014 at 12:22:13PM -0400, John W. Linville wrote:
> > > On Fri, Jul 18, 2014 at 05:26:47PM +0200, Benoit Taine wrote:
> > > > We should prefer `const struct pci_device_id` over
> > > > `DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
> > > > This issue was reported by checkpatch.
> > > 
> > > Honestly, I prefer the macro -- it stands-out more.  Maybe the style
> > > guidelines and/or checkpatch should change instead?
> > 
> > The macro is horrid, no other bus has this type of thing just to save a
> > few characters in typing
> 
> OK, so this is the macro:
> 
> #define DEFINE_PCI_DEVICE_TABLE(_table) \
> 	const struct pci_device_id _table[]
> 
> Could you explain what's so horrible?
> 
> The reason it's useful today is that people forget the const (and
> sometimes the [] making it a true table instead of a pointer).  If you
> use the DEFINE_PCI_DEVICE_TABLE macro, the compile breaks if you use it
> wrongly (good) and you automatically get the correct annotations.

We have almost 1000 more uses of the non-macro version than the "macro"
version in the kernel today:
$ git grep -w DEFINE_PCI_DEVICE_TABLE | wc -l
262
$ git grep "const struct pci_device_id" | wc -l
1254

My big complaint is that we need to be consistant, either pick one or
the other and stick to it.  As the macro is the least used, it's easiest
to fix up, and it also is more consistant with all other kernel
subsystems which do not have such a macro.

As there is no need for the __init macro mess anymore, there's no real
need for the DEFINE_PCI_DEVICE_TABLE macro either.  I think checkpatch
will catch the use of non-const users for the id table already today, it
catches lots of other uses like this already.

> > , so why should PCI be "special" in this regard
> > anymore?
> 
> I think the PCI usage dwarfs most other bus types now, so you could turn
> the question around.  However, I don't think majority voting is a good
> guide to best practise; lets debate the merits for their own sake.

Not really "dwarf", USB is close with over 700 such structures:
$ git grep "const struct usb_device_id" | wc -l
725

And i2c is almost just as big as PCI:
$ git grep "const struct i2c_device_id" | wc -l
1223

So again, this macro is not consistent with the majority of PCI drivers,
nor with any other type of "device id" declaration in the kernel, which
is why I feel it should be removed.

And finally, the PCI documentation itself says to not use this macro, so
this isn't a "new" thing.  From Documentation/PCI/pci.txt:

	The ID table is an array of struct pci_device_id entries ending with an
	all-zero entry.  Definitions with static const are generally preferred.
	Use of the deprecated macro DEFINE_PCI_DEVICE_TABLE should be avoided.

That wording went into the file last December, when we last talked about
this and everyone in that discussion agreed to remove the macro for the
above reasons.

Consistency matters.

thanks,

greg k-h


From James.Bottomley at HansenPartnership.com  Fri Jul 18 11:50:21 2014
From: James.Bottomley at HansenPartnership.com (James Bottomley)
Date: Fri, 18 Jul 2014 11:50:21 -0700
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <20140718181759.GB2193@kroah.com>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
 <20140718162213.GC31114@tuxdriver.com> <20140718164340.GA24960@kroah.com>
 <1405702472.30262.1.camel@dabdike.int.hansenpartnership.com>
 <20140718181759.GB2193@kroah.com>
Message-ID: <1405709421.30262.8.camel@dabdike.int.hansenpartnership.com>

On Fri, 2014-07-18 at 11:17 -0700, Greg KH wrote:
> On Fri, Jul 18, 2014 at 09:54:32AM -0700, James Bottomley wrote:
> > On Fri, 2014-07-18 at 09:43 -0700, Greg KH wrote:
> > > On Fri, Jul 18, 2014 at 12:22:13PM -0400, John W. Linville wrote:
> > > > On Fri, Jul 18, 2014 at 05:26:47PM +0200, Benoit Taine wrote:
> > > > > We should prefer `const struct pci_device_id` over
> > > > > `DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
> > > > > This issue was reported by checkpatch.
> > > > 
> > > > Honestly, I prefer the macro -- it stands-out more.  Maybe the style
> > > > guidelines and/or checkpatch should change instead?
> > > 
> > > The macro is horrid, no other bus has this type of thing just to save a
> > > few characters in typing
> > 
> > OK, so this is the macro:
> > 
> > #define DEFINE_PCI_DEVICE_TABLE(_table) \
> > 	const struct pci_device_id _table[]
> > 
> > Could you explain what's so horrible?
> > 
> > The reason it's useful today is that people forget the const (and
> > sometimes the [] making it a true table instead of a pointer).  If you
> > use the DEFINE_PCI_DEVICE_TABLE macro, the compile breaks if you use it
> > wrongly (good) and you automatically get the correct annotations.
> 
> We have almost 1000 more uses of the non-macro version than the "macro"
> version in the kernel today:
> $ git grep -w DEFINE_PCI_DEVICE_TABLE | wc -l
> 262
> $ git grep "const struct pci_device_id" | wc -l
> 1254
> 
> My big complaint is that we need to be consistant, either pick one or
> the other and stick to it.  As the macro is the least used, it's easiest
> to fix up, and it also is more consistant with all other kernel
> subsystems which do not have such a macro.

I've a weak preference for consistency, but not at the expense of
hundreds of patches churning the kernel to remove an innocuous macro.
Churn costs time and effort.

> As there is no need for the __init macro mess anymore, there's no real
> need for the DEFINE_PCI_DEVICE_TABLE macro either.  I think checkpatch
> will catch the use of non-const users for the id table already today, it
> catches lots of other uses like this already.
> 
> > > , so why should PCI be "special" in this regard
> > > anymore?
> > 
> > I think the PCI usage dwarfs most other bus types now, so you could turn
> > the question around.  However, I don't think majority voting is a good
> > guide to best practise; lets debate the merits for their own sake.
> 
> Not really "dwarf", USB is close with over 700 such structures:
> $ git grep "const struct usb_device_id" | wc -l
> 725
> 
> And i2c is almost just as big as PCI:
> $ git grep "const struct i2c_device_id" | wc -l
> 1223
> 
> So again, this macro is not consistent with the majority of PCI drivers,
> nor with any other type of "device id" declaration in the kernel, which
> is why I feel it should be removed.
> 
> And finally, the PCI documentation itself says to not use this macro, so
> this isn't a "new" thing.  From Documentation/PCI/pci.txt:
> 
> 	The ID table is an array of struct pci_device_id entries ending with an
> 	all-zero entry.  Definitions with static const are generally preferred.
> 	Use of the deprecated macro DEFINE_PCI_DEVICE_TABLE should be avoided.
> 
> That wording went into the file last December, when we last talked about
> this and everyone in that discussion agreed to remove the macro for the
> above reasons.
> 
> Consistency matters.

In this case, I don't think it does that much ... a cut and paste either
way (from a macro or non-macro based driver) yields correct code.  Since
there's no bug here and no apparent way to misuse the macro, why bother?

Anyway, it's PCI code ... let the PCI maintainer decide.  However, if he
does want this do it as one big bang patch via either the PCI or Trivial
tree (latter because Ji?? has experience doing this, but the former
might be useful so the decider feels the pain ...)

James




From airlied at gmail.com  Fri Jul 18 14:14:12 2014
From: airlied at gmail.com (Dave Airlie)
Date: Sat, 19 Jul 2014 07:14:12 +1000
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <20140718181759.GB2193@kroah.com>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
 <20140718162213.GC31114@tuxdriver.com>
 <20140718164340.GA24960@kroah.com>
 <1405702472.30262.1.camel@dabdike.int.hansenpartnership.com>
 <20140718181759.GB2193@kroah.com>
Message-ID: <CAPM=9tzgWdnv7jc+xjsJUf0EcyGU+V7nFHzzQ16ui1eE0ihyQA@mail.gmail.com>

>
> We have almost 1000 more uses of the non-macro version than the "macro"
> version in the kernel today:
> $ git grep -w DEFINE_PCI_DEVICE_TABLE | wc -l
> 262
> $ git grep "const struct pci_device_id" | wc -l
> 1254

did you check for non-const ones? just to see if we have any of the
broken case in the tree :-)

as for consistency, pci_dev vs usb_device :-P

Dave.


From greg at kroah.com  Fri Jul 18 14:27:00 2014
From: greg at kroah.com (Greg KH)
Date: Fri, 18 Jul 2014 14:27:00 -0700
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <CAPM=9tzgWdnv7jc+xjsJUf0EcyGU+V7nFHzzQ16ui1eE0ihyQA@mail.gmail.com>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
 <20140718162213.GC31114@tuxdriver.com>
 <20140718164340.GA24960@kroah.com>
 <1405702472.30262.1.camel@dabdike.int.hansenpartnership.com>
 <20140718181759.GB2193@kroah.com>
 <CAPM=9tzgWdnv7jc+xjsJUf0EcyGU+V7nFHzzQ16ui1eE0ihyQA@mail.gmail.com>
Message-ID: <20140718212700.GA12121@kroah.com>

On Sat, Jul 19, 2014 at 07:14:12AM +1000, Dave Airlie wrote:
> >
> > We have almost 1000 more uses of the non-macro version than the "macro"
> > version in the kernel today:
> > $ git grep -w DEFINE_PCI_DEVICE_TABLE | wc -l
> > 262
> > $ git grep "const struct pci_device_id" | wc -l
> > 1254
> 
> did you check for non-const ones? just to see if we have any of the
> broken case in the tree :-)

I didn't :)

> as for consistency, pci_dev vs usb_device :-P

Read farther down the email...



From davem at davemloft.net  Sun Jul 20 21:18:13 2014
From: davem at davemloft.net (David Miller)
Date: Sun, 20 Jul 2014 21:18:13 -0700 (PDT)
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
Message-ID: <20140720.211813.942862864883062133.davem@davemloft.net>

From: Benoit Taine <benoit.taine at lip6.fr>
Date: Fri, 18 Jul 2014 17:26:47 +0200

> We should prefer `const struct pci_device_id` over
> `DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
> This issue was reported by checkpatch.
> 
> A simplified version of the semantic patch that makes this change is as
> follows (http://coccinelle.lip6.fr/):
> 
> // <smpl>
> 
> @@
> identifier i;
> declarer name DEFINE_PCI_DEVICE_TABLE;
> initializer z;
> @@
> 
> - DEFINE_PCI_DEVICE_TABLE(i)
> + const struct pci_device_id i[]
> = z;
> 
> // </smpl>
> 
> I have 103 patches ready, and will only send a few for you to judge if
> it is useful enough, and to prevent from spamming too much.

I'm fine with this wrt. the networking changes, but I don't think this should
be merged via my tree.


From sw at simonwunderlich.de  Mon Jul 21 02:43:04 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Mon, 21 Jul 2014 11:43:04 +0200
Subject: [PATCH 2/2] ath10k: add spectral scan feature
In-Reply-To: <CAEFj986Vruig8wCP+RLS_gQf8utAirmTDCKwmMGyfj7B2vH9pw@mail.gmail.com>
References: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
 <1405689992-8538-3-git-send-email-sw@simonwunderlich.de>
 <CAEFj986Vruig8wCP+RLS_gQf8utAirmTDCKwmMGyfj7B2vH9pw@mail.gmail.com>
Message-ID: <201407211143.04868.sw@simonwunderlich.de>

> On Fri, Jul 18, 2014 at 9:26 PM, Simon Wunderlich <sw at simonwunderlich.de> 
wrote:
> > Adds the spectral scan feature for ath10k. The spectral scan is triggered
> > by configuring a mode through a debugfs control file. Samples can be
> > gathered via another relay debugfs file.
> > 
> > Essentially, to try it out:
> > 
> > ip link dev wlan0 set up
> 
> It should be "ip link set dev wlan0 up", right?

Whoops, yeah, that's right, I'll change that in the next iteration.
> 
> I have tried to capture the samples on ath10k and open it using fft_eval.
> 
> But found the following errors in my samples "invalid bin length 63".
> 
> I will send the samples in separate email.

Thanks for the output! Could it be that you are using the old RFC patch with 
the new fft-eval? I've added another byte (max_exp), so the header became 
longer. Please try again with the latest patch (from this thread), if that is 
the case. Otherwise we have to find out whats wrong ... The sample_len as used 
in fft_eval (tlv-header + data) should be 93 with that version.

Thanks!
    Simon


From sw at simonwunderlich.de  Mon Jul 21 02:59:25 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Mon, 21 Jul 2014 11:59:25 +0200
Subject: [PATCH 2/2] ath10k: add spectral scan feature
In-Reply-To: <CA+BoTQmrn0ddGe=p_d9+vCpMUMQ6dKhL+DmZ76OicacmxoYVMA@mail.gmail.com>
References: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
 <1405689992-8538-3-git-send-email-sw@simonwunderlich.de>
 <CA+BoTQmrn0ddGe=p_d9+vCpMUMQ6dKhL+DmZ76OicacmxoYVMA@mail.gmail.com>
Message-ID: <201407211159.26103.sw@simonwunderlich.de>

Hey Michal,

thanks for the review! I agree to most points and will fixed them in the next 
revision, for the rest I'm putting comments below:

[...]
> > +       nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
> > +       nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
> > +       chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
> > +       switch (chain_idx) {
> > +       case 0:
> > +               fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
> 
> Are you sure you want to & nf_list1 itself *before* the byte swap? You
> probably won't see a difference with an intel host system which is
> little-endian just like the target device.

That is intended as written: with le32_to_cpu() above we get the data into 
host order to process it, then we get the 16-bit noise values according to the 
chain index, and finally convert it to big endian as this is our exchange 
format to userspace - as you can see, we do the same for the other 16bit 
members of fft_sample as well.

[...]
> > +       arvif = ath10k_get_spectral_vdev(ar);
> > +       if (!arvif)
> > +               return -ENODEV;
> > +       vdev_id = arvif->vdev_id;
> > +
> > +       if (ar->spectral_mode == SPECTRAL_DISABLED)
> > +               return 0;
> > +
> > +       res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
> > +                                            
> > WMI_SPECTRAL_TRIGGER_CMD_CLEAR, +                                       
> >      WMI_SPECTRAL_ENABLE_CMD_ENABLE); +       if (res < 0)
> > +               return res;
> > +
> > +       res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
> > +                                            
> > WMI_SPECTRAL_TRIGGER_CMD_TRIGGER, +                                     
> >        WMI_SPECTRAL_ENABLE_CMD_ENABLE); +       if (res < 0)
> > +               return res;
> > +
> > +       return 0;
> > +}
> > +static int ath10k_spectral_scan_config(struct ath10k *ar,
> > +                                      enum ath10k_spectral_mode mode)
> > +{
> > +       struct wmi_vdev_spectral_conf_arg arg;
> > +       struct ath10k_vif *arvif;
> > +       int vdev_id, count, res = 0;
> > +
> 
> Ditto. lockdep_assert_held().

Actually both functions are calling ath10k_get_spectral_vdev() which already 
has that assert, but it doesn't hurt to put it here as well. Will do. :)
[...]

> 
> Did you test this against a firmware crash while spectral scan is
> enabled? ar->spectral_mode will be left as-is when restart is
> performed but no spectral scan will be actually configured. You either
> need to restart spectral scan (better from user perspective) or clear
> out the old mode (easier to code, but bad from user perspective
> because suddenly spectral scan would be stopped implicitly by device
> crash).

No, I didn't test that against a firmware crash yet ... Restarting spectral 
would probably a good idea in endless mode, but not if "count" has been set. 
I'll look into that and propose something in the next iteration.

Thanks. :)
    Simon


From michal.kazior at tieto.com  Mon Jul 21 03:15:34 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 21 Jul 2014 12:15:34 +0200
Subject: [PATCH 2/2] ath10k: add spectral scan feature
In-Reply-To: <201407211159.26103.sw@simonwunderlich.de>
References: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
 <1405689992-8538-3-git-send-email-sw@simonwunderlich.de>
 <CA+BoTQmrn0ddGe=p_d9+vCpMUMQ6dKhL+DmZ76OicacmxoYVMA@mail.gmail.com>
 <201407211159.26103.sw@simonwunderlich.de>
Message-ID: <CA+BoTQnCLDJYzGDLA-zHcaddY-cyuC48dMwTnoHJP+KYG2tN_Q@mail.gmail.com>

On 21 July 2014 11:59, Simon Wunderlich <sw at simonwunderlich.de> wrote:
> Hey Michal,
>
> thanks for the review! I agree to most points and will fixed them in the next
> revision, for the rest I'm putting comments below:
>
> [...]
>> > +       nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
>> > +       nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
>> > +       chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
>> > +       switch (chain_idx) {
>> > +       case 0:
>> > +               fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
>>
>> Are you sure you want to & nf_list1 itself *before* the byte swap? You
>> probably won't see a difference with an intel host system which is
>> little-endian just like the target device.
>
> That is intended as written: with le32_to_cpu() above we get the data into
> host order to process it, then we get the 16-bit noise values according to the
> chain index, and finally convert it to big endian as this is our exchange
> format to userspace - as you can see, we do the same for the other 16bit
> members of fft_sample as well.

Ah, I guess I should put on my glasses now. I parsed that line as
_to_cpu(). Sorry :-)


> [...]
>> > +       arvif = ath10k_get_spectral_vdev(ar);
>> > +       if (!arvif)
>> > +               return -ENODEV;
>> > +       vdev_id = arvif->vdev_id;
>> > +
>> > +       if (ar->spectral_mode == SPECTRAL_DISABLED)
>> > +               return 0;
>> > +
>> > +       res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
>> > +
>> > WMI_SPECTRAL_TRIGGER_CMD_CLEAR, +
>> >      WMI_SPECTRAL_ENABLE_CMD_ENABLE); +       if (res < 0)
>> > +               return res;
>> > +
>> > +       res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
>> > +
>> > WMI_SPECTRAL_TRIGGER_CMD_TRIGGER, +
>> >        WMI_SPECTRAL_ENABLE_CMD_ENABLE); +       if (res < 0)
>> > +               return res;
>> > +
>> > +       return 0;
>> > +}
>> > +static int ath10k_spectral_scan_config(struct ath10k *ar,
>> > +                                      enum ath10k_spectral_mode mode)
>> > +{
>> > +       struct wmi_vdev_spectral_conf_arg arg;
>> > +       struct ath10k_vif *arvif;
>> > +       int vdev_id, count, res = 0;
>> > +
>>
>> Ditto. lockdep_assert_held().
>
> Actually both functions are calling ath10k_get_spectral_vdev() which already
> has that assert, but it doesn't hurt to put it here as well. Will do. :)

True but those functions (scan_config, scan_trigger) also access
conf_mutex protected data themselves directly. If
ath10k_get_spectral_vdev() was to be changed to not require conf_mutex
you'd have to remember to move lockdep_assert_held() up the call
stack.


>> Did you test this against a firmware crash while spectral scan is
>> enabled? ar->spectral_mode will be left as-is when restart is
>> performed but no spectral scan will be actually configured. You either
>> need to restart spectral scan (better from user perspective) or clear
>> out the old mode (easier to code, but bad from user perspective
>> because suddenly spectral scan would be stopped implicitly by device
>> crash).
>
> No, I didn't test that against a firmware crash yet ...

There's 'simulate_fw_crash' in debugfs. I suggest 'hard' method.
'soft' works only with fw 636 now. Watch out for possible host lockups
though.


> Restarting spectral
> would probably a good idea in endless mode, but not if "count" has been set.

Hmm good point, but then what if you have count=20 and fw crashes in
the middle of performing the spectral scan run (e.g. at iteration 10)?

But then this is just a debug interface (or is it?). I don't know if
it's worth it going to great lengths to provide a super smooth user
experience.


Micha?


From michal.kazior at tieto.com  Mon Jul 21 04:11:19 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 21 Jul 2014 13:11:19 +0200
Subject: [PATCH 0/2] ath10k: scan fixes 2014-07-21
Message-ID: <1405941081-17359-1-git-send-email-michal.kazior@tieto.com>

Hi,

This addresses an issue found by Janusz with
current spectral scan patches from Simon.

This goes along patch `ath10k: prevent endless pci rx
loop` I've posted a few days ago.

There seems to be a condition in firmware which
causes some WMI events to be not delivered by
firmware to host most likely due to CE/PCI pipe
being full (that's a guess judging by the huge
amount of phyerrs reported and their behaviour
while spectral scan is enabled). This also
suggests some SWBA events may be dropped by
firmware when spectral scan is running (same goes
for management rx).

@Simon: you may be interested in applying these
patches if you run into trouble while testing
spectral scan + hw_scan/hw_roc.

@Ben: since you reported some scan issues in the
past you may be interested in this as well.


Michal Kazior (2):
  ath10k: introduce a stricter scan state machine
  ath10k: simplify scan debug prints

 drivers/net/wireless/ath/ath10k/core.c |   4 +-
 drivers/net/wireless/ath/ath10k/core.h |  10 +-
 drivers/net/wireless/ath/ath10k/mac.c  | 219 +++++++++++++++++++--------------
 drivers/net/wireless/ath/ath10k/mac.h  |   3 +-
 drivers/net/wireless/ath/ath10k/wmi.c  | 210 ++++++++++++++++++++++---------
 5 files changed, 290 insertions(+), 156 deletions(-)

-- 
1.8.5.3



From michal.kazior at tieto.com  Mon Jul 21 04:11:21 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 21 Jul 2014 13:11:21 +0200
Subject: [PATCH 2/2] ath10k: simplify scan debug prints
In-Reply-To: <1405941081-17359-1-git-send-email-michal.kazior@tieto.com>
References: <1405941081-17359-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1405941081-17359-3-git-send-email-michal.kazior@tieto.com>

This also reduces the cruft of printing scan event
names in capitals.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/wmi.c | 66 ++++++++++++++++++++---------------
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 7ff5280..b4930c4 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -792,6 +792,42 @@ static void ath10k_wmi_event_scan_foreign_chan(struct ath10k *ar, u32 freq)
 	}
 }
 
+static const char *
+ath10k_wmi_event_scan_type_str(enum wmi_scan_event_type type,
+			       enum wmi_scan_completion_reason reason)
+{
+	switch (type) {
+	case WMI_SCAN_EVENT_STARTED:
+		return "started";
+	case WMI_SCAN_EVENT_COMPLETED:
+		switch (reason) {
+		case WMI_SCAN_REASON_COMPLETED:
+			return "completed";
+		case WMI_SCAN_REASON_CANCELLED:
+			return "completed [cancelled]";
+		case WMI_SCAN_REASON_PREEMPTED:
+			return "completed [preempted]";
+		case WMI_SCAN_REASON_TIMEDOUT:
+			return "completed [timedout]";
+		case WMI_SCAN_REASON_MAX:
+			break;
+		}
+		return "completed [unknown]";
+	case WMI_SCAN_EVENT_BSS_CHANNEL:
+		return "bss channel";
+	case WMI_SCAN_EVENT_FOREIGN_CHANNEL:
+		return "foreign channel";
+	case WMI_SCAN_EVENT_DEQUEUED:
+		return "dequeued";
+	case WMI_SCAN_EVENT_PREEMPTED:
+		return "preempted";
+	case WMI_SCAN_EVENT_START_FAILED:
+		return "start failed";
+	default:
+		return "unknown";
+	}
+}
+
 static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data;
@@ -809,56 +845,30 @@ static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
 	scan_id    = __le32_to_cpu(event->scan_id);
 	vdev_id    = __le32_to_cpu(event->vdev_id);
 
-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENTID\n");
 	ath10k_dbg(ATH10K_DBG_WMI,
-		   "scan event type %d reason %d freq %d req_id %d "
+		   "scan event %s type %d reason %d freq %d req_id %d "
 		   "scan_id %d vdev_id %d\n",
+		   ath10k_wmi_event_scan_type_str(event_type, reason),
 		   event_type, reason, freq, req_id, scan_id, vdev_id);
 
 	spin_lock_bh(&ar->data_lock);
 
 	switch (event_type) {
 	case WMI_SCAN_EVENT_STARTED:
-		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_STARTED\n");
 		ath10k_wmi_event_scan_started(ar);
 		break;
 	case WMI_SCAN_EVENT_COMPLETED:
-		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_COMPLETED\n");
-		switch (reason) {
-		case WMI_SCAN_REASON_COMPLETED:
-			ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_COMPLETED\n");
-			break;
-		case WMI_SCAN_REASON_CANCELLED:
-			ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_CANCELED\n");
-			break;
-		case WMI_SCAN_REASON_PREEMPTED:
-			ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_PREEMPTED\n");
-			break;
-		case WMI_SCAN_REASON_TIMEDOUT:
-			ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_TIMEDOUT\n");
-			break;
-		default:
-			break;
-		}
 		ath10k_wmi_event_scan_completed(ar);
 		break;
 	case WMI_SCAN_EVENT_BSS_CHANNEL:
-		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_BSS_CHANNEL\n");
 		ath10k_wmi_event_scan_bss_chan(ar);
 		break;
 	case WMI_SCAN_EVENT_FOREIGN_CHANNEL:
-		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_FOREIGN_CHANNEL\n");
 		ath10k_wmi_event_scan_foreign_chan(ar, freq);
 		break;
 	case WMI_SCAN_EVENT_DEQUEUED:
-		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_DEQUEUED\n");
-		break;
 	case WMI_SCAN_EVENT_PREEMPTED:
-		ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENT_PREEMPTED\n");
-		break;
 	case WMI_SCAN_EVENT_START_FAILED:
-		ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENT_START_FAILED\n");
-		break;
 	default:
 		break;
 	}
-- 
1.8.5.3



From michal.kazior at tieto.com  Mon Jul 21 04:11:20 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 21 Jul 2014 13:11:20 +0200
Subject: [PATCH 1/2] ath10k: introduce a stricter scan state machine
In-Reply-To: <1405941081-17359-1-git-send-email-michal.kazior@tieto.com>
References: <1405941081-17359-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1405941081-17359-2-git-send-email-michal.kazior@tieto.com>

This aims at fixing some rare scan bugs related to
firmware reporting unexpected scan event
sequences.

One such bug was if spectral scan phyerr reporting
prevented firmware from properly propagating scan
events to host. This leadsl to scan timeout. After
that next scan would trigger scan completed event
first (before scan started event) leading to
ar->scan.in_progress and timeout timer states to
be overwritten incorrectly and making the very
next scan to hang forever.

Reported-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.c |   4 +-
 drivers/net/wireless/ath/ath10k/core.h |  10 +-
 drivers/net/wireless/ath/ath10k/mac.c  | 219 +++++++++++++++++++--------------
 drivers/net/wireless/ath/ath10k/mac.h  |   3 +-
 drivers/net/wireless/ath/ath10k/wmi.c  | 144 +++++++++++++++++-----
 5 files changed, 252 insertions(+), 128 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 93adb8c..f2e89f4 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -652,7 +652,7 @@ static void ath10k_core_restart(struct work_struct *work)
 	case ATH10K_STATE_ON:
 		ar->state = ATH10K_STATE_RESTARTING;
 		del_timer_sync(&ar->scan.timeout);
-		ath10k_reset_scan((unsigned long)ar);
+		ath10k_scan_reset(ar, true);
 		ieee80211_restart_hw(ar->hw);
 		break;
 	case ATH10K_STATE_OFF:
@@ -1062,7 +1062,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 	init_completion(&ar->install_key_done);
 	init_completion(&ar->vdev_setup_done);
 
-	setup_timer(&ar->scan.timeout, ath10k_reset_scan, (unsigned long)ar);
+	setup_timer(&ar->scan.timeout, ath10k_scan_timeout, (unsigned long)ar);
 
 	ar->workqueue = create_singlethread_workqueue("ath10k_wq");
 	if (!ar->workqueue)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 83a5fa9..2498d4f 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -341,6 +341,13 @@ enum ath10k_dev_flags {
 	ATH10K_FLAG_CORE_REGISTERED,
 };
 
+enum ath10k_scan_state {
+	ATH10K_SCAN_IDLE,
+	ATH10K_SCAN_STARTING,
+	ATH10K_SCAN_RUNNING,
+	ATH10K_SCAN_RUNNING_AND_ABORTING,
+};
+
 struct ath10k {
 	struct ath_common ath_common;
 	struct ieee80211_hw *hw;
@@ -411,9 +418,8 @@ struct ath10k {
 		struct completion completed;
 		struct completion on_channel;
 		struct timer_list timeout;
+		enum ath10k_scan_state state;
 		bool is_roc;
-		bool in_progress;
-		bool aborting;
 		int vdev_id;
 		int roc_freq;
 	} scan;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b8314a5..a22744b 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2138,34 +2138,43 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work)
 /* Scanning */
 /************/
 
-/*
- * This gets called if we dont get a heart-beat during scan.
- * This may indicate the FW has hung and we need to abort the
- * scan manually to prevent cancel_hw_scan() from deadlocking
- */
-void ath10k_reset_scan(unsigned long ptr)
+void ath10k_scan_reset(struct ath10k *ar, bool notify)
 {
-	struct ath10k *ar = (struct ath10k *)ptr;
-
 	spin_lock_bh(&ar->data_lock);
-	if (!ar->scan.in_progress) {
-		spin_unlock_bh(&ar->data_lock);
-		return;
-	}
 
-	ath10k_warn("scan timed out, firmware problem?\n");
+	switch (ar->scan.state) {
+	case ATH10K_SCAN_IDLE:
+		break;
+	case ATH10K_SCAN_STARTING:
+	case ATH10K_SCAN_RUNNING:
+	case ATH10K_SCAN_RUNNING_AND_ABORTING:
+		ath10k_warn("clearing scan state\n");
+
+		if (notify) {
+			if (ar->scan.is_roc)
+				ieee80211_remain_on_channel_expired(ar->hw);
+			else
+				ieee80211_scan_completed(ar->hw,
+							 1 /* aborted */);
+		}
 
-	if (ar->scan.is_roc)
-		ieee80211_remain_on_channel_expired(ar->hw);
-	else
-		ieee80211_scan_completed(ar->hw, 1 /* aborted */);
+		ar->scan.state = ATH10K_SCAN_IDLE;
+		ath10k_offchan_tx_purge(ar);
+		complete_all(&ar->scan.completed);
+		break;
+	}
 
-	ar->scan.in_progress = false;
-	complete_all(&ar->scan.completed);
 	spin_unlock_bh(&ar->data_lock);
 }
 
-static int ath10k_abort_scan(struct ath10k *ar)
+void ath10k_scan_timeout(unsigned long ptr)
+{
+	struct ath10k *ar = (struct ath10k *)ptr;
+
+	ath10k_scan_reset(ar, true);
+}
+
+static int ath10k_stop_scan(struct ath10k *ar)
 {
 	struct wmi_stop_scan_arg arg = {
 		.req_id = 1, /* FIXME */
@@ -2174,49 +2183,66 @@ static int ath10k_abort_scan(struct ath10k *ar)
 	};
 	int ret;
 
+	ret = ath10k_wmi_stop_scan(ar, &arg);
+	if (ret) {
+		ath10k_warn("failed to stop wmi scan: %d\n", ret);
+		goto out;
+	}
+
+	ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ);
+	if (ret == 0) {
+		ath10k_warn("failed to receive scan abortion completion: timed out\n");
+		ret = -ETIMEDOUT;
+	} else if (ret > 0) {
+		ret = 0;
+	}
+
+out:
+	/* Scan state should be updated upon scan completion but in case
+	 * firmware fails it is still desired to reset the scan state to avoid
+	 * scan request being refused later. There's a chance firmware will
+	 * recover on its own without a restart in due time.
+	 */
+	ath10k_scan_reset(ar, false);
+
+	return ret;
+}
+
+static void ath10k_abort_scan(struct ath10k *ar)
+{
+	int ret;
+
 	lockdep_assert_held(&ar->conf_mutex);
 
 	del_timer_sync(&ar->scan.timeout);
 
 	spin_lock_bh(&ar->data_lock);
-	if (!ar->scan.in_progress) {
+
+	switch (ar->scan.state) {
+	case ATH10K_SCAN_IDLE:
+		ath10k_warn("cannot abort scan: it is idle\n");
+		goto unlock;
+	case ATH10K_SCAN_STARTING:
+		ath10k_warn("cannot abort scan: it is starting\n");
+		goto unlock;
+	case ATH10K_SCAN_RUNNING:
+		ar->scan.state = ATH10K_SCAN_RUNNING_AND_ABORTING;
 		spin_unlock_bh(&ar->data_lock);
-		return 0;
-	}
 
-	ar->scan.aborting = true;
-	spin_unlock_bh(&ar->data_lock);
+		ret = ath10k_stop_scan(ar);
+		if (ret)
+			ath10k_warn("failed to abort scan: %d\n", ret);
 
-	ret = ath10k_wmi_stop_scan(ar, &arg);
-	if (ret) {
-		ath10k_warn("failed to stop wmi scan: %d\n", ret);
 		spin_lock_bh(&ar->data_lock);
-		ar->scan.in_progress = false;
-		ath10k_offchan_tx_purge(ar);
-		spin_unlock_bh(&ar->data_lock);
-		return -EIO;
+		break;
+	case ATH10K_SCAN_RUNNING_AND_ABORTING:
+		ath10k_warn("cannot abort scan: it is already being aborted\n");
+		goto unlock;
 	}
 
-	ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ);
-	if (ret == 0)
-		ath10k_warn("timed out while waiting for scan to stop\n");
-
-	/* scan completion may be done right after we timeout here, so let's
-	 * check the in_progress and tell mac80211 scan is completed. if we
-	 * don't do that and FW fails to send us scan completion indication
-	 * then userspace won't be able to scan anymore */
-	ret = 0;
-
-	spin_lock_bh(&ar->data_lock);
-	if (ar->scan.in_progress) {
-		ath10k_warn("failed to stop scan, it's still in progress\n");
-		ar->scan.in_progress = false;
-		ath10k_offchan_tx_purge(ar);
-		ret = -ETIMEDOUT;
-	}
+unlock:
 	spin_unlock_bh(&ar->data_lock);
-
-	return ret;
+	return;
 }
 
 static int ath10k_start_scan(struct ath10k *ar,
@@ -2232,15 +2258,14 @@ static int ath10k_start_scan(struct ath10k *ar,
 
 	ret = wait_for_completion_timeout(&ar->scan.started, 1*HZ);
 	if (ret == 0) {
-		ath10k_abort_scan(ar);
-		return ret;
+		ret = ath10k_stop_scan(ar);
+		if (ret)
+			ath10k_warn("failed to stop scan: %d\n", ret);
+
+		return -ETIMEDOUT;
 	}
 
-	/* the scan can complete earlier, before we even
-	 * start the timer. in that case the timer handler
-	 * checks ar->scan.in_progress and bails out if its
-	 * false. Add a 200ms margin to account event/command
-	 * processing. */
+	/* Add a 200ms margin to account for event/command processing */
 	mod_timer(&ar->scan.timeout, jiffies +
 		  msecs_to_jiffies(arg->max_scan_time+200));
 	return 0;
@@ -2323,8 +2348,6 @@ void ath10k_halt(struct ath10k *ar)
 		ath10k_monitor_stop(ar);
 	}
 
-	del_timer_sync(&ar->scan.timeout);
-	ath10k_reset_scan((unsigned long)ar);
 	ath10k_peer_cleanup_all(ar);
 	ath10k_core_stop(ar);
 	ath10k_hif_power_down(ar);
@@ -3149,20 +3172,26 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
 	mutex_lock(&ar->conf_mutex);
 
 	spin_lock_bh(&ar->data_lock);
-	if (ar->scan.in_progress) {
-		spin_unlock_bh(&ar->data_lock);
+	switch (ar->scan.state) {
+	case ATH10K_SCAN_IDLE:
+		reinit_completion(&ar->scan.started);
+		reinit_completion(&ar->scan.completed);
+		ar->scan.state = ATH10K_SCAN_STARTING;
+		ar->scan.is_roc = false;
+		ar->scan.vdev_id = arvif->vdev_id;
+		ret = 0;
+		break;
+	case ATH10K_SCAN_STARTING:
+	case ATH10K_SCAN_RUNNING:
+	case ATH10K_SCAN_RUNNING_AND_ABORTING:
 		ret = -EBUSY;
-		goto exit;
+		break;
 	}
-
-	reinit_completion(&ar->scan.started);
-	reinit_completion(&ar->scan.completed);
-	ar->scan.in_progress = true;
-	ar->scan.aborting = false;
-	ar->scan.is_roc = false;
-	ar->scan.vdev_id = arvif->vdev_id;
 	spin_unlock_bh(&ar->data_lock);
 
+	if (ret)
+		goto exit;
+
 	memset(&arg, 0, sizeof(arg));
 	ath10k_wmi_start_scan_init(ar, &arg);
 	arg.vdev_id = arvif->vdev_id;
@@ -3196,8 +3225,9 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
 	if (ret) {
 		ath10k_warn("failed to start hw scan: %d\n", ret);
 		spin_lock_bh(&ar->data_lock);
-		ar->scan.in_progress = false;
+		ar->scan.state = ATH10K_SCAN_IDLE;
 		spin_unlock_bh(&ar->data_lock);
+		goto exit;
 	}
 
 exit:
@@ -3209,14 +3239,9 @@ static void ath10k_cancel_hw_scan(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif)
 {
 	struct ath10k *ar = hw->priv;
-	int ret;
 
 	mutex_lock(&ar->conf_mutex);
-	ret = ath10k_abort_scan(ar);
-	if (ret) {
-		ath10k_warn("failed to abort scan: %d\n", ret);
-		ieee80211_scan_completed(hw, 1 /* aborted */);
-	}
+	ath10k_abort_scan(ar);
 	mutex_unlock(&ar->conf_mutex);
 }
 
@@ -3639,27 +3664,33 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	struct wmi_start_scan_arg arg;
-	int ret;
+	int ret = 0;
 
 	mutex_lock(&ar->conf_mutex);
 
 	spin_lock_bh(&ar->data_lock);
-	if (ar->scan.in_progress) {
-		spin_unlock_bh(&ar->data_lock);
+	switch (ar->scan.state) {
+	case ATH10K_SCAN_IDLE:
+		reinit_completion(&ar->scan.started);
+		reinit_completion(&ar->scan.completed);
+		reinit_completion(&ar->scan.on_channel);
+		ar->scan.state = ATH10K_SCAN_STARTING;
+		ar->scan.is_roc = true;
+		ar->scan.vdev_id = arvif->vdev_id;
+		ar->scan.roc_freq = chan->center_freq;
+		ret = 0;
+		break;
+	case ATH10K_SCAN_STARTING:
+	case ATH10K_SCAN_RUNNING:
+	case ATH10K_SCAN_RUNNING_AND_ABORTING:
 		ret = -EBUSY;
-		goto exit;
+		break;
 	}
-
-	reinit_completion(&ar->scan.started);
-	reinit_completion(&ar->scan.completed);
-	reinit_completion(&ar->scan.on_channel);
-	ar->scan.in_progress = true;
-	ar->scan.aborting = false;
-	ar->scan.is_roc = true;
-	ar->scan.vdev_id = arvif->vdev_id;
-	ar->scan.roc_freq = chan->center_freq;
 	spin_unlock_bh(&ar->data_lock);
 
+	if (ret)
+		goto exit;
+
 	memset(&arg, 0, sizeof(arg));
 	ath10k_wmi_start_scan_init(ar, &arg);
 	arg.vdev_id = arvif->vdev_id;
@@ -3676,7 +3707,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
 	if (ret) {
 		ath10k_warn("failed to start roc scan: %d\n", ret);
 		spin_lock_bh(&ar->data_lock);
-		ar->scan.in_progress = false;
+		ar->scan.state = ATH10K_SCAN_IDLE;
 		spin_unlock_bh(&ar->data_lock);
 		goto exit;
 	}
@@ -3684,7 +3715,11 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
 	ret = wait_for_completion_timeout(&ar->scan.on_channel, 3*HZ);
 	if (ret == 0) {
 		ath10k_warn("failed to switch to channel for roc scan\n");
-		ath10k_abort_scan(ar);
+
+		ret = ath10k_stop_scan(ar);
+		if (ret)
+			ath10k_warn("failed to stop scan: %d\n", ret);
+
 		ret = -ETIMEDOUT;
 		goto exit;
 	}
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index ba10219..19e63c0 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -31,7 +31,8 @@ void ath10k_mac_destroy(struct ath10k *ar);
 int ath10k_mac_register(struct ath10k *ar);
 void ath10k_mac_unregister(struct ath10k *ar);
 struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id);
-void ath10k_reset_scan(unsigned long ptr);
+void ath10k_scan_reset(struct ath10k *ar, bool notify);
+void ath10k_scan_timeout(unsigned long ptr);
 void ath10k_offchan_tx_purge(struct ath10k *ar);
 void ath10k_offchan_tx_work(struct work_struct *work);
 void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 6f83cae..7ff5280 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -690,6 +690,108 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
 	return ret;
 }
 
+static void ath10k_wmi_event_scan_started(struct ath10k *ar)
+{
+	lockdep_assert_held(&ar->data_lock);
+
+	switch (ar->scan.state) {
+	case ATH10K_SCAN_IDLE:
+		ath10k_warn("received scan started event without a scan request, ignoring\n");
+		break;
+	case ATH10K_SCAN_STARTING:
+		ar->scan.state = ATH10K_SCAN_RUNNING;
+
+		if (ar->scan.is_roc)
+			ieee80211_ready_on_channel(ar->hw);
+
+		complete(&ar->scan.started);
+		break;
+	case ATH10K_SCAN_RUNNING:
+		ath10k_warn("received scan started event but scan is already running, ignoring\n");
+		break;
+	case ATH10K_SCAN_RUNNING_AND_ABORTING:
+		ath10k_warn("received scan started event but scan is aborting, ignoring\n");
+		break;
+	}
+}
+
+static void ath10k_wmi_event_scan_completed(struct ath10k *ar)
+{
+	int aborting = 0;
+
+	lockdep_assert_held(&ar->data_lock);
+
+	switch (ar->scan.state) {
+	case ATH10K_SCAN_IDLE:
+		ath10k_warn("received unexpected scan event: completed while idle\n");
+		break;
+	case ATH10K_SCAN_STARTING:
+		/* One suspected reason this can happen is if firmware doesn't
+		 * deliver some scan events to the host for, e.g. when
+		 * transport pipe is full. This has been observed with spectral
+		 * scan phyerr events starving wmi transport pipe. In such case
+		 * the "scan completed" event should be (and is) ignored.
+		 */
+		ath10k_warn("received unexpected scan event: completed while starting\n");
+		break;
+	case ATH10K_SCAN_RUNNING_AND_ABORTING:
+		aborting = 1;
+		/* fall through */
+	case ATH10K_SCAN_RUNNING:
+		ar->scan_channel = NULL;
+
+		if (ar->scan.is_roc) {
+			ath10k_offchan_tx_purge(ar);
+
+			if (!aborting)
+				ieee80211_remain_on_channel_expired(ar->hw);
+		} else {
+			ieee80211_scan_completed(ar->hw, aborting);
+		}
+
+		ar->scan.state = ATH10K_SCAN_IDLE;
+		del_timer(&ar->scan.timeout);
+		complete_all(&ar->scan.completed);
+		break;
+	}
+}
+
+static void ath10k_wmi_event_scan_bss_chan(struct ath10k *ar)
+{
+	lockdep_assert_held(&ar->data_lock);
+
+	switch (ar->scan.state) {
+	case ATH10K_SCAN_IDLE:
+		break;
+	case ATH10K_SCAN_STARTING:
+		break;
+	case ATH10K_SCAN_RUNNING:
+	case ATH10K_SCAN_RUNNING_AND_ABORTING:
+		ar->scan_channel = NULL;
+		break;
+	}
+}
+
+static void ath10k_wmi_event_scan_foreign_chan(struct ath10k *ar, u32 freq)
+{
+	lockdep_assert_held(&ar->data_lock);
+
+	switch (ar->scan.state) {
+	case ATH10K_SCAN_IDLE:
+		break;
+	case ATH10K_SCAN_STARTING:
+		break;
+	case ATH10K_SCAN_RUNNING:
+	case ATH10K_SCAN_RUNNING_AND_ABORTING:
+		ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq);
+
+		if (ar->scan.is_roc && ar->scan.roc_freq == freq)
+			complete(&ar->scan.on_channel);
+
+		break;
+	}
+}
+
 static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data;
@@ -718,10 +820,7 @@ static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
 	switch (event_type) {
 	case WMI_SCAN_EVENT_STARTED:
 		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_STARTED\n");
-		if (ar->scan.in_progress && ar->scan.is_roc)
-			ieee80211_ready_on_channel(ar->hw);
-
-		complete(&ar->scan.started);
+		ath10k_wmi_event_scan_started(ar);
 		break;
 	case WMI_SCAN_EVENT_COMPLETED:
 		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_COMPLETED\n");
@@ -741,37 +840,15 @@ static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
 		default:
 			break;
 		}
-
-		ar->scan_channel = NULL;
-		if (!ar->scan.in_progress) {
-			ath10k_warn("no scan requested, ignoring\n");
-			break;
-		}
-
-		if (ar->scan.is_roc) {
-			ath10k_offchan_tx_purge(ar);
-
-			if (!ar->scan.aborting)
-				ieee80211_remain_on_channel_expired(ar->hw);
-		} else {
-			ieee80211_scan_completed(ar->hw, ar->scan.aborting);
-		}
-
-		del_timer(&ar->scan.timeout);
-		complete_all(&ar->scan.completed);
-		ar->scan.in_progress = false;
+		ath10k_wmi_event_scan_completed(ar);
 		break;
 	case WMI_SCAN_EVENT_BSS_CHANNEL:
 		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_BSS_CHANNEL\n");
-		ar->scan_channel = NULL;
+		ath10k_wmi_event_scan_bss_chan(ar);
 		break;
 	case WMI_SCAN_EVENT_FOREIGN_CHANNEL:
 		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_FOREIGN_CHANNEL\n");
-		ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq);
-		if (ar->scan.in_progress && ar->scan.is_roc &&
-		    ar->scan.roc_freq == freq) {
-			complete(&ar->scan.on_channel);
-		}
+		ath10k_wmi_event_scan_foreign_chan(ar, freq);
 		break;
 	case WMI_SCAN_EVENT_DEQUEUED:
 		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_DEQUEUED\n");
@@ -1041,9 +1118,14 @@ static void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
 
 	spin_lock_bh(&ar->data_lock);
 
-	if (!ar->scan.in_progress) {
-		ath10k_warn("chan info event without a scan request?\n");
+	switch (ar->scan.state) {
+	case ATH10K_SCAN_IDLE:
+	case ATH10K_SCAN_STARTING:
+		ath10k_warn("received chan info event without a scan request, ignoring\n");
 		goto exit;
+	case ATH10K_SCAN_RUNNING:
+	case ATH10K_SCAN_RUNNING_AND_ABORTING:
+		break;
 	}
 
 	idx = freq_to_idx(ar, freq);
-- 
1.8.5.3



From vh.nguyen at actiasodielec.fr  Mon Jul 21 05:10:38 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Mon, 21 Jul 2014 14:10:38 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>,
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>

>>>So probably the air condition you have forces the rate control to pick
>>>MCS7 as the most suitable rates.

>> What could I do to improve this? (Change the air conditioner LOL?)

>Heh, he meant the RF environment in the location you are. :)
>And ugh - this is why we need an open source ART already.

Thanks, I captured log from Wireshark and saw in the frame of broadcast of my AP that VHT Supported MCS 0-9 with NSS1,2,3 (both TX and RX MCS map)
but VHT Operation basic MCS map only indicate MCS 0-7 with NSS1 (strange cause if NSS1 I can not go up to 410 Mbps).
I might move my devices to a closed room to do the test so that I can avoid other RF effects.


NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE



From sw at simonwunderlich.de  Mon Jul 21 05:13:29 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Mon, 21 Jul 2014 14:13:29 +0200
Subject: [PATCH 2/2] ath10k: add spectral scan feature
In-Reply-To: <CA+BoTQnCLDJYzGDLA-zHcaddY-cyuC48dMwTnoHJP+KYG2tN_Q@mail.gmail.com>
References: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
 <201407211159.26103.sw@simonwunderlich.de>
 <CA+BoTQnCLDJYzGDLA-zHcaddY-cyuC48dMwTnoHJP+KYG2tN_Q@mail.gmail.com>
Message-ID: <201407211413.29392.sw@simonwunderlich.de>

> >> > +       arvif = ath10k_get_spectral_vdev(ar);
> >> > +       if (!arvif)
> >> > +               return -ENODEV;
> >> > +       vdev_id = arvif->vdev_id;
> >> > +
> >> > +       if (ar->spectral_mode == SPECTRAL_DISABLED)
> >> > +               return 0;
> >> > +
> >> > +       res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
> >> > +
> >> > WMI_SPECTRAL_TRIGGER_CMD_CLEAR, +
> >> > 
> >> >      WMI_SPECTRAL_ENABLE_CMD_ENABLE); +       if (res < 0)
> >> > 
> >> > +               return res;
> >> > +
> >> > +       res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
> >> > +
> >> > WMI_SPECTRAL_TRIGGER_CMD_TRIGGER, +
> >> > 
> >> >        WMI_SPECTRAL_ENABLE_CMD_ENABLE); +       if (res < 0)
> >> > 
> >> > +               return res;
> >> > +
> >> > +       return 0;
> >> > +}
> >> > +static int ath10k_spectral_scan_config(struct ath10k *ar,
> >> > +                                      enum ath10k_spectral_mode mode)
> >> > +{
> >> > +       struct wmi_vdev_spectral_conf_arg arg;
> >> > +       struct ath10k_vif *arvif;
> >> > +       int vdev_id, count, res = 0;
> >> > +
> >> 
> >> Ditto. lockdep_assert_held().
> > 
> > Actually both functions are calling ath10k_get_spectral_vdev() which
> > already has that assert, but it doesn't hurt to put it here as well.
> > Will do. :)
> 
> True but those functions (scan_config, scan_trigger) also access
> conf_mutex protected data themselves directly. If
> ath10k_get_spectral_vdev() was to be changed to not require conf_mutex
> you'd have to remember to move lockdep_assert_held() up the call
> stack.

Ah, that's right. I'll add that anyway. :)

> 
> >> Did you test this against a firmware crash while spectral scan is
> >> enabled? ar->spectral_mode will be left as-is when restart is
> >> performed but no spectral scan will be actually configured. You either
> >> need to restart spectral scan (better from user perspective) or clear
> >> out the old mode (easier to code, but bad from user perspective
> >> because suddenly spectral scan would be stopped implicitly by device
> >> crash).
> > 
> > No, I didn't test that against a firmware crash yet ...
> 
> There's 'simulate_fw_crash' in debugfs. I suggest 'hard' method.
> 'soft' works only with fw 636 now. Watch out for possible host lockups
> though.
> 

Thanks, the hard firmware crash worked for me.

> > Restarting spectral
> > would probably a good idea in endless mode, but not if "count" has been
> > set.
> 
> Hmm good point, but then what if you have count=20 and fw crashes in
> the middle of performing the spectral scan run (e.g. at iteration 10)?
> 
> But then this is just a debug interface (or is it?). I don't know if
> it's worth it going to great lengths to provide a super smooth user
> experience.

Well yeah, it's in debugfs so its a debug interface. ;) Since we don't really 
keep track whether a scan was triggered or not, and the firmware takes some 
time to recover, I don't think it's worth the hassle - without creating more 
confusion. I'll reset the spectral mode in any case so users at least see that 
its disabled.

I'll send the next round of patches in some minutes. :)

Thanks!
    Simon


From sw at simonwunderlich.de  Mon Jul 21 05:32:21 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Mon, 21 Jul 2014 14:32:21 +0200
Subject: [PATCHv2 0/2] ath10k spectral scan support
Message-ID: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>

This is the second "PATCH" patchset iteration for the ath10k spectral
scan feature. It includes a few cosmetic changes and now handles
firmware crashes (Thanks Michal and Chun-Yeow!).

The fft_eval tool has also been updated based on the new patchset, and
now supports both ath9k and ath10k sample formats in the same branch,
which has been merged into master [1]. Please make sure to use the
latest version of both fft_eval and this patchset for testing.

The count issue is still open: Even when a count is specified, the
hardware seems to send endless samples. It seems to work most of the
time in VHT80 mode though, but in HT20 and HT40 the count value seems
to be ignored. To reproduce this, start hostapd with the desired
channel width and do:

echo 8 > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_count
echo manual > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
echo trigger > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 >> /tmp/fft.dump

Repeating the last line and checking the filesize will easily show
whether ath10k still sends samples or not. We would expect 8 samples in
this configuration.

See the patch for more information on the changes.

Cheers,
	Simon

[1] https://github.com/simonwunderlich/FFT_eval

Simon Wunderlich (1):
  ath10k: add spectral scan feature

Sven Eckelmann (1):
  ath: Move spectral debugfs structs to shared header

 drivers/net/wireless/ath/ath10k/Kconfig    |   1 +
 drivers/net/wireless/ath/ath10k/Makefile   |   3 +-
 drivers/net/wireless/ath/ath10k/core.c     |   4 +
 drivers/net/wireless/ath/ath10k/core.h     |   8 +
 drivers/net/wireless/ath/ath10k/debug.c    |   3 +
 drivers/net/wireless/ath/ath10k/mac.c      |   9 +
 drivers/net/wireless/ath/ath10k/spectral.c | 563 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |  64 ++++
 drivers/net/wireless/ath/ath10k/wmi.c      | 104 +++++-
 drivers/net/wireless/ath/ath10k/wmi.h      |  94 +++++
 drivers/net/wireless/ath/ath9k/spectral.h  |  71 +---
 drivers/net/wireless/ath/spectral_common.h | 112 ++++++
 12 files changed, 965 insertions(+), 71 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h
 create mode 100644 drivers/net/wireless/ath/spectral_common.h

-- 
1.9.1



From sw at simonwunderlich.de  Mon Jul 21 05:32:23 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Mon, 21 Jul 2014 14:32:23 +0200
Subject: [PATCHv2 2/2] ath10k: add spectral scan feature
In-Reply-To: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
References: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <1405945943-8303-3-git-send-email-sw@simonwunderlich.de>

Adds the spectral scan feature for ath10k. The spectral scan is triggered by
configuring a mode through a debugfs control file. Samples can be gathered via
another relay debugfs file.

Essentially, to try it out:

ip link set dev wlan0 up
echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
iw dev wlan0 scan
echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples

This feature is still experimental. Based on the original RFC patch of
Sven Eckelmann.

Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
--
PATCHv2:
 * fixed usage example in commit message (Thanks Chun-Yeow Yeoh)
 * adding lockdep asserts and comment (Thanks Michal)
 * debug message cleanups (Michal)
 * disable spectral on firmware crash (Michal)

PATCH:
 * change the tlv format to a variable-length format, depending on the
   number of bins
 * perform dc interpolation and max_exp calculation in the driver (as
   for ath9k)
 * make fft_size configurable
 * background scan will only start after beeing trigger, like in ath9k
 * document at least some spectral configuration members (thanks Kathy)
 * fix sparse problems
 * sample bandwidth appears to be 110% of what is reported by the
   hardware according to the plotter (e.g. 20->22, 40->44 MHz etc),
   so fix that in the driver.
 * disable spectral for a vif when it's beeing deleted and still active
   (Michals comment)
 * modify ath_ prefix of function/struct/enum to ath10k_ (Michal)
 * changed variable ret to res (Michal)
 * added ath10k_warn messages (Michal)
 * renamed wmi functions (Michal)
 * use ar->conf_mutex for locking (Michal)
 * renamed mhz to chan_width_mhz (Michal)
 * only enable spectral scan files when ATH10K_DEBUGFS is enabled
---
 drivers/net/wireless/ath/ath10k/Kconfig    |   1 +
 drivers/net/wireless/ath/ath10k/Makefile   |   3 +-
 drivers/net/wireless/ath/ath10k/core.c     |   4 +
 drivers/net/wireless/ath/ath10k/core.h     |   8 +
 drivers/net/wireless/ath/ath10k/debug.c    |   3 +
 drivers/net/wireless/ath/ath10k/mac.c      |   9 +
 drivers/net/wireless/ath/ath10k/spectral.c | 563 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |  64 ++++
 drivers/net/wireless/ath/ath10k/wmi.c      | 104 +++++-
 drivers/net/wireless/ath/ath10k/wmi.h      |  94 +++++
 drivers/net/wireless/ath/spectral_common.h |  24 ++
 11 files changed, 875 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h

diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index 489bf8b..095dcaf 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -27,6 +27,7 @@ config ATH10K_DEBUG
 config ATH10K_DEBUGFS
 	bool "Atheros ath10k debugfs support"
 	depends on ATH10K
+	select RELAY
 	---help---
 	  Enabled debugfs support
 
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index 2110a5c..e1dcefd 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -8,7 +8,8 @@ ath10k_core-y += mac.o \
 		 htt_tx.o \
 		 txrx.o \
 		 wmi.o \
-		 bmi.o
+		 bmi.o \
+		 spectral.o
 
 ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
 
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index ebc5fc2..3a113fb 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -699,6 +699,10 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 	ar->hif.priv = hif_priv;
 	ar->hif.ops = hif_ops;
 
+	ar->spectral_mode = SPECTRAL_DISABLED;
+	ar->spec_config.count = WMI_SPECTRAL_COUNT_DEFAULT;
+	ar->spec_config.fft_size = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
+
 	init_completion(&ar->scan.started);
 	init_completion(&ar->scan.completed);
 	init_completion(&ar->scan.on_channel);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 80aa5a4..4af527a 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -31,6 +31,7 @@
 #include "../ath.h"
 #include "../regd.h"
 #include "../dfs_pattern_detector.h"
+#include "spectral.h"
 
 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -230,6 +231,7 @@ struct ath10k_vif {
 
 	bool is_started;
 	bool is_up;
+	bool spectral_enabled;
 	u32 aid;
 	u8 bssid[ETH_ALEN];
 
@@ -469,6 +471,12 @@ struct ath10k {
 #ifdef CONFIG_ATH10K_DEBUGFS
 	struct ath10k_debug debug;
 #endif
+
+	/* relay(fs) channel for spectral scan */
+	struct rchan *rfs_chan_spec_scan;
+	/* spectral_mode and spec_config are protected by conf_mutex */
+	enum ath10k_spectral_mode spectral_mode;
+	struct ath10k_spec_scan spec_config;
 };
 
 struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index f56f358..f8f4f6f 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -853,12 +853,15 @@ int ath10k_debug_create(struct ath10k *ar)
 				    &fops_dfs_stats);
 	}
 
+	ath10k_spectral_init_debug(ar);
+
 	return 0;
 }
 
 void ath10k_debug_destroy(struct ath10k *ar)
 {
 	cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
+	ath10k_spectral_deinit_debug(ar);
 }
 
 #endif /* CONFIG_ATH10K_DEBUGFS */
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 348a639..14d6234 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2201,6 +2201,7 @@ void ath10k_halt(struct ath10k *ar)
 	ath10k_peer_cleanup_all(ar);
 	ath10k_core_stop(ar);
 	ath10k_hif_power_down(ar);
+	ath10k_disable_spectral(ar);
 
 	spin_lock_bh(&ar->data_lock);
 	if (ar->scan.in_progress) {
@@ -2671,8 +2672,16 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 		dev_kfree_skb_any(arvif->beacon);
 		arvif->beacon = NULL;
 	}
+
 	spin_unlock_bh(&ar->data_lock);
 
+	if (arvif->spectral_enabled) {
+		ret = ath10k_disable_spectral(ar);
+		if (ret)
+			ath10k_warn("Failed to disable spectral for vdev %i: %d\n",
+				    arvif->vdev_id, ret);
+	}
+
 	ar->free_vdev_map |= 1 << (arvif->vdev_id);
 	list_del(&arvif->list);
 
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
new file mode 100644
index 0000000..4179efb
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -0,0 +1,563 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/relay.h>
+#include "core.h"
+#include "debug.h"
+
+static void
+ath10k_debug_send_fft_sample(struct ath10k *ar,
+			     const struct fft_sample_tlv *fft_sample_tlv)
+{
+	int length;
+
+	if (!ar->rfs_chan_spec_scan)
+		return;
+
+	length = __be16_to_cpu(fft_sample_tlv->length) +
+		 sizeof(*fft_sample_tlv);
+	relay_write(ar->rfs_chan_spec_scan, fft_sample_tlv, length);
+}
+
+static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
+			   u8 *data)
+{
+	int dc_pos;
+	u8 max_exp;
+
+	dc_pos = bin_len / 2;
+	/* peak index outside of bins */
+	if (dc_pos < max_index || -dc_pos >= max_index)
+		return 0;
+
+	for (max_exp = 0; max_exp < 8; max_exp++) {
+		if (data[dc_pos + max_index] == (max_magnitude >> max_exp))
+			break;
+	}
+
+	/* max_exp not found */
+	if (data[dc_pos + max_index] != (max_magnitude >> max_exp))
+		return 0;
+
+	return max_exp;
+}
+
+int ath10k_process_fft(struct ath10k *ar,
+		       struct wmi_single_phyerr_rx_event *event,
+		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
+{
+	struct fft_sample_ath10k *fft_sample;
+	u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
+	int dc_pos;
+	u32 reg0, reg1;
+	u16 peak_mag;
+	u8 *bins;
+	u16 freq1;
+	u16 freq2;
+	u16 total_gain_db;
+	u16 base_pwr_db;
+	u8 chain_idx;
+	u32 nf_list1;
+	u32 nf_list2;
+	u16 length;
+
+	fft_sample = (struct fft_sample_ath10k *)&buf;
+
+	if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
+		return -EINVAL;
+
+	reg0 = __le32_to_cpu(fftr->reg0);
+	reg1 = __le32_to_cpu(fftr->reg1);
+
+	length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + bin_len;
+	fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH10K;
+	fft_sample->tlv.length = __cpu_to_be16(length);
+
+	/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
+	 * but the results/plots suggest that its actually 22/44/88 MHz.
+	 */
+	switch (event->hdr.chan_width_mhz) {
+	case 20:
+		fft_sample->chan_width_mhz = 22;
+		break;
+	case 40:
+		fft_sample->chan_width_mhz = 44;
+		break;
+	case 80:
+		/* TODO: As experiments with an analogue sender and various
+		 * configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
+		 * show, the particular configuration of 80 MHz/64 bins does
+		 * not match with the other smaples at all. Until the reason
+		 * for that is found, don't report these samples.
+		 */
+		if (bin_len == 64)
+			return -EINVAL;
+		fft_sample->chan_width_mhz = 88;
+		break;
+	default:
+		fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
+	}
+	fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
+	fft_sample->avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
+
+	peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
+	fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
+	fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
+	fft_sample->rssi = event->hdr.rssi_combined;
+
+	total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
+	base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
+	fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
+	fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
+
+	freq1 = __le16_to_cpu(event->hdr.freq1);
+	freq2 = __le16_to_cpu(event->hdr.freq2);
+	fft_sample->freq1 = __cpu_to_be16(freq1);
+	fft_sample->freq2 = __cpu_to_be16(freq2);
+
+	nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
+	nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
+	chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
+	switch (chain_idx) {
+	case 0:
+		fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
+		break;
+	case 1:
+		fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
+		break;
+	case 2:
+		fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
+		break;
+	case 3:
+		fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
+		break;
+	}
+
+	bins = (u8 *)fftr;
+	bins += sizeof(*fftr);
+
+	fft_sample->tsf = __cpu_to_be64(tsf);
+	/* max_exp has been directly reported by previous hardware (ath9k),
+	 * maybe its possible to get it by other means?
+	 */
+	fft_sample->max_exp = get_max_exp(fft_sample->max_index, peak_mag,
+					  bin_len, bins);
+
+	memcpy(fft_sample->data, bins, bin_len);
+
+	/* DC value (value in the middle) is the blind spot of the spectral
+	 * sample and invalid, interpolate it.
+	 */
+	dc_pos = bin_len / 2;
+	fft_sample->data[dc_pos] = (fft_sample->data[dc_pos + 1] +
+				    fft_sample->data[dc_pos - 1]) / 2;
+
+	ath10k_debug_send_fft_sample(ar, &fft_sample->tlv);
+
+	return 0;
+}
+
+static struct ath10k_vif *ath10k_get_spectral_vdev(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	if (list_empty(&ar->arvifs))
+		return NULL;
+
+	/* if there already is a vif doing spectral, return that. */
+	list_for_each_entry(arvif, &ar->arvifs, list)
+		if (arvif->spectral_enabled)
+			return arvif;
+
+	/* otherwise, return the first vif. */
+	return list_first_entry(&ar->arvifs, typeof(*arvif), list);
+}
+
+static int ath10k_spectral_scan_trigger(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+	int res;
+	int vdev_id;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	arvif = ath10k_get_spectral_vdev(ar);
+	if (!arvif)
+		return -ENODEV;
+	vdev_id = arvif->vdev_id;
+
+	if (ar->spectral_mode == SPECTRAL_DISABLED)
+		return 0;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (res < 0)
+		return res;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
+					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (res < 0)
+		return res;
+
+	return 0;
+}
+
+static int ath10k_spectral_scan_config(struct ath10k *ar,
+				       enum ath10k_spectral_mode mode)
+{
+	struct wmi_vdev_spectral_conf_arg arg;
+	struct ath10k_vif *arvif;
+	int vdev_id, count, res = 0;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	arvif = ath10k_get_spectral_vdev(ar);
+	if (!arvif)
+		return -ENODEV;
+
+	vdev_id = arvif->vdev_id;
+
+	arvif->spectral_enabled = (mode != SPECTRAL_DISABLED);
+	ar->spectral_mode = mode;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					      WMI_SPECTRAL_ENABLE_CMD_DISABLE);
+	if (res < 0) {
+		ath10k_warn("failed to enable spectral scan: %d\n", res);
+		return res;
+	}
+
+	if (mode == SPECTRAL_DISABLED)
+		return 0;
+
+	if (mode == SPECTRAL_BACKGROUND)
+		count = WMI_SPECTRAL_COUNT_DEFAULT;
+	else
+		count = max_t(u8, 1, ar->spec_config.count);
+
+	arg.vdev_id              = vdev_id;
+	arg.scan_count           = count;
+	arg.scan_period          = WMI_SPECTRAL_PERIOD_DEFAULT;
+	arg.scan_priority        = WMI_SPECTRAL_PRIORITY_DEFAULT;
+	arg.scan_fft_size        = ar->spec_config.fft_size;
+	arg.scan_gc_ena          = WMI_SPECTRAL_GC_ENA_DEFAULT;
+	arg.scan_restart_ena     = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
+	arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
+	arg.scan_init_delay      = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
+	arg.scan_nb_tone_thr     = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
+	arg.scan_str_bin_thr     = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
+	arg.scan_wb_rpt_mode     = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
+	arg.scan_rssi_rpt_mode   = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
+	arg.scan_rssi_thr        = WMI_SPECTRAL_RSSI_THR_DEFAULT;
+	arg.scan_pwr_format      = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
+	arg.scan_rpt_mode        = WMI_SPECTRAL_RPT_MODE_DEFAULT;
+	arg.scan_bin_scale       = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	arg.scan_dbm_adj         = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
+	arg.scan_chn_mask        = WMI_SPECTRAL_CHN_MASK_DEFAULT;
+
+	res = ath10k_wmi_vdev_spectral_conf(ar, &arg);
+	if (res < 0) {
+		ath10k_warn("failed to configure spectral scan: %d\n", res);
+		return res;
+	}
+
+	return 0;
+}
+
+int ath10k_disable_spectral(struct ath10k *ar)
+{
+	return ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
+}
+
+/*********************/
+/* spectral_scan_ctl */
+/*********************/
+
+static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char *mode = "";
+	unsigned int len;
+	enum ath10k_spectral_mode spectral_mode;
+
+	mutex_lock(&ar->conf_mutex);
+	spectral_mode = ar->spectral_mode;
+	mutex_unlock(&ar->conf_mutex);
+
+	switch (spectral_mode) {
+	case SPECTRAL_DISABLED:
+		mode = "disable";
+		break;
+	case SPECTRAL_BACKGROUND:
+		mode = "background";
+		break;
+	case SPECTRAL_MANUAL:
+		mode = "manual";
+		break;
+	}
+
+	len = strlen(mode);
+	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
+}
+
+static ssize_t write_file_spec_scan_ctl(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	ssize_t len;
+	int res;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (strncmp("trigger", buf, 7) == 0) {
+		if (ar->spectral_mode == SPECTRAL_MANUAL ||
+		    ar->spectral_mode == SPECTRAL_BACKGROUND) {
+			/* reset the configuration to adopt possibly changed
+			 * debugfs parameters
+			 */
+			res = ath10k_spectral_scan_config(ar,
+							  ar->spectral_mode);
+			if (res < 0) {
+				ath10k_warn("failed to reconfigure spectral scan: %d\n",
+					    res);
+			}
+			res = ath10k_spectral_scan_trigger(ar);
+			if (res < 0) {
+				ath10k_warn("failed to trigger spectral scan: %d\n",
+					    res);
+			}
+		} else {
+			res = -EINVAL;
+		}
+	} else if (strncmp("background", buf, 9) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
+	} else if (strncmp("manual", buf, 6) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
+	} else if (strncmp("disable", buf, 7) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
+	} else {
+		res = -EINVAL;
+	}
+
+	mutex_unlock(&ar->conf_mutex);
+
+	if (res < 0)
+		return res;
+
+	return count;
+}
+
+static const struct file_operations fops_spec_scan_ctl = {
+	.read = read_file_spec_scan_ctl,
+	.write = write_file_spec_scan_ctl,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+/******************/
+/* spectral_count */
+/******************/
+
+static ssize_t read_file_spectral_count(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len;
+	u8 spectral_count;
+
+	mutex_lock(&ar->conf_mutex);
+	spectral_count = ar->spec_config.count;
+	mutex_unlock(&ar->conf_mutex);
+
+	len = sprintf(buf, "%d\n", spectral_count);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_count(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 0 || val > 255)
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+	ar->spec_config.count = val;
+	mutex_unlock(&ar->conf_mutex);
+
+	return count;
+}
+
+static const struct file_operations fops_spectral_count = {
+	.read = read_file_spectral_count,
+	.write = write_file_spectral_count,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+/*****************/
+/* spectral_bins */
+/*****************/
+
+static ssize_t read_file_spectral_bins(struct file *file,
+				       char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len;
+	unsigned int bins;
+
+	mutex_lock(&ar->conf_mutex);
+	bins = 1 << (ar->spec_config.fft_size - WMI_SPECTRAL_BIN_SCALE_DEFAULT);
+	mutex_unlock(&ar->conf_mutex);
+
+	len = sprintf(buf, "%d\n", bins);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_bins(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
+		return -EINVAL;
+
+	if (!is_power_of_2(val))
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+	ar->spec_config.fft_size = ilog2(val);
+	ar->spec_config.fft_size += WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	mutex_unlock(&ar->conf_mutex);
+
+	return count;
+}
+
+static const struct file_operations fops_spectral_bins = {
+	.read = read_file_spectral_bins,
+	.write = write_file_spectral_bins,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+/*******************/
+/* Relay interface */
+/*******************/
+
+static struct dentry *create_buf_file_handler(const char *filename,
+					      struct dentry *parent,
+					      umode_t mode,
+					      struct rchan_buf *buf,
+					      int *is_global)
+{
+	struct dentry *buf_file;
+
+	buf_file = debugfs_create_file(filename, mode, parent, buf,
+				       &relay_file_operations);
+	*is_global = 1;
+	return buf_file;
+}
+
+static int remove_buf_file_handler(struct dentry *dentry)
+{
+	debugfs_remove(dentry);
+
+	return 0;
+}
+
+static struct rchan_callbacks rfs_spec_scan_cb = {
+	.create_buf_file = create_buf_file_handler,
+	.remove_buf_file = remove_buf_file_handler,
+};
+
+/*********************/
+/* Debug Init/Deinit */
+/*********************/
+
+void ath10k_spectral_deinit_debug(struct ath10k *ar)
+{
+	if (config_enabled(CONFIG_ATH10K_DEBUGFS) && ar->rfs_chan_spec_scan) {
+		relay_close(ar->rfs_chan_spec_scan);
+		ar->rfs_chan_spec_scan = NULL;
+	}
+}
+
+void ath10k_spectral_init_debug(struct ath10k *ar)
+{
+#ifdef CONFIG_ATH10K_DEBUGFS
+	ar->rfs_chan_spec_scan = relay_open("spectral_scan",
+					    ar->debug.debugfs_phy,
+					    1024, 256, &rfs_spec_scan_cb,
+					    NULL);
+	debugfs_create_file("spectral_scan_ctl",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spec_scan_ctl);
+	debugfs_create_file("spectral_count",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_count);
+	debugfs_create_file("spectral_bins",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_bins);
+#endif
+}
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
new file mode 100644
index 0000000..ee10ad2
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_H
+#define SPECTRAL_H
+
+#include "../spectral_common.h"
+
+/**
+ * struct ath10k_spec_scan - parameters for Atheros spectral scan
+ *
+ * @count: number of scan results requested for manual mode
+ */
+struct ath10k_spec_scan {
+	u8 count;
+	u8 fft_size;
+};
+
+/* enum ath10k_spectral_mode:
+ *
+ * @SPECTRAL_DISABLED: spectral mode is disabled
+ * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
+ *	something else.
+ * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
+ *	is performed manually.
+ */
+enum ath10k_spectral_mode {
+	SPECTRAL_DISABLED = 0,
+	SPECTRAL_BACKGROUND,
+	SPECTRAL_MANUAL,
+};
+
+void ath10k_spectral_init_debug(struct ath10k *ar);
+void ath10k_spectral_deinit_debug(struct ath10k *ar);
+int ath10k_disable_spectral(struct ath10k *ar);
+
+#ifdef CONFIG_ATH10K_DEBUGFS
+int ath10k_process_fft(struct ath10k *ar,
+		       struct wmi_single_phyerr_rx_event *event,
+		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf);
+#else
+static inline int
+ath10k_process_fft(struct ath10k *ar,
+		   struct wmi_single_phyerr_rx_event *event,
+		   struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
+{
+	return 0;
+}
+#endif /* CONFIG_ATH10K_DEBUGFS */
+
+#endif /* SPECTRAL_H */
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index beac30d..1422296 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1649,7 +1649,53 @@ static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
 				struct wmi_single_phyerr_rx_event *event,
 				u64 tsf)
 {
-	ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n");
+	int buf_len, tlv_len, res, i = 0;
+	struct phyerr_tlv *tlv;
+	u8 *tlv_buf;
+	struct phyerr_fft_report *fftr;
+	size_t fftr_len;
+
+	buf_len = __le32_to_cpu(event->hdr.buf_len);
+
+	while (i < buf_len) {
+		if (i + sizeof(*tlv) > buf_len) {
+			ath10k_warn("failed to parse phyerr tlv header at byte %d\n",
+				    i);
+			return;
+		}
+
+		tlv = (struct phyerr_tlv *)&event->bufp[i];
+		tlv_len = __le16_to_cpu(tlv->len);
+		tlv_buf = &event->bufp[i + sizeof(*tlv)];
+
+		if (i + sizeof(*tlv) + tlv_len > buf_len) {
+			ath10k_warn("failed to parse phyerr tlv payload at byte %d\n",
+				    i);
+			return;
+		}
+
+		switch (tlv->tag) {
+		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
+			if (sizeof(*fftr) > tlv_len) {
+				ath10k_warn("failed to parse fft report at byte %d\n",
+					    i);
+				return;
+			}
+
+			fftr_len = tlv_len - sizeof(*fftr);
+			fftr = (struct phyerr_fft_report *)tlv_buf;
+			res = ath10k_process_fft(ar, event, fftr, fftr_len,
+						 tsf);
+			if (res < 0) {
+				ath10k_warn("failed to process fft report: %d\n",
+					    res);
+				return;
+			}
+			break;
+		}
+
+		i += sizeof(*tlv) + tlv_len;
+	}
 }
 
 static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
@@ -3191,6 +3237,62 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				   ar->wmi.cmd->vdev_install_key_cmdid);
 }
 
+int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
+				  const struct wmi_vdev_spectral_conf_arg *arg)
+{
+	struct wmi_vdev_spectral_conf_cmd *cmd;
+	struct sk_buff *skb;
+	u32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_conf_cmd *)skb->data;
+	cmd->vdev_id              = __cpu_to_le32(arg->vdev_id);
+	cmd->scan_count           = __cpu_to_le32(arg->scan_count);
+	cmd->scan_period          = __cpu_to_le32(arg->scan_period);
+	cmd->scan_priority        = __cpu_to_le32(arg->scan_priority);
+	cmd->scan_fft_size        = __cpu_to_le32(arg->scan_fft_size);
+	cmd->scan_gc_ena          = __cpu_to_le32(arg->scan_gc_ena);
+	cmd->scan_restart_ena     = __cpu_to_le32(arg->scan_restart_ena);
+	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
+	cmd->scan_init_delay      = __cpu_to_le32(arg->scan_init_delay);
+	cmd->scan_nb_tone_thr     = __cpu_to_le32(arg->scan_nb_tone_thr);
+	cmd->scan_str_bin_thr     = __cpu_to_le32(arg->scan_str_bin_thr);
+	cmd->scan_wb_rpt_mode     = __cpu_to_le32(arg->scan_wb_rpt_mode);
+	cmd->scan_rssi_rpt_mode   = __cpu_to_le32(arg->scan_rssi_rpt_mode);
+	cmd->scan_rssi_thr        = __cpu_to_le32(arg->scan_rssi_thr);
+	cmd->scan_pwr_format      = __cpu_to_le32(arg->scan_pwr_format);
+	cmd->scan_rpt_mode        = __cpu_to_le32(arg->scan_rpt_mode);
+	cmd->scan_bin_scale       = __cpu_to_le32(arg->scan_bin_scale);
+	cmd->scan_dbm_adj         = __cpu_to_le32(arg->scan_dbm_adj);
+	cmd->scan_chn_mask        = __cpu_to_le32(arg->scan_chn_mask);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_configure_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
+int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				    u32 enable)
+{
+	struct wmi_vdev_spectral_enable_cmd *cmd;
+	struct sk_buff *skb;
+	u32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_enable_cmd *)skb->data;
+	cmd->vdev_id     = __cpu_to_le32(vdev_id);
+	cmd->trigger_cmd = __cpu_to_le32(trigger);
+	cmd->enable_cmd  = __cpu_to_le32(enable);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_enable_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 			   const u8 peer_addr[ETH_ALEN])
 {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 4fcc96a..da5cbda 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2077,6 +2077,7 @@ struct wmi_comb_phyerr_rx_event {
 #define PHYERR_TLV_SIG				0xBB
 #define PHYERR_TLV_TAG_SEARCH_FFT_REPORT	0xFB
 #define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY	0xF8
+#define PHYERR_TLV_TAG_SPECTRAL_SUMMARY_REPORT	0xF9
 
 struct phyerr_radar_report {
 	__le32 reg0; /* RADAR_REPORT_REG0_* */
@@ -3381,6 +3382,95 @@ struct wmi_vdev_simple_event {
 /* unsupported VDEV combination */
 #define WMI_INIFIED_VDEV_START_RESPONSE_NOT_SUPPORTED	0x2
 
+/* TODO: please add more comments if you have in-depth information */
+struct wmi_vdev_spectral_conf_cmd {
+	__le32 vdev_id;
+	/* number of fft samples to send (0 for infinite) */
+	__le32 scan_count;
+	__le32 scan_period;
+	__le32 scan_priority;
+	/* number of bins in the FFT: 2^(fft_size - bin_scale) */
+	__le32 scan_fft_size;
+	__le32 scan_gc_ena;
+	__le32 scan_restart_ena;
+	__le32 scan_noise_floor_ref;
+	__le32 scan_init_delay;
+	__le32 scan_nb_tone_thr;
+	__le32 scan_str_bin_thr;
+	__le32 scan_wb_rpt_mode;
+	__le32 scan_rssi_rpt_mode;
+	__le32 scan_rssi_thr;
+	__le32 scan_pwr_format;
+	/* rpt_mode: Format of FFT report to software for spectral scan
+	 * triggered FFTs:
+	 *	0: No FFT report (only spectral scan summary report)
+	 *	1: 2-dword summary of metrics for each completed FFT + spectral
+	 *	   scan	summary report
+	 *	2: 2-dword summary of metrics for each completed FFT +
+	 *	   1x- oversampled bins(in-band) per FFT + spectral scan summary
+	 *	   report
+	 *	3: 2-dword summary of metrics for each completed FFT +
+	 *	   2x- oversampled bins	(all) per FFT + spectral scan summary
+	 */
+	__le32 scan_rpt_mode;
+	__le32 scan_bin_scale;
+	__le32 scan_dbm_adj;
+	__le32 scan_chn_mask;
+} __packed;
+
+struct wmi_vdev_spectral_conf_arg {
+	u32 vdev_id;
+	u32 scan_count;
+	u32 scan_period;
+	u32 scan_priority;
+	u32 scan_fft_size;
+	u32 scan_gc_ena;
+	u32 scan_restart_ena;
+	u32 scan_noise_floor_ref;
+	u32 scan_init_delay;
+	u32 scan_nb_tone_thr;
+	u32 scan_str_bin_thr;
+	u32 scan_wb_rpt_mode;
+	u32 scan_rssi_rpt_mode;
+	u32 scan_rssi_thr;
+	u32 scan_pwr_format;
+	u32 scan_rpt_mode;
+	u32 scan_bin_scale;
+	u32 scan_dbm_adj;
+	u32 scan_chn_mask;
+};
+
+#define WMI_SPECTRAL_ENABLE_DEFAULT              0
+#define WMI_SPECTRAL_COUNT_DEFAULT               0
+#define WMI_SPECTRAL_PERIOD_DEFAULT             35
+#define WMI_SPECTRAL_PRIORITY_DEFAULT            1
+#define WMI_SPECTRAL_FFT_SIZE_DEFAULT            7
+#define WMI_SPECTRAL_GC_ENA_DEFAULT              1
+#define WMI_SPECTRAL_RESTART_ENA_DEFAULT         0
+#define WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT   -96
+#define WMI_SPECTRAL_INIT_DELAY_DEFAULT         80
+#define WMI_SPECTRAL_NB_TONE_THR_DEFAULT        12
+#define WMI_SPECTRAL_STR_BIN_THR_DEFAULT         8
+#define WMI_SPECTRAL_WB_RPT_MODE_DEFAULT         0
+#define WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT       0
+#define WMI_SPECTRAL_RSSI_THR_DEFAULT         0xf0
+#define WMI_SPECTRAL_PWR_FORMAT_DEFAULT          0
+#define WMI_SPECTRAL_RPT_MODE_DEFAULT            2
+#define WMI_SPECTRAL_BIN_SCALE_DEFAULT           1
+#define WMI_SPECTRAL_DBM_ADJ_DEFAULT             1
+#define WMI_SPECTRAL_CHN_MASK_DEFAULT            1
+
+struct wmi_vdev_spectral_enable_cmd {
+	__le32 vdev_id;
+	__le32 trigger_cmd;
+	__le32 enable_cmd;
+} __packed;
+
+#define WMI_SPECTRAL_TRIGGER_CMD_TRIGGER  1
+#define WMI_SPECTRAL_TRIGGER_CMD_CLEAR    2
+#define WMI_SPECTRAL_ENABLE_CMD_ENABLE    1
+#define WMI_SPECTRAL_ENABLE_CMD_DISABLE   2
+
 /* Beacon processing related command and event structures */
 struct wmi_bcn_tx_hdr {
 	__le32 vdev_id;
@@ -4226,6 +4316,10 @@ int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id,
 			      u32 param_id, u32 param_value);
 int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				const struct wmi_vdev_install_key_arg *arg);
+int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
+				  const struct wmi_vdev_spectral_conf_arg *arg);
+int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				    u32 enable);
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 		    const u8 peer_addr[ETH_ALEN]);
 int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
index b9ab722..0827cb7 100644
--- a/drivers/net/wireless/ath/spectral_common.h
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -19,6 +19,10 @@
 
 #define SPECTRAL_HT20_NUM_BINS		56
 #define SPECTRAL_HT20_40_NUM_BINS		128
+/* TODO: could possibly be 512, but no samples this large
+ * could be acquired so far.
+ */
+#define SPECTRAL_ATH10K_MAX_NUM_BINS		256
 
 /* FFT sample format given to userspace via debugfs.
  *
@@ -31,6 +35,7 @@
 enum ath_fft_sample_type {
 	ATH_FFT_SAMPLE_HT20 = 1,
 	ATH_FFT_SAMPLE_HT20_40,
+	ATH_FFT_SAMPLE_ATH10K,
 };
 
 struct fft_sample_tlv {
@@ -85,4 +90,23 @@ struct fft_sample_ht20_40 {
 	u8 data[SPECTRAL_HT20_40_NUM_BINS];
 } __packed;
 
+struct fft_sample_ath10k {
+	struct fft_sample_tlv tlv;
+	u8 chan_width_mhz;
+	__be16 freq1;
+	__be16 freq2;
+	__be16 noise;
+	__be16 max_magnitude;
+	__be16 total_gain_db;
+	__be16 base_pwr_db;
+	__be64 tsf;
+	s8 max_index;
+	u8 rssi;
+	u8 relpwr_db;
+	u8 avgpwr_db;
+	u8 max_exp;
+
+	u8 data[0];
+} __packed;
+
 #endif /* SPECTRAL_COMMON_H */
-- 
1.9.1



From sw at simonwunderlich.de  Mon Jul 21 05:32:22 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Mon, 21 Jul 2014 14:32:22 +0200
Subject: [PATCHv2 1/2] ath: Move spectral debugfs structs to shared header
In-Reply-To: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
References: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <1405945943-8303-2-git-send-email-sw@simonwunderlich.de>

From: Sven Eckelmann <sven at narfation.org>

The ath9k and ath10k will share the definitions of the debugfs spectral
structures and enums. Having them in the same place helps to avoid conflicts.

Signed-off-by: Sven Eckelmann <sven at narfation.org>
Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
---
 drivers/net/wireless/ath/ath9k/spectral.h  | 71 +-----------------------
 drivers/net/wireless/ath/spectral_common.h | 88 ++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 69 deletions(-)
 create mode 100644 drivers/net/wireless/ath/spectral_common.h

diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h
index 137e2e6..0b9465e 100644
--- a/drivers/net/wireless/ath/ath9k/spectral.h
+++ b/drivers/net/wireless/ath/ath9k/spectral.h
@@ -17,6 +17,8 @@
 #ifndef SPECTRAL_H
 #define SPECTRAL_H
 
+#include "../spectral_common.h"
+
 /* enum spectral_mode:
  *
  * @SPECTRAL_DISABLED: spectral mode is disabled
@@ -54,8 +56,6 @@ struct ath_ht20_mag_info {
 	u8 max_exp;
 } __packed;
 
-#define SPECTRAL_HT20_NUM_BINS		56
-
 /* WARNING: don't actually use this struct! MAC may vary the amount of
  * data by -1/+2. This struct is for reference only.
  */
@@ -83,8 +83,6 @@ struct ath_ht20_40_mag_info {
 	u8 max_exp;
 } __packed;
 
-#define SPECTRAL_HT20_40_NUM_BINS		128
-
 /* WARNING: don't actually use this struct! MAC may vary the amount of
  * data. This struct is for reference only.
  */
@@ -125,71 +123,6 @@ static inline u8 spectral_bitmap_weight(u8 *bins)
 	return bins[0] & 0x3f;
 }
 
-/* FFT sample format given to userspace via debugfs.
- *
- * Please keep the type/length at the front position and change
- * other fields after adding another sample type
- *
- * TODO: this might need rework when switching to nl80211-based
- * interface.
- */
-enum ath_fft_sample_type {
-	ATH_FFT_SAMPLE_HT20 = 1,
-	ATH_FFT_SAMPLE_HT20_40,
-};
-
-struct fft_sample_tlv {
-	u8 type;	/* see ath_fft_sample */
-	__be16 length;
-	/* type dependent data follows */
-} __packed;
-
-struct fft_sample_ht20 {
-	struct fft_sample_tlv tlv;
-
-	u8 max_exp;
-
-	__be16 freq;
-	s8 rssi;
-	s8 noise;
-
-	__be16 max_magnitude;
-	u8 max_index;
-	u8 bitmap_weight;
-
-	__be64 tsf;
-
-	u8 data[SPECTRAL_HT20_NUM_BINS];
-} __packed;
-
-struct fft_sample_ht20_40 {
-	struct fft_sample_tlv tlv;
-
-	u8 channel_type;
-	__be16 freq;
-
-	s8 lower_rssi;
-	s8 upper_rssi;
-
-	__be64 tsf;
-
-	s8 lower_noise;
-	s8 upper_noise;
-
-	__be16 lower_max_magnitude;
-	__be16 upper_max_magnitude;
-
-	u8 lower_max_index;
-	u8 upper_max_index;
-
-	u8 lower_bitmap_weight;
-	u8 upper_bitmap_weight;
-
-	u8 max_exp;
-
-	u8 data[SPECTRAL_HT20_40_NUM_BINS];
-} __packed;
-
 void ath9k_spectral_init_debug(struct ath_softc *sc);
 void ath9k_spectral_deinit_debug(struct ath_softc *sc);
 
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
new file mode 100644
index 0000000..b9ab722
--- /dev/null
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_COMMON_H
+#define SPECTRAL_COMMON_H
+
+#define SPECTRAL_HT20_NUM_BINS		56
+#define SPECTRAL_HT20_40_NUM_BINS		128
+
+/* FFT sample format given to userspace via debugfs.
+ *
+ * Please keep the type/length at the front position and change
+ * other fields after adding another sample type
+ *
+ * TODO: this might need rework when switching to nl80211-based
+ * interface.
+ */
+enum ath_fft_sample_type {
+	ATH_FFT_SAMPLE_HT20 = 1,
+	ATH_FFT_SAMPLE_HT20_40,
+};
+
+struct fft_sample_tlv {
+	u8 type;	/* see ath_fft_sample */
+	__be16 length;
+	/* type dependent data follows */
+} __packed;
+
+struct fft_sample_ht20 {
+	struct fft_sample_tlv tlv;
+
+	u8 max_exp;
+
+	__be16 freq;
+	s8 rssi;
+	s8 noise;
+
+	__be16 max_magnitude;
+	u8 max_index;
+	u8 bitmap_weight;
+
+	__be64 tsf;
+
+	u8 data[SPECTRAL_HT20_NUM_BINS];
+} __packed;
+
+struct fft_sample_ht20_40 {
+	struct fft_sample_tlv tlv;
+
+	u8 channel_type;
+	__be16 freq;
+
+	s8 lower_rssi;
+	s8 upper_rssi;
+
+	__be64 tsf;
+
+	s8 lower_noise;
+	s8 upper_noise;
+
+	__be16 lower_max_magnitude;
+	__be16 upper_max_magnitude;
+
+	u8 lower_max_index;
+	u8 upper_max_index;
+
+	u8 lower_bitmap_weight;
+	u8 upper_bitmap_weight;
+
+	u8 max_exp;
+
+	u8 data[SPECTRAL_HT20_40_NUM_BINS];
+} __packed;
+
+#endif /* SPECTRAL_COMMON_H */
-- 
1.9.1



From luto at amacapital.net  Mon Jul 21 10:04:48 2014
From: luto at amacapital.net (Andy Lutomirski)
Date: Mon, 21 Jul 2014 10:04:48 -0700
Subject: ath10k tx to a Macbook Pro stalls
Message-ID: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>

On my Archer C7 v2, as soon as the MBP tries to do something like
playing a video, it seems like frames *to* the MBP no longer get
there.  At the very least, arp replies don't get there.

I have:

[   13.220000] ath10k: qca988x hw2.0 (0x4100016c, 0x043202ff) fw
10.1.467.2-1 api 2 htt 2.1

Station 3c:15:c2:[redacted] (on wlan0)
    inactive time:    1400 ms
    rx bytes:    2157688
    rx packets:    10309
    tx bytes:    16102107
    tx packets:    15622
    tx retries:    0
    tx failed:    0
    signal:      -55 dBm
    signal avg:    -55 dBm
    tx bitrate:    6.0 MBit/s
    rx bitrate:    877.5 MBit/s VHT-MCS 7 80MHz VHT-NSS 3
    authorized:    yes
    authenticated:    yes
    preamble:    long
    WMM/WME:    yes
    MFP:        no
    TDLS peer:    no

Interface wlan0
    ifindex 18
    wdev 0x4
    addr e8:94:f6:[redacted]
    ssid [redacted]
    type AP
    wiphy 0
    channel 149 (5745 MHz), width: 80 MHz, center1: 5775 MHz

# cat fw_stats

             ath10k PDEV stats
             =================

           Channel noise floor       -108
              Channel TX power         46
                TX frame count          0
                RX frame count          0
                RX clear count          0
                   Cycle count        941
               PHY error count       2612
                 RTS bad count          0
                RTS good count          0
                 FCS bad count        426
               No beacon count          0
                 MIB int count   48158964

          ath10k PDEV TX stats
             =================

            HTT cookies queued      15887
             HTT cookies disp.      15887
                   MSDU queued      21200
                   MPDU queued      20982
                 MSDUs dropped          0
                  Local enqued       5313
                   Local freed       5313
                     HW queued      21655
                  PPDUs reaped      21655
                 Num underruns          0
                 PPDUs cleaned          0
                  MPDUs requed        776
             Excessive retries        767
                       HW rate          3
            Sched self tiggers        334
     Dropped due to SW retries          0
       Illegal rate phy errors          0
         Pdev continous xretry          0
                    TX timeout          0
                   PDEV resets          0
                  PHY underrun          0
  MPDU is more than txop limit          0

          ath10k PDEV RX stats
             =================

         Mid PPDU route change          0
       Tot. number of statuses      52787
        Extra frags on rings 0          0
        Extra frags on rings 1          0
        Extra frags on rings 2          1
        Extra frags on rings 3          0
        MSDUs delivered to HTT      52787
        MPDUs delivered to HTT      52263
      MSDUs delivered to stack      37576
      MPDUs delivered to stack      37576
               Oversized AMSUs          0
                    PHY errors          0
              PHY errors drops       2610
   MPDU errors (FCS, MIC, ENC)       3129

             ath10k PEER stats (1)
             =================

              Peer MAC address 3c:15:c2:[redacted]
                     Peer RSSI 40
                  Peer TX rate 975000
                  Peer RX rate 877500


This is with the a brand-new OpenWRT build that (finally!) has a
correct board.bin for the card.

Is this possibly a rate control issue?  A firmware issue?  Is there
something else I can do to give a more helpful bug report?


Thanks,
Andy


From kvalo at qca.qualcomm.com  Mon Jul 21 10:30:32 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 21 Jul 2014 20:30:32 +0300
Subject: [PATCH] ath10k: handle attention flags correctly when A-MSDU
In-Reply-To: <CALhHN=q2XcvPiLpeDgw_DksU1xzQLvJtxjzk8iZte-VMd+viLg@mail.gmail.com>
 (Janusz Dziedzic's message of "Mon, 21 Jul 2014 10:53:16 +0200")
References: <1405342041-7114-1-git-send-email-janusz.dziedzic@tieto.com>
 <87pph225mq.fsf@kamboji.qca.qualcomm.com>
 <CALhHN=q2XcvPiLpeDgw_DksU1xzQLvJtxjzk8iZte-VMd+viLg@mail.gmail.com>
Message-ID: <87ha2ay5zb.fsf@kamboji.qca.qualcomm.com>

Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:

> On 18 July 2014 14:50, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:
>>
>>> In case of A-MSDU RX we should check flags for all
>>> MSDU subframes to be sure we have correct FCS status.
>>>
>>> Before we check attention flags only for first frame
>>> where we didn't have correct info about FCS status in
>>> case of A-MSDU. Next didn't mark RX_FLAG_FAILED_FCS_CRC
>>> for skb. As a side efect we see big TP drop when TCP used.
>>> This was easy to reproduce when AP interface was used
>>> and added monitor interface run in promiscuous mode.
>>>
>>> Reported-by: Denton Gentry <denton.gentry at gmail.com>
>>> Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
>>
>> I'm having a hard time to understand the commit log. I think it would
>> make it easier to read if you first clearly describe the bug you are
>> fixing and then, in a separate paragraph, tell how you fix it.
>
> Will change that.

Thanks. What you wrote in this email was really good, I understand the
issue now and I'm sure so do others. I think you should put the same in
the commit log, there's no max limit for that anyway :)

Also add verb "using" to the title: "ath10k: handle attention flags
correctly when using A-MSDU"

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Jul 21 10:39:26 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 21 Jul 2014 20:39:26 +0300
Subject: [RFC/RFT 1/2] ath10k: fix monitor start/stop sequences
In-Reply-To: <1405516873-26411-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Wed, 16 Jul 2014 15:21:12 +0200")
References: <1405516873-26411-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87d2cyy5kh.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> Fix some cases where monitor start failure left
> the driver in a confused state.
>
> This also makes the monitor code simpler.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

>From a quick review looks good to me. Are you planning to submit this as
a proper patch at some point?

Did anyone test this?

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Jul 21 10:52:20 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 21 Jul 2014 20:52:20 +0300
Subject: [PATCH] ath10k: workaround boot issues with KVM/PCI-passthrough
In-Reply-To: <1405515699-32452-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Wed, 16 Jul 2014 15:01:39 +0200")
References: <1405515699-32452-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <878unmy4yz.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> Apparently iomap writes that unmask CE irqs aren't
> propagated properly sometimes. Before failing try
> to poll for the control response message as it may
> have been delivered without an interrupt.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From dave.taht at gmail.com  Mon Jul 21 10:55:43 2014
From: dave.taht at gmail.com (Dave Taht)
Date: Mon, 21 Jul 2014 10:55:43 -0700
Subject: ath10k tx to a Macbook Pro stalls
In-Reply-To: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>
References: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>
Message-ID: <CAA93jw434cvqbYzxkohh4JaURosBGindH7eQVpoVBXdAe9_XRA@mail.gmail.com>

This may be related to:

https://dev.openwrt.org/ticket/15320
http://www.bufferbloat.net/issues/442
https://lists.bufferbloat.net/pipermail/cerowrt-devel/2014-July/003213.html

(both on ath9k)

It's been driving multiple folk crazy.

Some advice on more stuff to look at is in both bug reports.

On Mon, Jul 21, 2014 at 10:04 AM, Andy Lutomirski <luto at amacapital.net> wrote:
> On my Archer C7 v2, as soon as the MBP tries to do something like
> playing a video, it seems like frames *to* the MBP no longer get
> there.  At the very least, arp replies don't get there.
>
> I have:
>
> [   13.220000] ath10k: qca988x hw2.0 (0x4100016c, 0x043202ff) fw
> 10.1.467.2-1 api 2 htt 2.1
>
> Station 3c:15:c2:[redacted] (on wlan0)
>     inactive time:    1400 ms
>     rx bytes:    2157688
>     rx packets:    10309
>     tx bytes:    16102107
>     tx packets:    15622
>     tx retries:    0
>     tx failed:    0
>     signal:      -55 dBm
>     signal avg:    -55 dBm
>     tx bitrate:    6.0 MBit/s
>     rx bitrate:    877.5 MBit/s VHT-MCS 7 80MHz VHT-NSS 3
>     authorized:    yes
>     authenticated:    yes
>     preamble:    long
>     WMM/WME:    yes
>     MFP:        no
>     TDLS peer:    no
>
> Interface wlan0
>     ifindex 18
>     wdev 0x4
>     addr e8:94:f6:[redacted]
>     ssid [redacted]
>     type AP
>     wiphy 0
>     channel 149 (5745 MHz), width: 80 MHz, center1: 5775 MHz
>
> # cat fw_stats
>
>              ath10k PDEV stats
>              =================
>
>            Channel noise floor       -108
>               Channel TX power         46
>                 TX frame count          0
>                 RX frame count          0
>                 RX clear count          0
>                    Cycle count        941
>                PHY error count       2612
>                  RTS bad count          0
>                 RTS good count          0
>                  FCS bad count        426
>                No beacon count          0
>                  MIB int count   48158964
>
>           ath10k PDEV TX stats
>              =================
>
>             HTT cookies queued      15887
>              HTT cookies disp.      15887
>                    MSDU queued      21200
>                    MPDU queued      20982
>                  MSDUs dropped          0
>                   Local enqued       5313
>                    Local freed       5313
>                      HW queued      21655
>                   PPDUs reaped      21655
>                  Num underruns          0
>                  PPDUs cleaned          0
>                   MPDUs requed        776
>              Excessive retries        767
>                        HW rate          3
>             Sched self tiggers        334
>      Dropped due to SW retries          0
>        Illegal rate phy errors          0
>          Pdev continous xretry          0
>                     TX timeout          0
>                    PDEV resets          0
>                   PHY underrun          0
>   MPDU is more than txop limit          0
>
>           ath10k PDEV RX stats
>              =================
>
>          Mid PPDU route change          0
>        Tot. number of statuses      52787
>         Extra frags on rings 0          0
>         Extra frags on rings 1          0
>         Extra frags on rings 2          1
>         Extra frags on rings 3          0
>         MSDUs delivered to HTT      52787
>         MPDUs delivered to HTT      52263
>       MSDUs delivered to stack      37576
>       MPDUs delivered to stack      37576
>                Oversized AMSUs          0
>                     PHY errors          0
>               PHY errors drops       2610
>    MPDU errors (FCS, MIC, ENC)       3129
>
>              ath10k PEER stats (1)
>              =================
>
>               Peer MAC address 3c:15:c2:[redacted]
>                      Peer RSSI 40
>                   Peer TX rate 975000
>                   Peer RX rate 877500
>
>
> This is with the a brand-new OpenWRT build that (finally!) has a
> correct board.bin for the card.
>
> Is this possibly a rate control issue?  A firmware issue?  Is there
> something else I can do to give a more helpful bug report?
>
>
> Thanks,
> Andy
>
> _______________________________________________
> ath10k mailing list
> ath10k at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/ath10k



-- 
Dave T?ht

NSFW: https://w2.eff.org/Censorship/Internet_censorship_bills/russell_0296_indecent.article


From kvalo at qca.qualcomm.com  Mon Jul 21 11:02:16 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 21 Jul 2014 21:02:16 +0300
Subject: [PATCH] ath10k: prevent some tx flushing failures
In-Reply-To: <1405518073-14513-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Wed, 16 Jul 2014 15:41:13 +0200")
References: <1405518073-14513-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <874myay4if.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> Firmware could request inspection of some
> submitted tx requests. Since the callback wasn't
> implemented it was possible to bleed tx msdu_ids
> which could translate to tx flushing timeouts.
>
> There's nothing ath10k can do to help firmware
> with tx processing now so just report all tx
> frames as already inspected to prevent firmware
> from sending up inspection events and force it to
> report regular tx completion indications with
> discard status.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Jul 21 11:31:47 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 21 Jul 2014 21:31:47 +0300
Subject: ath10k tx to a Macbook Pro stalls
In-Reply-To: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>
 (Andy Lutomirski's message of "Mon, 21 Jul 2014 10:04:48 -0700")
References: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>
Message-ID: <87vbqqwoks.fsf@kamboji.qca.qualcomm.com>

Andy Lutomirski <luto at amacapital.net> writes:

> On my Archer C7 v2, as soon as the MBP tries to do something like
> playing a video, it seems like frames *to* the MBP no longer get
> there.  At the very least, arp replies don't get there.

A multicast problem? Can you run for example 'arping -b <macbook's ip>'
to check if multicast stops working at some point? What if you hardcode
the ARP address, do unicast packets go to the macbook still?

If there are multicast problems, my first suspect is always power save.
Is there a way to disable power save on the macbook for narrowing down
the problem?

Also we had discussion about macbook problems before and aggreation came
up as one suspect. Now we have a debugfs interface to change aggregation
settings, but I doubt openwrt has that yet. Check the archives for more.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Jul 21 11:35:58 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 21 Jul 2014 21:35:58 +0300
Subject: [PATCHv2 2/2] ath10k: add spectral scan feature
In-Reply-To: <1405945943-8303-3-git-send-email-sw@simonwunderlich.de> (Simon
 Wunderlich's message of "Mon, 21 Jul 2014 14:32:23 +0200")
References: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
 <1405945943-8303-3-git-send-email-sw@simonwunderlich.de>
Message-ID: <87r41ewodt.fsf@kamboji.qca.qualcomm.com>

Simon Wunderlich <sw at simonwunderlich.de> writes:

> Adds the spectral scan feature for ath10k. The spectral scan is triggered by
> configuring a mode through a debugfs control file. Samples can be gathered via
> another relay debugfs file.
>
> Essentially, to try it out:
>
> ip link set dev wlan0 up
> echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> iw dev wlan0 scan
> echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples
>
> This feature is still experimental. Based on the original RFC patch of
> Sven Eckelmann.
>
> Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
> Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>

While I was commiting this to ath-next-test for build tests and review,
I had a trivial conflict. Please check the patch:

https://github.com/kvalo/ath/commit/85dec746d1f4728176bd06a53b6da4ef014f2a27

Oddly enough with this patch I see a new warning:

include/uapi/linux/swab.h:71:16: error: undefined identifier '__builtin_bswap64'

But I guess there's not much we can do about that?

-- 
Kalle Valo


From luto at amacapital.net  Mon Jul 21 11:46:03 2014
From: luto at amacapital.net (Andy Lutomirski)
Date: Mon, 21 Jul 2014 11:46:03 -0700
Subject: ath10k tx to a Macbook Pro stalls
In-Reply-To: <87vbqqwoks.fsf@kamboji.qca.qualcomm.com>
References: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>
 <87vbqqwoks.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CALCETrXwiNFyX0XBFTuugzD3qoMzMgR29BU0MJF5-r=7emuFmw@mail.gmail.com>

On Mon, Jul 21, 2014 at 11:31 AM, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Andy Lutomirski <luto at amacapital.net> writes:
>
>> On my Archer C7 v2, as soon as the MBP tries to do something like
>> playing a video, it seems like frames *to* the MBP no longer get
>> there.  At the very least, arp replies don't get there.
>
> A multicast problem? Can you run for example 'arping -b <macbook's ip>'
> to check if multicast stops working at some point? What if you hardcode
> the ARP address, do unicast packets go to the macbook still?

I thought that ARP replies were unicast.  Certainly my laptop replies
to ARP requests with a unicast frame to the requester.

I was also unable to ping the MBP from my laptop, which suggests that
broadcasts were also not being received.  But I could have gotten
confused there.

>
> If there are multicast problems, my first suspect is always power save.
> Is there a way to disable power save on the macbook for narrowing down
> the problem?

No clue.  I'll take a look.

>
> Also we had discussion about macbook problems before and aggreation came
> up as one suspect. Now we have a debugfs interface to change aggregation
> settings, but I doubt openwrt has that yet. Check the archives for more.

This problem seems to be sporadic enough that it's hard to tell, but
changing the AP's mode from VHT80 to HT40 seems to have solved the
problem.

I'll try to reproduce this later tonight and see if I can learn more.

--Andy


From sven at narfation.org  Mon Jul 21 12:02:47 2014
From: sven at narfation.org (Sven Eckelmann)
Date: Mon, 21 Jul 2014 21:02:47 +0200
Subject: [PATCHv2 2/2] ath10k: add spectral scan feature
In-Reply-To: <1405945943-8303-3-git-send-email-sw@simonwunderlich.de>
References: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
 <1405945943-8303-3-git-send-email-sw@simonwunderlich.de>
Message-ID: <43945028.YYV8n3Af3F@sven-edge>

On Monday 21 July 2014 14:32:23 Simon Wunderlich wrote:
> diff --git a/drivers/net/wireless/ath/ath10k/Makefile
> b/drivers/net/wireless/ath/ath10k/Makefile index 2110a5c..e1dcefd 100644
> --- a/drivers/net/wireless/ath/ath10k/Makefile
> +++ b/drivers/net/wireless/ath/ath10k/Makefile
> @@ -8,7 +8,8 @@ ath10k_core-y += mac.o \
>  		 htt_tx.o \
>  		 txrx.o \
>  		 wmi.o \
> -		 bmi.o
> +		 bmi.o \
> +		 spectral.o


ath9k doesn't compile the debugfs+spectral source files when 
CONFIG_ATH9K_DEBUGFS is not enabled. So this most likely has to be changed to 

ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o

Otherwise the static inline functions in the spectral.h may collide with the 
functions inside spectral.c when CONFIG_ATH10K_DEBUGFS is disabled.

Kind regards,
	Sven


From greearb at candelatech.com  Mon Jul 21 16:02:32 2014
From: greearb at candelatech.com (Ben Greear)
Date: Mon, 21 Jul 2014 16:02:32 -0700
Subject: New CT firmware release is uploaded.
Message-ID: <53CD9C08.9090908@candelatech.com>

Release notes:

      Improve RAM usage:  Re-organized, trimmed, and otherwise made better use
      of RAM.  Allow compiling out swbmiss, beacon filtering, roaming code.
      Images with 'full' in their name do NOT have the previously mentioned features
      compiled out.

      Over-all, freed up about 80k of extra RAM, which can be used for more vdevs,
      peers, buffers, etc.

      Supports 64 vdevs (one should be reserved for monitor interface, so
      effectively 63 vdevs for current kernels.)

I have only lightly tested this on my 3.14 kernel so far.

A lot of these changes could potentially introduce run-time
crashes due to extensive use of a different type of RAM for
storing many structures.  Should be a quick fix should problems
arise.

As always, let me know if you find any problems.

Thanks,
Ben

-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From bhelgaas at google.com  Mon Jul 21 16:16:03 2014
From: bhelgaas at google.com (Bjorn Helgaas)
Date: Mon, 21 Jul 2014 17:16:03 -0600
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <1405709421.30262.8.camel@dabdike.int.hansenpartnership.com>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
 <20140718162213.GC31114@tuxdriver.com> <20140718164340.GA24960@kroah.com>
 <1405702472.30262.1.camel@dabdike.int.hansenpartnership.com>
 <20140718181759.GB2193@kroah.com>
 <1405709421.30262.8.camel@dabdike.int.hansenpartnership.com>
Message-ID: <CAErSpo7svKg0HiL=g8wWAHWUN3vs0UgCvVhvd84DM6nVDmT=FQ@mail.gmail.com>

[+cc Jingoo]

On Fri, Jul 18, 2014 at 12:50 PM, James Bottomley
<James.Bottomley at hansenpartnership.com> wrote:
> On Fri, 2014-07-18 at 11:17 -0700, Greg KH wrote:
>> On Fri, Jul 18, 2014 at 09:54:32AM -0700, James Bottomley wrote:
>> > On Fri, 2014-07-18 at 09:43 -0700, Greg KH wrote:
>> > > On Fri, Jul 18, 2014 at 12:22:13PM -0400, John W. Linville wrote:
>> > > > On Fri, Jul 18, 2014 at 05:26:47PM +0200, Benoit Taine wrote:
>> > > > > We should prefer `const struct pci_device_id` over
>> > > > > `DEFINE_PCI_DEVICE_TABLE` to meet kernel coding style guidelines.
>> > > > > This issue was reported by checkpatch.
>> > > >
>> > > > Honestly, I prefer the macro -- it stands-out more.  Maybe the style
>> > > > guidelines and/or checkpatch should change instead?
>> > >
>> > > The macro is horrid, no other bus has this type of thing just to save a
>> > > few characters in typing
>> >
>> > OK, so this is the macro:
>> >
>> > #define DEFINE_PCI_DEVICE_TABLE(_table) \
>> >     const struct pci_device_id _table[]
>> >
>> > Could you explain what's so horrible?
>> >
>> > The reason it's useful today is that people forget the const (and
>> > sometimes the [] making it a true table instead of a pointer).  If you
>> > use the DEFINE_PCI_DEVICE_TABLE macro, the compile breaks if you use it
>> > wrongly (good) and you automatically get the correct annotations.
>>
>> We have almost 1000 more uses of the non-macro version than the "macro"
>> version in the kernel today:
>> $ git grep -w DEFINE_PCI_DEVICE_TABLE | wc -l
>> 262
>> $ git grep "const struct pci_device_id" | wc -l
>> 1254
>>
>> My big complaint is that we need to be consistant, either pick one or
>> the other and stick to it.  As the macro is the least used, it's easiest
>> to fix up, and it also is more consistant with all other kernel
>> subsystems which do not have such a macro.
>
> I've a weak preference for consistency, but not at the expense of
> hundreds of patches churning the kernel to remove an innocuous macro.
> Churn costs time and effort.
>
>> As there is no need for the __init macro mess anymore, there's no real
>> need for the DEFINE_PCI_DEVICE_TABLE macro either.  I think checkpatch
>> will catch the use of non-const users for the id table already today, it
>> catches lots of other uses like this already.
>>
>> > > , so why should PCI be "special" in this regard
>> > > anymore?
>> >
>> > I think the PCI usage dwarfs most other bus types now, so you could turn
>> > the question around.  However, I don't think majority voting is a good
>> > guide to best practise; lets debate the merits for their own sake.
>>
>> Not really "dwarf", USB is close with over 700 such structures:
>> $ git grep "const struct usb_device_id" | wc -l
>> 725
>>
>> And i2c is almost just as big as PCI:
>> $ git grep "const struct i2c_device_id" | wc -l
>> 1223
>>
>> So again, this macro is not consistent with the majority of PCI drivers,
>> nor with any other type of "device id" declaration in the kernel, which
>> is why I feel it should be removed.
>>
>> And finally, the PCI documentation itself says to not use this macro, so
>> this isn't a "new" thing.  From Documentation/PCI/pci.txt:
>>
>>       The ID table is an array of struct pci_device_id entries ending with an
>>       all-zero entry.  Definitions with static const are generally preferred.
>>       Use of the deprecated macro DEFINE_PCI_DEVICE_TABLE should be avoided.
>>
>> That wording went into the file last December, when we last talked about
>> this and everyone in that discussion agreed to remove the macro for the
>> above reasons.
>>
>> Consistency matters.
>
> In this case, I don't think it does that much ... a cut and paste either
> way (from a macro or non-macro based driver) yields correct code.  Since
> there's no bug here and no apparent way to misuse the macro, why bother?
>
> Anyway, it's PCI code ... let the PCI maintainer decide.  However, if he
> does want this do it as one big bang patch via either the PCI or Trivial
> tree (latter because Ji?? has experience doing this, but the former
> might be useful so the decider feels the pain ...)

I don't feel strongly either way, so I guess I'm OK with this, and in
the spirit of feeling the pain, I'm willing to handle it.  Jingoo
proposed similar patches, so it might be nice to give him some credit.

Benoit, how about if you wait until about half-way through the merge
window after v3.16 releases, generate an up-to-date single patch, and
post that?  Then we can try to get it in before v3.17-rc1 to minimize
merge hassles.

Bjorn


From luto at amacapital.net  Mon Jul 21 21:12:35 2014
From: luto at amacapital.net (Andy Lutomirski)
Date: Mon, 21 Jul 2014 21:12:35 -0700
Subject: ath10k tx to a Macbook Pro stalls
In-Reply-To: <87vbqqwoks.fsf@kamboji.qca.qualcomm.com>
References: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>
 <87vbqqwoks.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CALCETrXtvTyFbc0RM0kHcW_UiX+eurRTdp0vdQER2ysUrd4FcQ@mail.gmail.com>

On Mon, Jul 21, 2014 at 11:31 AM, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Andy Lutomirski <luto at amacapital.net> writes:
>
>> On my Archer C7 v2, as soon as the MBP tries to do something like
>> playing a video, it seems like frames *to* the MBP no longer get
>> there.  At the very least, arp replies don't get there.
>
> A multicast problem? Can you run for example 'arping -b <macbook's ip>'
> to check if multicast stops working at some point? What if you hardcode
> the ARP address, do unicast packets go to the macbook still?

It's a unicast problem, actually.  arping -b works.  arping w/o -b
gets one reply.

arp -s <IP> ff:ff:ff:ff:ff:ff allows me to ping the MBP (with
moderately high loss).  (I'm actually a bit surprised that Linux is
okay with that.)

Does this mean that the MBP is failing to notice TIM entries, or that
ath10k somehow stops buffering packets to power-saving stations?

>
> If there are multicast problems, my first suspect is always power save.
> Is there a way to disable power save on the macbook for narrowing down
> the problem?
>
> Also we had discussion about macbook problems before and aggreation came
> up as one suspect. Now we have a debugfs interface to change aggregation
> settings, but I doubt openwrt has that yet. Check the archives for more.

I'll keep an eye out for it.

--Andy

>
> --
> Kalle Valo



-- 
Andy Lutomirski
AMA Capital Management, LLC


From yeohchunyeow at gmail.com  Mon Jul 21 21:59:20 2014
From: yeohchunyeow at gmail.com (Yeoh Chun-Yeow)
Date: Tue, 22 Jul 2014 12:59:20 +0800
Subject: [PATCH 2/2] ath10k: add spectral scan feature
In-Reply-To: <201407211143.04868.sw@simonwunderlich.de>
References: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
 <1405689992-8538-3-git-send-email-sw@simonwunderlich.de>
 <CAEFj986Vruig8wCP+RLS_gQf8utAirmTDCKwmMGyfj7B2vH9pw@mail.gmail.com>
 <201407211143.04868.sw@simonwunderlich.de>
Message-ID: <CAEFj9878tYieueZn4fn4EZSgPSTTnoTj4Xb8wu_Es1gHy0KEqQ@mail.gmail.com>

Hi, Simon

>
> Thanks for the output! Could it be that you are using the old RFC patch with
> the new fft-eval? I've added another byte (max_exp), so the header became
> longer. Please try again with the latest patch (from this thread), if that is
> the case. Otherwise we have to find out whats wrong ... The sample_len as used
> in fft_eval (tlv-header + data) should be 93 with that version.

Yes, you are right. I am picking out the ath-next-test branch which is
using the RFC old patch before that.

By the way, the new submitted patch v2 [1] has taken out the following:

if (mode == SPECTRAL_BACKGROUND)ath10k_spectral_scan_trigger(ar);


-----
Chun-Yeow

[1] http://lists.infradead.org/pipermail/ath10k/2014-July/002711.html


From yeohchunyeow at gmail.com  Mon Jul 21 22:02:01 2014
From: yeohchunyeow at gmail.com (Yeoh Chun-Yeow)
Date: Tue, 22 Jul 2014 13:02:01 +0800
Subject: [PATCH 2/2] ath10k: add spectral scan feature
In-Reply-To: <CAEFj9878tYieueZn4fn4EZSgPSTTnoTj4Xb8wu_Es1gHy0KEqQ@mail.gmail.com>
References: <1405689992-8538-1-git-send-email-sw@simonwunderlich.de>
 <1405689992-8538-3-git-send-email-sw@simonwunderlich.de>
 <CAEFj986Vruig8wCP+RLS_gQf8utAirmTDCKwmMGyfj7B2vH9pw@mail.gmail.com>
 <201407211143.04868.sw@simonwunderlich.de>
 <CAEFj9878tYieueZn4fn4EZSgPSTTnoTj4Xb8wu_Es1gHy0KEqQ@mail.gmail.com>
Message-ID: <CAEFj985r+nA3Sr2x0aExaZxnhzs24r=Teguowq+3AcDyV4Xt_A@mail.gmail.com>

Hi, Simon

Sorry, resend-email...

>>
>> Thanks for the output! Could it be that you are using the old RFC patch with
>> the new fft-eval? I've added another byte (max_exp), so the header became
>> longer. Please try again with the latest patch (from this thread), if that is
>> the case. Otherwise we have to find out whats wrong ... The sample_len as used
>> in fft_eval (tlv-header + data) should be 93 with that version.
>
Yes, you are right. I am picking out the ath-next-test branch which is
using the RFC old patch before that.

By the way, the new submitted patch v2 [1] has taken out the following:

if (mode == SPECTRAL_BACKGROUND)
ath10k_spectral_scan_trigger(ar);

So should we add the trigger command in the comment?

ip link set dev wlan0 up
echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
echo trigger > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
iw dev wlan0 scan
echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples

Otherwise, I am not able to get any useful data.

-----
Chun-Yeow

[1] http://lists.infradead.org/pipermail/ath10k/2014-July/002711.html


From michal.kazior at tieto.com  Tue Jul 22 01:07:05 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 22 Jul 2014 10:07:05 +0200
Subject: [PATCHv2 2/2] ath10k: add spectral scan feature
In-Reply-To: <1405945943-8303-3-git-send-email-sw@simonwunderlich.de>
References: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
 <1405945943-8303-3-git-send-email-sw@simonwunderlich.de>
Message-ID: <CA+BoTQ=ef+NsTK4q_A6oEw19TLXMANBmBeu7-1peERZ7Fmw0ww@mail.gmail.com>

On 21 July 2014 14:32, Simon Wunderlich <sw at simonwunderlich.de> wrote:
> Adds the spectral scan feature for ath10k. The spectral scan is triggered by
> configuring a mode through a debugfs control file. Samples can be gathered via
> another relay debugfs file.
[...]
>  #endif /* CONFIG_ATH10K_DEBUGFS */
> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
> index 348a639..14d6234 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -2201,6 +2201,7 @@ void ath10k_halt(struct ath10k *ar)
>         ath10k_peer_cleanup_all(ar);
>         ath10k_core_stop(ar);
>         ath10k_hif_power_down(ar);
> +       ath10k_disable_spectral(ar);

It makes little sense to call it after powering off the chip, no?
ath10k_disable_spectral() calls ath10k_wmi_vdev_spectral_enable()
which requires WMI (and thus firmware as a whole) to be running,
otherwise you'll fail to submit the command. Anyway, if you try to
send a WMI command when hw is restarting firmware won't respond
properly anyway and it'll print a warning.


>
>         spin_lock_bh(&ar->data_lock);
>         if (ar->scan.in_progress) {
> @@ -2671,8 +2672,16 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
>                 dev_kfree_skb_any(arvif->beacon);
>                 arvif->beacon = NULL;
>         }
> +
>         spin_unlock_bh(&ar->data_lock);
>
> +       if (arvif->spectral_enabled) {
> +               ret = ath10k_disable_spectral(ar);
> +               if (ret)
> +                       ath10k_warn("Failed to disable spectral for vdev %i: %d\n",
> +                                   arvif->vdev_id, ret);

I'm aware ath10k still has some capitalized warnings but it'd be nice
to have this lower case (this is something that has been agreed upon
some time ago but still not all prints have been updated since then).


Micha?


From michal.kazior at tieto.com  Tue Jul 22 01:14:03 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 22 Jul 2014 10:14:03 +0200
Subject: [RFC/RFT 1/2] ath10k: fix monitor start/stop sequences
In-Reply-To: <87d2cyy5kh.fsf@kamboji.qca.qualcomm.com>
References: <1405516873-26411-1-git-send-email-michal.kazior@tieto.com>
 <87d2cyy5kh.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQ=qXyEqo0ZpWcJVGjttGj0SSFo3Cj18qNZxT4xHhzSwgQ@mail.gmail.com>

On 21 July 2014 19:39, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
>
>> Fix some cases where monitor start failure left
>> the driver in a confused state.
>>
>> This also makes the monitor code simpler.
>>
>> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
>
> From a quick review looks good to me. Are you planning to submit this as
> a proper patch at some point?

I've been waiting for feedback in case this breaks someone's setup/use
cases (it shouldn't but hey). No one has complained so I guess I'll be
posting this as a PATCH soon.


Micha?


From kvalo at qca.qualcomm.com  Tue Jul 22 08:54:44 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 22 Jul 2014 18:54:44 +0300
Subject: [PATCH 1/2] ath10k: simplify tx helpers
In-Reply-To: <1405601122-29726-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 17 Jul 2014 14:45:21 +0200")
References: <1405601122-29726-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87iompv16j.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> It always bugged me how tid is computed and stored
> in a temporary var before written to the control
> buffer. It was confusing and it made it difficult
> to work with tx helpers.
>
> While at it rename the qos workaround function as
> it was misleading - it's not a workaround but
> preparation for nwifi tx mode.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, both patches applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Jul 22 09:02:13 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 22 Jul 2014 19:02:13 +0300
Subject: [PATCH] ath10k: extend debug code for RX path
In-Reply-To: <1405672472-16302-1-git-send-email-janusz.dziedzic@tieto.com>
 (Janusz Dziedzic's message of "Fri, 18 Jul 2014 10:34:31 +0200")
References: <1405672472-16302-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <87egxdv0u2.fsf@kamboji.qca.qualcomm.com>

Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:

> Print sequence number, AMSDU_MORE flag and AC when additional
> debug enabled in RX path. This is usefull for debugging purpose.
>
> Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
> ---
>  drivers/net/wireless/ath/ath10k/htt_rx.c |   32 ++++++++++++++++++++++++++++--
>  1 file changed, 30 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
> index 6db0e49..04140e3 100644
> --- a/drivers/net/wireless/ath/ath10k/htt_rx.c
> +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
> @@ -819,19 +819,46 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
>  	return true;
>  }
>  
> +static char *tid_to_ac[] = {

static const?

> +	"BE(0)",
> +	"BK(1)",
> +	"BK(2)",
> +	"BE(3)",
> +	"VI(4)",
> +	"VI(5)",
> +	"VO(6)",
> +	"VO(7)",
> +	"tid(8)",
> +	"tid(9)",
> +	"tid(10)",
> +	"tid(11)",
> +	"tid(12)",
> +	"tid(13)",
> +	"tid(14)",
> +	"tid(15)",
> +};

I don't see much point of adding tid number to the string when you could
print it with "%i". Also about the string format, maybe this would be
clearer:

"rx skb %p len %u peer %pM tid %i (%s) sn %u"

For example "...tid 4 (VI)..." and for tid > 7 we don't print "(VI)"
part at all, just the number.

>  static void ath10k_process_rx(struct ath10k *ar,
>  			      struct ieee80211_rx_status *rx_status,
>  			      struct sk_buff *skb)
>  {
>  	struct ieee80211_rx_status *status;
> +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
>  
>  	status = IEEE80211_SKB_RXCB(skb);
>  	*status = *rx_status;
>  
>  	ath10k_dbg(ATH10K_DBG_DATA,
> -		   "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %imic-err %i\n",
> +		   "rx skb %p len %u peer %pM %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
>  		   skb,
>  		   skb->len,
> +		   ieee80211_get_SA(hdr),

This looks ok.

> +		   ieee80211_is_data_qos(hdr->frame_control) ?
> +			(tid_to_ac[*(ieee80211_get_qos_ctl(hdr)) &
> +				   IEEE80211_QOS_CTL_TID_MASK]) :
> +			(is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
> +				"mcast" : "ucast"),
> +		   (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4,

But this is hard to read. Is it possible to have a helper function for
this?

-- 
Kalle Valo


From benoit.taine at lip6.fr  Tue Jul 22 10:12:43 2014
From: benoit.taine at lip6.fr (Benoit Taine)
Date: Tue, 22 Jul 2014 19:12:43 +0200
Subject: [PATCH 0/25] Replace DEFINE_PCI_DEVICE_TABLE macro use
In-Reply-To: <CAErSpo7svKg0HiL=g8wWAHWUN3vs0UgCvVhvd84DM6nVDmT=FQ@mail.gmail.com>
References: <1405697232-11785-1-git-send-email-benoit.taine@lip6.fr>
 <20140718162213.GC31114@tuxdriver.com>
 <20140718164340.GA24960@kroah.com>
 <1405702472.30262.1.camel@dabdike.int.hansenpartnership.com>
 <20140718181759.GB2193@kroah.com>
 <1405709421.30262.8.camel@dabdike.int.hansenpartnership.com>
 <CAErSpo7svKg0HiL=g8wWAHWUN3vs0UgCvVhvd84DM6nVDmT=FQ@mail.gmail.com>
Message-ID: <20140722171242.GA742@lip6.fr>

On 21/07/2014 17:16, Bjorn Helgaas wrote:
> [+cc Jingoo]
> 
> On Fri, Jul 18, 2014 at 12:50 PM, James Bottomley
> > Anyway, it's PCI code ... let the PCI maintainer decide.  However, if he
> > does want this do it as one big bang patch via either the PCI or Trivial
> > tree (latter because Ji?? has experience doing this, but the former
> > might be useful so the decider feels the pain ...)
> 
> I don't feel strongly either way, so I guess I'm OK with this, and in
> the spirit of feeling the pain, I'm willing to handle it.  Jingoo
> proposed similar patches, so it might be nice to give him some credit.
> 
> Benoit, how about if you wait until about half-way through the merge
> window after v3.16 releases, generate an up-to-date single patch, and
> post that?  Then we can try to get it in before v3.17-rc1 to minimize
> merge hassles.

Sure, I will do this.

-- 
Beno?t Taine
Master cycle intern
Regal Team. LIP6


From kvalo at qca.qualcomm.com  Tue Jul 22 11:27:34 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 22 Jul 2014 21:27:34 +0300
Subject: [PATCHv2 2/2] ath10k: add spectral scan feature
In-Reply-To: <1405945943-8303-3-git-send-email-sw@simonwunderlich.de> (Simon
 Wunderlich's message of "Mon, 21 Jul 2014 14:32:23 +0200")
References: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
 <1405945943-8303-3-git-send-email-sw@simonwunderlich.de>
Message-ID: <87zjg1tfjd.fsf@kamboji.qca.qualcomm.com>

Simon Wunderlich <sw at simonwunderlich.de> writes:

> Adds the spectral scan feature for ath10k. The spectral scan is triggered by
> configuring a mode through a debugfs control file. Samples can be gathered via
> another relay debugfs file.
>
> Essentially, to try it out:
>
> ip link set dev wlan0 up
> echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> iw dev wlan0 scan
> echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples
>
> This feature is still experimental. Based on the original RFC patch of
> Sven Eckelmann.
>
> Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
> Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>

Quick comments about the style.

> --- a/drivers/net/wireless/ath/ath10k/core.c
> +++ b/drivers/net/wireless/ath/ath10k/core.c
> @@ -699,6 +699,10 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
>  	ar->hif.priv = hif_priv;
>  	ar->hif.ops = hif_ops;
>  
> +	ar->spectral_mode = SPECTRAL_DISABLED;
> +	ar->spec_config.count = WMI_SPECTRAL_COUNT_DEFAULT;
> +	ar->spec_config.fft_size = WMI_SPECTRAL_FFT_SIZE_DEFAULT;

I would rather have ath10k_spectral_init() or similar to avoid
sprinkling this stuff all over the driver.

> --- a/drivers/net/wireless/ath/ath10k/core.h
> +++ b/drivers/net/wireless/ath/ath10k/core.h
> @@ -230,6 +231,7 @@ struct ath10k_vif {
>  
>  	bool is_started;
>  	bool is_up;
> +	bool spectral_enabled;
>  	u32 aid;
>  	u8 bssid[ETH_ALEN];
>  
> @@ -469,6 +471,12 @@ struct ath10k {
>  #ifdef CONFIG_ATH10K_DEBUGFS
>  	struct ath10k_debug debug;
>  #endif
> +
> +	/* relay(fs) channel for spectral scan */
> +	struct rchan *rfs_chan_spec_scan;
> +	/* spectral_mode and spec_config are protected by conf_mutex */
> +	enum ath10k_spectral_mode spectral_mode;
> +	struct ath10k_spec_scan spec_config;
>  };

For all spectral stuff I would prefer to have a "substructure", just
like mac has. That way it's easier to know who owns what fields.

I know this structure is a mess now, I have been sloppy on review...

> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
> index 348a639..14d6234 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -2201,6 +2201,7 @@ void ath10k_halt(struct ath10k *ar)
>  	ath10k_peer_cleanup_all(ar);
>  	ath10k_core_stop(ar);
>  	ath10k_hif_power_down(ar);
> +	ath10k_disable_spectral(ar);

Maybe ath10k_spectral_stop()?

>  
>  	spin_lock_bh(&ar->data_lock);
>  	if (ar->scan.in_progress) {
> @@ -2671,8 +2672,16 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
>  		dev_kfree_skb_any(arvif->beacon);
>  		arvif->beacon = NULL;
>  	}
> +
>  	spin_unlock_bh(&ar->data_lock);
>  
> +	if (arvif->spectral_enabled) {
> +		ret = ath10k_disable_spectral(ar);
> +		if (ret)
> +			ath10k_warn("Failed to disable spectral for vdev %i: %d\n",
> +				    arvif->vdev_id, ret);
> +	}

And here as well? And move the check for arvif->spectral_enabled inside
spectral.c?

> diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
> new file mode 100644
> index 0000000..4179efb
> --- /dev/null
> +++ b/drivers/net/wireless/ath/ath10k/spectral.c
> @@ -0,0 +1,563 @@
> +/*
> + * Copyright (c) 2013 Qualcomm Atheros, Inc.
> + *
> + * Permission to use, copy, modify, and/or distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <linux/relay.h>
> +#include "core.h"
> +#include "debug.h"
> +
> +static void
> +ath10k_debug_send_fft_sample(struct ath10k *ar,
> +			     const struct fft_sample_tlv *fft_sample_tlv)
> +{
> +	int length;
> +
> +	if (!ar->rfs_chan_spec_scan)
> +		return;
> +
> +	length = __be16_to_cpu(fft_sample_tlv->length) +
> +		 sizeof(*fft_sample_tlv);
> +	relay_write(ar->rfs_chan_spec_scan, fft_sample_tlv, length);
> +}
> +
> +static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
> +			   u8 *data)
> +{
> +	int dc_pos;
> +	u8 max_exp;
> +
> +	dc_pos = bin_len / 2;
> +	/* peak index outside of bins */
> +	if (dc_pos < max_index || -dc_pos >= max_index)
> +		return 0;

Empty line before the comment, please.

> +int ath10k_process_fft(struct ath10k *ar,
> +		       struct wmi_single_phyerr_rx_event *event,
> +		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
> +{
> +	struct fft_sample_ath10k *fft_sample;
> +	u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
> +	int dc_pos;
> +	u32 reg0, reg1;
> +	u16 peak_mag;
> +	u8 *bins;
> +	u16 freq1;
> +	u16 freq2;
> +	u16 total_gain_db;
> +	u16 base_pwr_db;
> +	u8 chain_idx;
> +	u32 nf_list1;
> +	u32 nf_list2;
> +	u16 length;

You could combine the variable declarations, for example:

u16 freq1, freq2, total_gain_db, and_so_on;

> +	fft_sample = (struct fft_sample_ath10k *)&buf;
> +
> +	if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
> +		return -EINVAL;
> +
> +	reg0 = __le32_to_cpu(fftr->reg0);
> +	reg1 = __le32_to_cpu(fftr->reg1);
> +
> +	length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + bin_len;
> +	fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH10K;
> +	fft_sample->tlv.length = __cpu_to_be16(length);
> +
> +	/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
> +	 * but the results/plots suggest that its actually 22/44/88 MHz.
> +	 */
> +	switch (event->hdr.chan_width_mhz) {
> +	case 20:
> +		fft_sample->chan_width_mhz = 22;
> +		break;
> +	case 40:
> +		fft_sample->chan_width_mhz = 44;
> +		break;
> +	case 80:
> +		/* TODO: As experiments with an analogue sender and various
> +		 * configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
> +		 * show, the particular configuration of 80 MHz/64 bins does
> +		 * not match with the other smaples at all. Until the reason
> +		 * for that is found, don't report these samples.
> +		 */
> +		if (bin_len == 64)
> +			return -EINVAL;
> +		fft_sample->chan_width_mhz = 88;
> +		break;
> +	default:
> +		fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
> +	}

Empty line here.

> +	fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
> +	fft_sample->avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
> +
> +	peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
> +	fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
> +	fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
> +	fft_sample->rssi = event->hdr.rssi_combined;
> +
> +	total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
> +	base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
> +	fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
> +	fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
> +
> +	freq1 = __le16_to_cpu(event->hdr.freq1);
> +	freq2 = __le16_to_cpu(event->hdr.freq2);
> +	fft_sample->freq1 = __cpu_to_be16(freq1);
> +	fft_sample->freq2 = __cpu_to_be16(freq2);
> +
> +	nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
> +	nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
> +	chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);

Empty line here.

> +	switch (chain_idx) {
> +	case 0:
> +		fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
> +		break;
> +	case 1:
> +		fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
> +		break;
> +	case 2:
> +		fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
> +		break;
> +	case 3:
> +		fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
> +		break;
> +	}
> +
> +	bins = (u8 *)fftr;
> +	bins += sizeof(*fftr);
> +
> +	fft_sample->tsf = __cpu_to_be64(tsf);

Empty line here.

> +	arg.vdev_id              = vdev_id;
> +	arg.scan_count           = count;
> +	arg.scan_period          = WMI_SPECTRAL_PERIOD_DEFAULT;
> +	arg.scan_priority        = WMI_SPECTRAL_PRIORITY_DEFAULT;
> +	arg.scan_fft_size        = ar->spec_config.fft_size;
> +	arg.scan_gc_ena          = WMI_SPECTRAL_GC_ENA_DEFAULT;
> +	arg.scan_restart_ena     = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
> +	arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
> +	arg.scan_init_delay      = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
> +	arg.scan_nb_tone_thr     = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
> +	arg.scan_str_bin_thr     = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
> +	arg.scan_wb_rpt_mode     = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
> +	arg.scan_rssi_rpt_mode   = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
> +	arg.scan_rssi_thr        = WMI_SPECTRAL_RSSI_THR_DEFAULT;
> +	arg.scan_pwr_format      = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
> +	arg.scan_rpt_mode        = WMI_SPECTRAL_RPT_MODE_DEFAULT;
> +	arg.scan_bin_scale       = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
> +	arg.scan_dbm_adj         = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
> +	arg.scan_chn_mask        = WMI_SPECTRAL_CHN_MASK_DEFAULT;

Please don't indent the '=':

        arg.scan_dbm_adj = WMI_SPECTRAL_DBM_ADJ_DEFAULT
        arg.scan_chn_mask = WMI_SPECTRAL_CHN_MASK_DEFAULT;

> +/******************/
> +/* spectral_count */
> +/******************/

I don't think there's any point of adding these comments for each
debugfs file. I don't see how spectral.c even needs these kind of
comments, it's only 500 lines long.

> +void ath10k_spectral_deinit_debug(struct ath10k *ar)
> +{
> +	if (config_enabled(CONFIG_ATH10K_DEBUGFS) && ar->rfs_chan_spec_scan) {
> +		relay_close(ar->rfs_chan_spec_scan);
> +		ar->rfs_chan_spec_scan = NULL;
> +	}
> +}
> +
> +void ath10k_spectral_init_debug(struct ath10k *ar)
> +{
> +#ifdef CONFIG_ATH10K_DEBUGFS
> +	ar->rfs_chan_spec_scan = relay_open("spectral_scan",
> +					    ar->debug.debugfs_phy,
> +					    1024, 256, &rfs_spec_scan_cb,
> +					    NULL);
> +	debugfs_create_file("spectral_scan_ctl",
> +			    S_IRUSR | S_IWUSR,
> +			    ar->debug.debugfs_phy, ar,
> +			    &fops_spec_scan_ctl);
> +	debugfs_create_file("spectral_count",
> +			    S_IRUSR | S_IWUSR,
> +			    ar->debug.debugfs_phy, ar,
> +			    &fops_spectral_count);
> +	debugfs_create_file("spectral_bins",
> +			    S_IRUSR | S_IWUSR,
> +			    ar->debug.debugfs_phy, ar,
> +			    &fops_spectral_bins);
> +#endif
> +}

Do we even bother compiling spectral.c when ATH10K_DEBUGFS is disabled?
Should we instead just do this:

ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o


> diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
> new file mode 100644
> index 0000000..ee10ad2
> --- /dev/null
> +++ b/drivers/net/wireless/ath/ath10k/spectral.h

[...]

> +void ath10k_spectral_init_debug(struct ath10k *ar);
> +void ath10k_spectral_deinit_debug(struct ath10k *ar);
> +int ath10k_disable_spectral(struct ath10k *ar);
> +
> +#ifdef CONFIG_ATH10K_DEBUGFS
> +int ath10k_process_fft(struct ath10k *ar,
> +		       struct wmi_single_phyerr_rx_event *event,
> +		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf);
> +#else
> +static inline int
> +ath10k_process_fft(struct ath10k *ar,
> +		   struct wmi_single_phyerr_rx_event *event,
> +		   struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
> +{
> +	return 0;
> +}
> +#endif /* CONFIG_ATH10K_DEBUGFS */

Why ath10k_spectral_init_debug() are not within the ifdef?

> +int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
> +				  const struct wmi_vdev_spectral_conf_arg *arg)
> +{
> +	struct wmi_vdev_spectral_conf_cmd *cmd;
> +	struct sk_buff *skb;
> +	u32 cmdid;
> +
> +	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	cmd = (struct wmi_vdev_spectral_conf_cmd *)skb->data;
> +	cmd->vdev_id              = __cpu_to_le32(arg->vdev_id);
> +	cmd->scan_count           = __cpu_to_le32(arg->scan_count);
> +	cmd->scan_period          = __cpu_to_le32(arg->scan_period);
> +	cmd->scan_priority        = __cpu_to_le32(arg->scan_priority);

Please do not indent the '='.

> +int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
> +				    u32 enable)
> +{
> +	struct wmi_vdev_spectral_enable_cmd *cmd;
> +	struct sk_buff *skb;
> +	u32 cmdid;
> +
> +	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	cmd = (struct wmi_vdev_spectral_enable_cmd *)skb->data;
> +	cmd->vdev_id     = __cpu_to_le32(vdev_id);
> +	cmd->trigger_cmd = __cpu_to_le32(trigger);
> +	cmd->enable_cmd  = __cpu_to_le32(enable);

Here as well.

> +/* TODO: please add more comments if you have in-depth information */
> +struct wmi_vdev_spectral_conf_cmd {
> +	__le32 vdev_id;
> +	/* number of fft samples to send (0 for infinite) */
> +	__le32 scan_count;
> +	__le32 scan_period;
> +	__le32 scan_priority;
> +	/* number of bins in the FFT: 2^(fft_size - bin_scale) */
> +	__le32 scan_fft_size;
> +	__le32 scan_gc_ena;
> +	__le32 scan_restart_ena;
> +	__le32 scan_noise_floor_ref;
> +	__le32 scan_init_delay;
> +	__le32 scan_nb_tone_thr;
> +	__le32 scan_str_bin_thr;
> +	__le32 scan_wb_rpt_mode;
> +	__le32 scan_rssi_rpt_mode;
> +	__le32 scan_rssi_thr;
> +	__le32 scan_pwr_format;
> +	/* rpt_mode: Format of FFT report to software for spectral scan
> +	 * triggered FFTs:
> +	 *	0: No FFT report (only spectral scan summary report)
> +	 *	1: 2-dword summary of metrics for each completed FFT + spectral
> +	 *	   scan	summary report
> +	 *	2: 2-dword summary of metrics for each completed FFT +
> +	 *	   1x- oversampled bins(in-band) per FFT + spectral scan summary
> +	 *	   report
> +	 *	3: 2-dword summary of metrics for each completed FFT +
> +	 *	   2x- oversampled bins	(all) per FFT + spectral scan summary
> +	 */
> +	__le32 scan_rpt_mode;
> +	__le32 scan_bin_scale;
> +	__le32 scan_dbm_adj;
> +	__le32 scan_chn_mask;
> +} __packed;

Empty lines before the comments.

> --- a/drivers/net/wireless/ath/spectral_common.h
> +++ b/drivers/net/wireless/ath/spectral_common.h
> @@ -19,6 +19,10 @@
>  
>  #define SPECTRAL_HT20_NUM_BINS		56
>  #define SPECTRAL_HT20_40_NUM_BINS		128
> +/* TODO: could possibly be 512, but no samples this large
> + * could be acquired so far.
> + */
> +#define SPECTRAL_ATH10K_MAX_NUM_BINS		256

Empty line before the comment.

> +struct fft_sample_ath10k {
> +	struct fft_sample_tlv tlv;
> +	u8 chan_width_mhz;
> +	__be16 freq1;
> +	__be16 freq2;
> +	__be16 noise;
> +	__be16 max_magnitude;
> +	__be16 total_gain_db;
> +	__be16 base_pwr_db;
> +	__be64 tsf;
> +	s8 max_index;
> +	u8 rssi;
> +	u8 relpwr_db;
> +	u8 avgpwr_db;
> +	u8 max_exp;
> +
> +	u8 data[0];
> +} __packed;

__be16, that's a first. Just making sure that this really is big endian?

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Jul 22 11:32:01 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 22 Jul 2014 21:32:01 +0300
Subject: [PATCH] ath10k: prevent endless pci rx loop
In-Reply-To: <1405687501-25917-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Fri, 18 Jul 2014 14:45:01 +0200")
References: <1405687501-25917-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87vbqptfby.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> It was possible to enter an endless loop while
> processing a single pci copy engine pipe. This
> could effectively render ath10k incapable of
> responding to any requests.
>
> An example case when this could happen is when
> firmware generates a lot of events, e.g. spectral
> scan phyerr via WMI.
>
> Reported-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Jul 22 11:37:29 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 22 Jul 2014 21:37:29 +0300
Subject: [PATCH v3] ath10k: fix Rx aggregation reordering
In-Reply-To: <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Wed, 16 Jul 2014 13:19:00 +0200")
References: <1405505855-13741-1-git-send-email-michal.kazior@tieto.com>
 <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87r41dtf2u.fsf@kamboji.qca.qualcomm.com>

(dropping linux-wireless)

Michal Kazior <michal.kazior at tieto.com> writes:

> Firmware doesn't perform Rx reordering so it is
> left to the host driver to do that.
>
> Use mac80211 to perform reordering instead of
> re-inventing the wheel.
>
> This fixes TCP throughput issues in some
> environments.
>
> Reported-by: Denton Gentry <denton.gentry at gmail.com>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
> ---
> This depends on:
>
>  * mac80211: fix Rx reordering with RX_FLAG_AMSDU_MORE
>  * mac80211: add support for Rx reordering offloading
>
> I'm still seeing some issues with TCP traffic.
> Apparently firmware/hardware sometimes stalls Rx
> for ~100ms and misses some aggregate frames. I
> wasn't able to pinpoint what the problem is. The
> more parallel TCP streams (iperf) the more often
> stalls happen. UDP doesn't seem to trigger the Rx
> stalls at all.

The mac80211 patches are in mac80211-next, but I can only apply this one
only once they are in wireless-next.

Also the other thing is that 3.17 merge window is very close. I might be
able to squeeze this in but there's the risk that this patch hasn't
received enough testing from being in ath.git. How safe (or risky) is
this patch? If we push this to 3.17, we could try to fix regressions in
-rc releases but that's always more difficult than waiting for 3.18.

-- 
Kalle Valo


From greearb at candelatech.com  Tue Jul 22 16:00:04 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 22 Jul 2014 16:00:04 -0700
Subject: [PATCH] ath10k:  Improve 'hard' simulate fw crash.
Message-ID: <1406070004-6238-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Different firmware may support different numbers of
vdevs.  Use value that is always out of range for all
firmware.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/debug.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 3030158..c9e35c87e 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -531,7 +531,10 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
 		ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
 	} else if (!strcmp(buf, "hard")) {
 		ath10k_info("simulating hard firmware crash\n");
-		ret = ath10k_wmi_vdev_set_param(ar, TARGET_NUM_VDEVS + 1,
+		/* 0x7fff is vdev id, and it is always out of range for all
+		 * firmware variants in order to force a firmware crash.
+		 */
+		ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
 					ar->wmi.vdev_param->rts_threshold, 0);
 	} else {
 		ret = -EINVAL;
-- 
1.7.11.7



From greearb at candelatech.com  Tue Jul 22 16:02:31 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 22 Jul 2014 16:02:31 -0700
Subject: [PATCH v3 2/5] ath10k:  save firmware debug log messages.
In-Reply-To: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
References: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
Message-ID: <1406070154-6614-2-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

They may be dumped through the firmware dump debugfs
file.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/wmi.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 6f83cae..df62115 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1089,6 +1089,12 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
 
 	trace_ath10k_wmi_dbglog(skb->data, skb->len);
 
+	/* First 4 bytes are a messages-dropped-due-to-overflow counter,
+	 * and should not be recorded in the dbglog buffer, so we skip
+	 * them.
+	 */
+	ath10k_dbg_save_fw_dbg_buffer(ar, skb->data + 4, skb->len - 4);
+
 	return 0;
 }
 
-- 
1.7.11.7



From greearb at candelatech.com  Tue Jul 22 16:02:33 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 22 Jul 2014 16:02:33 -0700
Subject: [PATCH v3 4/5] ath10k: Dump exception stack contents on firmware
 crash.
In-Reply-To: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
References: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
Message-ID: <1406070154-6614-4-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Firmware developers can decode this and maybe figure out
why the firmware crashed.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/core.h  |  3 +++
 drivers/net/wireless/ath/ath10k/debug.c |  8 ++++++++
 drivers/net/wireless/ath/ath10k/pci.c   | 13 +++++++++++--
 3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 2f200f6..f122eae 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -281,11 +281,13 @@ struct ath10k_vif_iter {
  * @ATH10K_FW_ERROR_DUMP_DBGLOG:  Recent firmware debug log entries
  * @ATH10K_FW_ERROR_DUMP_REGDUMP: Register crash dump in binary format
  * @ATH10K_FW_ERROR_DUMP_STACK:   Stack memory contents.
+ * @ATH10K_FW_ERROR_DUMP_EXC_STACK:  Exception stack contents
  */
 enum ath10k_fw_error_dump_type {
 	ATH10K_FW_ERROR_DUMP_DBGLOG = 0,
 	ATH10K_FW_ERROR_DUMP_REGDUMP = 1,
 	ATH10K_FW_ERROR_DUMP_STACK = 2,
+	ATH10K_FW_ERROR_DUMP_EXC_STACK = 3,
 
 	ATH10K_FW_ERROR_DUMP_MAX,
 };
@@ -367,6 +369,7 @@ struct ath10k_debug {
 	struct ath10k_dbglog_entry_storage dbglog_entry_data;
 	u32 reg_dump_values[REG_DUMP_COUNT_QCA988X];
 	unsigned char stack_buf[ATH10K_FW_STACK_SIZE];
+	unsigned char exc_stack_buf[ATH10K_FW_STACK_SIZE];
 };
 
 enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index befdc60..1cbc175 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -623,6 +623,7 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.reg_dump_values);
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.dbglog_entry_data);
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.stack_buf);
+	len += sizeof(*dump_tlv) + sizeof(ar->debug.exc_stack_buf);
 
 	lockdep_assert_held(&ar->conf_mutex);
 
@@ -696,6 +697,13 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	memcpy(dump_tlv->tlv_data, &ar->debug.stack_buf, dump_tlv->tlv_len);
 	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
 
+	/* Gather firmware exception (irq) stack dump */
+	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+	dump_tlv->type = ATH10K_FW_ERROR_DUMP_EXC_STACK;
+	dump_tlv->tlv_len = sizeof(ar->debug.exc_stack_buf);
+	memcpy(dump_tlv->tlv_data, &ar->debug.exc_stack_buf, dump_tlv->tlv_len);
+	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+
 	spin_unlock_irqrestore(&ar->data_lock, flags);
 
 	WARN_ON(sofar != len);
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index b58f1a1..d298e14 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -864,8 +864,15 @@ static void ath10k_save_firmware_stack(struct ath10k *ar)
 	ath10k_save_firmware_mem_helper(ar, ATH10K_FW_STACK_SIZE,
 					ar->debug.stack_buf, HI_ITEM(hi_stack));
 }
-#endif
 
+/* Save the firmware exception stack */
+static void ath10k_save_firmware_exc_stack(struct ath10k *ar)
+{
+	ath10k_save_firmware_mem_helper(ar, ATH10K_FW_STACK_SIZE,
+					ar->debug.exc_stack_buf,
+					HI_ITEM(hi_err_stack));
+}
+#endif
 
 static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 {
@@ -918,8 +925,10 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 #ifdef CONFIG_ATH10K_DEBUGFS
 	spin_lock_bh(&ar->data_lock);
 
-	if (!ar->debug.crashed_since_read)
+	if (!ar->debug.crashed_since_read) {
 		ath10k_save_firmware_stack(ar);
+		ath10k_save_firmware_exc_stack(ar);
+	}
 
 	spin_unlock_bh(&ar->data_lock);
 
-- 
1.7.11.7



From greearb at candelatech.com  Tue Jul 22 16:02:32 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 22 Jul 2014 16:02:32 -0700
Subject: [PATCH v3 3/5] ath10k:  save firmware stack upon firmware crash.
In-Reply-To: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
References: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
Message-ID: <1406070154-6614-3-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Should help debug firmware crashes, and give users a way
to provide some useful debug reports to firmware developers.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/core.h  |  3 +++
 drivers/net/wireless/ath/ath10k/debug.c |  9 ++++++++
 drivers/net/wireless/ath/ath10k/hw.h    |  1 +
 drivers/net/wireless/ath/ath10k/pci.c   | 41 +++++++++++++++++++++++++++++++++
 4 files changed, 54 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 5c0c5bf..2f200f6 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -280,10 +280,12 @@ struct ath10k_vif_iter {
  * enum ath10k_fw_error_dump_type - types of data in the dump file
  * @ATH10K_FW_ERROR_DUMP_DBGLOG:  Recent firmware debug log entries
  * @ATH10K_FW_ERROR_DUMP_REGDUMP: Register crash dump in binary format
+ * @ATH10K_FW_ERROR_DUMP_STACK:   Stack memory contents.
  */
 enum ath10k_fw_error_dump_type {
 	ATH10K_FW_ERROR_DUMP_DBGLOG = 0,
 	ATH10K_FW_ERROR_DUMP_REGDUMP = 1,
+	ATH10K_FW_ERROR_DUMP_STACK = 2,
 
 	ATH10K_FW_ERROR_DUMP_MAX,
 };
@@ -364,6 +366,7 @@ struct ath10k_debug {
 	bool crashed_since_read;
 	struct ath10k_dbglog_entry_storage dbglog_entry_data;
 	u32 reg_dump_values[REG_DUMP_COUNT_QCA988X];
+	unsigned char stack_buf[ATH10K_FW_STACK_SIZE];
 };
 
 enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index b952775..befdc60 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -622,6 +622,7 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	len = hdr_len;
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.reg_dump_values);
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.dbglog_entry_data);
+	len += sizeof(*dump_tlv) + sizeof(ar->debug.stack_buf);
 
 	lockdep_assert_held(&ar->conf_mutex);
 
@@ -688,8 +689,16 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	memcpy(dump_tlv->tlv_data, &ar->debug.reg_dump_values, dump_tlv->tlv_len);
 	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
 
+	/* Gather firmware stack dump */
+	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+	dump_tlv->type = ATH10K_FW_ERROR_DUMP_STACK;
+	dump_tlv->tlv_len = sizeof(ar->debug.stack_buf);
+	memcpy(dump_tlv->tlv_data, &ar->debug.stack_buf, dump_tlv->tlv_len);
+	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+
 	spin_unlock_irqrestore(&ar->data_lock, flags);
 
+	WARN_ON(sofar != len);
 	return dump_data;
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index d4df3f0..38a03e4 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -39,6 +39,7 @@
 #define ATH10K_FIRMWARE_MAGIC               "QCA-ATH10K"
 
 #define REG_DUMP_COUNT_QCA988X 60
+#define ATH10K_FW_STACK_SIZE 4096
 
 struct ath10k_fw_ie {
 	__le32 id;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 24ddc22..b58f1a1 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -833,6 +833,40 @@ static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
 	return ath10k_ce_num_free_src_entries(ar_pci->pipe_info[pipe].ce_hdl);
 }
 
+static void ath10k_save_firmware_mem_helper(struct ath10k *ar, u32 sz,
+					    unsigned char *to, u32 addr)
+{
+	u32 host_addr;
+	u32 reg_dump_area;
+	int ret;
+
+	host_addr = host_interest_item_address(addr);
+
+	ret = ath10k_pci_diag_read_mem(ar, host_addr, &reg_dump_area,
+				       sizeof(u32));
+	if (ret != 0) {
+		ath10k_warn("failed to read FW addr: %d (addr %d)\n",
+			    ret, addr);
+		return;
+	}
+
+	ret = ath10k_pci_diag_read_mem(ar, reg_dump_area, to, sz);
+	if (ret != 0)
+		ath10k_err("failed to read FW memory: %d (addr %d sz %d)\n",
+			   ret, reg_dump_area, sz);
+}
+
+#ifdef CONFIG_ATH10K_DEBUGFS
+/* Save the main firmware stack */
+static void ath10k_save_firmware_stack(struct ath10k *ar)
+{
+	BUILD_BUG_ON(ATH10K_FW_STACK_SIZE % 4);
+	ath10k_save_firmware_mem_helper(ar, ATH10K_FW_STACK_SIZE,
+					ar->debug.stack_buf, HI_ITEM(hi_stack));
+}
+#endif
+
+
 static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 {
 	u32 reg_dump_area = 0;
@@ -882,6 +916,13 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 			   reg_dump_values[i + 3]);
 
 #ifdef CONFIG_ATH10K_DEBUGFS
+	spin_lock_bh(&ar->data_lock);
+
+	if (!ar->debug.crashed_since_read)
+		ath10k_save_firmware_stack(ar);
+
+	spin_unlock_bh(&ar->data_lock);
+
 	/* Dump the debug logs on the target */
 	host_addr = host_interest_item_address(HI_ITEM(hi_dbglog_hdr));
 	ret = ath10k_pci_diag_read_mem(ar, host_addr,
-- 
1.7.11.7



From greearb at candelatech.com  Tue Jul 22 16:02:34 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 22 Jul 2014 16:02:34 -0700
Subject: [PATCH v3 5/5] ath10k: save firmware RAM and ROM BSS sections on
 crash.
In-Reply-To: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
References: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
Message-ID: <1406070154-6614-5-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

This can be used to get a useful back trace out of a firmware
crash that involves an interrupt handler.  For instance, a
null-pointer-exception would be this kind of trace.  A user-space
tool can read the debugfs file and decode things as wished.

This requires a packaged firmware with a new IE to describe the
BSS section starts and length.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/core.c  | 62 +++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/core.h  | 11 ++++++
 drivers/net/wireless/ath/ath10k/debug.c | 32 +++++++++++++++++
 drivers/net/wireless/ath/ath10k/hw.h    |  1 +
 drivers/net/wireless/ath/ath10k/pci.c   | 37 ++++++++++++++++++++
 5 files changed, 143 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 93adb8c..08e96e7 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -365,6 +365,12 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 	struct ath10k_fw_ie *hdr;
 	const u8 *data;
 	__le32 *timestamp;
+#ifdef CONFIG_ATH10K_DEBUGFS
+	u32 old_ram_bss_len = ar->debug.fw_ram_bss_len;
+	u32 old_rom_bss_len = ar->debug.fw_rom_bss_len;
+	unsigned char *t1, *t2;
+	unsigned long flags;
+#endif
 
 	/* first fetch the firmware file (firmware-*.bin) */
 	ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
@@ -479,6 +485,38 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 			ar->otp_len = ie_len;
 
 			break;
+		case ATH10K_FW_IE_BSS_INFO:
+#ifdef CONFIG_ATH10K_DEBUGFS
+			spin_lock_irqsave(&ar->data_lock, flags);
+
+			ar->debug.fw_ram_bss_addr = le32_to_cpu(((u32 *)(data))[0]);
+			ar->debug.fw_ram_bss_len = le32_to_cpu(((u32 *)(data))[1]);
+			ar->debug.fw_rom_bss_addr = le32_to_cpu(((u32 *)(data))[2]);
+			ar->debug.fw_rom_bss_len = le32_to_cpu(((u32 *)(data))[3]);
+			t1 = t2 = NULL;
+			if ((old_ram_bss_len < ar->debug.fw_ram_bss_len) &&
+			    ar->debug.ram_bss_buf) {
+				t1 = ar->debug.ram_bss_buf;
+				ar->debug.ram_bss_buf = NULL;
+			}
+			if ((old_rom_bss_len < ar->debug.fw_rom_bss_len) &&
+			    ar->debug.rom_bss_buf) {
+				t2 = ar->debug.rom_bss_buf;
+				ar->debug.rom_bss_buf = NULL;
+			}
+			spin_unlock_irqrestore(&ar->data_lock, flags);
+			if (t1)
+				vfree(t1);
+			if (t2)
+				vfree(t2);
+			ath10k_dbg(ATH10K_DBG_BOOT,
+				   "found FW bss info, RAM: addr 0x%x len 0x%x  ROM: addr 0x%x len 0x%x\n",
+				   ar->debug.fw_ram_bss_addr,
+				   ar->debug.fw_ram_bss_len,
+				   ar->debug.fw_rom_bss_addr,
+				   ar->debug.fw_rom_bss_len);
+#endif
+			break;
 		default:
 			ath10k_warn("Unknown FW IE: %u\n",
 				    le32_to_cpu(hdr->id));
@@ -1094,9 +1132,33 @@ EXPORT_SYMBOL(ath10k_core_create);
 
 void ath10k_core_destroy(struct ath10k *ar)
 {
+#ifdef CONFIG_ATH10K_DEBUGFS
+	unsigned long flags;
+	unsigned char *t1 = NULL;
+	unsigned char *t2 = NULL;
+#endif
+
 	flush_workqueue(ar->workqueue);
 	destroy_workqueue(ar->workqueue);
 
+#ifdef CONFIG_ATH10K_DEBUGFS
+	spin_lock_irqsave(&ar->data_lock, flags);
+	if (ar->debug.rom_bss_buf) {
+		t1 = ar->debug.rom_bss_buf;
+		ar->debug.rom_bss_buf = NULL;
+	}
+	if (ar->debug.ram_bss_buf) {
+		t2 = ar->debug.ram_bss_buf;
+		ar->debug.ram_bss_buf = NULL;
+	}
+	spin_unlock_irqrestore(&ar->data_lock, flags);
+
+	if (t1)
+		vfree(t1);
+	if (t2)
+		vfree(t2);
+#endif
+
 	ath10k_mac_destroy(ar);
 }
 EXPORT_SYMBOL(ath10k_core_destroy);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index f122eae..f44957f 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -282,12 +282,16 @@ struct ath10k_vif_iter {
  * @ATH10K_FW_ERROR_DUMP_REGDUMP: Register crash dump in binary format
  * @ATH10K_FW_ERROR_DUMP_STACK:   Stack memory contents.
  * @ATH10K_FW_ERROR_DUMP_EXC_STACK:  Exception stack contents
+ * @ATH10K_FW_ERROR_DUMP_RAM_BSS:  BSS area for RAM code
+ * @ATH10K_FW_ERROR_DUMP_ROM_BSS:  BSS area for ROM code
  */
 enum ath10k_fw_error_dump_type {
 	ATH10K_FW_ERROR_DUMP_DBGLOG = 0,
 	ATH10K_FW_ERROR_DUMP_REGDUMP = 1,
 	ATH10K_FW_ERROR_DUMP_STACK = 2,
 	ATH10K_FW_ERROR_DUMP_EXC_STACK = 3,
+	ATH10K_FW_ERROR_DUMP_RAM_BSS = 4,
+	ATH10K_FW_ERROR_DUMP_ROM_BSS = 5,
 
 	ATH10K_FW_ERROR_DUMP_MAX,
 };
@@ -370,6 +374,13 @@ struct ath10k_debug {
 	u32 reg_dump_values[REG_DUMP_COUNT_QCA988X];
 	unsigned char stack_buf[ATH10K_FW_STACK_SIZE];
 	unsigned char exc_stack_buf[ATH10K_FW_STACK_SIZE];
+
+	unsigned char *rom_bss_buf;
+	unsigned char *ram_bss_buf;
+	unsigned int fw_ram_bss_addr;
+	unsigned int fw_ram_bss_len;
+	unsigned int fw_rom_bss_addr;
+	unsigned int fw_rom_bss_len;
 };
 
 enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 1cbc175..450b31d 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -618,6 +618,8 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	int hdr_len = sizeof(*dump_data);
 	unsigned long flags;
 	struct timespec timestamp;
+	int rom_bss_len = 0;
+	int ram_bss_len = 0;
 
 	len = hdr_len;
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.reg_dump_values);
@@ -625,6 +627,19 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.stack_buf);
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.exc_stack_buf);
 
+	/* Need to store local copies to detect races */
+	spin_lock_irqsave(&ar->data_lock, flags);
+
+	ram_bss_len = ar->debug.fw_ram_bss_len;
+	rom_bss_len = ar->debug.fw_ram_bss_len;
+
+	if (ram_bss_len && ar->debug.ram_bss_buf)
+		len += sizeof(*dump_tlv) + ram_bss_len;
+	if (rom_bss_len && ar->debug.rom_bss_buf)
+		len += sizeof(*dump_tlv) + rom_bss_len;
+
+	spin_unlock_irqrestore(&ar->data_lock, flags);
+
 	lockdep_assert_held(&ar->conf_mutex);
 
 	sofar += hdr_len;
@@ -704,6 +719,23 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	memcpy(dump_tlv->tlv_data, &ar->debug.exc_stack_buf, dump_tlv->tlv_len);
 	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
 
+	if (ram_bss_len >= ar->debug.fw_ram_bss_len &&
+	    ar->debug.fw_ram_bss_len && ar->debug.ram_bss_buf) {
+		dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+		dump_tlv->type = ATH10K_FW_ERROR_DUMP_RAM_BSS;
+		dump_tlv->tlv_len = ar->debug.fw_ram_bss_len;
+		memcpy(dump_tlv->tlv_data, ar->debug.ram_bss_buf, dump_tlv->tlv_len);
+		sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+	}
+	if (rom_bss_len >= ar->debug.fw_rom_bss_len &&
+	    ar->debug.fw_rom_bss_len && ar->debug.rom_bss_buf) {
+		dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+		dump_tlv->type = ATH10K_FW_ERROR_DUMP_ROM_BSS;
+		dump_tlv->tlv_len = ar->debug.fw_rom_bss_len;
+		memcpy(dump_tlv->tlv_data, ar->debug.rom_bss_buf, dump_tlv->tlv_len);
+		sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+	}
+
 	spin_unlock_irqrestore(&ar->data_lock, flags);
 
 	WARN_ON(sofar != len);
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 38a03e4..724bd94 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -53,6 +53,7 @@ enum ath10k_fw_ie_type {
 	ATH10K_FW_IE_FEATURES = 2,
 	ATH10K_FW_IE_FW_IMAGE = 3,
 	ATH10K_FW_IE_OTP_IMAGE = 4,
+	ATH10K_FW_IE_BSS_INFO = 5,
 };
 
 /* Known pecularities:
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index d298e14..6d43845 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -872,6 +872,37 @@ static void ath10k_save_firmware_exc_stack(struct ath10k *ar)
 					ar->debug.exc_stack_buf,
 					HI_ITEM(hi_err_stack));
 }
+
+static void ath10k_check_dump_fw_bss(struct ath10k *ar, u32 addr, u32 len,
+				     bool is_rom) {
+	int ret;
+
+	if (!addr)
+		return;
+	if (is_rom) {
+		if (!ar->debug.rom_bss_buf)
+			ar->debug.rom_bss_buf = kmalloc(len, GFP_ATOMIC);
+		if (!ar->debug.rom_bss_buf)
+			return;
+
+		ret = ath10k_pci_diag_read_mem(ar, addr, ar->debug.rom_bss_buf,
+					       len);
+		if (ret != 0)
+			ath10k_err("failed to read FW ROM BSS memory: %d (addr %d sz %d)\n",
+				   ret, addr, len);
+	} else {
+		if (!ar->debug.ram_bss_buf)
+			ar->debug.ram_bss_buf = kmalloc(len, GFP_ATOMIC);
+		if (!ar->debug.ram_bss_buf)
+			return;
+
+		ret = ath10k_pci_diag_read_mem(ar, addr, ar->debug.ram_bss_buf,
+					       len);
+		if (ret != 0)
+			ath10k_err("failed to read FW RAM BSS memory: %d (addr %d sz %d)\n",
+				   ret, addr, len);
+	}
+}
 #endif
 
 static void ath10k_pci_hif_dump_area(struct ath10k *ar)
@@ -928,6 +959,12 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 	if (!ar->debug.crashed_since_read) {
 		ath10k_save_firmware_stack(ar);
 		ath10k_save_firmware_exc_stack(ar);
+
+		/* And the RAM BSS region, if we know it. */
+		ath10k_check_dump_fw_bss(ar, ar->debug.fw_ram_bss_addr,
+					 ar->debug.fw_ram_bss_len, false);
+		ath10k_check_dump_fw_bss(ar, ar->debug.fw_rom_bss_addr,
+					 ar->debug.fw_rom_bss_len, true);
 	}
 
 	spin_unlock_bh(&ar->data_lock);
-- 
1.7.11.7



From greearb at candelatech.com  Tue Jul 22 16:02:30 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 22 Jul 2014 16:02:30 -0700
Subject: [PATCH v3 1/5] ath10k:  provide firmware crash info via debugfs.
Message-ID: <1406070154-6614-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Store the firmware crash registers and last 128 or so
firmware debug-log ids and present them to user-space
via debugfs.

Should help with figuring out why the firmware crashed.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

changes from v3:

* Use 'data_lock' instead of a new lock.
* Move storage to the 'debug' object.
* Add new patch-5 that also dumps BSS regions if FW supports it.
* Fix compile problem when ath10k-debugfs is not enabled.

 drivers/net/wireless/ath/ath10k/core.h  |  71 ++++++++++++++
 drivers/net/wireless/ath/ath10k/debug.c | 166 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/debug.h |   8 ++
 drivers/net/wireless/ath/ath10k/hw.h    |  24 +++++
 drivers/net/wireless/ath/ath10k/pci.c   | 106 +++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/pci.h   |   3 -
 6 files changed, 373 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 83a5fa9..5c0c5bf 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -276,6 +276,70 @@ struct ath10k_vif_iter {
 	struct ath10k_vif *arvif;
 };
 
+/**
+ * enum ath10k_fw_error_dump_type - types of data in the dump file
+ * @ATH10K_FW_ERROR_DUMP_DBGLOG:  Recent firmware debug log entries
+ * @ATH10K_FW_ERROR_DUMP_REGDUMP: Register crash dump in binary format
+ */
+enum ath10k_fw_error_dump_type {
+	ATH10K_FW_ERROR_DUMP_DBGLOG = 0,
+	ATH10K_FW_ERROR_DUMP_REGDUMP = 1,
+
+	ATH10K_FW_ERROR_DUMP_MAX,
+};
+
+struct ath10k_tlv_dump_data {
+	u32 type; /* see ath10k_fw_error_dump_type above */
+	u32 tlv_len; /* in bytes */
+	u8 tlv_data[]; /* Pad to 32-bit boundaries as needed. */
+} __packed;
+
+struct ath10k_dump_file_data {
+	/* Dump file information */
+	char df_magic[16]; /* ATH10K-FW-DUMP */
+	u32 len;
+	u32 big_endian; /* 0x1 if host is big-endian */
+	u32 version; /* File dump version, 1 for now. */
+
+	/* Some info we can get from ath10k struct that might help. */
+	u32 chip_id;
+	u32 bus_type; /* 0 for now, in place for later hardware */
+	u32 target_version;
+	u32 fw_version_major;
+	u32 fw_version_minor;
+	u32 fw_version_release;
+	u32 fw_version_build;
+	u32 phy_capability;
+	u32 hw_min_tx_power;
+	u32 hw_max_tx_power;
+	u32 ht_cap_info;
+	u32 vht_cap_info;
+	u32 num_rf_chains;
+	char fw_ver[ETHTOOL_FWVERS_LEN]; /* Firmware version string */
+
+	/* Kernel related information */
+	u32 tv_sec_hi; /* time-of-day stamp, high 32-bits for seconds */
+	u32 tv_sec_lo; /* time-of-day stamp, low 32-bits for seconds */
+	u32 tv_nsec_hi; /* time-of-day stamp, nano-seconds, high bits */
+	u32 tv_nsec_lo; /* time-of-day stamp, nano-seconds, low bits */
+	u32 kernel_ver_code; /* LINUX_VERSION_CODE */
+	char kernel_ver[64]; /* VERMAGIC_STRING */
+
+	u8 unused[128]; /* Room for growth w/out changing binary format */
+
+	u8 data[0]; /* struct ath10k_tlv_dump_data + more */
+} __packed;
+
+/* This will store at least the last 128 entries.  Each dbglog message
+ * is a max of 7 32-bit integers in length, but the length can be less
+ * than that as well.
+ */
+#define ATH10K_DBGLOG_DATA_LEN (128 * 7 * sizeof(u32))
+struct ath10k_dbglog_entry_storage {
+	u32 next_idx; /* Where to write next chunk of data */
+	u8 data[ATH10K_DBGLOG_DATA_LEN];
+};
+
 struct ath10k_debug {
 	struct dentry *debugfs_phy;
 
@@ -293,6 +357,13 @@ struct ath10k_debug {
 
 	u8 htt_max_amsdu;
 	u8 htt_max_ampdu;
+
+	/* Used for crash-dump storage */
+	/* Don't over-write dump info until someone reads the data. */
+	/* Protected by data-lock */
+	bool crashed_since_read;
+	struct ath10k_dbglog_entry_storage dbglog_entry_data;
+	u32 reg_dump_values[REG_DUMP_COUNT_QCA988X];
 };
 
 enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index c9e35c87e..b952775 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -17,6 +17,9 @@
 
 #include <linux/module.h>
 #include <linux/debugfs.h>
+#include <linux/version.h>
+#include <linux/vermagic.h>
+#include <linux/vmalloc.h>
 
 #include "core.h"
 #include "debug.h"
@@ -580,6 +583,166 @@ static const struct file_operations fops_chip_id = {
 	.llseek = default_llseek,
 };
 
+void ath10k_dbg_save_fw_dbg_buffer(struct ath10k *ar, u8 *buffer, int len)
+{
+	int i;
+	int z = ar->debug.dbglog_entry_data.next_idx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ar->data_lock, flags);
+
+	/* Don't save any new logs until user-space reads this. */
+	if (ar->debug.crashed_since_read)
+		goto exit;
+
+	for (i = 0; i < len; i++) {
+		ar->debug.dbglog_entry_data.data[z] = buffer[i];
+		z++;
+		if (z >= ATH10K_DBGLOG_DATA_LEN)
+			z = 0;
+	}
+
+	ar->debug.dbglog_entry_data.next_idx = z;
+exit:
+	spin_unlock_irqrestore(&ar->data_lock, flags);
+}
+EXPORT_SYMBOL(ath10k_dbg_save_fw_dbg_buffer);
+
+static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
+{
+	unsigned int len;
+	unsigned int sofar = 0;
+	unsigned char *buf;
+	struct ath10k_tlv_dump_data *dump_tlv;
+	struct ath10k_dump_file_data *dump_data;
+	int hdr_len = sizeof(*dump_data);
+	unsigned long flags;
+	struct timespec timestamp;
+
+	len = hdr_len;
+	len += sizeof(*dump_tlv) + sizeof(ar->debug.reg_dump_values);
+	len += sizeof(*dump_tlv) + sizeof(ar->debug.dbglog_entry_data);
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	sofar += hdr_len;
+
+	/* This is going to get big when we start dumping FW RAM and such,
+	 * so go ahead and use vmalloc.
+	 */
+	buf = vmalloc(len);
+	if (!buf)
+		return NULL;
+
+	memset(buf, 0, len);
+	dump_data = (struct ath10k_dump_file_data *)(buf);
+	strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
+		sizeof(dump_data->df_magic));
+	dump_data->len = len;
+#ifdef __BIG_ENDIAN
+	dump_data->big_endian = 1;
+#else
+	dump_data->big_endian = 0;
+#endif
+	dump_data->version = 1;
+	dump_data->chip_id = ar->chip_id;
+	dump_data->bus_type = 0;
+	dump_data->target_version = ar->target_version;
+	dump_data->fw_version_major = ar->fw_version_major;
+	dump_data->fw_version_minor = ar->fw_version_minor;
+	dump_data->fw_version_release = ar->fw_version_release;
+	dump_data->fw_version_build = ar->fw_version_build;
+	dump_data->phy_capability = ar->phy_capability;
+	dump_data->hw_min_tx_power = ar->hw_min_tx_power;
+	dump_data->hw_max_tx_power = ar->hw_max_tx_power;
+	dump_data->ht_cap_info = ar->ht_cap_info;
+	dump_data->vht_cap_info = ar->vht_cap_info;
+	dump_data->num_rf_chains = ar->num_rf_chains;
+
+	strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
+		sizeof(dump_data->fw_ver));
+
+	dump_data->kernel_ver_code = LINUX_VERSION_CODE;
+	strlcpy(dump_data->kernel_ver, VERMAGIC_STRING,
+		sizeof(dump_data->kernel_ver));
+
+	getnstimeofday(&timestamp);
+	dump_data->tv_sec_hi = timestamp.tv_sec >> 32;
+	dump_data->tv_sec_lo = timestamp.tv_sec;
+	dump_data->tv_nsec_hi = timestamp.tv_nsec >> 32;
+	dump_data->tv_nsec_lo = timestamp.tv_nsec;
+
+	spin_lock_irqsave(&ar->data_lock, flags);
+
+	/* Gather dbg-log */
+	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+	dump_tlv->type = ATH10K_FW_ERROR_DUMP_DBGLOG;
+	dump_tlv->tlv_len = sizeof(ar->debug.dbglog_entry_data);
+	memcpy(dump_tlv->tlv_data, &ar->debug.dbglog_entry_data, dump_tlv->tlv_len);
+	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+
+	/* Gather crash-dump */
+	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+	dump_tlv->type = ATH10K_FW_ERROR_DUMP_REGDUMP;
+	dump_tlv->tlv_len = sizeof(ar->debug.reg_dump_values);
+	memcpy(dump_tlv->tlv_data, &ar->debug.reg_dump_values, dump_tlv->tlv_len);
+	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+
+	spin_unlock_irqrestore(&ar->data_lock, flags);
+
+	return dump_data;
+}
+
+static int ath10k_fw_error_dump_open(struct inode *inode, struct file *file)
+{
+	struct ath10k *ar = inode->i_private;
+	int ret;
+	struct ath10k_dump_file_data *dump;
+
+	mutex_lock(&ar->conf_mutex);
+
+	dump = ath10k_build_dump_file(ar);
+	if (!dump) {
+		ret = -ENODATA;
+		goto out;
+	}
+
+	file->private_data = dump;
+	ar->debug.crashed_since_read = false;
+	ret = 0;
+
+out:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
+}
+
+static ssize_t ath10k_fw_error_dump_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct ath10k_dump_file_data *dump_file = file->private_data;
+
+	return simple_read_from_buffer(user_buf, count, ppos,
+				       dump_file,
+				       dump_file->len);
+}
+
+static int ath10k_fw_error_dump_release(struct inode *inode,
+					struct file *file)
+{
+	vfree(file->private_data);
+
+	return 0;
+}
+
+static const struct file_operations fops_fw_error_dump = {
+	.open = ath10k_fw_error_dump_open,
+	.read = ath10k_fw_error_dump_read,
+	.release = ath10k_fw_error_dump_release,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 static int ath10k_debug_htt_stats_req(struct ath10k *ar)
 {
 	u64 cookie;
@@ -933,6 +1096,9 @@ int ath10k_debug_create(struct ath10k *ar)
 	debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_simulate_fw_crash);
 
+	debugfs_create_file("fw_error_dump", S_IRUSR, ar->debug.debugfs_phy,
+			    ar, &fops_fw_error_dump);
+
 	debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_chip_id);
 
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index a582499..6e8f5f6 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -96,6 +96,8 @@ __printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask,
 void ath10k_dbg_dump(enum ath10k_debug_mask mask,
 		     const char *msg, const char *prefix,
 		     const void *buf, size_t len);
+void ath10k_dbg_save_fw_dbg_buffer(struct ath10k *ar, u8 *buffer, int len);
+
 #else /* CONFIG_ATH10K_DEBUG */
 
 static inline int ath10k_dbg(enum ath10k_debug_mask dbg_mask,
@@ -109,5 +111,11 @@ static inline void ath10k_dbg_dump(enum ath10k_debug_mask mask,
 				   const void *buf, size_t len)
 {
 }
+
+static inline void ath10k_dbg_save_fw_dbg_buffer(struct ath10k *ar,
+						 u8 *buffer, int len)
+{
+}
 #endif /* CONFIG_ATH10K_DEBUG */
+
 #endif /* _DEBUG_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 007e855..d4df3f0 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -38,6 +38,8 @@
 /* includes also the null byte */
 #define ATH10K_FIRMWARE_MAGIC               "QCA-ATH10K"
 
+#define REG_DUMP_COUNT_QCA988X 60
+
 struct ath10k_fw_ie {
 	__le32 id;
 	__le32 len;
@@ -361,4 +363,26 @@ enum ath10k_mcast2ucast_mode {
 
 #define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB)
 
+
+/* Target debug log related defines and structs */
+
+/* Target is 32-bit CPU, so we just use u32 for
+ * the pointers.  The memory space is relative to the
+ * target, not the host.
+ */
+struct ath10k_fw_dbglog_buf {
+	u32 next; /* pointer to dblog_buf_s. */
+	u32 buffer; /* pointer to u8 buffer */
+	u32 bufsize;
+	u32 length;
+	u32 count;
+	u32 free;
+} __packed;
+
+struct ath10k_fw_dbglog_hdr {
+	u32 dbuf; /* pointer to dbglog_buf_s */
+	u32 dropped;
+} __packed;
+
+
 #endif /* _HW_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 06840d1..24ddc22 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -840,6 +840,12 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 	u32 host_addr;
 	int ret;
 	u32 i;
+#ifdef CONFIG_ATH10K_DEBUGFS
+	struct ath10k_fw_dbglog_hdr dbg_hdr;
+	u32 dbufp; /* pointer in target memory space */
+	struct ath10k_fw_dbglog_buf dbuf;
+	u8 *buffer;
+#endif
 
 	ath10k_err("firmware crashed!\n");
 	ath10k_err("hardware name %s version 0x%x\n",
@@ -851,7 +857,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 				       &reg_dump_area, sizeof(u32));
 	if (ret) {
 		ath10k_err("failed to read FW dump area address: %d\n", ret);
-		return;
+		goto exit;
 	}
 
 	ath10k_err("target register Dump Location: 0x%08X\n", reg_dump_area);
@@ -861,7 +867,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 				       REG_DUMP_COUNT_QCA988X * sizeof(u32));
 	if (ret != 0) {
 		ath10k_err("failed to read FW dump area: %d\n", ret);
-		return;
+		goto exit;
 	}
 
 	BUILD_BUG_ON(REG_DUMP_COUNT_QCA988X % 4);
@@ -875,6 +881,102 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 			   reg_dump_values[i + 2],
 			   reg_dump_values[i + 3]);
 
+#ifdef CONFIG_ATH10K_DEBUGFS
+	/* Dump the debug logs on the target */
+	host_addr = host_interest_item_address(HI_ITEM(hi_dbglog_hdr));
+	ret = ath10k_pci_diag_read_mem(ar, host_addr,
+				       &reg_dump_area, sizeof(u32));
+	if (ret != 0) {
+		ath10k_warn("failed to read hi_dbglog_hdr: %d\n", ret);
+		goto exit_save_regs;
+	}
+
+	ret = ath10k_pci_diag_read_mem(ar, reg_dump_area,
+				       &dbg_hdr, sizeof(dbg_hdr));
+	if (ret != 0) {
+		ath10k_err("failed to dump debug log area: %d (addr 0x%x)\n",
+			   ret, reg_dump_area);
+		goto exit_save_regs;
+	}
+
+	ath10k_dbg(ATH10K_DBG_PCI,
+		   "Debug Log Header, dbuf: 0x%x  dropped: %i\n",
+		   dbg_hdr.dbuf, dbg_hdr.dropped);
+	dbufp = dbg_hdr.dbuf;
+
+	/* i is for logging purposes and sanity check in case firmware buffers
+	 * are corrupted and will not properly terminate the list.
+	 * In standard firmware, it appears there are no more than 2
+	 * buffers, so 10 should be safe upper limit even if firmware
+	 * changes quite a bit.
+	 */
+	i = 0;
+	while (dbufp && i < 10) {
+		ret = ath10k_pci_diag_read_mem(ar, dbufp,
+					       &dbuf, sizeof(dbuf));
+		if (ret != 0) {
+			ath10k_err("failed to read debug log area: %d (addr 0x%x)\n",
+				   ret, dbufp);
+			goto exit_save_regs;
+		}
+
+		/* We have a buffer of data */
+		ath10k_dbg(ATH10K_DBG_PCI,
+			   "[%i] next: 0x%x buf: 0x%x sz: %i len: %i count: %i free: %i\n",
+			   i, dbuf.next, dbuf.buffer, dbuf.bufsize, dbuf.length,
+			   dbuf.count, dbuf.free);
+		if (dbuf.buffer == 0 || dbuf.length == 0)
+			goto next;
+
+		/* Pick arbitrary upper bound in case firmware is corrupted for
+		 * whatever reason.
+		 */
+		if (dbuf.length > 16000) {
+			ath10k_err("debuglog buf length is out of bounds: %d\n",
+				   dbuf.length);
+			/* Do not trust the next pointer either... */
+			goto exit_save_regs;
+		}
+
+		buffer = kmalloc(dbuf.length, GFP_ATOMIC);
+
+		if (!buffer)
+			goto next;
+
+		ret = ath10k_pci_diag_read_mem(ar, dbuf.buffer, buffer,
+					       dbuf.length);
+		if (ret != 0) {
+			ath10k_err("failed to read debug log buffer: %d (addr 0x%x)\n",
+				   ret, dbuf.buffer);
+			kfree(buffer);
+			goto exit_save_regs;
+		}
+
+		ath10k_dbg_save_fw_dbg_buffer(ar, buffer, dbuf.length);
+		kfree(buffer);
+
+next:
+		dbufp = dbuf.next;
+		if (dbufp == dbg_hdr.dbuf) {
+			/* It is a circular buffer it seems, bail if next
+			 * is head
+			 */
+			break;
+		}
+		i++;
+	} /* While we have a debug buffer to read */
+
+exit_save_regs:
+	spin_lock_bh(&ar->data_lock);
+	if (!ar->debug.crashed_since_read) {
+		ar->debug.crashed_since_read = true;
+		memcpy(ar->debug.reg_dump_values, reg_dump_values,
+		       sizeof(ar->debug.reg_dump_values));
+	}
+	spin_unlock_bh(&ar->data_lock);
+#endif /* debugfs */
+
+exit:
 	queue_work(ar->workqueue, &ar->restart_work);
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index 9401292..f72a7cd 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -23,9 +23,6 @@
 #include "hw.h"
 #include "ce.h"
 
-/* FW dump area */
-#define REG_DUMP_COUNT_QCA988X 60
-
 /*
  * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite
  */
-- 
1.7.11.7



From michal.kazior at tieto.com  Wed Jul 23 01:25:16 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 23 Jul 2014 10:25:16 +0200
Subject: [PATCH v3 1/5] ath10k: provide firmware crash info via debugfs.
In-Reply-To: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
References: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
Message-ID: <CA+BoTQnngYO_AzqQnxFpWQrez-q7Z=hBUNOt+H8FybE9+fq5fA@mail.gmail.com>

On 23 July 2014 01:02,  <greearb at candelatech.com> wrote:
> From: Ben Greear <greearb at candelatech.com>
>
> Store the firmware crash registers and last 128 or so
> firmware debug-log ids and present them to user-space
> via debugfs.
>
> Should help with figuring out why the firmware crashed.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>
[...]
> +struct ath10k_dump_file_data {
> +       /* Dump file information */
> +       char df_magic[16]; /* ATH10K-FW-DUMP */
> +       u32 len;
> +       u32 big_endian; /* 0x1 if host is big-endian */
> +       u32 version; /* File dump version, 1 for now. */
> +
> +       /* Some info we can get from ath10k struct that might help. */
> +       u32 chip_id;
> +       u32 bus_type; /* 0 for now, in place for later hardware */
> +       u32 target_version;
> +       u32 fw_version_major;
> +       u32 fw_version_minor;
> +       u32 fw_version_release;
> +       u32 fw_version_build;
> +       u32 phy_capability;
> +       u32 hw_min_tx_power;
> +       u32 hw_max_tx_power;
> +       u32 ht_cap_info;
> +       u32 vht_cap_info;
> +       u32 num_rf_chains;
> +       char fw_ver[ETHTOOL_FWVERS_LEN]; /* Firmware version string */
> +
> +       /* Kernel related information */
> +       u32 tv_sec_hi; /* time-of-day stamp, high 32-bits for seconds */
> +       u32 tv_sec_lo; /* time-of-day stamp, low 32-bits for seconds */
> +       u32 tv_nsec_hi; /* time-of-day stamp, nano-seconds, high bits */
> +       u32 tv_nsec_lo; /* time-of-day stamp, nano-seconds, low bits */
> +       u32 kernel_ver_code; /* LINUX_VERSION_CODE */
> +       char kernel_ver[64]; /* VERMAGIC_STRING */
> +
> +       u8 unused[128]; /* Room for growth w/out changing binary format */
> +
> +       u8 data[0]; /* struct ath10k_tlv_dump_data + more */
> +} __packed;

I think it would be a lot better if this format had a fixed endianess
(__le/__be instead of u32). But see below.


> +static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
[...]
> +       getnstimeofday(&timestamp);
> +       dump_data->tv_sec_hi = timestamp.tv_sec >> 32;
> +       dump_data->tv_sec_lo = timestamp.tv_sec;
> +       dump_data->tv_nsec_hi = timestamp.tv_nsec >> 32;
> +       dump_data->tv_nsec_lo = timestamp.tv_nsec;
> +
> +       spin_lock_irqsave(&ar->data_lock, flags);

You can't just use _irqsave with data_lock like that. You have to
convert *all* data_lock usages from _bh to _irqsave.

Is it really necessary to use the _irqsave here anyway? We can
probably make sure dump function is never called directly from an
interrupt. I think that's already the case anyway.


> +/* Target debug log related defines and structs */
> +
> +/* Target is 32-bit CPU, so we just use u32 for
> + * the pointers.  The memory space is relative to the
> + * target, not the host.
> + */
> +struct ath10k_fw_dbglog_buf {
> +       u32 next; /* pointer to dblog_buf_s. */
> +       u32 buffer; /* pointer to u8 buffer */
> +       u32 bufsize;
> +       u32 length;
> +       u32 count;
> +       u32 free;
> +} __packed;
> +
> +struct ath10k_fw_dbglog_hdr {
> +       u32 dbuf; /* pointer to dbglog_buf_s */
> +       u32 dropped;
> +} __packed;

These structures are target device specific, right? Since the target
is little-endian I'd think these structures should be defined as such
(i.e. __le32 instead of u32).

But then ath10k_pci_diag_read/write_mem() do byte-swapping
automatically (hint: they shouldn't, but since it's my fault I guess I
should be the one to fix it up.. :).

This would also explain why you defined a big_endian bool in the dump
structure instead of using __be/__le and explicit conversion. It's all
good until you start dumping RAM and try to deal with non-word data
(e.g. mac addresses).


Micha?


From egrumbach at gmail.com  Wed Jul 23 01:34:52 2014
From: egrumbach at gmail.com (Emmanuel Grumbach)
Date: Wed, 23 Jul 2014 11:34:52 +0300
Subject: [PATCH v3 1/5] ath10k: provide firmware crash info via debugfs.
In-Reply-To: <CA+BoTQnngYO_AzqQnxFpWQrez-q7Z=hBUNOt+H8FybE9+fq5fA@mail.gmail.com>
References: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQnngYO_AzqQnxFpWQrez-q7Z=hBUNOt+H8FybE9+fq5fA@mail.gmail.com>
Message-ID: <CANUX_P3BaQU6Xx+U2Ujwin6JSvsnf-jdB3Hi7vA1sXJDrvmm-Q@mail.gmail.com>

On Wed, Jul 23, 2014 at 11:25 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
> On 23 July 2014 01:02,  <greearb at candelatech.com> wrote:
>> From: Ben Greear <greearb at candelatech.com>
>>
>> Store the firmware crash registers and last 128 or so
>> firmware debug-log ids and present them to user-space
>> via debugfs.
>>
>> Should help with figuring out why the firmware crashed.
>>

Do we plan to have a common place for all the drivers?
I'd suggest to have mac80211 / cfg80211 link to a file created by the
driver. This would allow us to have this file even if we haven't
registered to mac80211 yet - although it'd be under a different place.
What do you think?


From michal.kazior at tieto.com  Wed Jul 23 02:50:02 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 23 Jul 2014 11:50:02 +0200
Subject: [PATCH v3] ath10k: fix Rx aggregation reordering
In-Reply-To: <87r41dtf2u.fsf@kamboji.qca.qualcomm.com>
References: <1405505855-13741-1-git-send-email-michal.kazior@tieto.com>
 <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
 <87r41dtf2u.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQng1xwLEbwfQ6P-T=VWYby529jFZ=duTH6hC=HzMW9Y=w@mail.gmail.com>

On 22 July 2014 20:37, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> (dropping linux-wireless)
>
> Michal Kazior <michal.kazior at tieto.com> writes:
>
>> Firmware doesn't perform Rx reordering so it is
>> left to the host driver to do that.
>>
>> Use mac80211 to perform reordering instead of
>> re-inventing the wheel.
>>
>> This fixes TCP throughput issues in some
>> environments.
>>
>> Reported-by: Denton Gentry <denton.gentry at gmail.com>
>> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
>> ---
>> This depends on:
>>
>>  * mac80211: fix Rx reordering with RX_FLAG_AMSDU_MORE
>>  * mac80211: add support for Rx reordering offloading
>>
>> I'm still seeing some issues with TCP traffic.
>> Apparently firmware/hardware sometimes stalls Rx
>> for ~100ms and misses some aggregate frames. I
>> wasn't able to pinpoint what the problem is. The
>> more parallel TCP streams (iperf) the more often
>> stalls happen. UDP doesn't seem to trigger the Rx
>> stalls at all.
>
> The mac80211 patches are in mac80211-next, but I can only apply this one
> only once they are in wireless-next.
>
> Also the other thing is that 3.17 merge window is very close. I might be
> able to squeeze this in but there's the risk that this patch hasn't
> received enough testing from being in ath.git. How safe (or risky) is
> this patch? If we push this to 3.17, we could try to fix regressions in
> -rc releases but that's always more difficult than waiting for 3.18.

I think it should be fairly safe. The stalls I've observed don't make
it worse than it is without Rx reordering.

But! I need to re-spin this patch since there's an endianess bug with
info0 being treated as __le32 while its __le16.


Micha?


From michal.kazior at tieto.com  Wed Jul 23 02:58:09 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 23 Jul 2014 11:58:09 +0200
Subject: [PATCH] ath10k: don't advertise IBSS iftype for 10.x
Message-ID: <1406109489-17928-1-git-send-email-michal.kazior@tieto.com>

The 10.x firmware does not support IBSS mode at
all. It can't beacon and it crashes when trying to
scan.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 3f9afaa..5122d1b 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4700,7 +4700,6 @@ int ath10k_mac_register(struct ath10k *ar)
 
 	ar->hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC) |
 		BIT(NL80211_IFTYPE_AP);
 
 	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
@@ -4770,6 +4769,8 @@ int ath10k_mac_register(struct ath10k *ar)
 		ar->hw->wiphy->iface_combinations = ath10k_if_comb;
 		ar->hw->wiphy->n_iface_combinations =
 			ARRAY_SIZE(ath10k_if_comb);
+
+		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
 	}
 
 	ar->hw->netdev_features = NETIF_F_HW_CSUM;
-- 
1.8.5.3



From michal.kazior at tieto.com  Wed Jul 23 03:20:33 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 23 Jul 2014 12:20:33 +0200
Subject: [PATCH v4] ath10k: fix Rx aggregation reordering
In-Reply-To: <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
References: <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1406110833-14031-1-git-send-email-michal.kazior@tieto.com>

Firmware doesn't perform Rx reordering so it is
left to the host driver to do that.

Use mac80211 to perform reordering instead of
re-inventing the wheel.

This fixes TCP throughput issues in some
environments.

Reported-by: Denton Gentry <denton.gentry at gmail.com>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
This depends on:

 * mac80211: fix Rx reordering with RX_FLAG_AMSDU_MORE
 * mac80211: add support for Rx reordering offloading

I'm still seeing some issues with TCP traffic.
Apparently firmware/hardware sometimes stalls Rx
for ~100ms and misses some aggregate frames. I
wasn't able to pinpoint what the problem is. The
more parallel TCP streams (iperf) the more often
stalls happen. UDP doesn't seem to trigger the Rx
stalls at all.


Notes:
    v4:
     * return immediatelly instead break [Varka]
     * fix endianess conversion (__le32 -> __le16)
     * use rx_delba in delba callback
    
    v3:
     * make ath10k_ampdu_action() static
    
    v2:
     * split addba/delba handling into separate functions [Kalle]
     * extend ampdu_action debug print (+vdev_id, +sta addr, +tid)

 drivers/net/wireless/ath/ath10k/htt_rx.c | 92 +++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/mac.c    | 33 ++++++++++++
 drivers/net/wireless/ath/ath10k/txrx.c   |  3 +-
 drivers/net/wireless/ath/ath10k/txrx.h   |  1 +
 4 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 318efc3..77cdc21 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -21,6 +21,7 @@
 #include "txrx.h"
 #include "debug.h"
 #include "trace.h"
+#include "mac.h"
 
 #include <linux/log2.h>
 
@@ -1422,6 +1423,86 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
 	}
 }
 
+static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
+{
+	struct htt_rx_addba *ev = &resp->rx_addba;
+	struct ath10k_peer *peer;
+	struct ath10k_vif *arvif;
+	u16 info0, tid, peer_id;
+
+	info0 = __le16_to_cpu(ev->info0);
+	tid = MS(info0, HTT_RX_BA_INFO0_TID);
+	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx addba tid %hu peer_id %hu size %hhu\n",
+		   tid, peer_id, ev->window_size);
+
+	spin_lock_bh(&ar->data_lock);
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer) {
+		ath10k_warn("received addba event for invalid peer_id: %hu\n",
+			    peer_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	arvif = ath10k_get_arvif(ar, peer->vdev_id);
+	if (!arvif) {
+		ath10k_warn("received addba event for invalid vdev_id: %u\n",
+			    peer->vdev_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx start rx ba session sta %pM tid %hu size %hhu\n",
+		   peer->addr, tid, ev->window_size);
+
+	ieee80211_start_rx_ba_session_offl(arvif->vif, peer->addr, tid);
+	spin_unlock_bh(&ar->data_lock);
+}
+
+static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
+{
+	struct htt_rx_delba *ev = &resp->rx_delba;
+	struct ath10k_peer *peer;
+	struct ath10k_vif *arvif;
+	u16 info0, tid, peer_id;
+
+	info0 = __le16_to_cpu(ev->info0);
+	tid = MS(info0, HTT_RX_BA_INFO0_TID);
+	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx delba tid %hu peer_id %hu\n",
+		   tid, peer_id);
+
+	spin_lock_bh(&ar->data_lock);
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer) {
+		ath10k_warn("received addba event for invalid peer_id: %hu\n",
+			    peer_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	arvif = ath10k_get_arvif(ar, peer->vdev_id);
+	if (!arvif) {
+		ath10k_warn("received addba event for invalid vdev_id: %u\n",
+			    peer->vdev_id);
+		spin_unlock_bh(&ar->data_lock);
+		return;
+	}
+
+	ath10k_dbg(ATH10K_DBG_HTT,
+		   "htt rx stop rx ba session sta %pM tid %hu\n",
+		   peer->addr, tid);
+
+	ieee80211_stop_rx_ba_session_offl(arvif->vif, peer->addr, tid);
+	spin_unlock_bh(&ar->data_lock);
+}
+
 void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct ath10k_htt *htt = &ar->htt;
@@ -1524,8 +1605,17 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 		ath10k_warn("received an unexpected htt tx inspect event\n");
 		break;
 	case HTT_T2H_MSG_TYPE_RX_ADDBA:
+		ath10k_htt_rx_addba(ar, resp);
+		break;
 	case HTT_T2H_MSG_TYPE_RX_DELBA:
-	case HTT_T2H_MSG_TYPE_RX_FLUSH:
+		ath10k_htt_rx_delba(ar, resp);
+		break;
+	case HTT_T2H_MSG_TYPE_RX_FLUSH: {
+		/* Ignore this event because mac80211 takes care of Rx
+		 * aggregation reordering.
+		 */
+		break;
+	}
 	default:
 		ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n",
 			   resp->hdr.msg_type);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 3f9afaa..3baa229 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4333,6 +4333,38 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	return 0;
 }
 
+static int ath10k_ampdu_action(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       enum ieee80211_ampdu_mlme_action action,
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size)
+{
+	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+
+	ath10k_dbg(ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
+		   arvif->vdev_id, sta->addr, tid, action);
+
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+	case IEEE80211_AMPDU_RX_STOP:
+		/* HTT AddBa/DelBa events trigger mac80211 Rx BA session
+		 * creation/removal. Do we need to verify this?
+		 */
+		return 0;
+	case IEEE80211_AMPDU_TX_START:
+	case IEEE80211_AMPDU_TX_STOP_CONT:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		/* Firmware offloads Tx aggregation entirely so deny mac80211
+		 * Tx aggregation requests.
+		 */
+		return -EOPNOTSUPP;
+	}
+
+	return -EINVAL;
+}
+
 static const struct ieee80211_ops ath10k_ops = {
 	.tx				= ath10k_tx,
 	.start				= ath10k_start,
@@ -4360,6 +4392,7 @@ static const struct ieee80211_ops ath10k_ops = {
 	.set_bitrate_mask		= ath10k_set_bitrate_mask,
 	.sta_rc_update			= ath10k_sta_rc_update,
 	.get_tsf			= ath10k_get_tsf,
+	.ampdu_action			= ath10k_ampdu_action,
 #ifdef CONFIG_PM
 	.suspend			= ath10k_suspend,
 	.resume				= ath10k_resume,
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 82669a7..f4fa22d 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -119,8 +119,7 @@ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
 	return NULL;
 }
 
-static struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar,
-						  int peer_id)
+struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
 {
 	struct ath10k_peer *peer;
 
diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h
index aee3e20..a90e09f 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.h
+++ b/drivers/net/wireless/ath/ath10k/txrx.h
@@ -24,6 +24,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
 
 struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
 				     const u8 *addr);
+struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id);
 int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id,
 				 const u8 *addr);
 int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id,
-- 
1.8.5.3



From greearb at candelatech.com  Wed Jul 23 05:45:22 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 23 Jul 2014 05:45:22 -0700
Subject: [PATCH v3 1/5] ath10k: provide firmware crash info via debugfs.
In-Reply-To: <CA+BoTQnngYO_AzqQnxFpWQrez-q7Z=hBUNOt+H8FybE9+fq5fA@mail.gmail.com>
References: <1406070154-6614-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQnngYO_AzqQnxFpWQrez-q7Z=hBUNOt+H8FybE9+fq5fA@mail.gmail.com>
Message-ID: <53CFAE62.2050401@candelatech.com>



On 07/23/2014 01:25 AM, Michal Kazior wrote:
> On 23 July 2014 01:02,  <greearb at candelatech.com> wrote:
>> From: Ben Greear <greearb at candelatech.com>
>>
>> Store the firmware crash registers and last 128 or so
>> firmware debug-log ids and present them to user-space
>> via debugfs.
>>
>> Should help with figuring out why the firmware crashed.
>>
>> Signed-off-by: Ben Greear <greearb at candelatech.com>
> [...]
>> +struct ath10k_dump_file_data {
>> +       /* Dump file information */
>> +       char df_magic[16]; /* ATH10K-FW-DUMP */
>> +       u32 len;
>> +       u32 big_endian; /* 0x1 if host is big-endian */
>> +       u32 version; /* File dump version, 1 for now. */
>> +
>> +       /* Some info we can get from ath10k struct that might help. */
>> +       u32 chip_id;
>> +       u32 bus_type; /* 0 for now, in place for later hardware */
>> +       u32 target_version;
>> +       u32 fw_version_major;
>> +       u32 fw_version_minor;
>> +       u32 fw_version_release;
>> +       u32 fw_version_build;
>> +       u32 phy_capability;
>> +       u32 hw_min_tx_power;
>> +       u32 hw_max_tx_power;
>> +       u32 ht_cap_info;
>> +       u32 vht_cap_info;
>> +       u32 num_rf_chains;
>> +       char fw_ver[ETHTOOL_FWVERS_LEN]; /* Firmware version string */
>> +
>> +       /* Kernel related information */
>> +       u32 tv_sec_hi; /* time-of-day stamp, high 32-bits for seconds */
>> +       u32 tv_sec_lo; /* time-of-day stamp, low 32-bits for seconds */
>> +       u32 tv_nsec_hi; /* time-of-day stamp, nano-seconds, high bits */
>> +       u32 tv_nsec_lo; /* time-of-day stamp, nano-seconds, low bits */
>> +       u32 kernel_ver_code; /* LINUX_VERSION_CODE */
>> +       char kernel_ver[64]; /* VERMAGIC_STRING */
>> +
>> +       u8 unused[128]; /* Room for growth w/out changing binary format */
>> +
>> +       u8 data[0]; /* struct ath10k_tlv_dump_data + more */
>> +} __packed;
>
> I think it would be a lot better if this format had a fixed endianess
> (__le/__be instead of u32). But see below.
>
>
>> +static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
> [...]
>> +       getnstimeofday(&timestamp);
>> +       dump_data->tv_sec_hi = timestamp.tv_sec >> 32;
>> +       dump_data->tv_sec_lo = timestamp.tv_sec;
>> +       dump_data->tv_nsec_hi = timestamp.tv_nsec >> 32;
>> +       dump_data->tv_nsec_lo = timestamp.tv_nsec;
>> +
>> +       spin_lock_irqsave(&ar->data_lock, flags);
>
> You can't just use _irqsave with data_lock like that. You have to
> convert *all* data_lock usages from _bh to _irqsave.
>
> Is it really necessary to use the _irqsave here anyway? We can
> probably make sure dump function is never called directly from an
> interrupt. I think that's already the case anyway.

I can change to bh variant and make sure lockdep doesn't complain.

>> +/* Target debug log related defines and structs */
>> +
>> +/* Target is 32-bit CPU, so we just use u32 for
>> + * the pointers.  The memory space is relative to the
>> + * target, not the host.
>> + */
>> +struct ath10k_fw_dbglog_buf {
>> +       u32 next; /* pointer to dblog_buf_s. */
>> +       u32 buffer; /* pointer to u8 buffer */
>> +       u32 bufsize;
>> +       u32 length;
>> +       u32 count;
>> +       u32 free;
>> +} __packed;
>> +
>> +struct ath10k_fw_dbglog_hdr {
>> +       u32 dbuf; /* pointer to dbglog_buf_s */
>> +       u32 dropped;
>> +} __packed;
>
> These structures are target device specific, right? Since the target
> is little-endian I'd think these structures should be defined as such
> (i.e. __le32 instead of u32).
>
> But then ath10k_pci_diag_read/write_mem() do byte-swapping
> automatically (hint: they shouldn't, but since it's my fault I guess I
> should be the one to fix it up.. :).
>
> This would also explain why you defined a big_endian bool in the dump
> structure instead of using __be/__le and explicit conversion. It's all
> good until you start dumping RAM and try to deal with non-word data
> (e.g. mac addresses).

This can all be handled in the decode tool, so I'd like to just keep the
kernel bit as is.

Thanks,
Ben


-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


From sw at simonwunderlich.de  Wed Jul 23 08:12:43 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Wed, 23 Jul 2014 17:12:43 +0200
Subject: [PATCHv2 2/2] ath10k: add spectral scan feature
In-Reply-To: <87zjg1tfjd.fsf@kamboji.qca.qualcomm.com>
References: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
 <1405945943-8303-3-git-send-email-sw@simonwunderlich.de>
 <87zjg1tfjd.fsf@kamboji.qca.qualcomm.com>
Message-ID: <201407231712.43500.sw@simonwunderlich.de>

Hey Kalle,

thanks for all the comments!

I'll make the changes as you suggested, although I'd like to point out that 
the "empty line before comment" and the "no indentation for WMI command 
parameters" things are not really consistent - there are also empty lines 
missing (e.g. struct wmi_start_scan_cmd) and indentation present (e.g. 
ath10k_wmi_peer_assoc and many others). Maybe that should be cleaned up at 
some point if you think that's important. :)

> > +struct fft_sample_ath10k {
> > +	struct fft_sample_tlv tlv;
> > +	u8 chan_width_mhz;
> > +	__be16 freq1;
> > +	__be16 freq2;
> > +	__be16 noise;
> > +	__be16 max_magnitude;
> > +	__be16 total_gain_db;
> > +	__be16 base_pwr_db;
> > +	__be64 tsf;
> > +	s8 max_index;
> > +	u8 rssi;
> > +	u8 relpwr_db;
> > +	u8 avgpwr_db;
> > +	u8 max_exp;
> > +
> > +	u8 data[0];
> > +} __packed;
> 
> __be16, that's a first. Just making sure that this really is big endian?

As the __le32 you use in other ath10k structs, this is just for checking - at 
least sparse should check that, maybe other tools as well.

I'll send a new patchset with the suggestions of Michal, Chun-Yeow and you 
soon. :)

Thanks!
    Simon


From sw at simonwunderlich.de  Wed Jul 23 08:53:55 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Wed, 23 Jul 2014 17:53:55 +0200
Subject: [PATCHv3 0/2] ath10k spectral scan support
Message-ID: <1406130837-10353-1-git-send-email-sw@simonwunderlich.de>

This is the third "PATCH" patchset iteration for the ath10k spectral
scan feature. It includes quite a few style fixes, the compile issues
were fixed when debugfs were disabled, and sending WMI commands after
a firmware crash should not happen any more. Thanks to Michal, Chun-Yeow
and Kalle for reviewing!

To view the samples, please have a look at the fft_eval tool [1] which
now supports both ath9k and ath10k formats.

The count issue is still open: Even when a count is specified, the
hardware seems to send endless samples. It seems to work most of the
time in VHT80 mode though, but in HT20 and HT40 the count value seems
to be ignored. To reproduce this, start hostapd with the desired
channel width and do:

echo 8 > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_count
echo manual > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
echo trigger > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 >> /tmp/fft.dump

Repeating the last line and checking the filesize will easily show
whether ath10k still sends samples or not. We would expect 8 samples in
this configuration.

Please see the patches for more information on the changes.

Cheers,
    Simon

[1] https://github.com/simonwunderlich/FFT_eval

Simon Wunderlich (1):
  ath10k: add spectral scan feature

Sven Eckelmann (1):
  ath: Move spectral debugfs structs to shared header

 drivers/net/wireless/ath/ath10k/Kconfig    |   1 +
 drivers/net/wireless/ath/ath10k/Makefile   |   1 +
 drivers/net/wireless/ath/ath10k/core.c     |   7 +-
 drivers/net/wireless/ath/ath10k/core.h     |  10 +
 drivers/net/wireless/ath/ath10k/debug.c    |   3 +
 drivers/net/wireless/ath/ath10k/mac.c      |   7 +
 drivers/net/wireless/ath/ath10k/spectral.c | 557 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |  82 +++++
 drivers/net/wireless/ath/ath10k/wmi.c      | 104 +++++-
 drivers/net/wireless/ath/ath10k/wmi.h      |  97 +++++
 drivers/net/wireless/ath/ath9k/spectral.h  |  71 +---
 drivers/net/wireless/ath/spectral_common.h | 113 ++++++
 12 files changed, 982 insertions(+), 71 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h
 create mode 100644 drivers/net/wireless/ath/spectral_common.h

-- 
1.9.1



From sw at simonwunderlich.de  Wed Jul 23 08:53:56 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Wed, 23 Jul 2014 17:53:56 +0200
Subject: [PATCHv3 1/2] ath: Move spectral debugfs structs to shared header
In-Reply-To: <1406130837-10353-1-git-send-email-sw@simonwunderlich.de>
References: <1406130837-10353-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <1406130837-10353-2-git-send-email-sw@simonwunderlich.de>

From: Sven Eckelmann <sven at narfation.org>

The ath9k and ath10k will share the definitions of the debugfs spectral
structures and enums. Having them in the same place helps to avoid conflicts.

Signed-off-by: Sven Eckelmann <sven at narfation.org>
Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
---
 drivers/net/wireless/ath/ath9k/spectral.h  | 71 +-----------------------
 drivers/net/wireless/ath/spectral_common.h | 88 ++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 69 deletions(-)
 create mode 100644 drivers/net/wireless/ath/spectral_common.h

diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h
index 137e2e6..0b9465e 100644
--- a/drivers/net/wireless/ath/ath9k/spectral.h
+++ b/drivers/net/wireless/ath/ath9k/spectral.h
@@ -17,6 +17,8 @@
 #ifndef SPECTRAL_H
 #define SPECTRAL_H
 
+#include "../spectral_common.h"
+
 /* enum spectral_mode:
  *
  * @SPECTRAL_DISABLED: spectral mode is disabled
@@ -54,8 +56,6 @@ struct ath_ht20_mag_info {
 	u8 max_exp;
 } __packed;
 
-#define SPECTRAL_HT20_NUM_BINS		56
-
 /* WARNING: don't actually use this struct! MAC may vary the amount of
  * data by -1/+2. This struct is for reference only.
  */
@@ -83,8 +83,6 @@ struct ath_ht20_40_mag_info {
 	u8 max_exp;
 } __packed;
 
-#define SPECTRAL_HT20_40_NUM_BINS		128
-
 /* WARNING: don't actually use this struct! MAC may vary the amount of
  * data. This struct is for reference only.
  */
@@ -125,71 +123,6 @@ static inline u8 spectral_bitmap_weight(u8 *bins)
 	return bins[0] & 0x3f;
 }
 
-/* FFT sample format given to userspace via debugfs.
- *
- * Please keep the type/length at the front position and change
- * other fields after adding another sample type
- *
- * TODO: this might need rework when switching to nl80211-based
- * interface.
- */
-enum ath_fft_sample_type {
-	ATH_FFT_SAMPLE_HT20 = 1,
-	ATH_FFT_SAMPLE_HT20_40,
-};
-
-struct fft_sample_tlv {
-	u8 type;	/* see ath_fft_sample */
-	__be16 length;
-	/* type dependent data follows */
-} __packed;
-
-struct fft_sample_ht20 {
-	struct fft_sample_tlv tlv;
-
-	u8 max_exp;
-
-	__be16 freq;
-	s8 rssi;
-	s8 noise;
-
-	__be16 max_magnitude;
-	u8 max_index;
-	u8 bitmap_weight;
-
-	__be64 tsf;
-
-	u8 data[SPECTRAL_HT20_NUM_BINS];
-} __packed;
-
-struct fft_sample_ht20_40 {
-	struct fft_sample_tlv tlv;
-
-	u8 channel_type;
-	__be16 freq;
-
-	s8 lower_rssi;
-	s8 upper_rssi;
-
-	__be64 tsf;
-
-	s8 lower_noise;
-	s8 upper_noise;
-
-	__be16 lower_max_magnitude;
-	__be16 upper_max_magnitude;
-
-	u8 lower_max_index;
-	u8 upper_max_index;
-
-	u8 lower_bitmap_weight;
-	u8 upper_bitmap_weight;
-
-	u8 max_exp;
-
-	u8 data[SPECTRAL_HT20_40_NUM_BINS];
-} __packed;
-
 void ath9k_spectral_init_debug(struct ath_softc *sc);
 void ath9k_spectral_deinit_debug(struct ath_softc *sc);
 
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
new file mode 100644
index 0000000..b9ab722
--- /dev/null
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_COMMON_H
+#define SPECTRAL_COMMON_H
+
+#define SPECTRAL_HT20_NUM_BINS		56
+#define SPECTRAL_HT20_40_NUM_BINS		128
+
+/* FFT sample format given to userspace via debugfs.
+ *
+ * Please keep the type/length at the front position and change
+ * other fields after adding another sample type
+ *
+ * TODO: this might need rework when switching to nl80211-based
+ * interface.
+ */
+enum ath_fft_sample_type {
+	ATH_FFT_SAMPLE_HT20 = 1,
+	ATH_FFT_SAMPLE_HT20_40,
+};
+
+struct fft_sample_tlv {
+	u8 type;	/* see ath_fft_sample */
+	__be16 length;
+	/* type dependent data follows */
+} __packed;
+
+struct fft_sample_ht20 {
+	struct fft_sample_tlv tlv;
+
+	u8 max_exp;
+
+	__be16 freq;
+	s8 rssi;
+	s8 noise;
+
+	__be16 max_magnitude;
+	u8 max_index;
+	u8 bitmap_weight;
+
+	__be64 tsf;
+
+	u8 data[SPECTRAL_HT20_NUM_BINS];
+} __packed;
+
+struct fft_sample_ht20_40 {
+	struct fft_sample_tlv tlv;
+
+	u8 channel_type;
+	__be16 freq;
+
+	s8 lower_rssi;
+	s8 upper_rssi;
+
+	__be64 tsf;
+
+	s8 lower_noise;
+	s8 upper_noise;
+
+	__be16 lower_max_magnitude;
+	__be16 upper_max_magnitude;
+
+	u8 lower_max_index;
+	u8 upper_max_index;
+
+	u8 lower_bitmap_weight;
+	u8 upper_bitmap_weight;
+
+	u8 max_exp;
+
+	u8 data[SPECTRAL_HT20_40_NUM_BINS];
+} __packed;
+
+#endif /* SPECTRAL_COMMON_H */
-- 
1.9.1



From sw at simonwunderlich.de  Wed Jul 23 08:53:57 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Wed, 23 Jul 2014 17:53:57 +0200
Subject: [PATCHv3 2/2] ath10k: add spectral scan feature
In-Reply-To: <1406130837-10353-1-git-send-email-sw@simonwunderlich.de>
References: <1406130837-10353-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <1406130837-10353-3-git-send-email-sw@simonwunderlich.de>

Adds the spectral scan feature for ath10k. The spectral scan is triggered by
configuring a mode through a debugfs control file. Samples can be gathered via
another relay debugfs file.

Essentially, to try it out:

ip link set dev wlan0 up
echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
echo trigger > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
iw dev wlan0 scan
echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples

This feature is still experimental. Based on the original RFC patch of
Sven Eckelmann.

Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
--
PATCHv3:
 * fix compilation with debugfs disabled (Thanks Kalle)
 * add trigger command to commit message (Thanks Chun-Yeow)
 * change error message capitalization (Thanks Michal)
 * don't send WMI on core halt (Thanks Michal)
 * various style changes: indetation, empty lines before comments, moved
   initialization into separate function, create substruct for spectral
   parameters (Thanks Kalle)

PATCHv2:
 * fixed usage example in commit message (Thanks Chun-Yeow Yeoh)
 * adding lockdep asserts and comment (Thanks Michal)
 * debug message cleanups (Michal)
 * disable spectral on firmware crash (Michal)

PATCH:
 * change the tlv format to a variable-length format, depending on the
   number of bins
 * perform dc interpolation and max_exp calculation in the driver (as
   for ath9k)
 * make fft_size configurable
 * background scan will only start after beeing trigger, like in ath9k
 * document at least some spectral configuration members (thanks Kathy)
 * fix sparse problems
 * sample bandwidth appears to be 110% of what is reported by the
   hardware according to the plotter (e.g. 20->22, 40->44 MHz etc),
   so fix that in the driver.
 * disable spectral for a vif when it's beeing deleted and still active
   (Michals comment)
 * modify ath_ prefix of function/struct/enum to ath10k_ (Michal)
 * changed variable ret to res (Michal)
 * added ath10k_warn messages (Michal)
 * renamed wmi functions (Michal)
 * use ar->conf_mutex for locking (Michal)
 * renamed mhz to chan_width_mhz (Michal)
 * only enable spectral scan files when ATH10K_DEBUGFS is enabled
---
 drivers/net/wireless/ath/ath10k/Kconfig    |   1 +
 drivers/net/wireless/ath/ath10k/Makefile   |   1 +
 drivers/net/wireless/ath/ath10k/core.c     |   7 +-
 drivers/net/wireless/ath/ath10k/core.h     |  10 +
 drivers/net/wireless/ath/ath10k/debug.c    |   3 +
 drivers/net/wireless/ath/ath10k/mac.c      |   7 +
 drivers/net/wireless/ath/ath10k/spectral.c | 557 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |  82 +++++
 drivers/net/wireless/ath/ath10k/wmi.c      | 104 +++++-
 drivers/net/wireless/ath/ath10k/wmi.h      |  97 +++++
 drivers/net/wireless/ath/spectral_common.h |  25 ++
 11 files changed, 892 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h

diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index 489bf8b..095dcaf 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -27,6 +27,7 @@ config ATH10K_DEBUG
 config ATH10K_DEBUGFS
 	bool "Atheros ath10k debugfs support"
 	depends on ATH10K
+	select RELAY
 	---help---
 	  Enabled debugfs support
 
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index 2110a5c..9c12cc6 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -10,6 +10,7 @@ ath10k_core-y += mac.o \
 		 wmi.o \
 		 bmi.o
 
+ath10k_core-$(CPTCFG_ATH10K_DEBUGFS) += spectral.o
 ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
 
 obj-$(CPTCFG_ATH10K_PCI) += ath10k_pci.o
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index ebc5fc2..9022e5b 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -728,6 +728,12 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 
 	INIT_WORK(&ar->restart_work, ath10k_core_restart);
 
+	INIT_LIST_HEAD(&ar->arvifs);
+
+	mutex_lock(&ar->conf_mutex);
+	ath10k_spectral_init(ar);
+	mutex_unlock(&ar->conf_mutex);
+
 	return ar;
 
 err_wq:
@@ -832,7 +838,6 @@ int ath10k_core_start(struct ath10k *ar)
 		goto err_disconnect_htc;
 
 	ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
-	INIT_LIST_HEAD(&ar->arvifs);
 
 	if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
 		ath10k_info("%s (0x%x) fw %s api %d htt %d.%d\n",
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 80aa5a4..93a17ba 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -31,6 +31,7 @@
 #include "../ath.h"
 #include "../regd.h"
 #include "../dfs_pattern_detector.h"
+#include "spectral.h"
 
 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -230,6 +231,7 @@ struct ath10k_vif {
 
 	bool is_started;
 	bool is_up;
+	bool spectral_enabled;
 	u32 aid;
 	u8 bssid[ETH_ALEN];
 
@@ -469,6 +471,14 @@ struct ath10k {
 #ifdef CPTCFG_ATH10K_DEBUGFS
 	struct ath10k_debug debug;
 #endif
+
+	struct {
+		/* relay(fs) channel for spectral scan */
+		struct rchan *rfs_chan_spec_scan;
+		/* spectral_mode and spec_config are protected by conf_mutex */
+		enum ath10k_spectral_mode mode;
+		struct ath10k_spec_scan config;
+	} spectral;
 };
 
 struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index f56f358..f8f4f6f 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -853,12 +853,15 @@ int ath10k_debug_create(struct ath10k *ar)
 				    &fops_dfs_stats);
 	}
 
+	ath10k_spectral_init_debug(ar);
+
 	return 0;
 }
 
 void ath10k_debug_destroy(struct ath10k *ar)
 {
 	cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
+	ath10k_spectral_deinit_debug(ar);
 }
 
 #endif /* CPTCFG_ATH10K_DEBUGFS */
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 348a639..591b7fa 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2201,6 +2201,7 @@ void ath10k_halt(struct ath10k *ar)
 	ath10k_peer_cleanup_all(ar);
 	ath10k_core_stop(ar);
 	ath10k_hif_power_down(ar);
+	ath10k_spectral_init(ar);
 
 	spin_lock_bh(&ar->data_lock);
 	if (ar->scan.in_progress) {
@@ -2671,8 +2672,14 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 		dev_kfree_skb_any(arvif->beacon);
 		arvif->beacon = NULL;
 	}
+
 	spin_unlock_bh(&ar->data_lock);
 
+	ret = ath10k_spectral_stop(arvif);
+	if (ret)
+		ath10k_warn("failed to disable spectral for vdev %i: %d\n",
+			    arvif->vdev_id, ret);
+
 	ar->free_vdev_map |= 1 << (arvif->vdev_id);
 	list_del(&arvif->list);
 
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
new file mode 100644
index 0000000..db836e0
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/relay.h>
+#include "core.h"
+#include "debug.h"
+
+static void
+ath10k_debug_send_fft_sample(struct ath10k *ar,
+			     const struct fft_sample_tlv *fft_sample_tlv)
+{
+	int length;
+
+	if (!ar->spectral.rfs_chan_spec_scan)
+		return;
+
+	length = __be16_to_cpu(fft_sample_tlv->length) +
+		 sizeof(*fft_sample_tlv);
+	relay_write(ar->spectral.rfs_chan_spec_scan, fft_sample_tlv, length);
+}
+
+static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
+			   u8 *data)
+{
+	int dc_pos;
+	u8 max_exp;
+
+	dc_pos = bin_len / 2;
+
+	/* peak index outside of bins */
+	if (dc_pos < max_index || -dc_pos >= max_index)
+		return 0;
+
+	for (max_exp = 0; max_exp < 8; max_exp++) {
+		if (data[dc_pos + max_index] == (max_magnitude >> max_exp))
+			break;
+	}
+
+	/* max_exp not found */
+	if (data[dc_pos + max_index] != (max_magnitude >> max_exp))
+		return 0;
+
+	return max_exp;
+}
+
+int ath10k_process_fft(struct ath10k *ar,
+		       struct wmi_single_phyerr_rx_event *event,
+		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
+{
+	struct fft_sample_ath10k *fft_sample;
+	u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
+	u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag;
+	u32 reg0, reg1, nf_list1, nf_list2;
+	u8 chain_idx, *bins;
+	int dc_pos;
+
+	fft_sample = (struct fft_sample_ath10k *)&buf;
+
+	if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
+		return -EINVAL;
+
+	reg0 = __le32_to_cpu(fftr->reg0);
+	reg1 = __le32_to_cpu(fftr->reg1);
+
+	length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + bin_len;
+	fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH10K;
+	fft_sample->tlv.length = __cpu_to_be16(length);
+
+	/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
+	 * but the results/plots suggest that its actually 22/44/88 MHz.
+	 */
+	switch (event->hdr.chan_width_mhz) {
+	case 20:
+		fft_sample->chan_width_mhz = 22;
+		break;
+	case 40:
+		fft_sample->chan_width_mhz = 44;
+		break;
+	case 80:
+		/* TODO: As experiments with an analogue sender and various
+		 * configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
+		 * show, the particular configuration of 80 MHz/64 bins does
+		 * not match with the other smaples at all. Until the reason
+		 * for that is found, don't report these samples.
+		 */
+		if (bin_len == 64)
+			return -EINVAL;
+		fft_sample->chan_width_mhz = 88;
+		break;
+	default:
+		fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
+	}
+
+	fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
+	fft_sample->avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
+
+	peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
+	fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
+	fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
+	fft_sample->rssi = event->hdr.rssi_combined;
+
+	total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
+	base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
+	fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
+	fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
+
+	freq1 = __le16_to_cpu(event->hdr.freq1);
+	freq2 = __le16_to_cpu(event->hdr.freq2);
+	fft_sample->freq1 = __cpu_to_be16(freq1);
+	fft_sample->freq2 = __cpu_to_be16(freq2);
+
+	nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
+	nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
+	chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
+
+	switch (chain_idx) {
+	case 0:
+		fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
+		break;
+	case 1:
+		fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
+		break;
+	case 2:
+		fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
+		break;
+	case 3:
+		fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
+		break;
+	}
+
+	bins = (u8 *)fftr;
+	bins += sizeof(*fftr);
+
+	fft_sample->tsf = __cpu_to_be64(tsf);
+
+	/* max_exp has been directly reported by previous hardware (ath9k),
+	 * maybe its possible to get it by other means?
+	 */
+	fft_sample->max_exp = get_max_exp(fft_sample->max_index, peak_mag,
+					  bin_len, bins);
+
+	memcpy(fft_sample->data, bins, bin_len);
+
+	/* DC value (value in the middle) is the blind spot of the spectral
+	 * sample and invalid, interpolate it.
+	 */
+	dc_pos = bin_len / 2;
+	fft_sample->data[dc_pos] = (fft_sample->data[dc_pos + 1] +
+				    fft_sample->data[dc_pos - 1]) / 2;
+
+	ath10k_debug_send_fft_sample(ar, &fft_sample->tlv);
+
+	return 0;
+}
+
+static struct ath10k_vif *ath10k_get_spectral_vdev(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	if (list_empty(&ar->arvifs))
+		return NULL;
+
+	/* if there already is a vif doing spectral, return that. */
+	list_for_each_entry(arvif, &ar->arvifs, list)
+		if (arvif->spectral_enabled)
+			return arvif;
+
+	/* otherwise, return the first vif. */
+	return list_first_entry(&ar->arvifs, typeof(*arvif), list);
+}
+
+static int ath10k_spectral_scan_trigger(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+	int res;
+	int vdev_id;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	arvif = ath10k_get_spectral_vdev(ar);
+	if (!arvif)
+		return -ENODEV;
+	vdev_id = arvif->vdev_id;
+
+	if (ar->spectral.mode == SPECTRAL_DISABLED)
+		return 0;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (res < 0)
+		return res;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
+					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (res < 0)
+		return res;
+
+	return 0;
+}
+
+static int ath10k_spectral_scan_config(struct ath10k *ar,
+				       enum ath10k_spectral_mode mode)
+{
+	struct wmi_vdev_spectral_conf_arg arg;
+	struct ath10k_vif *arvif;
+	int vdev_id, count, res = 0;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	arvif = ath10k_get_spectral_vdev(ar);
+	if (!arvif)
+		return -ENODEV;
+
+	vdev_id = arvif->vdev_id;
+
+	arvif->spectral_enabled = (mode != SPECTRAL_DISABLED);
+	ar->spectral.mode = mode;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					      WMI_SPECTRAL_ENABLE_CMD_DISABLE);
+	if (res < 0) {
+		ath10k_warn("failed to enable spectral scan: %d\n", res);
+		return res;
+	}
+
+	if (mode == SPECTRAL_DISABLED)
+		return 0;
+
+	if (mode == SPECTRAL_BACKGROUND)
+		count = WMI_SPECTRAL_COUNT_DEFAULT;
+	else
+		count = max_t(u8, 1, ar->spectral.config.count);
+
+	arg.vdev_id = vdev_id;
+	arg.scan_count = count;
+	arg.scan_period = WMI_SPECTRAL_PERIOD_DEFAULT;
+	arg.scan_priority = WMI_SPECTRAL_PRIORITY_DEFAULT;
+	arg.scan_fft_size = ar->spectral.config.fft_size;
+	arg.scan_gc_ena = WMI_SPECTRAL_GC_ENA_DEFAULT;
+	arg.scan_restart_ena = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
+	arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
+	arg.scan_init_delay = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
+	arg.scan_nb_tone_thr = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
+	arg.scan_str_bin_thr = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
+	arg.scan_wb_rpt_mode = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
+	arg.scan_rssi_rpt_mode = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
+	arg.scan_rssi_thr = WMI_SPECTRAL_RSSI_THR_DEFAULT;
+	arg.scan_pwr_format = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
+	arg.scan_rpt_mode = WMI_SPECTRAL_RPT_MODE_DEFAULT;
+	arg.scan_bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	arg.scan_dbm_adj = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
+	arg.scan_chn_mask = WMI_SPECTRAL_CHN_MASK_DEFAULT;
+
+	res = ath10k_wmi_vdev_spectral_conf(ar, &arg);
+	if (res < 0) {
+		ath10k_warn("failed to configure spectral scan: %d\n", res);
+		return res;
+	}
+
+	return 0;
+}
+
+void ath10k_spectral_init(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	ar->spectral.mode = SPECTRAL_DISABLED;
+	ar->spectral.config.count = WMI_SPECTRAL_COUNT_DEFAULT;
+	ar->spectral.config.fft_size = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
+
+	list_for_each_entry(arvif, &ar->arvifs, list)
+		arvif->spectral_enabled = 0;
+}
+
+int ath10k_spectral_stop(struct ath10k_vif *arvif)
+{
+	if (!arvif->spectral_enabled)
+		return 0;
+
+	return ath10k_spectral_scan_config(arvif->ar, SPECTRAL_DISABLED);
+}
+
+static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char *mode = "";
+	unsigned int len;
+	enum ath10k_spectral_mode spectral_mode;
+
+	mutex_lock(&ar->conf_mutex);
+	spectral_mode = ar->spectral.mode;
+	mutex_unlock(&ar->conf_mutex);
+
+	switch (spectral_mode) {
+	case SPECTRAL_DISABLED:
+		mode = "disable";
+		break;
+	case SPECTRAL_BACKGROUND:
+		mode = "background";
+		break;
+	case SPECTRAL_MANUAL:
+		mode = "manual";
+		break;
+	}
+
+	len = strlen(mode);
+	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
+}
+
+static ssize_t write_file_spec_scan_ctl(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	ssize_t len;
+	int res;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (strncmp("trigger", buf, 7) == 0) {
+		if (ar->spectral.mode == SPECTRAL_MANUAL ||
+		    ar->spectral.mode == SPECTRAL_BACKGROUND) {
+			/* reset the configuration to adopt possibly changed
+			 * debugfs parameters
+			 */
+			res = ath10k_spectral_scan_config(ar,
+							  ar->spectral.mode);
+			if (res < 0) {
+				ath10k_warn("failed to reconfigure spectral scan: %d\n",
+					    res);
+			}
+			res = ath10k_spectral_scan_trigger(ar);
+			if (res < 0) {
+				ath10k_warn("failed to trigger spectral scan: %d\n",
+					    res);
+			}
+		} else {
+			res = -EINVAL;
+		}
+	} else if (strncmp("background", buf, 9) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
+	} else if (strncmp("manual", buf, 6) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
+	} else if (strncmp("disable", buf, 7) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
+	} else {
+		res = -EINVAL;
+	}
+
+	mutex_unlock(&ar->conf_mutex);
+
+	if (res < 0)
+		return res;
+
+	return count;
+}
+
+static const struct file_operations fops_spec_scan_ctl = {
+	.read = read_file_spec_scan_ctl,
+	.write = write_file_spec_scan_ctl,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static ssize_t read_file_spectral_count(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len;
+	u8 spectral_count;
+
+	mutex_lock(&ar->conf_mutex);
+	spectral_count = ar->spectral.config.count;
+	mutex_unlock(&ar->conf_mutex);
+
+	len = sprintf(buf, "%d\n", spectral_count);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_count(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 0 || val > 255)
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+	ar->spectral.config.count = val;
+	mutex_unlock(&ar->conf_mutex);
+
+	return count;
+}
+
+static const struct file_operations fops_spectral_count = {
+	.read = read_file_spectral_count,
+	.write = write_file_spectral_count,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static ssize_t read_file_spectral_bins(struct file *file,
+				       char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len, bins, fft_size, bin_scale;
+
+	mutex_lock(&ar->conf_mutex);
+
+	fft_size = ar->spectral.config.fft_size;
+	bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	bins = 1 << (fft_size - bin_scale);
+
+	mutex_unlock(&ar->conf_mutex);
+
+	len = sprintf(buf, "%d\n", bins);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_bins(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
+		return -EINVAL;
+
+	if (!is_power_of_2(val))
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+	ar->spectral.config.fft_size = ilog2(val);
+	ar->spectral.config.fft_size += WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	mutex_unlock(&ar->conf_mutex);
+
+	return count;
+}
+
+static const struct file_operations fops_spectral_bins = {
+	.read = read_file_spectral_bins,
+	.write = write_file_spectral_bins,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static struct dentry *create_buf_file_handler(const char *filename,
+					      struct dentry *parent,
+					      umode_t mode,
+					      struct rchan_buf *buf,
+					      int *is_global)
+{
+	struct dentry *buf_file;
+
+	buf_file = debugfs_create_file(filename, mode, parent, buf,
+				       &relay_file_operations);
+	*is_global = 1;
+	return buf_file;
+}
+
+static int remove_buf_file_handler(struct dentry *dentry)
+{
+	debugfs_remove(dentry);
+
+	return 0;
+}
+
+static struct rchan_callbacks rfs_spec_scan_cb = {
+	.create_buf_file = create_buf_file_handler,
+	.remove_buf_file = remove_buf_file_handler,
+};
+
+void ath10k_spectral_deinit_debug(struct ath10k *ar)
+{
+	if (ar->spectral.rfs_chan_spec_scan) {
+		relay_close(ar->spectral.rfs_chan_spec_scan);
+		ar->spectral.rfs_chan_spec_scan = NULL;
+	}
+}
+
+void ath10k_spectral_init_debug(struct ath10k *ar)
+{
+	ar->spectral.rfs_chan_spec_scan = relay_open("spectral_scan",
+						     ar->debug.debugfs_phy,
+						     1024, 256,
+						     &rfs_spec_scan_cb, NULL);
+	debugfs_create_file("spectral_scan_ctl",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spec_scan_ctl);
+	debugfs_create_file("spectral_count",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_count);
+	debugfs_create_file("spectral_bins",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_bins);
+}
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
new file mode 100644
index 0000000..55c1689
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_H
+#define SPECTRAL_H
+
+#include "../spectral_common.h"
+
+/**
+ * struct ath10k_spec_scan - parameters for Atheros spectral scan
+ *
+ * @count: number of scan results requested for manual mode
+ * @fft_size: number of bins to be requested = 2^(fft_size - bin_scale)
+ */
+struct ath10k_spec_scan {
+	u8 count;
+	u8 fft_size;
+};
+
+/* enum ath10k_spectral_mode:
+ *
+ * @SPECTRAL_DISABLED: spectral mode is disabled
+ * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
+ *	something else.
+ * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
+ *	is performed manually.
+ */
+enum ath10k_spectral_mode {
+	SPECTRAL_DISABLED = 0,
+	SPECTRAL_BACKGROUND,
+	SPECTRAL_MANUAL,
+};
+
+#ifdef CPTCFG_ATH10K_DEBUGFS
+void ath10k_spectral_init_debug(struct ath10k *ar);
+void ath10k_spectral_deinit_debug(struct ath10k *ar);
+int ath10k_process_fft(struct ath10k *ar,
+		       struct wmi_single_phyerr_rx_event *event,
+		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf);
+void ath10k_spectral_init(struct ath10k *ar);
+int ath10k_spectral_stop(struct ath10k_vif *arvif);
+#else
+static inline void ath10k_spectral_init_debug(struct ath10k *ar)
+{
+}
+
+static inline void ath10k_spectral_deinit_debug(struct ath10k *ar)
+{
+}
+
+static inline int
+ath10k_process_fft(struct ath10k *ar,
+		   struct wmi_single_phyerr_rx_event *event,
+		   struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
+{
+	return 0;
+}
+
+static inline void ath10k_spectral_init(struct ath10k *ar)
+{
+}
+
+static inline int ath10k_spectral_stop(struct ath10k_vif *arvif)
+{
+	return 0;
+}
+#endif /* CPTCFG_ATH10K_DEBUGFS */
+
+#endif /* SPECTRAL_H */
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index beac30d..40467cd 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1649,7 +1649,53 @@ static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
 				struct wmi_single_phyerr_rx_event *event,
 				u64 tsf)
 {
-	ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n");
+	int buf_len, tlv_len, res, i = 0;
+	struct phyerr_tlv *tlv;
+	u8 *tlv_buf;
+	struct phyerr_fft_report *fftr;
+	size_t fftr_len;
+
+	buf_len = __le32_to_cpu(event->hdr.buf_len);
+
+	while (i < buf_len) {
+		if (i + sizeof(*tlv) > buf_len) {
+			ath10k_warn("failed to parse phyerr tlv header at byte %d\n",
+				    i);
+			return;
+		}
+
+		tlv = (struct phyerr_tlv *)&event->bufp[i];
+		tlv_len = __le16_to_cpu(tlv->len);
+		tlv_buf = &event->bufp[i + sizeof(*tlv)];
+
+		if (i + sizeof(*tlv) + tlv_len > buf_len) {
+			ath10k_warn("failed to parse phyerr tlv payload at byte %d\n",
+				    i);
+			return;
+		}
+
+		switch (tlv->tag) {
+		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
+			if (sizeof(*fftr) > tlv_len) {
+				ath10k_warn("failed to parse fft report at byte %d\n",
+					    i);
+				return;
+			}
+
+			fftr_len = tlv_len - sizeof(*fftr);
+			fftr = (struct phyerr_fft_report *)tlv_buf;
+			res = ath10k_process_fft(ar, event, fftr, fftr_len,
+						 tsf);
+			if (res < 0) {
+				ath10k_warn("failed to process fft report: %d\n",
+					    res);
+				return;
+			}
+			break;
+		}
+
+		i += sizeof(*tlv) + tlv_len;
+	}
 }
 
 static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
@@ -3191,6 +3237,62 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				   ar->wmi.cmd->vdev_install_key_cmdid);
 }
 
+int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
+				  const struct wmi_vdev_spectral_conf_arg *arg)
+{
+	struct wmi_vdev_spectral_conf_cmd *cmd;
+	struct sk_buff *skb;
+	u32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_conf_cmd *)skb->data;
+	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
+	cmd->scan_count = __cpu_to_le32(arg->scan_count);
+	cmd->scan_period = __cpu_to_le32(arg->scan_period);
+	cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
+	cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
+	cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
+	cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
+	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
+	cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
+	cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
+	cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
+	cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
+	cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
+	cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
+	cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
+	cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
+	cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
+	cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
+	cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_configure_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
+int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				    u32 enable)
+{
+	struct wmi_vdev_spectral_enable_cmd *cmd;
+	struct sk_buff *skb;
+	u32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_enable_cmd *)skb->data;
+	cmd->vdev_id = __cpu_to_le32(vdev_id);
+	cmd->trigger_cmd = __cpu_to_le32(trigger);
+	cmd->enable_cmd = __cpu_to_le32(enable);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_enable_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 			   const u8 peer_addr[ETH_ALEN])
 {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 4fcc96a..a1660a8 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2077,6 +2077,7 @@ struct wmi_comb_phyerr_rx_event {
 #define PHYERR_TLV_SIG				0xBB
 #define PHYERR_TLV_TAG_SEARCH_FFT_REPORT	0xFB
 #define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY	0xF8
+#define PHYERR_TLV_TAG_SPECTRAL_SUMMARY_REPORT	0xF9
 
 struct phyerr_radar_report {
 	__le32 reg0; /* RADAR_REPORT_REG0_* */
@@ -3381,6 +3382,98 @@ struct wmi_vdev_simple_event {
 /* unsupported VDEV combination */
 #define WMI_INIFIED_VDEV_START_RESPONSE_NOT_SUPPORTED	0x2
 
+/* TODO: please add more comments if you have in-depth information */
+struct wmi_vdev_spectral_conf_cmd {
+	__le32 vdev_id;
+
+	/* number of fft samples to send (0 for infinite) */
+	__le32 scan_count;
+	__le32 scan_period;
+	__le32 scan_priority;
+
+	/* number of bins in the FFT: 2^(fft_size - bin_scale) */
+	__le32 scan_fft_size;
+	__le32 scan_gc_ena;
+	__le32 scan_restart_ena;
+	__le32 scan_noise_floor_ref;
+	__le32 scan_init_delay;
+	__le32 scan_nb_tone_thr;
+	__le32 scan_str_bin_thr;
+	__le32 scan_wb_rpt_mode;
+	__le32 scan_rssi_rpt_mode;
+	__le32 scan_rssi_thr;
+	__le32 scan_pwr_format;
+
+	/* rpt_mode: Format of FFT report to software for spectral scan
+	 * triggered FFTs:
+	 *	0: No FFT report (only spectral scan summary report)
+	 *	1: 2-dword summary of metrics for each completed FFT + spectral
+	 *	   scan	summary report
+	 *	2: 2-dword summary of metrics for each completed FFT +
+	 *	   1x- oversampled bins(in-band) per FFT + spectral scan summary
+	 *	   report
+	 *	3: 2-dword summary of metrics for each completed FFT +
+	 *	   2x- oversampled bins	(all) per FFT + spectral scan summary
+	 */
+	__le32 scan_rpt_mode;
+	__le32 scan_bin_scale;
+	__le32 scan_dbm_adj;
+	__le32 scan_chn_mask;
+} __packed;
+
+struct wmi_vdev_spectral_conf_arg {
+	u32 vdev_id;
+	u32 scan_count;
+	u32 scan_period;
+	u32 scan_priority;
+	u32 scan_fft_size;
+	u32 scan_gc_ena;
+	u32 scan_restart_ena;
+	u32 scan_noise_floor_ref;
+	u32 scan_init_delay;
+	u32 scan_nb_tone_thr;
+	u32 scan_str_bin_thr;
+	u32 scan_wb_rpt_mode;
+	u32 scan_rssi_rpt_mode;
+	u32 scan_rssi_thr;
+	u32 scan_pwr_format;
+	u32 scan_rpt_mode;
+	u32 scan_bin_scale;
+	u32 scan_dbm_adj;
+	u32 scan_chn_mask;
+};
+
+#define WMI_SPECTRAL_ENABLE_DEFAULT              0
+#define WMI_SPECTRAL_COUNT_DEFAULT               0
+#define WMI_SPECTRAL_PERIOD_DEFAULT             35
+#define WMI_SPECTRAL_PRIORITY_DEFAULT            1
+#define WMI_SPECTRAL_FFT_SIZE_DEFAULT            7
+#define WMI_SPECTRAL_GC_ENA_DEFAULT              1
+#define WMI_SPECTRAL_RESTART_ENA_DEFAULT         0
+#define WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT   -96
+#define WMI_SPECTRAL_INIT_DELAY_DEFAULT         80
+#define WMI_SPECTRAL_NB_TONE_THR_DEFAULT        12
+#define WMI_SPECTRAL_STR_BIN_THR_DEFAULT         8
+#define WMI_SPECTRAL_WB_RPT_MODE_DEFAULT         0
+#define WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT       0
+#define WMI_SPECTRAL_RSSI_THR_DEFAULT         0xf0
+#define WMI_SPECTRAL_PWR_FORMAT_DEFAULT          0
+#define WMI_SPECTRAL_RPT_MODE_DEFAULT            2
+#define WMI_SPECTRAL_BIN_SCALE_DEFAULT           1
+#define WMI_SPECTRAL_DBM_ADJ_DEFAULT             1
+#define WMI_SPECTRAL_CHN_MASK_DEFAULT            1
+
+struct wmi_vdev_spectral_enable_cmd {
+	__le32 vdev_id;
+	__le32 trigger_cmd;
+	__le32 enable_cmd;
+} __packed;
+
+#define WMI_SPECTRAL_TRIGGER_CMD_TRIGGER  1
+#define WMI_SPECTRAL_TRIGGER_CMD_CLEAR    2
+#define WMI_SPECTRAL_ENABLE_CMD_ENABLE    1
+#define WMI_SPECTRAL_ENABLE_CMD_DISABLE   2
+
 /* Beacon processing related command and event structures */
 struct wmi_bcn_tx_hdr {
 	__le32 vdev_id;
@@ -4226,6 +4319,10 @@ int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id,
 			      u32 param_id, u32 param_value);
 int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				const struct wmi_vdev_install_key_arg *arg);
+int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
+				  const struct wmi_vdev_spectral_conf_arg *arg);
+int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				    u32 enable);
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 		    const u8 peer_addr[ETH_ALEN]);
 int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
index b9ab722..0d742ac 100644
--- a/drivers/net/wireless/ath/spectral_common.h
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -20,6 +20,11 @@
 #define SPECTRAL_HT20_NUM_BINS		56
 #define SPECTRAL_HT20_40_NUM_BINS		128
 
+/* TODO: could possibly be 512, but no samples this large
+ * could be acquired so far.
+ */
+#define SPECTRAL_ATH10K_MAX_NUM_BINS		256
+
 /* FFT sample format given to userspace via debugfs.
  *
  * Please keep the type/length at the front position and change
@@ -31,6 +36,7 @@
 enum ath_fft_sample_type {
 	ATH_FFT_SAMPLE_HT20 = 1,
 	ATH_FFT_SAMPLE_HT20_40,
+	ATH_FFT_SAMPLE_ATH10K,
 };
 
 struct fft_sample_tlv {
@@ -85,4 +91,23 @@ struct fft_sample_ht20_40 {
 	u8 data[SPECTRAL_HT20_40_NUM_BINS];
 } __packed;
 
+struct fft_sample_ath10k {
+	struct fft_sample_tlv tlv;
+	u8 chan_width_mhz;
+	__be16 freq1;
+	__be16 freq2;
+	__be16 noise;
+	__be16 max_magnitude;
+	__be16 total_gain_db;
+	__be16 base_pwr_db;
+	__be64 tsf;
+	s8 max_index;
+	u8 rssi;
+	u8 relpwr_db;
+	u8 avgpwr_db;
+	u8 max_exp;
+
+	u8 data[0];
+} __packed;
+
 #endif /* SPECTRAL_COMMON_H */
-- 
1.9.1



From kvalo at qca.qualcomm.com  Wed Jul 23 09:20:46 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 23 Jul 2014 19:20:46 +0300
Subject: [PATCH v3] ath10k: fix Rx aggregation reordering
In-Reply-To: <CA+BoTQng1xwLEbwfQ6P-T=VWYby529jFZ=duTH6hC=HzMW9Y=w@mail.gmail.com>
 (Michal Kazior's message of "Wed, 23 Jul 2014 11:50:02 +0200")
References: <1405505855-13741-1-git-send-email-michal.kazior@tieto.com>
 <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
 <87r41dtf2u.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQng1xwLEbwfQ6P-T=VWYby529jFZ=duTH6hC=HzMW9Y=w@mail.gmail.com>
Message-ID: <87fvhst5b5.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

>> The mac80211 patches are in mac80211-next, but I can only apply this one
>> only once they are in wireless-next.
>>
>> Also the other thing is that 3.17 merge window is very close. I might be
>> able to squeeze this in but there's the risk that this patch hasn't
>> received enough testing from being in ath.git. How safe (or risky) is
>> this patch? If we push this to 3.17, we could try to fix regressions in
>> -rc releases but that's always more difficult than waiting for 3.18.
>
> I think it should be fairly safe. The stalls I've observed don't make
> it worse than it is without Rx reordering.
>
> But! I need to re-spin this patch since there's an endianess bug with
> info0 being treated as __le32 while its __le16.

Ok, let's try to get the new version of this patch to 3.17, if at all
possible. But if there are any regressions, please let me know ASAP so
that we can quickly fix it and push the fix to -rc releases.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Jul 23 09:34:33 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 23 Jul 2014 19:34:33 +0300
Subject: [PATCHv2 2/2] ath10k: add spectral scan feature
In-Reply-To: <201407231712.43500.sw@simonwunderlich.de> (Simon Wunderlich's
 message of "Wed, 23 Jul 2014 17:12:43 +0200")
References: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
 <1405945943-8303-3-git-send-email-sw@simonwunderlich.de>
 <87zjg1tfjd.fsf@kamboji.qca.qualcomm.com>
 <201407231712.43500.sw@simonwunderlich.de>
Message-ID: <8738dst4o6.fsf@kamboji.qca.qualcomm.com>

Simon Wunderlich <sw at simonwunderlich.de> writes:

> Hey Kalle,
>
> thanks for all the comments!
>
> I'll make the changes as you suggested, although I'd like to point out that 
> the "empty line before comment" and the "no indentation for WMI command 
> parameters" things are not really consistent - there are also empty lines 
> missing (e.g. struct wmi_start_scan_cmd) and indentation present (e.g. 
> ath10k_wmi_peer_assoc and many others). Maybe that should be cleaned up at 
> some point if you think that's important. :)

Yeah, I have been sloppy in reviewing those part before but not anymore
:) Also struct ath10k is quite a mess now. Sorry for the confusion.

I'm planning to fix these at some point, but if someone else wants to do
it I'm very happy to take patches.

>> > +struct fft_sample_ath10k {
>> > +	struct fft_sample_tlv tlv;
>> > +	u8 chan_width_mhz;
>> > +	__be16 freq1;
>> > +	__be16 freq2;
>> > +	__be16 noise;
>> > +	__be16 max_magnitude;
>> > +	__be16 total_gain_db;
>> > +	__be16 base_pwr_db;
>> > +	__be64 tsf;
>> > +	s8 max_index;
>> > +	u8 rssi;
>> > +	u8 relpwr_db;
>> > +	u8 avgpwr_db;
>> > +	u8 max_exp;
>> > +
>> > +	u8 data[0];
>> > +} __packed;
>> 
>> __be16, that's a first. Just making sure that this really is big endian?
>
> As the __le32 you use in other ath10k structs, this is just for checking - at 
> least sparse should check that, maybe other tools as well.

Sorry, I didn't understand your comment here. But basically I was asking
is the fft sample really in big endian? I assume it would be little
endian as everything else coming from the firmware.

-- 
Kalle Valo


From greearb at candelatech.com  Wed Jul 23 09:38:04 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Wed, 23 Jul 2014 09:38:04 -0700
Subject: [PATCH v4 2/5] ath10k:  save firmware debug log messages.
In-Reply-To: <1406133487-7541-1-git-send-email-greearb@candelatech.com>
References: <1406133487-7541-1-git-send-email-greearb@candelatech.com>
Message-ID: <1406133487-7541-2-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

They may be dumped through the firmware dump debugfs
file.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/wmi.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 6f83cae..df62115 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1089,6 +1089,12 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
 
 	trace_ath10k_wmi_dbglog(skb->data, skb->len);
 
+	/* First 4 bytes are a messages-dropped-due-to-overflow counter,
+	 * and should not be recorded in the dbglog buffer, so we skip
+	 * them.
+	 */
+	ath10k_dbg_save_fw_dbg_buffer(ar, skb->data + 4, skb->len - 4);
+
 	return 0;
 }
 
-- 
1.7.11.7



From greearb at candelatech.com  Wed Jul 23 09:38:06 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Wed, 23 Jul 2014 09:38:06 -0700
Subject: [PATCH v4 4/5] ath10k: Dump exception stack contents on firmware
 crash.
In-Reply-To: <1406133487-7541-1-git-send-email-greearb@candelatech.com>
References: <1406133487-7541-1-git-send-email-greearb@candelatech.com>
Message-ID: <1406133487-7541-4-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Firmware developers can decode this and maybe figure out
why the firmware crashed.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/core.h  |  3 +++
 drivers/net/wireless/ath/ath10k/debug.c |  8 ++++++++
 drivers/net/wireless/ath/ath10k/pci.c   | 13 +++++++++++--
 3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 2f200f6..f122eae 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -281,11 +281,13 @@ struct ath10k_vif_iter {
  * @ATH10K_FW_ERROR_DUMP_DBGLOG:  Recent firmware debug log entries
  * @ATH10K_FW_ERROR_DUMP_REGDUMP: Register crash dump in binary format
  * @ATH10K_FW_ERROR_DUMP_STACK:   Stack memory contents.
+ * @ATH10K_FW_ERROR_DUMP_EXC_STACK:  Exception stack contents
  */
 enum ath10k_fw_error_dump_type {
 	ATH10K_FW_ERROR_DUMP_DBGLOG = 0,
 	ATH10K_FW_ERROR_DUMP_REGDUMP = 1,
 	ATH10K_FW_ERROR_DUMP_STACK = 2,
+	ATH10K_FW_ERROR_DUMP_EXC_STACK = 3,
 
 	ATH10K_FW_ERROR_DUMP_MAX,
 };
@@ -367,6 +369,7 @@ struct ath10k_debug {
 	struct ath10k_dbglog_entry_storage dbglog_entry_data;
 	u32 reg_dump_values[REG_DUMP_COUNT_QCA988X];
 	unsigned char stack_buf[ATH10K_FW_STACK_SIZE];
+	unsigned char exc_stack_buf[ATH10K_FW_STACK_SIZE];
 };
 
 enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 6fec433..8995f0f 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -621,6 +621,7 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.reg_dump_values);
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.dbglog_entry_data);
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.stack_buf);
+	len += sizeof(*dump_tlv) + sizeof(ar->debug.exc_stack_buf);
 
 	lockdep_assert_held(&ar->conf_mutex);
 
@@ -694,6 +695,13 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	memcpy(dump_tlv->tlv_data, &ar->debug.stack_buf, dump_tlv->tlv_len);
 	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
 
+	/* Gather firmware exception (irq) stack dump */
+	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+	dump_tlv->type = ATH10K_FW_ERROR_DUMP_EXC_STACK;
+	dump_tlv->tlv_len = sizeof(ar->debug.exc_stack_buf);
+	memcpy(dump_tlv->tlv_data, &ar->debug.exc_stack_buf, dump_tlv->tlv_len);
+	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+
 	spin_unlock_bh(&ar->data_lock);
 
 	WARN_ON(sofar != len);
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index b58f1a1..d298e14 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -864,8 +864,15 @@ static void ath10k_save_firmware_stack(struct ath10k *ar)
 	ath10k_save_firmware_mem_helper(ar, ATH10K_FW_STACK_SIZE,
 					ar->debug.stack_buf, HI_ITEM(hi_stack));
 }
-#endif
 
+/* Save the firmware exception stack */
+static void ath10k_save_firmware_exc_stack(struct ath10k *ar)
+{
+	ath10k_save_firmware_mem_helper(ar, ATH10K_FW_STACK_SIZE,
+					ar->debug.exc_stack_buf,
+					HI_ITEM(hi_err_stack));
+}
+#endif
 
 static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 {
@@ -918,8 +925,10 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 #ifdef CONFIG_ATH10K_DEBUGFS
 	spin_lock_bh(&ar->data_lock);
 
-	if (!ar->debug.crashed_since_read)
+	if (!ar->debug.crashed_since_read) {
 		ath10k_save_firmware_stack(ar);
+		ath10k_save_firmware_exc_stack(ar);
+	}
 
 	spin_unlock_bh(&ar->data_lock);
 
-- 
1.7.11.7



From greearb at candelatech.com  Wed Jul 23 09:38:05 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Wed, 23 Jul 2014 09:38:05 -0700
Subject: [PATCH v4 3/5] ath10k:  save firmware stack upon firmware crash.
In-Reply-To: <1406133487-7541-1-git-send-email-greearb@candelatech.com>
References: <1406133487-7541-1-git-send-email-greearb@candelatech.com>
Message-ID: <1406133487-7541-3-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Should help debug firmware crashes, and give users a way
to provide some useful debug reports to firmware developers.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/core.h  |  3 +++
 drivers/net/wireless/ath/ath10k/debug.c |  9 ++++++++
 drivers/net/wireless/ath/ath10k/hw.h    |  1 +
 drivers/net/wireless/ath/ath10k/pci.c   | 41 +++++++++++++++++++++++++++++++++
 4 files changed, 54 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 5c0c5bf..2f200f6 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -280,10 +280,12 @@ struct ath10k_vif_iter {
  * enum ath10k_fw_error_dump_type - types of data in the dump file
  * @ATH10K_FW_ERROR_DUMP_DBGLOG:  Recent firmware debug log entries
  * @ATH10K_FW_ERROR_DUMP_REGDUMP: Register crash dump in binary format
+ * @ATH10K_FW_ERROR_DUMP_STACK:   Stack memory contents.
  */
 enum ath10k_fw_error_dump_type {
 	ATH10K_FW_ERROR_DUMP_DBGLOG = 0,
 	ATH10K_FW_ERROR_DUMP_REGDUMP = 1,
+	ATH10K_FW_ERROR_DUMP_STACK = 2,
 
 	ATH10K_FW_ERROR_DUMP_MAX,
 };
@@ -364,6 +366,7 @@ struct ath10k_debug {
 	bool crashed_since_read;
 	struct ath10k_dbglog_entry_storage dbglog_entry_data;
 	u32 reg_dump_values[REG_DUMP_COUNT_QCA988X];
+	unsigned char stack_buf[ATH10K_FW_STACK_SIZE];
 };
 
 enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index cc81a99..6fec433 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -620,6 +620,7 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	len = hdr_len;
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.reg_dump_values);
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.dbglog_entry_data);
+	len += sizeof(*dump_tlv) + sizeof(ar->debug.stack_buf);
 
 	lockdep_assert_held(&ar->conf_mutex);
 
@@ -686,8 +687,16 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	memcpy(dump_tlv->tlv_data, &ar->debug.reg_dump_values, dump_tlv->tlv_len);
 	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
 
+	/* Gather firmware stack dump */
+	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+	dump_tlv->type = ATH10K_FW_ERROR_DUMP_STACK;
+	dump_tlv->tlv_len = sizeof(ar->debug.stack_buf);
+	memcpy(dump_tlv->tlv_data, &ar->debug.stack_buf, dump_tlv->tlv_len);
+	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+
 	spin_unlock_bh(&ar->data_lock);
 
+	WARN_ON(sofar != len);
 	return dump_data;
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index d4df3f0..38a03e4 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -39,6 +39,7 @@
 #define ATH10K_FIRMWARE_MAGIC               "QCA-ATH10K"
 
 #define REG_DUMP_COUNT_QCA988X 60
+#define ATH10K_FW_STACK_SIZE 4096
 
 struct ath10k_fw_ie {
 	__le32 id;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 24ddc22..b58f1a1 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -833,6 +833,40 @@ static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
 	return ath10k_ce_num_free_src_entries(ar_pci->pipe_info[pipe].ce_hdl);
 }
 
+static void ath10k_save_firmware_mem_helper(struct ath10k *ar, u32 sz,
+					    unsigned char *to, u32 addr)
+{
+	u32 host_addr;
+	u32 reg_dump_area;
+	int ret;
+
+	host_addr = host_interest_item_address(addr);
+
+	ret = ath10k_pci_diag_read_mem(ar, host_addr, &reg_dump_area,
+				       sizeof(u32));
+	if (ret != 0) {
+		ath10k_warn("failed to read FW addr: %d (addr %d)\n",
+			    ret, addr);
+		return;
+	}
+
+	ret = ath10k_pci_diag_read_mem(ar, reg_dump_area, to, sz);
+	if (ret != 0)
+		ath10k_err("failed to read FW memory: %d (addr %d sz %d)\n",
+			   ret, reg_dump_area, sz);
+}
+
+#ifdef CONFIG_ATH10K_DEBUGFS
+/* Save the main firmware stack */
+static void ath10k_save_firmware_stack(struct ath10k *ar)
+{
+	BUILD_BUG_ON(ATH10K_FW_STACK_SIZE % 4);
+	ath10k_save_firmware_mem_helper(ar, ATH10K_FW_STACK_SIZE,
+					ar->debug.stack_buf, HI_ITEM(hi_stack));
+}
+#endif
+
+
 static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 {
 	u32 reg_dump_area = 0;
@@ -882,6 +916,13 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 			   reg_dump_values[i + 3]);
 
 #ifdef CONFIG_ATH10K_DEBUGFS
+	spin_lock_bh(&ar->data_lock);
+
+	if (!ar->debug.crashed_since_read)
+		ath10k_save_firmware_stack(ar);
+
+	spin_unlock_bh(&ar->data_lock);
+
 	/* Dump the debug logs on the target */
 	host_addr = host_interest_item_address(HI_ITEM(hi_dbglog_hdr));
 	ret = ath10k_pci_diag_read_mem(ar, host_addr,
-- 
1.7.11.7



From greearb at candelatech.com  Wed Jul 23 09:38:07 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Wed, 23 Jul 2014 09:38:07 -0700
Subject: [PATCH v4 5/5] ath10k: save firmware RAM and ROM BSS sections on
 crash.
In-Reply-To: <1406133487-7541-1-git-send-email-greearb@candelatech.com>
References: <1406133487-7541-1-git-send-email-greearb@candelatech.com>
Message-ID: <1406133487-7541-5-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

This can be used to get a useful back trace out of a firmware
crash that involves an interrupt handler.  For instance, a
null-pointer-exception would be this kind of trace.  A user-space
tool can read the debugfs file and decode things as wished.

This requires a packaged firmware with a new IE to describe the
BSS section starts and length.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/core.c  | 56 +++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/core.h  | 11 +++++++
 drivers/net/wireless/ath/ath10k/debug.c | 32 +++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hw.h    |  1 +
 drivers/net/wireless/ath/ath10k/pci.c   | 37 ++++++++++++++++++++++
 5 files changed, 137 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 93adb8c..576c263 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -365,6 +365,11 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 	struct ath10k_fw_ie *hdr;
 	const u8 *data;
 	__le32 *timestamp;
+#ifdef CONFIG_ATH10K_DEBUGFS
+	u32 old_ram_bss_len = ar->debug.fw_ram_bss_len;
+	u32 old_rom_bss_len = ar->debug.fw_rom_bss_len;
+	unsigned char *t1, *t2;
+#endif
 
 	/* first fetch the firmware file (firmware-*.bin) */
 	ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
@@ -479,6 +484,36 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 			ar->otp_len = ie_len;
 
 			break;
+		case ATH10K_FW_IE_BSS_INFO:
+#ifdef CONFIG_ATH10K_DEBUGFS
+			spin_lock_bh(&ar->data_lock);
+
+			ar->debug.fw_ram_bss_addr = le32_to_cpu(((u32 *)(data))[0]);
+			ar->debug.fw_ram_bss_len = le32_to_cpu(((u32 *)(data))[1]);
+			ar->debug.fw_rom_bss_addr = le32_to_cpu(((u32 *)(data))[2]);
+			ar->debug.fw_rom_bss_len = le32_to_cpu(((u32 *)(data))[3]);
+			t1 = t2 = NULL;
+			if ((old_ram_bss_len < ar->debug.fw_ram_bss_len) &&
+			    ar->debug.ram_bss_buf) {
+				t1 = ar->debug.ram_bss_buf;
+				ar->debug.ram_bss_buf = NULL;
+			}
+			if ((old_rom_bss_len < ar->debug.fw_rom_bss_len) &&
+			    ar->debug.rom_bss_buf) {
+				t2 = ar->debug.rom_bss_buf;
+				ar->debug.rom_bss_buf = NULL;
+			}
+			spin_unlock_bh(&ar->data_lock);
+			kfree(t1);
+			kfree(t2);
+			ath10k_dbg(ATH10K_DBG_BOOT,
+				   "found FW bss info, RAM: addr 0x%x len 0x%x  ROM: addr 0x%x len 0x%x\n",
+				   ar->debug.fw_ram_bss_addr,
+				   ar->debug.fw_ram_bss_len,
+				   ar->debug.fw_rom_bss_addr,
+				   ar->debug.fw_rom_bss_len);
+#endif
+			break;
 		default:
 			ath10k_warn("Unknown FW IE: %u\n",
 				    le32_to_cpu(hdr->id));
@@ -1094,9 +1129,30 @@ EXPORT_SYMBOL(ath10k_core_create);
 
 void ath10k_core_destroy(struct ath10k *ar)
 {
+#ifdef CONFIG_ATH10K_DEBUGFS
+	unsigned char *t1 = NULL;
+	unsigned char *t2 = NULL;
+#endif
+
 	flush_workqueue(ar->workqueue);
 	destroy_workqueue(ar->workqueue);
 
+#ifdef CONFIG_ATH10K_DEBUGFS
+	spin_lock_bh(&ar->data_lock);
+	if (ar->debug.rom_bss_buf) {
+		t1 = ar->debug.rom_bss_buf;
+		ar->debug.rom_bss_buf = NULL;
+	}
+	if (ar->debug.ram_bss_buf) {
+		t2 = ar->debug.ram_bss_buf;
+		ar->debug.ram_bss_buf = NULL;
+	}
+	spin_unlock_bh(&ar->data_lock);
+
+	kfree(t1);
+	kfree(t2);
+#endif
+
 	ath10k_mac_destroy(ar);
 }
 EXPORT_SYMBOL(ath10k_core_destroy);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index f122eae..f44957f 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -282,12 +282,16 @@ struct ath10k_vif_iter {
  * @ATH10K_FW_ERROR_DUMP_REGDUMP: Register crash dump in binary format
  * @ATH10K_FW_ERROR_DUMP_STACK:   Stack memory contents.
  * @ATH10K_FW_ERROR_DUMP_EXC_STACK:  Exception stack contents
+ * @ATH10K_FW_ERROR_DUMP_RAM_BSS:  BSS area for RAM code
+ * @ATH10K_FW_ERROR_DUMP_ROM_BSS:  BSS area for ROM code
  */
 enum ath10k_fw_error_dump_type {
 	ATH10K_FW_ERROR_DUMP_DBGLOG = 0,
 	ATH10K_FW_ERROR_DUMP_REGDUMP = 1,
 	ATH10K_FW_ERROR_DUMP_STACK = 2,
 	ATH10K_FW_ERROR_DUMP_EXC_STACK = 3,
+	ATH10K_FW_ERROR_DUMP_RAM_BSS = 4,
+	ATH10K_FW_ERROR_DUMP_ROM_BSS = 5,
 
 	ATH10K_FW_ERROR_DUMP_MAX,
 };
@@ -370,6 +374,13 @@ struct ath10k_debug {
 	u32 reg_dump_values[REG_DUMP_COUNT_QCA988X];
 	unsigned char stack_buf[ATH10K_FW_STACK_SIZE];
 	unsigned char exc_stack_buf[ATH10K_FW_STACK_SIZE];
+
+	unsigned char *rom_bss_buf;
+	unsigned char *ram_bss_buf;
+	unsigned int fw_ram_bss_addr;
+	unsigned int fw_ram_bss_len;
+	unsigned int fw_rom_bss_addr;
+	unsigned int fw_rom_bss_len;
 };
 
 enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 8995f0f..1823b0b 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -616,6 +616,8 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	struct ath10k_dump_file_data *dump_data;
 	int hdr_len = sizeof(*dump_data);
 	struct timespec timestamp;
+	int rom_bss_len = 0;
+	int ram_bss_len = 0;
 
 	len = hdr_len;
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.reg_dump_values);
@@ -623,6 +625,19 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.stack_buf);
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.exc_stack_buf);
 
+	/* Need to store local copies to detect races */
+	spin_lock_bh(&ar->data_lock);
+
+	ram_bss_len = ar->debug.fw_ram_bss_len;
+	rom_bss_len = ar->debug.fw_ram_bss_len;
+
+	if (ram_bss_len && ar->debug.ram_bss_buf)
+		len += sizeof(*dump_tlv) + ram_bss_len;
+	if (rom_bss_len && ar->debug.rom_bss_buf)
+		len += sizeof(*dump_tlv) + rom_bss_len;
+
+	spin_unlock_bh(&ar->data_lock);
+
 	lockdep_assert_held(&ar->conf_mutex);
 
 	sofar += hdr_len;
@@ -702,6 +717,23 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	memcpy(dump_tlv->tlv_data, &ar->debug.exc_stack_buf, dump_tlv->tlv_len);
 	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
 
+	if (ram_bss_len >= ar->debug.fw_ram_bss_len &&
+	    ar->debug.fw_ram_bss_len && ar->debug.ram_bss_buf) {
+		dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+		dump_tlv->type = ATH10K_FW_ERROR_DUMP_RAM_BSS;
+		dump_tlv->tlv_len = ar->debug.fw_ram_bss_len;
+		memcpy(dump_tlv->tlv_data, ar->debug.ram_bss_buf, dump_tlv->tlv_len);
+		sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+	}
+	if (rom_bss_len >= ar->debug.fw_rom_bss_len &&
+	    ar->debug.fw_rom_bss_len && ar->debug.rom_bss_buf) {
+		dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+		dump_tlv->type = ATH10K_FW_ERROR_DUMP_ROM_BSS;
+		dump_tlv->tlv_len = ar->debug.fw_rom_bss_len;
+		memcpy(dump_tlv->tlv_data, ar->debug.rom_bss_buf, dump_tlv->tlv_len);
+		sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+	}
+
 	spin_unlock_bh(&ar->data_lock);
 
 	WARN_ON(sofar != len);
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 38a03e4..724bd94 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -53,6 +53,7 @@ enum ath10k_fw_ie_type {
 	ATH10K_FW_IE_FEATURES = 2,
 	ATH10K_FW_IE_FW_IMAGE = 3,
 	ATH10K_FW_IE_OTP_IMAGE = 4,
+	ATH10K_FW_IE_BSS_INFO = 5,
 };
 
 /* Known pecularities:
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index d298e14..6d43845 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -872,6 +872,37 @@ static void ath10k_save_firmware_exc_stack(struct ath10k *ar)
 					ar->debug.exc_stack_buf,
 					HI_ITEM(hi_err_stack));
 }
+
+static void ath10k_check_dump_fw_bss(struct ath10k *ar, u32 addr, u32 len,
+				     bool is_rom) {
+	int ret;
+
+	if (!addr)
+		return;
+	if (is_rom) {
+		if (!ar->debug.rom_bss_buf)
+			ar->debug.rom_bss_buf = kmalloc(len, GFP_ATOMIC);
+		if (!ar->debug.rom_bss_buf)
+			return;
+
+		ret = ath10k_pci_diag_read_mem(ar, addr, ar->debug.rom_bss_buf,
+					       len);
+		if (ret != 0)
+			ath10k_err("failed to read FW ROM BSS memory: %d (addr %d sz %d)\n",
+				   ret, addr, len);
+	} else {
+		if (!ar->debug.ram_bss_buf)
+			ar->debug.ram_bss_buf = kmalloc(len, GFP_ATOMIC);
+		if (!ar->debug.ram_bss_buf)
+			return;
+
+		ret = ath10k_pci_diag_read_mem(ar, addr, ar->debug.ram_bss_buf,
+					       len);
+		if (ret != 0)
+			ath10k_err("failed to read FW RAM BSS memory: %d (addr %d sz %d)\n",
+				   ret, addr, len);
+	}
+}
 #endif
 
 static void ath10k_pci_hif_dump_area(struct ath10k *ar)
@@ -928,6 +959,12 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 	if (!ar->debug.crashed_since_read) {
 		ath10k_save_firmware_stack(ar);
 		ath10k_save_firmware_exc_stack(ar);
+
+		/* And the RAM BSS region, if we know it. */
+		ath10k_check_dump_fw_bss(ar, ar->debug.fw_ram_bss_addr,
+					 ar->debug.fw_ram_bss_len, false);
+		ath10k_check_dump_fw_bss(ar, ar->debug.fw_rom_bss_addr,
+					 ar->debug.fw_rom_bss_len, true);
 	}
 
 	spin_unlock_bh(&ar->data_lock);
-- 
1.7.11.7



From greearb at candelatech.com  Wed Jul 23 09:38:03 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Wed, 23 Jul 2014 09:38:03 -0700
Subject: [PATCH v4 1/5] ath10k:  provide firmware crash info via debugfs.
Message-ID: <1406133487-7541-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Store the firmware crash registers and last 128 or so
firmware debug-log ids and present them to user-space
via debugfs.

Should help with figuring out why the firmware crashed.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

v4:  Use _bh spinlock variants everywhere.

For patch 0005:  Fix kmalloc/vfree problem. 

drivers/net/wireless/ath/ath10k/core.h  |  71 ++++++++++++++
 drivers/net/wireless/ath/ath10k/debug.c | 164 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/debug.h |   8 ++
 drivers/net/wireless/ath/ath10k/hw.h    |  24 +++++
 drivers/net/wireless/ath/ath10k/pci.c   | 106 ++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/pci.h   |   3 -
 6 files changed, 371 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 83a5fa9..5c0c5bf 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -276,6 +276,70 @@ struct ath10k_vif_iter {
 	struct ath10k_vif *arvif;
 };
 
+/**
+ * enum ath10k_fw_error_dump_type - types of data in the dump file
+ * @ATH10K_FW_ERROR_DUMP_DBGLOG:  Recent firmware debug log entries
+ * @ATH10K_FW_ERROR_DUMP_REGDUMP: Register crash dump in binary format
+ */
+enum ath10k_fw_error_dump_type {
+	ATH10K_FW_ERROR_DUMP_DBGLOG = 0,
+	ATH10K_FW_ERROR_DUMP_REGDUMP = 1,
+
+	ATH10K_FW_ERROR_DUMP_MAX,
+};
+
+struct ath10k_tlv_dump_data {
+	u32 type; /* see ath10k_fw_error_dump_type above */
+	u32 tlv_len; /* in bytes */
+	u8 tlv_data[]; /* Pad to 32-bit boundaries as needed. */
+} __packed;
+
+struct ath10k_dump_file_data {
+	/* Dump file information */
+	char df_magic[16]; /* ATH10K-FW-DUMP */
+	u32 len;
+	u32 big_endian; /* 0x1 if host is big-endian */
+	u32 version; /* File dump version, 1 for now. */
+
+	/* Some info we can get from ath10k struct that might help. */
+	u32 chip_id;
+	u32 bus_type; /* 0 for now, in place for later hardware */
+	u32 target_version;
+	u32 fw_version_major;
+	u32 fw_version_minor;
+	u32 fw_version_release;
+	u32 fw_version_build;
+	u32 phy_capability;
+	u32 hw_min_tx_power;
+	u32 hw_max_tx_power;
+	u32 ht_cap_info;
+	u32 vht_cap_info;
+	u32 num_rf_chains;
+	char fw_ver[ETHTOOL_FWVERS_LEN]; /* Firmware version string */
+
+	/* Kernel related information */
+	u32 tv_sec_hi; /* time-of-day stamp, high 32-bits for seconds */
+	u32 tv_sec_lo; /* time-of-day stamp, low 32-bits for seconds */
+	u32 tv_nsec_hi; /* time-of-day stamp, nano-seconds, high bits */
+	u32 tv_nsec_lo; /* time-of-day stamp, nano-seconds, low bits */
+	u32 kernel_ver_code; /* LINUX_VERSION_CODE */
+	char kernel_ver[64]; /* VERMAGIC_STRING */
+
+	u8 unused[128]; /* Room for growth w/out changing binary format */
+
+	u8 data[0]; /* struct ath10k_tlv_dump_data + more */
+} __packed;
+
+/* This will store at least the last 128 entries.  Each dbglog message
+ * is a max of 7 32-bit integers in length, but the length can be less
+ * than that as well.
+ */
+#define ATH10K_DBGLOG_DATA_LEN (128 * 7 * sizeof(u32))
+struct ath10k_dbglog_entry_storage {
+	u32 next_idx; /* Where to write next chunk of data */
+	u8 data[ATH10K_DBGLOG_DATA_LEN];
+};
+
 struct ath10k_debug {
 	struct dentry *debugfs_phy;
 
@@ -293,6 +357,13 @@ struct ath10k_debug {
 
 	u8 htt_max_amsdu;
 	u8 htt_max_ampdu;
+
+	/* Used for crash-dump storage */
+	/* Don't over-write dump info until someone reads the data. */
+	/* Protected by data-lock */
+	bool crashed_since_read;
+	struct ath10k_dbglog_entry_storage dbglog_entry_data;
+	u32 reg_dump_values[REG_DUMP_COUNT_QCA988X];
 };
 
 enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index c9e35c87e..cc81a99 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -17,6 +17,9 @@
 
 #include <linux/module.h>
 #include <linux/debugfs.h>
+#include <linux/version.h>
+#include <linux/vermagic.h>
+#include <linux/vmalloc.h>
 
 #include "core.h"
 #include "debug.h"
@@ -580,6 +583,164 @@ static const struct file_operations fops_chip_id = {
 	.llseek = default_llseek,
 };
 
+void ath10k_dbg_save_fw_dbg_buffer(struct ath10k *ar, u8 *buffer, int len)
+{
+	int i;
+	int z = ar->debug.dbglog_entry_data.next_idx;
+
+	spin_lock_bh(&ar->data_lock);
+
+	/* Don't save any new logs until user-space reads this. */
+	if (ar->debug.crashed_since_read)
+		goto exit;
+
+	for (i = 0; i < len; i++) {
+		ar->debug.dbglog_entry_data.data[z] = buffer[i];
+		z++;
+		if (z >= ATH10K_DBGLOG_DATA_LEN)
+			z = 0;
+	}
+
+	ar->debug.dbglog_entry_data.next_idx = z;
+exit:
+	spin_unlock_bh(&ar->data_lock);
+}
+EXPORT_SYMBOL(ath10k_dbg_save_fw_dbg_buffer);
+
+static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
+{
+	unsigned int len;
+	unsigned int sofar = 0;
+	unsigned char *buf;
+	struct ath10k_tlv_dump_data *dump_tlv;
+	struct ath10k_dump_file_data *dump_data;
+	int hdr_len = sizeof(*dump_data);
+	struct timespec timestamp;
+
+	len = hdr_len;
+	len += sizeof(*dump_tlv) + sizeof(ar->debug.reg_dump_values);
+	len += sizeof(*dump_tlv) + sizeof(ar->debug.dbglog_entry_data);
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	sofar += hdr_len;
+
+	/* This is going to get big when we start dumping FW RAM and such,
+	 * so go ahead and use vmalloc.
+	 */
+	buf = vmalloc(len);
+	if (!buf)
+		return NULL;
+
+	memset(buf, 0, len);
+	dump_data = (struct ath10k_dump_file_data *)(buf);
+	strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
+		sizeof(dump_data->df_magic));
+	dump_data->len = len;
+#ifdef __BIG_ENDIAN
+	dump_data->big_endian = 1;
+#else
+	dump_data->big_endian = 0;
+#endif
+	dump_data->version = 1;
+	dump_data->chip_id = ar->chip_id;
+	dump_data->bus_type = 0;
+	dump_data->target_version = ar->target_version;
+	dump_data->fw_version_major = ar->fw_version_major;
+	dump_data->fw_version_minor = ar->fw_version_minor;
+	dump_data->fw_version_release = ar->fw_version_release;
+	dump_data->fw_version_build = ar->fw_version_build;
+	dump_data->phy_capability = ar->phy_capability;
+	dump_data->hw_min_tx_power = ar->hw_min_tx_power;
+	dump_data->hw_max_tx_power = ar->hw_max_tx_power;
+	dump_data->ht_cap_info = ar->ht_cap_info;
+	dump_data->vht_cap_info = ar->vht_cap_info;
+	dump_data->num_rf_chains = ar->num_rf_chains;
+
+	strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
+		sizeof(dump_data->fw_ver));
+
+	dump_data->kernel_ver_code = LINUX_VERSION_CODE;
+	strlcpy(dump_data->kernel_ver, VERMAGIC_STRING,
+		sizeof(dump_data->kernel_ver));
+
+	getnstimeofday(&timestamp);
+	dump_data->tv_sec_hi = timestamp.tv_sec >> 32;
+	dump_data->tv_sec_lo = timestamp.tv_sec;
+	dump_data->tv_nsec_hi = timestamp.tv_nsec >> 32;
+	dump_data->tv_nsec_lo = timestamp.tv_nsec;
+
+	spin_lock_bh(&ar->data_lock);
+
+	/* Gather dbg-log */
+	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+	dump_tlv->type = ATH10K_FW_ERROR_DUMP_DBGLOG;
+	dump_tlv->tlv_len = sizeof(ar->debug.dbglog_entry_data);
+	memcpy(dump_tlv->tlv_data, &ar->debug.dbglog_entry_data, dump_tlv->tlv_len);
+	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+
+	/* Gather crash-dump */
+	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+	dump_tlv->type = ATH10K_FW_ERROR_DUMP_REGDUMP;
+	dump_tlv->tlv_len = sizeof(ar->debug.reg_dump_values);
+	memcpy(dump_tlv->tlv_data, &ar->debug.reg_dump_values, dump_tlv->tlv_len);
+	sofar += sizeof(*dump_tlv) + dump_tlv->tlv_len;
+
+	spin_unlock_bh(&ar->data_lock);
+
+	return dump_data;
+}
+
+static int ath10k_fw_error_dump_open(struct inode *inode, struct file *file)
+{
+	struct ath10k *ar = inode->i_private;
+	int ret;
+	struct ath10k_dump_file_data *dump;
+
+	mutex_lock(&ar->conf_mutex);
+
+	dump = ath10k_build_dump_file(ar);
+	if (!dump) {
+		ret = -ENODATA;
+		goto out;
+	}
+
+	file->private_data = dump;
+	ar->debug.crashed_since_read = false;
+	ret = 0;
+
+out:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
+}
+
+static ssize_t ath10k_fw_error_dump_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct ath10k_dump_file_data *dump_file = file->private_data;
+
+	return simple_read_from_buffer(user_buf, count, ppos,
+				       dump_file,
+				       dump_file->len);
+}
+
+static int ath10k_fw_error_dump_release(struct inode *inode,
+					struct file *file)
+{
+	vfree(file->private_data);
+
+	return 0;
+}
+
+static const struct file_operations fops_fw_error_dump = {
+	.open = ath10k_fw_error_dump_open,
+	.read = ath10k_fw_error_dump_read,
+	.release = ath10k_fw_error_dump_release,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 static int ath10k_debug_htt_stats_req(struct ath10k *ar)
 {
 	u64 cookie;
@@ -933,6 +1094,9 @@ int ath10k_debug_create(struct ath10k *ar)
 	debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_simulate_fw_crash);
 
+	debugfs_create_file("fw_error_dump", S_IRUSR, ar->debug.debugfs_phy,
+			    ar, &fops_fw_error_dump);
+
 	debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_chip_id);
 
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index a582499..6e8f5f6 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -96,6 +96,8 @@ __printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask,
 void ath10k_dbg_dump(enum ath10k_debug_mask mask,
 		     const char *msg, const char *prefix,
 		     const void *buf, size_t len);
+void ath10k_dbg_save_fw_dbg_buffer(struct ath10k *ar, u8 *buffer, int len);
+
 #else /* CONFIG_ATH10K_DEBUG */
 
 static inline int ath10k_dbg(enum ath10k_debug_mask dbg_mask,
@@ -109,5 +111,11 @@ static inline void ath10k_dbg_dump(enum ath10k_debug_mask mask,
 				   const void *buf, size_t len)
 {
 }
+
+static inline void ath10k_dbg_save_fw_dbg_buffer(struct ath10k *ar,
+						 u8 *buffer, int len)
+{
+}
 #endif /* CONFIG_ATH10K_DEBUG */
+
 #endif /* _DEBUG_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 007e855..d4df3f0 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -38,6 +38,8 @@
 /* includes also the null byte */
 #define ATH10K_FIRMWARE_MAGIC               "QCA-ATH10K"
 
+#define REG_DUMP_COUNT_QCA988X 60
+
 struct ath10k_fw_ie {
 	__le32 id;
 	__le32 len;
@@ -361,4 +363,26 @@ enum ath10k_mcast2ucast_mode {
 
 #define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB)
 
+
+/* Target debug log related defines and structs */
+
+/* Target is 32-bit CPU, so we just use u32 for
+ * the pointers.  The memory space is relative to the
+ * target, not the host.
+ */
+struct ath10k_fw_dbglog_buf {
+	u32 next; /* pointer to dblog_buf_s. */
+	u32 buffer; /* pointer to u8 buffer */
+	u32 bufsize;
+	u32 length;
+	u32 count;
+	u32 free;
+} __packed;
+
+struct ath10k_fw_dbglog_hdr {
+	u32 dbuf; /* pointer to dbglog_buf_s */
+	u32 dropped;
+} __packed;
+
+
 #endif /* _HW_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 06840d1..24ddc22 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -840,6 +840,12 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 	u32 host_addr;
 	int ret;
 	u32 i;
+#ifdef CONFIG_ATH10K_DEBUGFS
+	struct ath10k_fw_dbglog_hdr dbg_hdr;
+	u32 dbufp; /* pointer in target memory space */
+	struct ath10k_fw_dbglog_buf dbuf;
+	u8 *buffer;
+#endif
 
 	ath10k_err("firmware crashed!\n");
 	ath10k_err("hardware name %s version 0x%x\n",
@@ -851,7 +857,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 				       &reg_dump_area, sizeof(u32));
 	if (ret) {
 		ath10k_err("failed to read FW dump area address: %d\n", ret);
-		return;
+		goto exit;
 	}
 
 	ath10k_err("target register Dump Location: 0x%08X\n", reg_dump_area);
@@ -861,7 +867,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 				       REG_DUMP_COUNT_QCA988X * sizeof(u32));
 	if (ret != 0) {
 		ath10k_err("failed to read FW dump area: %d\n", ret);
-		return;
+		goto exit;
 	}
 
 	BUILD_BUG_ON(REG_DUMP_COUNT_QCA988X % 4);
@@ -875,6 +881,102 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
 			   reg_dump_values[i + 2],
 			   reg_dump_values[i + 3]);
 
+#ifdef CONFIG_ATH10K_DEBUGFS
+	/* Dump the debug logs on the target */
+	host_addr = host_interest_item_address(HI_ITEM(hi_dbglog_hdr));
+	ret = ath10k_pci_diag_read_mem(ar, host_addr,
+				       &reg_dump_area, sizeof(u32));
+	if (ret != 0) {
+		ath10k_warn("failed to read hi_dbglog_hdr: %d\n", ret);
+		goto exit_save_regs;
+	}
+
+	ret = ath10k_pci_diag_read_mem(ar, reg_dump_area,
+				       &dbg_hdr, sizeof(dbg_hdr));
+	if (ret != 0) {
+		ath10k_err("failed to dump debug log area: %d (addr 0x%x)\n",
+			   ret, reg_dump_area);
+		goto exit_save_regs;
+	}
+
+	ath10k_dbg(ATH10K_DBG_PCI,
+		   "Debug Log Header, dbuf: 0x%x  dropped: %i\n",
+		   dbg_hdr.dbuf, dbg_hdr.dropped);
+	dbufp = dbg_hdr.dbuf;
+
+	/* i is for logging purposes and sanity check in case firmware buffers
+	 * are corrupted and will not properly terminate the list.
+	 * In standard firmware, it appears there are no more than 2
+	 * buffers, so 10 should be safe upper limit even if firmware
+	 * changes quite a bit.
+	 */
+	i = 0;
+	while (dbufp && i < 10) {
+		ret = ath10k_pci_diag_read_mem(ar, dbufp,
+					       &dbuf, sizeof(dbuf));
+		if (ret != 0) {
+			ath10k_err("failed to read debug log area: %d (addr 0x%x)\n",
+				   ret, dbufp);
+			goto exit_save_regs;
+		}
+
+		/* We have a buffer of data */
+		ath10k_dbg(ATH10K_DBG_PCI,
+			   "[%i] next: 0x%x buf: 0x%x sz: %i len: %i count: %i free: %i\n",
+			   i, dbuf.next, dbuf.buffer, dbuf.bufsize, dbuf.length,
+			   dbuf.count, dbuf.free);
+		if (dbuf.buffer == 0 || dbuf.length == 0)
+			goto next;
+
+		/* Pick arbitrary upper bound in case firmware is corrupted for
+		 * whatever reason.
+		 */
+		if (dbuf.length > 16000) {
+			ath10k_err("debuglog buf length is out of bounds: %d\n",
+				   dbuf.length);
+			/* Do not trust the next pointer either... */
+			goto exit_save_regs;
+		}
+
+		buffer = kmalloc(dbuf.length, GFP_ATOMIC);
+
+		if (!buffer)
+			goto next;
+
+		ret = ath10k_pci_diag_read_mem(ar, dbuf.buffer, buffer,
+					       dbuf.length);
+		if (ret != 0) {
+			ath10k_err("failed to read debug log buffer: %d (addr 0x%x)\n",
+				   ret, dbuf.buffer);
+			kfree(buffer);
+			goto exit_save_regs;
+		}
+
+		ath10k_dbg_save_fw_dbg_buffer(ar, buffer, dbuf.length);
+		kfree(buffer);
+
+next:
+		dbufp = dbuf.next;
+		if (dbufp == dbg_hdr.dbuf) {
+			/* It is a circular buffer it seems, bail if next
+			 * is head
+			 */
+			break;
+		}
+		i++;
+	} /* While we have a debug buffer to read */
+
+exit_save_regs:
+	spin_lock_bh(&ar->data_lock);
+	if (!ar->debug.crashed_since_read) {
+		ar->debug.crashed_since_read = true;
+		memcpy(ar->debug.reg_dump_values, reg_dump_values,
+		       sizeof(ar->debug.reg_dump_values));
+	}
+	spin_unlock_bh(&ar->data_lock);
+#endif /* debugfs */
+
+exit:
 	queue_work(ar->workqueue, &ar->restart_work);
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index 9401292..f72a7cd 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -23,9 +23,6 @@
 #include "hw.h"
 #include "ce.h"
 
-/* FW dump area */
-#define REG_DUMP_COUNT_QCA988X 60
-
 /*
  * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite
  */
-- 
1.7.11.7



From sw at simonwunderlich.de  Wed Jul 23 09:40:22 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Wed, 23 Jul 2014 18:40:22 +0200
Subject: [PATCHv2 2/2] ath10k: add spectral scan feature
In-Reply-To: <8738dst4o6.fsf@kamboji.qca.qualcomm.com>
References: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
 <201407231712.43500.sw@simonwunderlich.de>
 <8738dst4o6.fsf@kamboji.qca.qualcomm.com>
Message-ID: <201407231840.22674.sw@simonwunderlich.de>

Hey Kalle,

> Simon Wunderlich <sw at simonwunderlich.de> writes:
> >> > +struct fft_sample_ath10k {
> >> > +	struct fft_sample_tlv tlv;
> >> > +	u8 chan_width_mhz;
> >> > +	__be16 freq1;
> >> > +	__be16 freq2;
> >> > +	__be16 noise;
> >> > +	__be16 max_magnitude;
> >> > +	__be16 total_gain_db;
> >> > +	__be16 base_pwr_db;
> >> > +	__be64 tsf;
> >> > +	s8 max_index;
> >> > +	u8 rssi;
> >> > +	u8 relpwr_db;
> >> > +	u8 avgpwr_db;
> >> > +	u8 max_exp;
> >> > +
> >> > +	u8 data[0];
> >> > +} __packed;
> >> 
> >> __be16, that's a first. Just making sure that this really is big endian?
> > 
> > As the __le32 you use in other ath10k structs, this is just for checking
> > - at least sparse should check that, maybe other tools as well.
> 
> Sorry, I didn't understand your comment here. But basically I was asking
> is the fft sample really in big endian? I assume it would be little
> endian as everything else coming from the firmware.

Yeah that is intended - we are also using big endian in ath9k to send fft 
samples to userspace, because that is the network byte order and we then just 
use ntohs() and friends in userspace to read samples from any system. 
Therefore we intent to use the same encoding in ath10k. :)

Cheers,
    Simon


From kvalo at qca.qualcomm.com  Wed Jul 23 09:44:54 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 23 Jul 2014 19:44:54 +0300
Subject: [PATCHv2 2/2] ath10k: add spectral scan feature
In-Reply-To: <201407231840.22674.sw@simonwunderlich.de> (Simon Wunderlich's
 message of "Wed, 23 Jul 2014 18:40:22 +0200")
References: <1405945943-8303-1-git-send-email-sw@simonwunderlich.de>
 <201407231712.43500.sw@simonwunderlich.de>
 <8738dst4o6.fsf@kamboji.qca.qualcomm.com>
 <201407231840.22674.sw@simonwunderlich.de>
Message-ID: <87y4vkrpmh.fsf@kamboji.qca.qualcomm.com>

Simon Wunderlich <sw at simonwunderlich.de> writes:

> Hey Kalle,
>
>> Simon Wunderlich <sw at simonwunderlich.de> writes:
>> >> > +struct fft_sample_ath10k {
>> >> > +	struct fft_sample_tlv tlv;
>> >> > +	u8 chan_width_mhz;
>> >> > +	__be16 freq1;
>> >> > +	__be16 freq2;
>> >> > +	__be16 noise;
>> >> > +	__be16 max_magnitude;
>> >> > +	__be16 total_gain_db;
>> >> > +	__be16 base_pwr_db;
>> >> > +	__be64 tsf;
>> >> > +	s8 max_index;
>> >> > +	u8 rssi;
>> >> > +	u8 relpwr_db;
>> >> > +	u8 avgpwr_db;
>> >> > +	u8 max_exp;
>> >> > +
>> >> > +	u8 data[0];
>> >> > +} __packed;
>> >> 
>> >> __be16, that's a first. Just making sure that this really is big endian?
>> > 
>> > As the __le32 you use in other ath10k structs, this is just for checking
>> > - at least sparse should check that, maybe other tools as well.
>> 
>> Sorry, I didn't understand your comment here. But basically I was asking
>> is the fft sample really in big endian? I assume it would be little
>> endian as everything else coming from the firmware.
>
> Yeah that is intended - we are also using big endian in ath9k to send fft 
> samples to userspace, because that is the network byte order and we then just 
> use ntohs() and friends in userspace to read samples from any system. 
> Therefore we intent to use the same encoding in ath10k. :)

Ah, this is the struct going to user space? I thought it's coming from
the firmware. Then forget my question :)

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Jul 23 10:14:53 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 23 Jul 2014 20:14:53 +0300
Subject: [PATCHv3 0/2] ath10k spectral scan support
In-Reply-To: <1406130837-10353-1-git-send-email-sw@simonwunderlich.de> (Simon
 Wunderlich's message of "Wed, 23 Jul 2014 17:53:55 +0200")
References: <1406130837-10353-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <87mwc0ro8i.fsf@kamboji.qca.qualcomm.com>

Simon Wunderlich <sw at simonwunderlich.de> writes:

> This is the third "PATCH" patchset iteration for the ath10k spectral
> scan feature. It includes quite a few style fixes, the compile issues
> were fixed when debugfs were disabled, and sending WMI commands after
> a firmware crash should not happen any more. Thanks to Michal, Chun-Yeow
> and Kalle for reviewing!
>
> To view the samples, please have a look at the fft_eval tool [1] which
> now supports both ath9k and ath10k formats.
>
> The count issue is still open: Even when a count is specified, the
> hardware seems to send endless samples. It seems to work most of the
> time in VHT80 mode though, but in HT20 and HT40 the count value seems
> to be ignored. To reproduce this, start hostapd with the desired
> channel width and do:
>
> echo 8 > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_count
> echo manual > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> echo trigger > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 >> /tmp/fft.dump
>
> Repeating the last line and checking the filesize will easily show
> whether ath10k still sends samples or not. We would expect 8 samples in
> this configuration.
>
> Please see the patches for more information on the changes.

This one had conflicts so I'm dropping it.

-- 
Kalle Valo


From sw at simonwunderlich.de  Wed Jul 23 10:32:53 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Wed, 23 Jul 2014 19:32:53 +0200
Subject: [PATCHv3-ath-resend 2/2] ath10k: add spectral scan feature
In-Reply-To: <87mwc0ro8i.fsf@kamboji.qca.qualcomm.com>
References: <87mwc0ro8i.fsf@kamboji.qca.qualcomm.com>
Message-ID: <1406136773-19957-1-git-send-email-sw@simonwunderlich.de>

Adds the spectral scan feature for ath10k. The spectral scan is triggered by
configuring a mode through a debugfs control file. Samples can be gathered via
another relay debugfs file.

Essentially, to try it out:

ip link set dev wlan0 up
echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
echo trigger > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
iw dev wlan0 scan
echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples

This feature is still experimental. Based on the original RFC patch of
Sven Eckelmann.

Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
--
PATCHv3-ath-resend:
 * based on ath/master

PATCHv3:
 * fix compilation with debugfs disabled (Thanks Kalle)
 * add trigger command to commit message (Thanks Chun-Yeow)
 * change error message capitalization (Thanks Michal)
 * don't send WMI on core halt (Thanks Michal)
 * various style changes: indetation, empty lines before comments, moved
   initialization into separate function, create substruct for spectral
   parameters (Thanks Kalle)

PATCHv2:
 * fixed usage example in commit message (Thanks Chun-Yeow Yeoh)
 * adding lockdep asserts and comment (Thanks Michal)
 * debug message cleanups (Michal)
 * disable spectral on firmware crash (Michal)

PATCH:
 * change the tlv format to a variable-length format, depending on the
   number of bins
 * perform dc interpolation and max_exp calculation in the driver (as
   for ath9k)
 * make fft_size configurable
 * background scan will only start after beeing trigger, like in ath9k
 * document at least some spectral configuration members (thanks Kathy)
 * fix sparse problems
 * sample bandwidth appears to be 110% of what is reported by the
   hardware according to the plotter (e.g. 20->22, 40->44 MHz etc),
   so fix that in the driver.
 * disable spectral for a vif when it's beeing deleted and still active
   (Michals comment)
 * modify ath_ prefix of function/struct/enum to ath10k_ (Michal)
 * changed variable ret to res (Michal)
 * added ath10k_warn messages (Michal)
 * renamed wmi functions (Michal)
 * use ar->conf_mutex for locking (Michal)
 * renamed mhz to chan_width_mhz (Michal)
 * only enable spectral scan files when ATH10K_DEBUGFS is enabled
---
 drivers/net/wireless/ath/ath10k/Kconfig    |   1 +
 drivers/net/wireless/ath/ath10k/Makefile   |   1 +
 drivers/net/wireless/ath/ath10k/core.c     |   8 +-
 drivers/net/wireless/ath/ath10k/core.h     |  10 +
 drivers/net/wireless/ath/ath10k/debug.c    |   3 +
 drivers/net/wireless/ath/ath10k/mac.c      |   7 +
 drivers/net/wireless/ath/ath10k/spectral.c | 557 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |  82 +++++
 drivers/net/wireless/ath/ath10k/wmi.c      | 104 +++++-
 drivers/net/wireless/ath/ath10k/wmi.h      |  97 +++++
 drivers/net/wireless/ath/spectral_common.h |  25 ++
 11 files changed, 892 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h

diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index a6f5285..1053bb5 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -25,6 +25,7 @@ config ATH10K_DEBUG
 config ATH10K_DEBUGFS
 	bool "Atheros ath10k debugfs support"
 	depends on ATH10K
+	select RELAY
 	---help---
 	  Enabled debugfs support
 
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index a4179f4..3241ef9 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -10,6 +10,7 @@ ath10k_core-y += mac.o \
 		 wmi.o \
 		 bmi.o
 
+ath10k_core-$(CPTCFG_ATH10K_DEBUGFS) += spectral.o
 ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
 
 obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 93adb8c..a4fcdf9 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -800,8 +800,6 @@ int ath10k_core_start(struct ath10k *ar)
 	else
 		ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
 
-	INIT_LIST_HEAD(&ar->arvifs);
-
 	if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
 		ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
 			    ar->hw_params.name,
@@ -1084,6 +1082,12 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 	INIT_WORK(&ar->register_work, ath10k_core_register_work);
 	INIT_WORK(&ar->restart_work, ath10k_core_restart);
 
+	INIT_LIST_HEAD(&ar->arvifs);
+
+	mutex_lock(&ar->conf_mutex);
+	ath10k_spectral_init(ar);
+	mutex_unlock(&ar->conf_mutex);
+
 	return ar;
 
 err_wq:
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 83a5fa9..12194db 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -31,6 +31,7 @@
 #include "../ath.h"
 #include "../regd.h"
 #include "../dfs_pattern_detector.h"
+#include "spectral.h"
 
 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -237,6 +238,7 @@ struct ath10k_vif {
 
 	bool is_started;
 	bool is_up;
+	bool spectral_enabled;
 	u32 aid;
 	u8 bssid[ETH_ALEN];
 
@@ -494,6 +496,14 @@ struct ath10k {
 #ifdef CONFIG_ATH10K_DEBUGFS
 	struct ath10k_debug debug;
 #endif
+
+	struct {
+		/* relay(fs) channel for spectral scan */
+		struct rchan *rfs_chan_spec_scan;
+		/* spectral_mode and spec_config are protected by conf_mutex */
+		enum ath10k_spectral_mode mode;
+		struct ath10k_spec_scan config;
+	} spectral;
 };
 
 struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 3030158..42cb448 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -957,12 +957,15 @@ int ath10k_debug_create(struct ath10k *ar)
 				    &fops_dfs_stats);
 	}
 
+	ath10k_spectral_init_debug(ar);
+
 	return 0;
 }
 
 void ath10k_debug_destroy(struct ath10k *ar)
 {
 	cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
+	ath10k_spectral_deinit_debug(ar);
 }
 
 #endif /* CONFIG_ATH10K_DEBUGFS */
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 3f9afaa..74dbd88 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2330,6 +2330,7 @@ void ath10k_halt(struct ath10k *ar)
 	ath10k_peer_cleanup_all(ar);
 	ath10k_core_stop(ar);
 	ath10k_hif_power_down(ar);
+	ath10k_spectral_init(ar);
 
 	spin_lock_bh(&ar->data_lock);
 	list_for_each_entry(arvif, &ar->arvifs, list) {
@@ -2892,8 +2893,14 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 		dev_kfree_skb_any(arvif->beacon);
 		arvif->beacon = NULL;
 	}
+
 	spin_unlock_bh(&ar->data_lock);
 
+	ret = ath10k_spectral_stop(arvif);
+	if (ret)
+		ath10k_warn("failed to disable spectral for vdev %i: %d\n",
+			    arvif->vdev_id, ret);
+
 	ar->free_vdev_map |= 1 << (arvif->vdev_id);
 	list_del(&arvif->list);
 
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
new file mode 100644
index 0000000..db836e0
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/relay.h>
+#include "core.h"
+#include "debug.h"
+
+static void
+ath10k_debug_send_fft_sample(struct ath10k *ar,
+			     const struct fft_sample_tlv *fft_sample_tlv)
+{
+	int length;
+
+	if (!ar->spectral.rfs_chan_spec_scan)
+		return;
+
+	length = __be16_to_cpu(fft_sample_tlv->length) +
+		 sizeof(*fft_sample_tlv);
+	relay_write(ar->spectral.rfs_chan_spec_scan, fft_sample_tlv, length);
+}
+
+static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
+			   u8 *data)
+{
+	int dc_pos;
+	u8 max_exp;
+
+	dc_pos = bin_len / 2;
+
+	/* peak index outside of bins */
+	if (dc_pos < max_index || -dc_pos >= max_index)
+		return 0;
+
+	for (max_exp = 0; max_exp < 8; max_exp++) {
+		if (data[dc_pos + max_index] == (max_magnitude >> max_exp))
+			break;
+	}
+
+	/* max_exp not found */
+	if (data[dc_pos + max_index] != (max_magnitude >> max_exp))
+		return 0;
+
+	return max_exp;
+}
+
+int ath10k_process_fft(struct ath10k *ar,
+		       struct wmi_single_phyerr_rx_event *event,
+		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
+{
+	struct fft_sample_ath10k *fft_sample;
+	u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
+	u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag;
+	u32 reg0, reg1, nf_list1, nf_list2;
+	u8 chain_idx, *bins;
+	int dc_pos;
+
+	fft_sample = (struct fft_sample_ath10k *)&buf;
+
+	if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
+		return -EINVAL;
+
+	reg0 = __le32_to_cpu(fftr->reg0);
+	reg1 = __le32_to_cpu(fftr->reg1);
+
+	length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + bin_len;
+	fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH10K;
+	fft_sample->tlv.length = __cpu_to_be16(length);
+
+	/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
+	 * but the results/plots suggest that its actually 22/44/88 MHz.
+	 */
+	switch (event->hdr.chan_width_mhz) {
+	case 20:
+		fft_sample->chan_width_mhz = 22;
+		break;
+	case 40:
+		fft_sample->chan_width_mhz = 44;
+		break;
+	case 80:
+		/* TODO: As experiments with an analogue sender and various
+		 * configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
+		 * show, the particular configuration of 80 MHz/64 bins does
+		 * not match with the other smaples at all. Until the reason
+		 * for that is found, don't report these samples.
+		 */
+		if (bin_len == 64)
+			return -EINVAL;
+		fft_sample->chan_width_mhz = 88;
+		break;
+	default:
+		fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
+	}
+
+	fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
+	fft_sample->avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
+
+	peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
+	fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
+	fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
+	fft_sample->rssi = event->hdr.rssi_combined;
+
+	total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
+	base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
+	fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
+	fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
+
+	freq1 = __le16_to_cpu(event->hdr.freq1);
+	freq2 = __le16_to_cpu(event->hdr.freq2);
+	fft_sample->freq1 = __cpu_to_be16(freq1);
+	fft_sample->freq2 = __cpu_to_be16(freq2);
+
+	nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
+	nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
+	chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
+
+	switch (chain_idx) {
+	case 0:
+		fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
+		break;
+	case 1:
+		fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
+		break;
+	case 2:
+		fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
+		break;
+	case 3:
+		fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
+		break;
+	}
+
+	bins = (u8 *)fftr;
+	bins += sizeof(*fftr);
+
+	fft_sample->tsf = __cpu_to_be64(tsf);
+
+	/* max_exp has been directly reported by previous hardware (ath9k),
+	 * maybe its possible to get it by other means?
+	 */
+	fft_sample->max_exp = get_max_exp(fft_sample->max_index, peak_mag,
+					  bin_len, bins);
+
+	memcpy(fft_sample->data, bins, bin_len);
+
+	/* DC value (value in the middle) is the blind spot of the spectral
+	 * sample and invalid, interpolate it.
+	 */
+	dc_pos = bin_len / 2;
+	fft_sample->data[dc_pos] = (fft_sample->data[dc_pos + 1] +
+				    fft_sample->data[dc_pos - 1]) / 2;
+
+	ath10k_debug_send_fft_sample(ar, &fft_sample->tlv);
+
+	return 0;
+}
+
+static struct ath10k_vif *ath10k_get_spectral_vdev(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	if (list_empty(&ar->arvifs))
+		return NULL;
+
+	/* if there already is a vif doing spectral, return that. */
+	list_for_each_entry(arvif, &ar->arvifs, list)
+		if (arvif->spectral_enabled)
+			return arvif;
+
+	/* otherwise, return the first vif. */
+	return list_first_entry(&ar->arvifs, typeof(*arvif), list);
+}
+
+static int ath10k_spectral_scan_trigger(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+	int res;
+	int vdev_id;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	arvif = ath10k_get_spectral_vdev(ar);
+	if (!arvif)
+		return -ENODEV;
+	vdev_id = arvif->vdev_id;
+
+	if (ar->spectral.mode == SPECTRAL_DISABLED)
+		return 0;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (res < 0)
+		return res;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
+					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (res < 0)
+		return res;
+
+	return 0;
+}
+
+static int ath10k_spectral_scan_config(struct ath10k *ar,
+				       enum ath10k_spectral_mode mode)
+{
+	struct wmi_vdev_spectral_conf_arg arg;
+	struct ath10k_vif *arvif;
+	int vdev_id, count, res = 0;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	arvif = ath10k_get_spectral_vdev(ar);
+	if (!arvif)
+		return -ENODEV;
+
+	vdev_id = arvif->vdev_id;
+
+	arvif->spectral_enabled = (mode != SPECTRAL_DISABLED);
+	ar->spectral.mode = mode;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					      WMI_SPECTRAL_ENABLE_CMD_DISABLE);
+	if (res < 0) {
+		ath10k_warn("failed to enable spectral scan: %d\n", res);
+		return res;
+	}
+
+	if (mode == SPECTRAL_DISABLED)
+		return 0;
+
+	if (mode == SPECTRAL_BACKGROUND)
+		count = WMI_SPECTRAL_COUNT_DEFAULT;
+	else
+		count = max_t(u8, 1, ar->spectral.config.count);
+
+	arg.vdev_id = vdev_id;
+	arg.scan_count = count;
+	arg.scan_period = WMI_SPECTRAL_PERIOD_DEFAULT;
+	arg.scan_priority = WMI_SPECTRAL_PRIORITY_DEFAULT;
+	arg.scan_fft_size = ar->spectral.config.fft_size;
+	arg.scan_gc_ena = WMI_SPECTRAL_GC_ENA_DEFAULT;
+	arg.scan_restart_ena = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
+	arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
+	arg.scan_init_delay = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
+	arg.scan_nb_tone_thr = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
+	arg.scan_str_bin_thr = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
+	arg.scan_wb_rpt_mode = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
+	arg.scan_rssi_rpt_mode = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
+	arg.scan_rssi_thr = WMI_SPECTRAL_RSSI_THR_DEFAULT;
+	arg.scan_pwr_format = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
+	arg.scan_rpt_mode = WMI_SPECTRAL_RPT_MODE_DEFAULT;
+	arg.scan_bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	arg.scan_dbm_adj = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
+	arg.scan_chn_mask = WMI_SPECTRAL_CHN_MASK_DEFAULT;
+
+	res = ath10k_wmi_vdev_spectral_conf(ar, &arg);
+	if (res < 0) {
+		ath10k_warn("failed to configure spectral scan: %d\n", res);
+		return res;
+	}
+
+	return 0;
+}
+
+void ath10k_spectral_init(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	ar->spectral.mode = SPECTRAL_DISABLED;
+	ar->spectral.config.count = WMI_SPECTRAL_COUNT_DEFAULT;
+	ar->spectral.config.fft_size = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
+
+	list_for_each_entry(arvif, &ar->arvifs, list)
+		arvif->spectral_enabled = 0;
+}
+
+int ath10k_spectral_stop(struct ath10k_vif *arvif)
+{
+	if (!arvif->spectral_enabled)
+		return 0;
+
+	return ath10k_spectral_scan_config(arvif->ar, SPECTRAL_DISABLED);
+}
+
+static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char *mode = "";
+	unsigned int len;
+	enum ath10k_spectral_mode spectral_mode;
+
+	mutex_lock(&ar->conf_mutex);
+	spectral_mode = ar->spectral.mode;
+	mutex_unlock(&ar->conf_mutex);
+
+	switch (spectral_mode) {
+	case SPECTRAL_DISABLED:
+		mode = "disable";
+		break;
+	case SPECTRAL_BACKGROUND:
+		mode = "background";
+		break;
+	case SPECTRAL_MANUAL:
+		mode = "manual";
+		break;
+	}
+
+	len = strlen(mode);
+	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
+}
+
+static ssize_t write_file_spec_scan_ctl(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	ssize_t len;
+	int res;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (strncmp("trigger", buf, 7) == 0) {
+		if (ar->spectral.mode == SPECTRAL_MANUAL ||
+		    ar->spectral.mode == SPECTRAL_BACKGROUND) {
+			/* reset the configuration to adopt possibly changed
+			 * debugfs parameters
+			 */
+			res = ath10k_spectral_scan_config(ar,
+							  ar->spectral.mode);
+			if (res < 0) {
+				ath10k_warn("failed to reconfigure spectral scan: %d\n",
+					    res);
+			}
+			res = ath10k_spectral_scan_trigger(ar);
+			if (res < 0) {
+				ath10k_warn("failed to trigger spectral scan: %d\n",
+					    res);
+			}
+		} else {
+			res = -EINVAL;
+		}
+	} else if (strncmp("background", buf, 9) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
+	} else if (strncmp("manual", buf, 6) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
+	} else if (strncmp("disable", buf, 7) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
+	} else {
+		res = -EINVAL;
+	}
+
+	mutex_unlock(&ar->conf_mutex);
+
+	if (res < 0)
+		return res;
+
+	return count;
+}
+
+static const struct file_operations fops_spec_scan_ctl = {
+	.read = read_file_spec_scan_ctl,
+	.write = write_file_spec_scan_ctl,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static ssize_t read_file_spectral_count(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len;
+	u8 spectral_count;
+
+	mutex_lock(&ar->conf_mutex);
+	spectral_count = ar->spectral.config.count;
+	mutex_unlock(&ar->conf_mutex);
+
+	len = sprintf(buf, "%d\n", spectral_count);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_count(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 0 || val > 255)
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+	ar->spectral.config.count = val;
+	mutex_unlock(&ar->conf_mutex);
+
+	return count;
+}
+
+static const struct file_operations fops_spectral_count = {
+	.read = read_file_spectral_count,
+	.write = write_file_spectral_count,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static ssize_t read_file_spectral_bins(struct file *file,
+				       char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len, bins, fft_size, bin_scale;
+
+	mutex_lock(&ar->conf_mutex);
+
+	fft_size = ar->spectral.config.fft_size;
+	bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	bins = 1 << (fft_size - bin_scale);
+
+	mutex_unlock(&ar->conf_mutex);
+
+	len = sprintf(buf, "%d\n", bins);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_bins(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
+		return -EINVAL;
+
+	if (!is_power_of_2(val))
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+	ar->spectral.config.fft_size = ilog2(val);
+	ar->spectral.config.fft_size += WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	mutex_unlock(&ar->conf_mutex);
+
+	return count;
+}
+
+static const struct file_operations fops_spectral_bins = {
+	.read = read_file_spectral_bins,
+	.write = write_file_spectral_bins,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static struct dentry *create_buf_file_handler(const char *filename,
+					      struct dentry *parent,
+					      umode_t mode,
+					      struct rchan_buf *buf,
+					      int *is_global)
+{
+	struct dentry *buf_file;
+
+	buf_file = debugfs_create_file(filename, mode, parent, buf,
+				       &relay_file_operations);
+	*is_global = 1;
+	return buf_file;
+}
+
+static int remove_buf_file_handler(struct dentry *dentry)
+{
+	debugfs_remove(dentry);
+
+	return 0;
+}
+
+static struct rchan_callbacks rfs_spec_scan_cb = {
+	.create_buf_file = create_buf_file_handler,
+	.remove_buf_file = remove_buf_file_handler,
+};
+
+void ath10k_spectral_deinit_debug(struct ath10k *ar)
+{
+	if (ar->spectral.rfs_chan_spec_scan) {
+		relay_close(ar->spectral.rfs_chan_spec_scan);
+		ar->spectral.rfs_chan_spec_scan = NULL;
+	}
+}
+
+void ath10k_spectral_init_debug(struct ath10k *ar)
+{
+	ar->spectral.rfs_chan_spec_scan = relay_open("spectral_scan",
+						     ar->debug.debugfs_phy,
+						     1024, 256,
+						     &rfs_spec_scan_cb, NULL);
+	debugfs_create_file("spectral_scan_ctl",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spec_scan_ctl);
+	debugfs_create_file("spectral_count",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_count);
+	debugfs_create_file("spectral_bins",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_bins);
+}
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
new file mode 100644
index 0000000..55c1689
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_H
+#define SPECTRAL_H
+
+#include "../spectral_common.h"
+
+/**
+ * struct ath10k_spec_scan - parameters for Atheros spectral scan
+ *
+ * @count: number of scan results requested for manual mode
+ * @fft_size: number of bins to be requested = 2^(fft_size - bin_scale)
+ */
+struct ath10k_spec_scan {
+	u8 count;
+	u8 fft_size;
+};
+
+/* enum ath10k_spectral_mode:
+ *
+ * @SPECTRAL_DISABLED: spectral mode is disabled
+ * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
+ *	something else.
+ * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
+ *	is performed manually.
+ */
+enum ath10k_spectral_mode {
+	SPECTRAL_DISABLED = 0,
+	SPECTRAL_BACKGROUND,
+	SPECTRAL_MANUAL,
+};
+
+#ifdef CPTCFG_ATH10K_DEBUGFS
+void ath10k_spectral_init_debug(struct ath10k *ar);
+void ath10k_spectral_deinit_debug(struct ath10k *ar);
+int ath10k_process_fft(struct ath10k *ar,
+		       struct wmi_single_phyerr_rx_event *event,
+		       struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf);
+void ath10k_spectral_init(struct ath10k *ar);
+int ath10k_spectral_stop(struct ath10k_vif *arvif);
+#else
+static inline void ath10k_spectral_init_debug(struct ath10k *ar)
+{
+}
+
+static inline void ath10k_spectral_deinit_debug(struct ath10k *ar)
+{
+}
+
+static inline int
+ath10k_process_fft(struct ath10k *ar,
+		   struct wmi_single_phyerr_rx_event *event,
+		   struct phyerr_fft_report *fftr, size_t bin_len, u64 tsf)
+{
+	return 0;
+}
+
+static inline void ath10k_spectral_init(struct ath10k *ar)
+{
+}
+
+static inline int ath10k_spectral_stop(struct ath10k_vif *arvif)
+{
+	return 0;
+}
+#endif /* CPTCFG_ATH10K_DEBUGFS */
+
+#endif /* SPECTRAL_H */
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index c2c87c9..476bd65 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1659,7 +1659,53 @@ static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
 				struct wmi_single_phyerr_rx_event *event,
 				u64 tsf)
 {
-	ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n");
+	int buf_len, tlv_len, res, i = 0;
+	struct phyerr_tlv *tlv;
+	u8 *tlv_buf;
+	struct phyerr_fft_report *fftr;
+	size_t fftr_len;
+
+	buf_len = __le32_to_cpu(event->hdr.buf_len);
+
+	while (i < buf_len) {
+		if (i + sizeof(*tlv) > buf_len) {
+			ath10k_warn("failed to parse phyerr tlv header at byte %d\n",
+				    i);
+			return;
+		}
+
+		tlv = (struct phyerr_tlv *)&event->bufp[i];
+		tlv_len = __le16_to_cpu(tlv->len);
+		tlv_buf = &event->bufp[i + sizeof(*tlv)];
+
+		if (i + sizeof(*tlv) + tlv_len > buf_len) {
+			ath10k_warn("failed to parse phyerr tlv payload at byte %d\n",
+				    i);
+			return;
+		}
+
+		switch (tlv->tag) {
+		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
+			if (sizeof(*fftr) > tlv_len) {
+				ath10k_warn("failed to parse fft report at byte %d\n",
+					    i);
+				return;
+			}
+
+			fftr_len = tlv_len - sizeof(*fftr);
+			fftr = (struct phyerr_fft_report *)tlv_buf;
+			res = ath10k_process_fft(ar, event, fftr, fftr_len,
+						 tsf);
+			if (res < 0) {
+				ath10k_warn("failed to process fft report: %d\n",
+					    res);
+				return;
+			}
+			break;
+		}
+
+		i += sizeof(*tlv) + tlv_len;
+	}
 }
 
 static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
@@ -3236,6 +3282,62 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				   ar->wmi.cmd->vdev_install_key_cmdid);
 }
 
+int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
+				  const struct wmi_vdev_spectral_conf_arg *arg)
+{
+	struct wmi_vdev_spectral_conf_cmd *cmd;
+	struct sk_buff *skb;
+	u32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_conf_cmd *)skb->data;
+	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
+	cmd->scan_count = __cpu_to_le32(arg->scan_count);
+	cmd->scan_period = __cpu_to_le32(arg->scan_period);
+	cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
+	cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
+	cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
+	cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
+	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
+	cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
+	cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
+	cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
+	cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
+	cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
+	cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
+	cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
+	cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
+	cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
+	cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
+	cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_configure_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
+int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				    u32 enable)
+{
+	struct wmi_vdev_spectral_enable_cmd *cmd;
+	struct sk_buff *skb;
+	u32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_enable_cmd *)skb->data;
+	cmd->vdev_id = __cpu_to_le32(vdev_id);
+	cmd->trigger_cmd = __cpu_to_le32(trigger);
+	cmd->enable_cmd = __cpu_to_le32(enable);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_enable_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 			   const u8 peer_addr[ETH_ALEN])
 {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index e93df2c..ce940c8 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2067,6 +2067,7 @@ struct wmi_comb_phyerr_rx_event {
 #define PHYERR_TLV_SIG				0xBB
 #define PHYERR_TLV_TAG_SEARCH_FFT_REPORT	0xFB
 #define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY	0xF8
+#define PHYERR_TLV_TAG_SPECTRAL_SUMMARY_REPORT	0xF9
 
 struct phyerr_radar_report {
 	__le32 reg0; /* RADAR_REPORT_REG0_* */
@@ -3444,6 +3445,98 @@ struct wmi_vdev_simple_event {
 /* unsupported VDEV combination */
 #define WMI_INIFIED_VDEV_START_RESPONSE_NOT_SUPPORTED	0x2
 
+/* TODO: please add more comments if you have in-depth information */
+struct wmi_vdev_spectral_conf_cmd {
+	__le32 vdev_id;
+
+	/* number of fft samples to send (0 for infinite) */
+	__le32 scan_count;
+	__le32 scan_period;
+	__le32 scan_priority;
+
+	/* number of bins in the FFT: 2^(fft_size - bin_scale) */
+	__le32 scan_fft_size;
+	__le32 scan_gc_ena;
+	__le32 scan_restart_ena;
+	__le32 scan_noise_floor_ref;
+	__le32 scan_init_delay;
+	__le32 scan_nb_tone_thr;
+	__le32 scan_str_bin_thr;
+	__le32 scan_wb_rpt_mode;
+	__le32 scan_rssi_rpt_mode;
+	__le32 scan_rssi_thr;
+	__le32 scan_pwr_format;
+
+	/* rpt_mode: Format of FFT report to software for spectral scan
+	 * triggered FFTs:
+	 *	0: No FFT report (only spectral scan summary report)
+	 *	1: 2-dword summary of metrics for each completed FFT + spectral
+	 *	   scan	summary report
+	 *	2: 2-dword summary of metrics for each completed FFT +
+	 *	   1x- oversampled bins(in-band) per FFT + spectral scan summary
+	 *	   report
+	 *	3: 2-dword summary of metrics for each completed FFT +
+	 *	   2x- oversampled bins	(all) per FFT + spectral scan summary
+	 */
+	__le32 scan_rpt_mode;
+	__le32 scan_bin_scale;
+	__le32 scan_dbm_adj;
+	__le32 scan_chn_mask;
+} __packed;
+
+struct wmi_vdev_spectral_conf_arg {
+	u32 vdev_id;
+	u32 scan_count;
+	u32 scan_period;
+	u32 scan_priority;
+	u32 scan_fft_size;
+	u32 scan_gc_ena;
+	u32 scan_restart_ena;
+	u32 scan_noise_floor_ref;
+	u32 scan_init_delay;
+	u32 scan_nb_tone_thr;
+	u32 scan_str_bin_thr;
+	u32 scan_wb_rpt_mode;
+	u32 scan_rssi_rpt_mode;
+	u32 scan_rssi_thr;
+	u32 scan_pwr_format;
+	u32 scan_rpt_mode;
+	u32 scan_bin_scale;
+	u32 scan_dbm_adj;
+	u32 scan_chn_mask;
+};
+
+#define WMI_SPECTRAL_ENABLE_DEFAULT              0
+#define WMI_SPECTRAL_COUNT_DEFAULT               0
+#define WMI_SPECTRAL_PERIOD_DEFAULT             35
+#define WMI_SPECTRAL_PRIORITY_DEFAULT            1
+#define WMI_SPECTRAL_FFT_SIZE_DEFAULT            7
+#define WMI_SPECTRAL_GC_ENA_DEFAULT              1
+#define WMI_SPECTRAL_RESTART_ENA_DEFAULT         0
+#define WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT   -96
+#define WMI_SPECTRAL_INIT_DELAY_DEFAULT         80
+#define WMI_SPECTRAL_NB_TONE_THR_DEFAULT        12
+#define WMI_SPECTRAL_STR_BIN_THR_DEFAULT         8
+#define WMI_SPECTRAL_WB_RPT_MODE_DEFAULT         0
+#define WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT       0
+#define WMI_SPECTRAL_RSSI_THR_DEFAULT         0xf0
+#define WMI_SPECTRAL_PWR_FORMAT_DEFAULT          0
+#define WMI_SPECTRAL_RPT_MODE_DEFAULT            2
+#define WMI_SPECTRAL_BIN_SCALE_DEFAULT           1
+#define WMI_SPECTRAL_DBM_ADJ_DEFAULT             1
+#define WMI_SPECTRAL_CHN_MASK_DEFAULT            1
+
+struct wmi_vdev_spectral_enable_cmd {
+	__le32 vdev_id;
+	__le32 trigger_cmd;
+	__le32 enable_cmd;
+} __packed;
+
+#define WMI_SPECTRAL_TRIGGER_CMD_TRIGGER  1
+#define WMI_SPECTRAL_TRIGGER_CMD_CLEAR    2
+#define WMI_SPECTRAL_ENABLE_CMD_ENABLE    1
+#define WMI_SPECTRAL_ENABLE_CMD_DISABLE   2
+
 /* Beacon processing related command and event structures */
 struct wmi_bcn_tx_hdr {
 	__le32 vdev_id;
@@ -4290,6 +4383,10 @@ int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id,
 			      u32 param_id, u32 param_value);
 int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				const struct wmi_vdev_install_key_arg *arg);
+int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
+				  const struct wmi_vdev_spectral_conf_arg *arg);
+int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				    u32 enable);
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 		    const u8 peer_addr[ETH_ALEN]);
 int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
index b9ab722..0d742ac 100644
--- a/drivers/net/wireless/ath/spectral_common.h
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -20,6 +20,11 @@
 #define SPECTRAL_HT20_NUM_BINS		56
 #define SPECTRAL_HT20_40_NUM_BINS		128
 
+/* TODO: could possibly be 512, but no samples this large
+ * could be acquired so far.
+ */
+#define SPECTRAL_ATH10K_MAX_NUM_BINS		256
+
 /* FFT sample format given to userspace via debugfs.
  *
  * Please keep the type/length at the front position and change
@@ -31,6 +36,7 @@
 enum ath_fft_sample_type {
 	ATH_FFT_SAMPLE_HT20 = 1,
 	ATH_FFT_SAMPLE_HT20_40,
+	ATH_FFT_SAMPLE_ATH10K,
 };
 
 struct fft_sample_tlv {
@@ -85,4 +91,23 @@ struct fft_sample_ht20_40 {
 	u8 data[SPECTRAL_HT20_40_NUM_BINS];
 } __packed;
 
+struct fft_sample_ath10k {
+	struct fft_sample_tlv tlv;
+	u8 chan_width_mhz;
+	__be16 freq1;
+	__be16 freq2;
+	__be16 noise;
+	__be16 max_magnitude;
+	__be16 total_gain_db;
+	__be16 base_pwr_db;
+	__be64 tsf;
+	s8 max_index;
+	u8 rssi;
+	u8 relpwr_db;
+	u8 avgpwr_db;
+	u8 max_exp;
+
+	u8 data[0];
+} __packed;
+
 #endif /* SPECTRAL_COMMON_H */
-- 
1.9.1



From kvalo at qca.qualcomm.com  Wed Jul 23 10:37:23 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 23 Jul 2014 20:37:23 +0300
Subject: [PATCH v4 1/5] ath10k:  provide firmware crash info via debugfs.
In-Reply-To: <1406133487-7541-1-git-send-email-greearb@candelatech.com>
 (greearb@candelatech.com's message of "Wed, 23 Jul 2014 09:38:03
 -0700")
References: <1406133487-7541-1-git-send-email-greearb@candelatech.com>
Message-ID: <87a980rn70.fsf@kamboji.qca.qualcomm.com>

greearb at candelatech.com writes:

> From: Ben Greear <greearb at candelatech.com>
>
> Store the firmware crash registers and last 128 or so
> firmware debug-log ids and present them to user-space
> via debugfs.
>
> Should help with figuring out why the firmware crashed.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>
> ---
>
> v4:  Use _bh spinlock variants everywhere.
>
> For patch 0005:  Fix kmalloc/vfree problem. 

I see quite a few sparse and checkpatch warnings. But I think we can
ignore about LINUX_VERSION_CODE.

drivers/net/wireless/ath/ath10k/debug.c: In function 'ath10k_build_dump_file':
drivers/net/wireless/ath/ath10k/debug.c:685:2: warning: right shift count >= width of type [enabled by default]
drivers/net/wireless/ath/ath10k/debug.c:687:2: warning: right shift count >= width of type [enabled by default]
drivers/net/wireless/ath/ath10k/debug.c:685:49: warning: shift too big (32) for type long
drivers/net/wireless/ath/ath10k/debug.c:687:51: warning: shift too big (32) for type long
drivers/net/wireless/ath/ath10k/core.c:491:53: warning: cast to restricted __le32
drivers/net/wireless/ath/ath10k/core.c:492:52: warning: cast to restricted __le32
drivers/net/wireless/ath/ath10k/core.c:493:53: warning: cast to restricted __le32
drivers/net/wireless/ath/ath10k/core.c:494:52: warning: cast to restricted __le32
drivers/net/wireless/ath/ath10k/core.c:491: WARNING: line over 80 characters
drivers/net/wireless/ath/ath10k/core.c:492: WARNING: line over 80 characters
drivers/net/wireless/ath/ath10k/core.c:493: WARNING: line over 80 characters
drivers/net/wireless/ath/ath10k/core.c:494: WARNING: line over 80 characters
drivers/net/wireless/ath/ath10k/core.c:495: CHECK: multiple assignments should be avoided
drivers/net/wireless/ath/ath10k/debug.c:680: WARNING: LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged
drivers/net/wireless/ath/ath10k/debug.c:696: WARNING: line over 80 characters
drivers/net/wireless/ath/ath10k/debug.c:703: WARNING: line over 80 characters
drivers/net/wireless/ath/ath10k/debug.c:725: WARNING: line over 80 characters
drivers/net/wireless/ath/ath10k/debug.c:733: WARNING: line over 80 characters

-- 
Kalle Valo


From janusz.dziedzic at tieto.com  Thu Jul 24 00:17:29 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Thu, 24 Jul 2014 09:17:29 +0200
Subject: [PATCH] ath10k: extend debug code for RX path
In-Reply-To: <87egxdv0u2.fsf@kamboji.qca.qualcomm.com>
References: <1405672472-16302-1-git-send-email-janusz.dziedzic@tieto.com>
 <87egxdv0u2.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CALhHN=oOWgAhWL4B15OduHuL-qrLs3DaSMnpYJDa1xqmK=aZ6Q@mail.gmail.com>

On 22 July 2014 18:02, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:
>
>> Print sequence number, AMSDU_MORE flag and AC when additional
>> debug enabled in RX path. This is usefull for debugging purpose.
>>
>> Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
>> ---
>>  drivers/net/wireless/ath/ath10k/htt_rx.c |   32 ++++++++++++++++++++++++++++--
>>  1 file changed, 30 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
>> index 6db0e49..04140e3 100644
>> --- a/drivers/net/wireless/ath/ath10k/htt_rx.c
>> +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
>> @@ -819,19 +819,46 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
>>       return true;
>>  }
>>
>> +static char *tid_to_ac[] = {
>
> static const?
>
>> +     "BE(0)",
>> +     "BK(1)",
>> +     "BK(2)",
>> +     "BE(3)",
>> +     "VI(4)",
>> +     "VI(5)",
>> +     "VO(6)",
>> +     "VO(7)",
>> +     "tid(8)",
>> +     "tid(9)",
>> +     "tid(10)",
>> +     "tid(11)",
>> +     "tid(12)",
>> +     "tid(13)",
>> +     "tid(14)",
>> +     "tid(15)",
>> +};
>
> I don't see much point of adding tid number to the string when you could
> print it with "%i". Also about the string format, maybe this would be
> clearer:
>
> "rx skb %p len %u peer %pM tid %i (%s) sn %u"
>
> For example "...tid 4 (VI)..." and for tid > 7 we don't print "(VI)"
> part at all, just the number.
>
tid don't need to be always present (eg sta with disabled qos).
So I can use:
- table as above
- buffer[] + snprintf() + %i
Depends what you prefer here.

>>  static void ath10k_process_rx(struct ath10k *ar,
>>                             struct ieee80211_rx_status *rx_status,
>>                             struct sk_buff *skb)
>>  {
>>       struct ieee80211_rx_status *status;
>> +     struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
>>
>>       status = IEEE80211_SKB_RXCB(skb);
>>       *status = *rx_status;
>>
>>       ath10k_dbg(ATH10K_DBG_DATA,
>> -                "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %imic-err %i\n",
>> +                "rx skb %p len %u peer %pM %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
>>                  skb,
>>                  skb->len,
>> +                ieee80211_get_SA(hdr),
>
> This looks ok.
>
>> +                ieee80211_is_data_qos(hdr->frame_control) ?
>> +                     (tid_to_ac[*(ieee80211_get_qos_ctl(hdr)) &
>> +                                IEEE80211_QOS_CTL_TID_MASK]) :
>> +                     (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
>> +                             "mcast" : "ucast"),
>> +                (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4,
>
> But this is hard to read. Is it possible to have a helper function for
> this?
Sure I can put this in the function.

BR
Janusz


From janusz.dziedzic at tieto.com  Thu Jul 24 02:25:31 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Thu, 24 Jul 2014 11:25:31 +0200
Subject: [PATCH v2] ath10k: handle attention flags correctly when using A-MSDU
Message-ID: <1406193931-5478-1-git-send-email-janusz.dziedzic@tieto.com>

In case of A-MSDU RX we should check attention flags
correctly to be sure we report correct FCS status for
A-MSDU subframes. Without a patch we could report A-MSDU
subframes with wrong FCS as a correct to the stack, next
get a lot of DUP ACK TCP packets. Finally TP drop is seen
and this drop depends on FCS errors ratio for A-MSDU frame.

Example test case when TP drop is seen:
- ath10k configured as an AP
- used ath10k station
- forced A-MSDU (7 frames) on STA
- other traffic on channel (often FCS errors)
- monitor iface added on AP
- TCP STA -> AP traffic (iperf)

a) Iperf logs for case without the patch:

echo "1 64" > htt_max_amsdu_ampdu // disable A-MSDU
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 5.0 sec  56.6 MBytes  95.0 Mbits/sec
[  3]  5.0-10.0 sec  60.4 MBytes   101 Mbits/sec
[  3] 10.0-15.0 sec  60.2 MBytes   101 Mbits/sec
[  3] 15.0-20.0 sec  60.2 MBytes   101 Mbits/sec
[  3] 20.0-25.0 sec  63.8 MBytes   107 Mbits/sec
[  3] 25.0-30.0 sec  64.9 MBytes   109 Mbits/sec

echo "7 64" > htt_max_amsdu_ampdu  // set 7 A-MSDU subframes
[  3] 30.0-35.0 sec  40.0 MBytes  67.1 Mbits/sec
[  3] 35.0-40.0 sec  35.9 MBytes  60.2 Mbits/sec
[  3] 40.0-45.0 sec  36.9 MBytes  61.9 Mbits/sec
[  3] 45.0-50.0 sec  37.9 MBytes  63.5 Mbits/sec
[  3] 50.0-55.0 sec  34.5 MBytes  57.9 Mbits/sec
[  3] 55.0-60.0 sec  25.4 MBytes  42.6 Mbits/sec
[  3] 60.0-65.0 sec  48.2 MBytes  81.0 Mbits/sec
[  3] 65.0-70.0 sec  28.8 MBytes  48.2 Mbits/sec
[  3] 70.0-75.0 sec  29.2 MBytes  49.1 Mbits/sec
[  3] 75.0-80.0 sec  22.9 MBytes  38.4 Mbits/sec
[  3] 80.0-85.0 sec  26.4 MBytes  44.2 Mbits/sec
[  3] 85.0-90.0 sec  31.5 MBytes  52.8 Mbits/sec

b) Iperf logs for case with patch:

echo "1 64" > htt_max_amsdu_ampdu // disable A-MSDU
[  3] local 192.168.12.2 port 57512 connected with 192.168.12.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 5.0 sec  60.8 MBytes   102 Mbits/sec
[  3]  5.0-10.0 sec  62.2 MBytes   104 Mbits/sec
[  3] 10.0-15.0 sec  60.9 MBytes   102 Mbits/sec

echo "7 64" > htt_max_amsdu_ampdu  // set 7 A-MSDU subframes
[  3] 15.0-20.0 sec  68.1 MBytes   114 Mbits/sec
[  3] 20.0-25.0 sec  80.5 MBytes   135 Mbits/sec
[  3] 25.0-30.0 sec  83.0 MBytes   139 Mbits/sec
[  3] 30.0-35.0 sec  79.1 MBytes   133 Mbits/sec
[  3] 35.0-40.0 sec  77.1 MBytes   129 Mbits/sec
[  3] 40.0-45.0 sec  77.4 MBytes   130 Mbits/sec

Reported-by: Denton Gentry <denton.gentry at gmail.com>
Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
---
*v2 - changed commit message

 drivers/net/wireless/ath/ath10k/htt_rx.c |   23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 8e14c58..4767d22 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -307,7 +307,8 @@ static void ath10k_htt_rx_free_msdu_chain(struct sk_buff *skb)
 static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
 				   u8 **fw_desc, int *fw_desc_len,
 				   struct sk_buff **head_msdu,
-				   struct sk_buff **tail_msdu)
+				   struct sk_buff **tail_msdu,
+				   u32 *attention)
 {
 	int msdu_len, msdu_chaining = 0;
 	struct sk_buff *msdu;
@@ -357,6 +358,11 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
 			break;
 		}
 
+		*attention |= __le32_to_cpu(rx_desc->attention.flags) &
+					    (RX_ATTENTION_FLAGS_TKIP_MIC_ERR |
+					     RX_ATTENTION_FLAGS_DECRYPT_ERR |
+					     RX_ATTENTION_FLAGS_FCS_ERR |
+					     RX_ATTENTION_FLAGS_MGMT_TYPE);
 		/*
 		 * Copy the FW rx descriptor for this MSDU from the rx
 		 * indication message into the MSDU's netbuf. HL uses the
@@ -1256,13 +1262,15 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
 		for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) {
 			struct sk_buff *msdu_head, *msdu_tail;
 
+			attention = 0;
 			msdu_head = NULL;
 			msdu_tail = NULL;
 			ret = ath10k_htt_rx_amsdu_pop(htt,
 						      &fw_desc,
 						      &fw_desc_len,
 						      &msdu_head,
-						      &msdu_tail);
+						      &msdu_tail,
+						      &attention);
 
 			if (ret < 0) {
 				ath10k_warn("failed to pop amsdu from htt rx ring %d\n",
@@ -1274,7 +1282,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
 			rxd = container_of((void *)msdu_head->data,
 					   struct htt_rx_desc,
 					   msdu_payload);
-			attention = __le32_to_cpu(rxd->attention.flags);
 
 			if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head,
 							 status,
@@ -1327,6 +1334,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
 	u8 *fw_desc;
 	int fw_desc_len, hdrlen, paramlen;
 	int trim;
+	u32 attention = 0;
 
 	fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes);
 	fw_desc = (u8 *)frag->fw_msdu_rx_desc;
@@ -1336,7 +1344,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
 
 	spin_lock_bh(&htt->rx_ring.lock);
 	ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
-				      &msdu_head, &msdu_tail);
+				      &msdu_head, &msdu_tail,
+				      &attention);
 	spin_unlock_bh(&htt->rx_ring.lock);
 
 	ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
@@ -1353,10 +1362,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
 
 	hdr = (struct ieee80211_hdr *)msdu_head->data;
 	rxd = (void *)msdu_head->data - sizeof(*rxd);
-	tkip_mic_err = !!(__le32_to_cpu(rxd->attention.flags) &
-				RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
-	decrypt_err = !!(__le32_to_cpu(rxd->attention.flags) &
-				RX_ATTENTION_FLAGS_DECRYPT_ERR);
+	tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
+	decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
 	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
 			RX_MSDU_START_INFO1_DECAP_FORMAT);
 
-- 
1.7.9.5



From kvalo at qca.qualcomm.com  Thu Jul 24 02:29:07 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 24 Jul 2014 12:29:07 +0300
Subject: [PATCHv3-ath-resend 2/2] ath10k: add spectral scan feature
In-Reply-To: <1406136773-19957-1-git-send-email-sw@simonwunderlich.de> (Simon
 Wunderlich's message of "Wed, 23 Jul 2014 19:32:53 +0200")
References: <87mwc0ro8i.fsf@kamboji.qca.qualcomm.com>
 <1406136773-19957-1-git-send-email-sw@simonwunderlich.de>
Message-ID: <871ttbrtp8.fsf@kamboji.qca.qualcomm.com>

Simon Wunderlich <sw at simonwunderlich.de> writes:

> Adds the spectral scan feature for ath10k. The spectral scan is triggered by
> configuring a mode through a debugfs control file. Samples can be gathered via
> another relay debugfs file.
>
> Essentially, to try it out:
>
> ip link set dev wlan0 up
> echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> echo trigger > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> iw dev wlan0 scan
> echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
> cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples
>
> This feature is still experimental. Based on the original RFC patch of
> Sven Eckelmann.
>
> Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
> Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>

[...]

> diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
> index a4179f4..3241ef9 100644
> --- a/drivers/net/wireless/ath/ath10k/Makefile
> +++ b/drivers/net/wireless/ath/ath10k/Makefile
> @@ -10,6 +10,7 @@ ath10k_core-y += mac.o \
>  		 wmi.o \
>  		 bmi.o
>  
> +ath10k_core-$(CPTCFG_ATH10K_DEBUGFS) += spectral.o

This one still uses CPTCFG_ prefix, I'll fix those.

> @@ -800,8 +800,6 @@ int ath10k_core_start(struct ath10k *ar)
>  	else
>  		ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
>  
> -	INIT_LIST_HEAD(&ar->arvifs);
> -
>  	if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
>  		ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
>  			    ar->hw_params.name,
> @@ -1084,6 +1082,12 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
>  	INIT_WORK(&ar->register_work, ath10k_core_register_work);
>  	INIT_WORK(&ar->restart_work, ath10k_core_restart);
>  
> +	INIT_LIST_HEAD(&ar->arvifs);

I'm a bit suspicious about this, why is it needed?

-- 
Kalle Valo


From michal.kazior at tieto.com  Thu Jul 24 02:34:12 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 24 Jul 2014 11:34:12 +0200
Subject: [PATCHv3-ath-resend 2/2] ath10k: add spectral scan feature
In-Reply-To: <871ttbrtp8.fsf@kamboji.qca.qualcomm.com>
References: <87mwc0ro8i.fsf@kamboji.qca.qualcomm.com>
 <1406136773-19957-1-git-send-email-sw@simonwunderlich.de>
 <871ttbrtp8.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQkmEoJ4TTDvBE9cagUGRFPKWVBFjGcyXfMsHHD9-bdDJA@mail.gmail.com>

On 24 July 2014 11:29, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Simon Wunderlich <sw at simonwunderlich.de> writes:
>
>> Adds the spectral scan feature for ath10k. The spectral scan is triggered by
>> configuring a mode through a debugfs control file. Samples can be gathered via
>> another relay debugfs file.
>>
[...]
>> @@ -800,8 +800,6 @@ int ath10k_core_start(struct ath10k *ar)
>>       else
>>               ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
>>
>> -     INIT_LIST_HEAD(&ar->arvifs);
>> -
>>       if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
>>               ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
>>                           ar->hw_params.name,
>> @@ -1084,6 +1082,12 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
>>       INIT_WORK(&ar->register_work, ath10k_core_register_work);
>>       INIT_WORK(&ar->restart_work, ath10k_core_restart);
>>
>> +     INIT_LIST_HEAD(&ar->arvifs);
>
> I'm a bit suspicious about this, why is it needed?

Good hunch. ar->arvifs must be re-initialized in core_start for
recovery to work correctly.


Micha?


From sw at simonwunderlich.de  Thu Jul 24 02:36:07 2014
From: sw at simonwunderlich.de (Simon Wunderlich)
Date: Thu, 24 Jul 2014 11:36:07 +0200
Subject: [PATCHv3-ath-resend 2/2] ath10k: add spectral scan feature
In-Reply-To: <871ttbrtp8.fsf@kamboji.qca.qualcomm.com>
References: <87mwc0ro8i.fsf@kamboji.qca.qualcomm.com>
 <1406136773-19957-1-git-send-email-sw@simonwunderlich.de>
 <871ttbrtp8.fsf@kamboji.qca.qualcomm.com>
Message-ID: <201407241136.08090.sw@simonwunderlich.de>

> > +ath10k_core-$(CPTCFG_ATH10K_DEBUGFS) += spectral.o
> 
> This one still uses CPTCFG_ prefix, I'll fix those.
> 

Argh, OK, thanks!

> > @@ -800,8 +800,6 @@ int ath10k_core_start(struct ath10k *ar)
> > 
> >  	else
> >  	
> >  		ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
> > 
> > -	INIT_LIST_HEAD(&ar->arvifs);
> > -
> > 
> >  	if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
> >  	
> >  		ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
> >  		
> >  			    ar->hw_params.name,
> > 
> > @@ -1084,6 +1082,12 @@ struct ath10k *ath10k_core_create(void *hif_priv,
> > struct device *dev,
> > 
> >  	INIT_WORK(&ar->register_work, ath10k_core_register_work);
> >  	INIT_WORK(&ar->restart_work, ath10k_core_restart);
> > 
> > +	INIT_LIST_HEAD(&ar->arvifs);
> 
> I'm a bit suspicious about this, why is it needed?

ath10k_spectral_init() clears the spectral_enabled bit for each vif, and 
therefore needs the list to be initialized ... it is also called on firmware 
crash by ath10k_halt, where checking the list is more useful.

Thanks,
    Simon


From michal.kazior at tieto.com  Thu Jul 24 02:40:39 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 24 Jul 2014 11:40:39 +0200
Subject: [PATCHv3-ath-resend 2/2] ath10k: add spectral scan feature
In-Reply-To: <201407241136.08090.sw@simonwunderlich.de>
References: <87mwc0ro8i.fsf@kamboji.qca.qualcomm.com>
 <1406136773-19957-1-git-send-email-sw@simonwunderlich.de>
 <871ttbrtp8.fsf@kamboji.qca.qualcomm.com>
 <201407241136.08090.sw@simonwunderlich.de>
Message-ID: <CA+BoTQn13tktL9eZi8UD+=WR8fS+FFHML2ab8huvb1QdS49tiQ@mail.gmail.com>

On 24 July 2014 11:36, Simon Wunderlich <sw at simonwunderlich.de> wrote:
>> > @@ -800,8 +800,6 @@ int ath10k_core_start(struct ath10k *ar)
>> >
>> >     else
>> >
>> >             ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
>> >
>> > -   INIT_LIST_HEAD(&ar->arvifs);
>> > -
>> >
>> >     if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
>> >
>> >             ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
>> >
>> >                         ar->hw_params.name,
>> >
>> > @@ -1084,6 +1082,12 @@ struct ath10k *ath10k_core_create(void *hif_priv,
>> > struct device *dev,
>> >
>> >     INIT_WORK(&ar->register_work, ath10k_core_register_work);
>> >     INIT_WORK(&ar->restart_work, ath10k_core_restart);
>> >
>> > +   INIT_LIST_HEAD(&ar->arvifs);
>>
>> I'm a bit suspicious about this, why is it needed?
>
> ath10k_spectral_init() clears the spectral_enabled bit for each vif, and
> therefore needs the list to be initialized ... it is also called on firmware
> crash by ath10k_halt, where checking the list is more useful.

You don't really need to clear arvif->spectral_enabled on crash.
arvif's are re-inserted by mac80211 via ath10k_add_interface which
uses memset() to clear everything before adding to ar->arvifs.


Micha?


From kvalo at qca.qualcomm.com  Thu Jul 24 02:45:21 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 24 Jul 2014 12:45:21 +0300
Subject: [PATCHv3-ath-resend 2/2] ath10k: add spectral scan feature
In-Reply-To: <CA+BoTQkmEoJ4TTDvBE9cagUGRFPKWVBFjGcyXfMsHHD9-bdDJA@mail.gmail.com>
 (Michal Kazior's message of "Thu, 24 Jul 2014 11:34:12 +0200")
References: <87mwc0ro8i.fsf@kamboji.qca.qualcomm.com>
 <1406136773-19957-1-git-send-email-sw@simonwunderlich.de>
 <871ttbrtp8.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQkmEoJ4TTDvBE9cagUGRFPKWVBFjGcyXfMsHHD9-bdDJA@mail.gmail.com>
Message-ID: <87wqb3qedq.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> On 24 July 2014 11:29, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> Simon Wunderlich <sw at simonwunderlich.de> writes:
>>
>>> Adds the spectral scan feature for ath10k. The spectral scan is triggered by
>>> configuring a mode through a debugfs control file. Samples can be gathered via
>>> another relay debugfs file.
>>>
> [...]
>>> @@ -800,8 +800,6 @@ int ath10k_core_start(struct ath10k *ar)
>>>       else
>>>               ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
>>>
>>> -     INIT_LIST_HEAD(&ar->arvifs);
>>> -
>>>       if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
>>>               ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
>>>                           ar->hw_params.name,
>>> @@ -1084,6 +1082,12 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
>>>       INIT_WORK(&ar->register_work, ath10k_core_register_work);
>>>       INIT_WORK(&ar->restart_work, ath10k_core_restart);
>>>
>>> +     INIT_LIST_HEAD(&ar->arvifs);
>>
>> I'm a bit suspicious about this, why is it needed?
>
> Good hunch. ar->arvifs must be re-initialized in core_start for
> recovery to work correctly.

Thanks for the confirmation. I think I found a way to rework the
spectral initialisation which also fixes this issue, I'll send a new
version later today. Need to run some tests first.

-- 
Kalle Valo


From michal.kazior at tieto.com  Thu Jul 24 05:36:14 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 24 Jul 2014 14:36:14 +0200
Subject: [PATCH] ath10k: fix aggregated 4addr Rx
Message-ID: <1406205374-24858-1-git-send-email-michal.kazior@tieto.com>

A-MSDU 4addr frames weren't reconstructed properly
and in some cases this resulted in a warning:

 br0: received packet on wlan0.sta1 with own address as source address

Since this was only related to A-MSDU it would
trigger when more intense traffic was generated.

Reported-by: Vu Hai NGUYEN <vh.nguyen at actiasodielec.fr>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 318efc3..a8328f9 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -859,7 +859,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 	enum rx_msdu_decap_format fmt;
 	enum htt_rx_mpdu_encrypt_type enctype;
 	struct ieee80211_hdr *hdr;
-	u8 hdr_buf[64], addr[ETH_ALEN], *qos;
+	u8 hdr_buf[64], da[ETH_ALEN], sa[ETH_ALEN], *qos;
 	unsigned int hdr_len;
 
 	rxd = (void *)skb->data - sizeof(*rxd);
@@ -897,10 +897,11 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 			skb_trim(skb, skb->len - FCS_LEN);
 			break;
 		case RX_MSDU_DECAP_NATIVE_WIFI:
-			/* pull decapped header and copy DA */
+			/* pull decapped header and copy SA & DA */
 			hdr = (struct ieee80211_hdr *)skb->data;
 			hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
-			memcpy(addr, ieee80211_get_DA(hdr), ETH_ALEN);
+			memcpy(da, ieee80211_get_DA(hdr), ETH_ALEN);
+			memcpy(sa, ieee80211_get_SA(hdr), ETH_ALEN);
 			skb_pull(skb, hdr_len);
 
 			/* push original 802.11 header */
@@ -914,8 +915,11 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 			qos = ieee80211_get_qos_ctl(hdr);
 			qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
 
-			/* original 802.11 header has a different DA */
-			memcpy(ieee80211_get_DA(hdr), addr, ETH_ALEN);
+			/* original 802.11 header has a different DA and in
+			 * case of 4addr it may also have different SA
+			 */
+			memcpy(ieee80211_get_DA(hdr), da, ETH_ALEN);
+			memcpy(ieee80211_get_SA(hdr), sa, ETH_ALEN);
 			break;
 		case RX_MSDU_DECAP_ETHERNET2_DIX:
 			/* strip ethernet header and insert decapped 802.11
-- 
1.8.5.3



From kvalo at qca.qualcomm.com  Fri Jul 25 01:18:30 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 25 Jul 2014 11:18:30 +0300
Subject: [PATCH v4] ath10k: fix Rx aggregation reordering
In-Reply-To: <1406110833-14031-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Wed, 23 Jul 2014 12:20:33 +0200")
References: <1405509540-32691-1-git-send-email-michal.kazior@tieto.com>
 <1406110833-14031-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87ha25rgvd.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> Firmware doesn't perform Rx reordering so it is
> left to the host driver to do that.
>
> Use mac80211 to perform reordering instead of
> re-inventing the wheel.
>
> This fixes TCP throughput issues in some
> environments.
>
> Reported-by: Denton Gentry <denton.gentry at gmail.com>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Fri Jul 25 01:19:33 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 25 Jul 2014 11:19:33 +0300
Subject: [PATCH] ath10k: don't advertise IBSS iftype for 10.x
In-Reply-To: <1406109489-17928-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Wed, 23 Jul 2014 11:58:09 +0200")
References: <1406109489-17928-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87d2ctrgtm.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> The 10.x firmware does not support IBSS mode at
> all. It can't beacon and it crashes when trying to
> scan.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Fri Jul 25 01:56:04 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 25 Jul 2014 11:56:04 +0300
Subject: [PATCH v2] ath10k: handle attention flags correctly when using
 A-MSDU
In-Reply-To: <1406193931-5478-1-git-send-email-janusz.dziedzic@tieto.com>
 (Janusz Dziedzic's message of "Thu, 24 Jul 2014 11:25:31 +0200")
References: <1406193931-5478-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <871tt9rf4r.fsf@kamboji.qca.qualcomm.com>

Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:

> In case of A-MSDU RX we should check attention flags
> correctly to be sure we report correct FCS status for
> A-MSDU subframes. Without a patch we could report A-MSDU
> subframes with wrong FCS as a correct to the stack, next
> get a lot of DUP ACK TCP packets. Finally TP drop is seen
> and this drop depends on FCS errors ratio for A-MSDU frame.
>
> Example test case when TP drop is seen:
> - ath10k configured as an AP
> - used ath10k station
> - forced A-MSDU (7 frames) on STA
> - other traffic on channel (often FCS errors)
> - monitor iface added on AP
> - TCP STA -> AP traffic (iperf)
>
> a) Iperf logs for case without the patch:
>
> echo "1 64" > htt_max_amsdu_ampdu // disable A-MSDU
> [ ID] Interval       Transfer     Bandwidth
> [  3]  0.0- 5.0 sec  56.6 MBytes  95.0 Mbits/sec
> [  3]  5.0-10.0 sec  60.4 MBytes   101 Mbits/sec
> [  3] 10.0-15.0 sec  60.2 MBytes   101 Mbits/sec
> [  3] 15.0-20.0 sec  60.2 MBytes   101 Mbits/sec
> [  3] 20.0-25.0 sec  63.8 MBytes   107 Mbits/sec
> [  3] 25.0-30.0 sec  64.9 MBytes   109 Mbits/sec
>
> echo "7 64" > htt_max_amsdu_ampdu  // set 7 A-MSDU subframes
> [  3] 30.0-35.0 sec  40.0 MBytes  67.1 Mbits/sec
> [  3] 35.0-40.0 sec  35.9 MBytes  60.2 Mbits/sec
> [  3] 40.0-45.0 sec  36.9 MBytes  61.9 Mbits/sec
> [  3] 45.0-50.0 sec  37.9 MBytes  63.5 Mbits/sec
> [  3] 50.0-55.0 sec  34.5 MBytes  57.9 Mbits/sec
> [  3] 55.0-60.0 sec  25.4 MBytes  42.6 Mbits/sec
> [  3] 60.0-65.0 sec  48.2 MBytes  81.0 Mbits/sec
> [  3] 65.0-70.0 sec  28.8 MBytes  48.2 Mbits/sec
> [  3] 70.0-75.0 sec  29.2 MBytes  49.1 Mbits/sec
> [  3] 75.0-80.0 sec  22.9 MBytes  38.4 Mbits/sec
> [  3] 80.0-85.0 sec  26.4 MBytes  44.2 Mbits/sec
> [  3] 85.0-90.0 sec  31.5 MBytes  52.8 Mbits/sec
>
> b) Iperf logs for case with patch:
>
> echo "1 64" > htt_max_amsdu_ampdu // disable A-MSDU
> [  3] local 192.168.12.2 port 57512 connected with 192.168.12.1 port 5001
> [ ID] Interval       Transfer     Bandwidth
> [  3]  0.0- 5.0 sec  60.8 MBytes   102 Mbits/sec
> [  3]  5.0-10.0 sec  62.2 MBytes   104 Mbits/sec
> [  3] 10.0-15.0 sec  60.9 MBytes   102 Mbits/sec
>
> echo "7 64" > htt_max_amsdu_ampdu  // set 7 A-MSDU subframes
> [  3] 15.0-20.0 sec  68.1 MBytes   114 Mbits/sec
> [  3] 20.0-25.0 sec  80.5 MBytes   135 Mbits/sec
> [  3] 25.0-30.0 sec  83.0 MBytes   139 Mbits/sec
> [  3] 30.0-35.0 sec  79.1 MBytes   133 Mbits/sec
> [  3] 35.0-40.0 sec  77.1 MBytes   129 Mbits/sec
> [  3] 40.0-45.0 sec  77.4 MBytes   130 Mbits/sec
>
> Reported-by: Denton Gentry <denton.gentry at gmail.com>
> Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>

Thanks, applied.

> *v2 - changed commit message

And extra thanks to the good commit log. This is exactly what I want to
see in a commit log and I'm sure I'm not alone on this :)

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Fri Jul 25 02:10:57 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 25 Jul 2014 12:10:57 +0300
Subject: Pull request: ath 20140725
Message-ID: <87wqb1pzvi.fsf@kamboji.qca.qualcomm.com>

Hi John,

here's an ath10k pull request which I'm still hoping to get to 3.17,
especially because of the rx reordering and IBSS advertisement fixes.
But if we don't get these to 3.17 it won't be the end of the world
either :)

Please let me know if there are any problems.

The changelog:

Michal and Janusz did some important RX aggregation fixes, basically we
were missing RX reordering altogether. The 10.1 firmware doesn't support
Ad-Hoc mode and Michal fixed ath10k so that it doesn't advertise Ad-Hoc
support with that firmware. Also he implemented a workaround for a KVM
issue.


The following changes since commit bac9832076ee3b134bc859e07698c99276fc9459:

  b43: enable 5 GHz support for N-PHY devices (2014-07-23 13:08:36 -0400)

are available in the git repository at:

  git://github.com/kvalo/ath.git tags/for-linville-20140725

for you to fetch changes up to 0ccb7a3485e5526dca69f036b0d6c5148c78b3f8:

  ath10k: handle attention flags correctly when using A-MSDU (2014-07-25 11:51:07 +0300)

----------------------------------------------------------------
Janusz Dziedzic (1):
      ath10k: handle attention flags correctly when using A-MSDU

Kalle Valo (1):
      Merge remote-tracking branch 'wireless-next/master' into ath-next

Michal Kazior (7):
      ath10k: workaround boot issues with KVM/PCI-passthrough
      ath10k: prevent some tx flushing failures
      ath10k: simplify tx helpers
      ath10k: workaround qos nullfunc bug
      ath10k: prevent endless pci rx loop
      ath10k: fix Rx aggregation reordering
      ath10k: don't advertise IBSS iftype for 10.x

 drivers/net/wireless/ath/ath10k/htc.c    |   20 ++++-
 drivers/net/wireless/ath/ath10k/htt_rx.c |  122 +++++++++++++++++++++++++++---
 drivers/net/wireless/ath/ath10k/htt_tx.c |    6 ++
 drivers/net/wireless/ath/ath10k/mac.c    |   96 +++++++++++++++--------
 drivers/net/wireless/ath/ath10k/mac.h    |    4 +-
 drivers/net/wireless/ath/ath10k/pci.c    |   17 +++--
 drivers/net/wireless/ath/ath10k/txrx.c   |    3 +-
 drivers/net/wireless/ath/ath10k/txrx.h   |    1 +
 drivers/net/wireless/ath/ath10k/wmi.c    |    2 +-
 9 files changed, 217 insertions(+), 54 deletions(-)

-- 
Kalle Valo


From michal.kazior at tieto.com  Fri Jul 25 04:32:17 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Fri, 25 Jul 2014 13:32:17 +0200
Subject: [PATCH] ath10k: add support for 10.2 firmware
Message-ID: <1406287937-26507-1-git-send-email-michal.kazior@tieto.com>

The 10.2 firmware is a successor of 10.1 firmware
(formerly identified as 10.x). Both share a lot
but have some slight ABI differences that need to
be taken care of.

The 10.2 firmware introduces some new features but
those can be added in subsequent patches. This
patch makes ath10k boot and work with 10.2 with
comparable functionality to 10.1.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.c |  14 +
 drivers/net/wireless/ath/ath10k/core.h |   5 +
 drivers/net/wireless/ath/ath10k/hw.h   |   3 +-
 drivers/net/wireless/ath/ath10k/pci.c  |   2 +-
 drivers/net/wireless/ath/ath10k/wmi.c  | 453 +++++++++++++++++++++++++++++++--
 drivers/net/wireless/ath/ath10k/wmi.h  | 233 ++++++++++++++++-
 6 files changed, 680 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 93adb8c..bef797d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -499,6 +499,13 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 		goto err;
 	}
 
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
+	    !test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+		ath10k_err("feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
+		ret = -EINVAL;
+		goto err;
+	}
+
 	/* now fetch the board file */
 	if (ar->hw_params.fw.board == NULL) {
 		ath10k_err("board data file not defined");
@@ -531,6 +538,13 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
 {
 	int ret;
 
+	ar->fw_api = 3;
+	ath10k_dbg(ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
+
+	ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE);
+	if (ret == 0)
+		goto success;
+
 	ar->fw_api = 2;
 	ath10k_dbg(ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
 
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 83a5fa9..ded3af2 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -330,6 +330,11 @@ enum ath10k_fw_features {
 	/* Firmware does not support P2P */
 	ATH10K_FW_FEATURE_NO_P2P = 3,
 
+	/* Firmware 10.2 feature bit. The ATH10K_FW_FEATURE_WMI_10X feature bit
+	 * is required to be set as well.
+	 */
+	ATH10K_FW_FEATURE_WMI_10_2 = 4,
+
 	/* keep last */
 	ATH10K_FW_FEATURE_COUNT,
 };
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 007e855..ffd0489 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -28,12 +28,13 @@
 #define QCA988X_HW_2_0_CHIP_ID_REV	0x2
 #define QCA988X_HW_2_0_FW_DIR		"ath10k/QCA988X/hw2.0"
 #define QCA988X_HW_2_0_FW_FILE		"firmware.bin"
-#define QCA988X_HW_2_0_FW_2_FILE	"firmware-2.bin"
+#define QCA988X_HW_2_0_FW_3_FILE	"firmware-3.bin"
 #define QCA988X_HW_2_0_OTP_FILE		"otp.bin"
 #define QCA988X_HW_2_0_BOARD_DATA_FILE	"board.bin"
 #define QCA988X_HW_2_0_PATCH_LOAD_ADDR	0x1234
 
 #define ATH10K_FW_API2_FILE		"firmware-2.bin"
+#define ATH10K_FW_API3_FILE		"firmware-3.bin"
 
 /* includes also the null byte */
 #define ATH10K_FIRMWARE_MAGIC               "QCA-ATH10K"
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 0ffff20..2d340cc 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -2809,5 +2809,5 @@ module_exit(ath10k_pci_exit);
 MODULE_AUTHOR("Qualcomm Atheros");
 MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices");
 MODULE_LICENSE("Dual BSD/GPL");
-MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_2_FILE);
+MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_3_FILE);
 MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index c2c87c9..f96106f 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -487,6 +487,127 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
 	.burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE,
 };
 
+/* firmware 10.2 specific mappings */
+static struct wmi_cmd_map wmi_10_2_cmd_map = {
+	.init_cmdid = WMI_10_2_INIT_CMDID,
+	.start_scan_cmdid = WMI_10_2_START_SCAN_CMDID,
+	.stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID,
+	.scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID,
+	.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED,
+	.pdev_set_regdomain_cmdid = WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
+	.pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID,
+	.pdev_set_param_cmdid = WMI_10_2_PDEV_SET_PARAM_CMDID,
+	.pdev_pktlog_enable_cmdid = WMI_10_2_PDEV_PKTLOG_ENABLE_CMDID,
+	.pdev_pktlog_disable_cmdid = WMI_10_2_PDEV_PKTLOG_DISABLE_CMDID,
+	.pdev_set_wmm_params_cmdid = WMI_10_2_PDEV_SET_WMM_PARAMS_CMDID,
+	.pdev_set_ht_cap_ie_cmdid = WMI_10_2_PDEV_SET_HT_CAP_IE_CMDID,
+	.pdev_set_vht_cap_ie_cmdid = WMI_10_2_PDEV_SET_VHT_CAP_IE_CMDID,
+	.pdev_set_quiet_mode_cmdid = WMI_10_2_PDEV_SET_QUIET_MODE_CMDID,
+	.pdev_green_ap_ps_enable_cmdid = WMI_10_2_PDEV_GREEN_AP_PS_ENABLE_CMDID,
+	.pdev_get_tpc_config_cmdid = WMI_10_2_PDEV_GET_TPC_CONFIG_CMDID,
+	.pdev_set_base_macaddr_cmdid = WMI_10_2_PDEV_SET_BASE_MACADDR_CMDID,
+	.vdev_create_cmdid = WMI_10_2_VDEV_CREATE_CMDID,
+	.vdev_delete_cmdid = WMI_10_2_VDEV_DELETE_CMDID,
+	.vdev_start_request_cmdid = WMI_10_2_VDEV_START_REQUEST_CMDID,
+	.vdev_restart_request_cmdid = WMI_10_2_VDEV_RESTART_REQUEST_CMDID,
+	.vdev_up_cmdid = WMI_10_2_VDEV_UP_CMDID,
+	.vdev_stop_cmdid = WMI_10_2_VDEV_STOP_CMDID,
+	.vdev_down_cmdid = WMI_10_2_VDEV_DOWN_CMDID,
+	.vdev_set_param_cmdid = WMI_10_2_VDEV_SET_PARAM_CMDID,
+	.vdev_install_key_cmdid = WMI_10_2_VDEV_INSTALL_KEY_CMDID,
+	.peer_create_cmdid = WMI_10_2_PEER_CREATE_CMDID,
+	.peer_delete_cmdid = WMI_10_2_PEER_DELETE_CMDID,
+	.peer_flush_tids_cmdid = WMI_10_2_PEER_FLUSH_TIDS_CMDID,
+	.peer_set_param_cmdid = WMI_10_2_PEER_SET_PARAM_CMDID,
+	.peer_assoc_cmdid = WMI_10_2_PEER_ASSOC_CMDID,
+	.peer_add_wds_entry_cmdid = WMI_10_2_PEER_ADD_WDS_ENTRY_CMDID,
+	.peer_remove_wds_entry_cmdid = WMI_10_2_PEER_REMOVE_WDS_ENTRY_CMDID,
+	.peer_mcast_group_cmdid = WMI_10_2_PEER_MCAST_GROUP_CMDID,
+	.bcn_tx_cmdid = WMI_10_2_BCN_TX_CMDID,
+	.pdev_send_bcn_cmdid = WMI_10_2_PDEV_SEND_BCN_CMDID,
+	.bcn_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
+	.bcn_filter_rx_cmdid = WMI_10_2_BCN_FILTER_RX_CMDID,
+	.prb_req_filter_rx_cmdid = WMI_10_2_PRB_REQ_FILTER_RX_CMDID,
+	.mgmt_tx_cmdid = WMI_10_2_MGMT_TX_CMDID,
+	.prb_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
+	.addba_clear_resp_cmdid = WMI_10_2_ADDBA_CLEAR_RESP_CMDID,
+	.addba_send_cmdid = WMI_10_2_ADDBA_SEND_CMDID,
+	.addba_status_cmdid = WMI_10_2_ADDBA_STATUS_CMDID,
+	.delba_send_cmdid = WMI_10_2_DELBA_SEND_CMDID,
+	.addba_set_resp_cmdid = WMI_10_2_ADDBA_SET_RESP_CMDID,
+	.send_singleamsdu_cmdid = WMI_10_2_SEND_SINGLEAMSDU_CMDID,
+	.sta_powersave_mode_cmdid = WMI_10_2_STA_POWERSAVE_MODE_CMDID,
+	.sta_powersave_param_cmdid = WMI_10_2_STA_POWERSAVE_PARAM_CMDID,
+	.sta_mimo_ps_mode_cmdid = WMI_10_2_STA_MIMO_PS_MODE_CMDID,
+	.pdev_dfs_enable_cmdid = WMI_10_2_PDEV_DFS_ENABLE_CMDID,
+	.pdev_dfs_disable_cmdid = WMI_10_2_PDEV_DFS_DISABLE_CMDID,
+	.roam_scan_mode = WMI_10_2_ROAM_SCAN_MODE,
+	.roam_scan_rssi_threshold = WMI_10_2_ROAM_SCAN_RSSI_THRESHOLD,
+	.roam_scan_period = WMI_10_2_ROAM_SCAN_PERIOD,
+	.roam_scan_rssi_change_threshold =
+				WMI_10_2_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
+	.roam_ap_profile = WMI_10_2_ROAM_AP_PROFILE,
+	.ofl_scan_add_ap_profile = WMI_10_2_OFL_SCAN_ADD_AP_PROFILE,
+	.ofl_scan_remove_ap_profile = WMI_10_2_OFL_SCAN_REMOVE_AP_PROFILE,
+	.ofl_scan_period = WMI_10_2_OFL_SCAN_PERIOD,
+	.p2p_dev_set_device_info = WMI_10_2_P2P_DEV_SET_DEVICE_INFO,
+	.p2p_dev_set_discoverability = WMI_10_2_P2P_DEV_SET_DISCOVERABILITY,
+	.p2p_go_set_beacon_ie = WMI_10_2_P2P_GO_SET_BEACON_IE,
+	.p2p_go_set_probe_resp_ie = WMI_10_2_P2P_GO_SET_PROBE_RESP_IE,
+	.p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED,
+	.ap_ps_peer_param_cmdid = WMI_10_2_AP_PS_PEER_PARAM_CMDID,
+	.ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED,
+	.peer_rate_retry_sched_cmdid = WMI_10_2_PEER_RATE_RETRY_SCHED_CMDID,
+	.wlan_profile_trigger_cmdid = WMI_10_2_WLAN_PROFILE_TRIGGER_CMDID,
+	.wlan_profile_set_hist_intvl_cmdid =
+				WMI_10_2_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
+	.wlan_profile_get_profile_data_cmdid =
+				WMI_10_2_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
+	.wlan_profile_enable_profile_id_cmdid =
+				WMI_10_2_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
+	.wlan_profile_list_profile_id_cmdid =
+				WMI_10_2_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
+	.pdev_suspend_cmdid = WMI_10_2_PDEV_SUSPEND_CMDID,
+	.pdev_resume_cmdid = WMI_10_2_PDEV_RESUME_CMDID,
+	.add_bcn_filter_cmdid = WMI_10_2_ADD_BCN_FILTER_CMDID,
+	.rmv_bcn_filter_cmdid = WMI_10_2_RMV_BCN_FILTER_CMDID,
+	.wow_add_wake_pattern_cmdid = WMI_10_2_WOW_ADD_WAKE_PATTERN_CMDID,
+	.wow_del_wake_pattern_cmdid = WMI_10_2_WOW_DEL_WAKE_PATTERN_CMDID,
+	.wow_enable_disable_wake_event_cmdid =
+				WMI_10_2_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
+	.wow_enable_cmdid = WMI_10_2_WOW_ENABLE_CMDID,
+	.wow_hostwakeup_from_sleep_cmdid =
+				WMI_10_2_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
+	.rtt_measreq_cmdid = WMI_10_2_RTT_MEASREQ_CMDID,
+	.rtt_tsf_cmdid = WMI_10_2_RTT_TSF_CMDID,
+	.vdev_spectral_scan_configure_cmdid =
+				WMI_10_2_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
+	.vdev_spectral_scan_enable_cmdid =
+				WMI_10_2_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
+	.request_stats_cmdid = WMI_10_2_REQUEST_STATS_CMDID,
+	.set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED,
+	.network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED,
+	.gtk_offload_cmdid = WMI_CMD_UNSUPPORTED,
+	.csa_offload_enable_cmdid = WMI_CMD_UNSUPPORTED,
+	.csa_offload_chanswitch_cmdid = WMI_CMD_UNSUPPORTED,
+	.chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED,
+	.peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED,
+	.peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED,
+	.sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED,
+	.sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED,
+	.sta_keepalive_cmd = WMI_CMD_UNSUPPORTED,
+	.echo_cmdid = WMI_10_2_ECHO_CMDID,
+	.pdev_utf_cmdid = WMI_10_2_PDEV_UTF_CMDID,
+	.dbglog_cfg_cmdid = WMI_10_2_DBGLOG_CFG_CMDID,
+	.pdev_qvit_cmdid = WMI_10_2_PDEV_QVIT_CMDID,
+	.pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED,
+	.vdev_set_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
+	.vdev_get_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
+	.force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED,
+	.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
+	.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
+};
+
 int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
 {
 	int ret;
@@ -2325,20 +2446,146 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
 	dev_kfree_skb(skb);
 }
 
+static void ath10k_wmi_10_2_process_rx(struct ath10k *ar, struct sk_buff *skb)
+{
+	struct wmi_cmd_hdr *cmd_hdr;
+	enum wmi_10_2_event_id id;
+
+	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
+	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
+
+	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
+		return;
+
+	trace_ath10k_wmi_event(id, skb->data, skb->len);
+
+	switch (id) {
+
+
+	case WMI_10_2_MGMT_RX_EVENTID:
+		ath10k_wmi_event_mgmt_rx(ar, skb);
+		/* mgmt_rx() owns the skb now! */
+		return;
+	case WMI_10_2_SCAN_EVENTID:
+		ath10k_wmi_event_scan(ar, skb);
+		break;
+	case WMI_10_2_CHAN_INFO_EVENTID:
+		ath10k_wmi_event_chan_info(ar, skb);
+		break;
+	case WMI_10_2_ECHO_EVENTID:
+		ath10k_wmi_event_echo(ar, skb);
+		break;
+	case WMI_10_2_DEBUG_MESG_EVENTID:
+		ath10k_wmi_event_debug_mesg(ar, skb);
+		break;
+	case WMI_10_2_UPDATE_STATS_EVENTID:
+		ath10k_wmi_event_update_stats(ar, skb);
+		break;
+	case WMI_10_2_VDEV_START_RESP_EVENTID:
+		ath10k_wmi_event_vdev_start_resp(ar, skb);
+		break;
+	case WMI_10_2_VDEV_STOPPED_EVENTID:
+		ath10k_wmi_event_vdev_stopped(ar, skb);
+		break;
+	case WMI_10_2_PEER_STA_KICKOUT_EVENTID:
+		ath10k_wmi_event_peer_sta_kickout(ar, skb);
+		break;
+	case WMI_10_2_HOST_SWBA_EVENTID:
+		ath10k_wmi_event_host_swba(ar, skb);
+		break;
+	case WMI_10_2_TBTTOFFSET_UPDATE_EVENTID:
+		ath10k_wmi_event_tbttoffset_update(ar, skb);
+		break;
+	case WMI_10_2_PHYERR_EVENTID:
+		ath10k_wmi_event_phyerr(ar, skb);
+		break;
+	case WMI_10_2_ROAM_EVENTID:
+		ath10k_wmi_event_roam(ar, skb);
+		break;
+	case WMI_10_2_PROFILE_MATCH:
+		ath10k_wmi_event_profile_match(ar, skb);
+		break;
+	case WMI_10_2_DEBUG_PRINT_EVENTID:
+		ath10k_wmi_event_debug_print(ar, skb);
+		break;
+	case WMI_10_2_PDEV_QVIT_EVENTID:
+		ath10k_wmi_event_pdev_qvit(ar, skb);
+		break;
+	case WMI_10_2_WLAN_PROFILE_DATA_EVENTID:
+		ath10k_wmi_event_wlan_profile_data(ar, skb);
+		break;
+	case WMI_10_2_RTT_MEASUREMENT_REPORT_EVENTID:
+		ath10k_wmi_event_rtt_measurement_report(ar, skb);
+		break;
+	case WMI_10_2_TSF_MEASUREMENT_REPORT_EVENTID:
+		ath10k_wmi_event_tsf_measurement_report(ar, skb);
+		break;
+	case WMI_10_2_RTT_ERROR_REPORT_EVENTID:
+		ath10k_wmi_event_rtt_error_report(ar, skb);
+		break;
+	case WMI_10_2_WOW_WAKEUP_HOST_EVENTID:
+		ath10k_wmi_event_wow_wakeup_host(ar, skb);
+		break;
+	case WMI_10_2_DCS_INTERFERENCE_EVENTID:
+		ath10k_wmi_event_dcs_interference(ar, skb);
+		break;
+	case WMI_10_2_PDEV_TPC_CONFIG_EVENTID:
+		ath10k_wmi_event_pdev_tpc_config(ar, skb);
+		break;
+	case WMI_10_2_INST_RSSI_STATS_EVENTID:
+		ath10k_wmi_event_inst_rssi_stats(ar, skb);
+		break;
+	case WMI_10_2_VDEV_STANDBY_REQ_EVENTID:
+		ath10k_wmi_event_vdev_standby_req(ar, skb);
+		break;
+	case WMI_10_2_VDEV_RESUME_REQ_EVENTID:
+		ath10k_wmi_event_vdev_resume_req(ar, skb);
+		break;
+	case WMI_10_2_SERVICE_READY_EVENTID:
+		ath10k_wmi_10x_service_ready_event_rx(ar, skb);
+		break;
+	case WMI_10_2_READY_EVENTID:
+		ath10k_wmi_ready_event_rx(ar, skb);
+		break;
+	case WMI_10_2_RTT_KEEPALIVE_EVENTID:
+	case WMI_10_2_GPIO_INPUT_EVENTID:
+	case WMI_10_2_PEER_RATECODE_LIST_EVENTID:
+	case WMI_10_2_GENERIC_BUFFER_EVENTID:
+	case WMI_10_2_MCAST_BUF_RELEASE_EVENTID:
+	case WMI_10_2_MCAST_LIST_AGEOUT_EVENTID:
+	case WMI_10_2_WDS_PEER_EVENTID:
+		ath10k_dbg(ATH10K_DBG_WMI,
+			   "received event id %d not implemented\n", id);
+		break;
+	default:
+		ath10k_warn("Unknown eventid: %d\n", id);
+		break;
+	}
+
+	dev_kfree_skb(skb);
+}
 
 static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
 {
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-		ath10k_wmi_10x_process_rx(ar, skb);
-	else
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+		if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
+			ath10k_wmi_10_2_process_rx(ar, skb);
+		else
+			ath10k_wmi_10x_process_rx(ar, skb);
+	} else {
 		ath10k_wmi_main_process_rx(ar, skb);
+	}
 }
 
 /* WMI Initialization functions */
 int ath10k_wmi_attach(struct ath10k *ar)
 {
 	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-		ar->wmi.cmd = &wmi_10x_cmd_map;
+		if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
+			ar->wmi.cmd = &wmi_10_2_cmd_map;
+		else
+			ar->wmi.cmd = &wmi_10x_cmd_map;
+
 		ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
 		ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
 	} else {
@@ -2738,14 +2985,109 @@ out:
 	return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
 }
 
+static int ath10k_wmi_10_2_cmd_init(struct ath10k *ar)
+{
+	struct wmi_init_cmd_10_2 *cmd;
+	struct sk_buff *buf;
+	struct wmi_resource_config_10x config = {};
+	u32 len, val;
+	int i;
+
+	config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
+	config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
+	config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS);
+	config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS);
+	config.ast_skid_limit = __cpu_to_le32(TARGET_10X_AST_SKID_LIMIT);
+	config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK);
+	config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK);
+	config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
+	config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
+	config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
+	config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI);
+	config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE);
+
+	config.scan_max_pending_reqs =
+		__cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS);
+
+	config.bmiss_offload_max_vdev =
+		__cpu_to_le32(TARGET_10X_BMISS_OFFLOAD_MAX_VDEV);
+
+	config.roam_offload_max_vdev =
+		__cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_VDEV);
+
+	config.roam_offload_max_ap_profiles =
+		__cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES);
+
+	config.num_mcast_groups = __cpu_to_le32(TARGET_10X_NUM_MCAST_GROUPS);
+	config.num_mcast_table_elems =
+		__cpu_to_le32(TARGET_10X_NUM_MCAST_TABLE_ELEMS);
+
+	config.mcast2ucast_mode = __cpu_to_le32(TARGET_10X_MCAST2UCAST_MODE);
+	config.tx_dbg_log_size = __cpu_to_le32(TARGET_10X_TX_DBG_LOG_SIZE);
+	config.num_wds_entries = __cpu_to_le32(TARGET_10X_NUM_WDS_ENTRIES);
+	config.dma_burst_size = __cpu_to_le32(TARGET_10X_DMA_BURST_SIZE);
+	config.mac_aggr_delim = __cpu_to_le32(TARGET_10X_MAC_AGGR_DELIM);
+
+	val = TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK;
+	config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val);
+
+	config.vow_config = __cpu_to_le32(TARGET_10X_VOW_CONFIG);
+
+	config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC);
+	config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES);
+
+	len = sizeof(*cmd) +
+	      (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
+
+	buf = ath10k_wmi_alloc_skb(len);
+	if (!buf)
+		return -ENOMEM;
+
+	cmd = (struct wmi_init_cmd_10_2 *)buf->data;
+
+	if (ar->wmi.num_mem_chunks == 0) {
+		cmd->num_host_mem_chunks = 0;
+		goto out;
+	}
+
+	ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
+		   ar->wmi.num_mem_chunks);
+
+	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
+
+	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+		cmd->host_mem_chunks[i].ptr =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
+		cmd->host_mem_chunks[i].size =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].len);
+		cmd->host_mem_chunks[i].req_id =
+			__cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
+
+		ath10k_dbg(ATH10K_DBG_WMI,
+			   "wmi chunk %d len %d requested, addr 0x%llx\n",
+			   i,
+			   ar->wmi.mem_chunks[i].len,
+			   (unsigned long long)ar->wmi.mem_chunks[i].paddr);
+	}
+out:
+	memcpy(&cmd->resource_config.common, &config, sizeof(config));
+
+	ath10k_dbg(ATH10K_DBG_WMI, "wmi init 10.2\n");
+	return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
+}
+
 int ath10k_wmi_cmd_init(struct ath10k *ar)
 {
 	int ret;
 
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-		ret = ath10k_wmi_10x_cmd_init(ar);
-	else
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+		if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
+			ret = ath10k_wmi_10_2_cmd_init(ar);
+		else
+			ret = ath10k_wmi_10x_cmd_init(ar);
+	} else {
 		ret = ath10k_wmi_main_cmd_init(ar);
+	}
 
 	return ret;
 }
@@ -2865,8 +3207,8 @@ int ath10k_wmi_start_scan(struct ath10k *ar,
 		channels->num_chan = __cpu_to_le32(arg->n_channels);
 
 		for (i = 0; i < arg->n_channels; i++)
-			channels->channel_list[i] =
-				__cpu_to_le32(arg->channels[i]);
+			channels->channel_list[i].freq =
+				__cpu_to_le16(arg->channels[i]);
 
 		off += sizeof(*channels);
 		off += sizeof(__le32) * arg->n_channels;
@@ -3447,24 +3789,12 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar,
 	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid);
 }
 
-int ath10k_wmi_peer_assoc(struct ath10k *ar,
-			  const struct wmi_peer_assoc_complete_arg *arg)
+static void
+ath10k_wmi_peer_assoc_fill(struct ath10k *ar, void *buf,
+			   const struct wmi_peer_assoc_complete_arg *arg)
 {
-	struct wmi_peer_assoc_complete_cmd *cmd;
-	struct sk_buff *skb;
+	struct wmi_common_peer_assoc_complete_cmd *cmd = buf;
 
-	if (arg->peer_mpdu_density > 16)
-		return -EINVAL;
-	if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
-		return -EINVAL;
-	if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
-		return -EINVAL;
-
-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-	if (!skb)
-		return -ENOMEM;
-
-	cmd = (struct wmi_peer_assoc_complete_cmd *)skb->data;
 	cmd->vdev_id            = __cpu_to_le32(arg->vdev_id);
 	cmd->peer_new_assoc     = __cpu_to_le32(arg->peer_reassoc ? 0 : 1);
 	cmd->peer_associd       = __cpu_to_le32(arg->peer_aid);
@@ -3499,6 +3829,78 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar,
 		__cpu_to_le32(arg->peer_vht_rates.tx_max_rate);
 	cmd->peer_vht_rates.tx_mcs_set =
 		__cpu_to_le32(arg->peer_vht_rates.tx_mcs_set);
+}
+
+static void
+ath10k_wmi_peer_assoc_fill_main_636(struct ath10k *ar, void *buf,
+				    const struct wmi_peer_assoc_complete_arg *arg)
+{
+	struct wmi_main_636_peer_assoc_complete_cmd *cmd = buf;
+
+	ath10k_wmi_peer_assoc_fill(ar, buf, arg);
+	memset(cmd->peer_ht_info, 0, sizeof(cmd->peer_ht_info));
+}
+
+static void
+ath10k_wmi_peer_assoc_fill_10_1(struct ath10k *ar, void *buf,
+				const struct wmi_peer_assoc_complete_arg *arg)
+{
+	ath10k_wmi_peer_assoc_fill(ar, buf, arg);
+}
+
+static void
+ath10k_wmi_peer_assoc_fill_10_2(struct ath10k *ar, void *buf,
+				const struct wmi_peer_assoc_complete_arg *arg)
+{
+	struct wmi_10_2_peer_assoc_complete_cmd *cmd = buf;
+	int max_mcs, max_nss;
+	u32 info0;
+
+	/* TODO: Is using max values okay with firmware? */
+	max_mcs = 0xf;
+	max_nss = 0xf;
+
+	info0 = SM(max_mcs, WMI_PEER_ASSOC_INFO0_MAX_MCS_IDX) |
+		SM(max_nss, WMI_PEER_ASSOC_INFO0_MAX_NSS);
+
+	ath10k_wmi_peer_assoc_fill(ar, buf, arg);
+	cmd->info0 = __cpu_to_le32(info0);
+}
+
+int ath10k_wmi_peer_assoc(struct ath10k *ar,
+			  const struct wmi_peer_assoc_complete_arg *arg)
+{
+	struct sk_buff *skb;
+	int len;
+
+	if (arg->peer_mpdu_density > 16)
+		return -EINVAL;
+	if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
+		return -EINVAL;
+	if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
+		return -EINVAL;
+
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+		if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
+			len = sizeof(struct wmi_10_2_peer_assoc_complete_cmd);
+		else
+			len = sizeof(struct wmi_10_1_peer_assoc_complete_cmd);
+	} else {
+		len = sizeof(struct wmi_main_636_peer_assoc_complete_cmd);
+	}
+
+	skb = ath10k_wmi_alloc_skb(len);
+	if (!skb)
+		return -ENOMEM;
+
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+		if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
+			ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg);
+		else
+			ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg);
+	} else {
+		ath10k_wmi_peer_assoc_fill_main_636(ar, skb->data, arg);
+	}
 
 	ath10k_dbg(ATH10K_DBG_WMI,
 		   "wmi peer assoc vdev %d addr %pM (%s)\n",
@@ -3532,6 +3934,7 @@ int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif)
 	cmd->msdu_id = 0;
 	cmd->frame_control = __cpu_to_le32(fc);
 	cmd->flags = 0;
+	cmd->antenna_mask = __cpu_to_le32(WMI_BCN_TX_REF_DEF_ANTENNA);
 
 	if (ATH10K_SKB_CB(beacon)->bcn.dtim_zero)
 		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index e93df2c..a29f082 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -803,6 +803,159 @@ enum wmi_10x_event_id {
 	WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID-1,
 };
 
+enum wmi_10_2_cmd_id {
+	WMI_10_2_START_CMDID = 0x9000,
+	WMI_10_2_END_CMDID = 0x9FFF,
+	WMI_10_2_INIT_CMDID,
+	WMI_10_2_START_SCAN_CMDID = WMI_10_2_START_CMDID,
+	WMI_10_2_STOP_SCAN_CMDID,
+	WMI_10_2_SCAN_CHAN_LIST_CMDID,
+	WMI_10_2_ECHO_CMDID,
+	WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
+	WMI_10_2_PDEV_SET_CHANNEL_CMDID,
+	WMI_10_2_PDEV_SET_PARAM_CMDID,
+	WMI_10_2_PDEV_PKTLOG_ENABLE_CMDID,
+	WMI_10_2_PDEV_PKTLOG_DISABLE_CMDID,
+	WMI_10_2_PDEV_SET_WMM_PARAMS_CMDID,
+	WMI_10_2_PDEV_SET_HT_CAP_IE_CMDID,
+	WMI_10_2_PDEV_SET_VHT_CAP_IE_CMDID,
+	WMI_10_2_PDEV_SET_BASE_MACADDR_CMDID,
+	WMI_10_2_PDEV_SET_QUIET_MODE_CMDID,
+	WMI_10_2_PDEV_GREEN_AP_PS_ENABLE_CMDID,
+	WMI_10_2_PDEV_GET_TPC_CONFIG_CMDID,
+	WMI_10_2_VDEV_CREATE_CMDID,
+	WMI_10_2_VDEV_DELETE_CMDID,
+	WMI_10_2_VDEV_START_REQUEST_CMDID,
+	WMI_10_2_VDEV_RESTART_REQUEST_CMDID,
+	WMI_10_2_VDEV_UP_CMDID,
+	WMI_10_2_VDEV_STOP_CMDID,
+	WMI_10_2_VDEV_DOWN_CMDID,
+	WMI_10_2_VDEV_STANDBY_RESPONSE_CMDID,
+	WMI_10_2_VDEV_RESUME_RESPONSE_CMDID,
+	WMI_10_2_VDEV_SET_PARAM_CMDID,
+	WMI_10_2_VDEV_INSTALL_KEY_CMDID,
+	WMI_10_2_VDEV_SET_DSCP_TID_MAP_CMDID,
+	WMI_10_2_PEER_CREATE_CMDID,
+	WMI_10_2_PEER_DELETE_CMDID,
+	WMI_10_2_PEER_FLUSH_TIDS_CMDID,
+	WMI_10_2_PEER_SET_PARAM_CMDID,
+	WMI_10_2_PEER_ASSOC_CMDID,
+	WMI_10_2_PEER_ADD_WDS_ENTRY_CMDID,
+	WMI_10_2_PEER_UPDATE_WDS_ENTRY_CMDID,
+	WMI_10_2_PEER_REMOVE_WDS_ENTRY_CMDID,
+	WMI_10_2_PEER_MCAST_GROUP_CMDID,
+	WMI_10_2_BCN_TX_CMDID,
+	WMI_10_2_BCN_PRB_TMPL_CMDID,
+	WMI_10_2_BCN_FILTER_RX_CMDID,
+	WMI_10_2_PRB_REQ_FILTER_RX_CMDID,
+	WMI_10_2_MGMT_TX_CMDID,
+	WMI_10_2_ADDBA_CLEAR_RESP_CMDID,
+	WMI_10_2_ADDBA_SEND_CMDID,
+	WMI_10_2_ADDBA_STATUS_CMDID,
+	WMI_10_2_DELBA_SEND_CMDID,
+	WMI_10_2_ADDBA_SET_RESP_CMDID,
+	WMI_10_2_SEND_SINGLEAMSDU_CMDID,
+	WMI_10_2_STA_POWERSAVE_MODE_CMDID,
+	WMI_10_2_STA_POWERSAVE_PARAM_CMDID,
+	WMI_10_2_STA_MIMO_PS_MODE_CMDID,
+	WMI_10_2_DBGLOG_CFG_CMDID,
+	WMI_10_2_PDEV_DFS_ENABLE_CMDID,
+	WMI_10_2_PDEV_DFS_DISABLE_CMDID,
+	WMI_10_2_PDEV_QVIT_CMDID,
+	WMI_10_2_ROAM_SCAN_MODE,
+	WMI_10_2_ROAM_SCAN_RSSI_THRESHOLD,
+	WMI_10_2_ROAM_SCAN_PERIOD,
+	WMI_10_2_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
+	WMI_10_2_ROAM_AP_PROFILE,
+	WMI_10_2_OFL_SCAN_ADD_AP_PROFILE,
+	WMI_10_2_OFL_SCAN_REMOVE_AP_PROFILE,
+	WMI_10_2_OFL_SCAN_PERIOD,
+	WMI_10_2_P2P_DEV_SET_DEVICE_INFO,
+	WMI_10_2_P2P_DEV_SET_DISCOVERABILITY,
+	WMI_10_2_P2P_GO_SET_BEACON_IE,
+	WMI_10_2_P2P_GO_SET_PROBE_RESP_IE,
+	WMI_10_2_AP_PS_PEER_PARAM_CMDID,
+	WMI_10_2_AP_PS_PEER_UAPSD_COEX_CMDID,
+	WMI_10_2_PEER_RATE_RETRY_SCHED_CMDID,
+	WMI_10_2_WLAN_PROFILE_TRIGGER_CMDID,
+	WMI_10_2_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
+	WMI_10_2_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
+	WMI_10_2_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
+	WMI_10_2_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
+	WMI_10_2_PDEV_SUSPEND_CMDID,
+	WMI_10_2_PDEV_RESUME_CMDID,
+	WMI_10_2_ADD_BCN_FILTER_CMDID,
+	WMI_10_2_RMV_BCN_FILTER_CMDID,
+	WMI_10_2_WOW_ADD_WAKE_PATTERN_CMDID,
+	WMI_10_2_WOW_DEL_WAKE_PATTERN_CMDID,
+	WMI_10_2_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
+	WMI_10_2_WOW_ENABLE_CMDID,
+	WMI_10_2_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
+	WMI_10_2_RTT_MEASREQ_CMDID,
+	WMI_10_2_RTT_TSF_CMDID,
+	WMI_10_2_RTT_KEEPALIVE_CMDID,
+	WMI_10_2_PDEV_SEND_BCN_CMDID,
+	WMI_10_2_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
+	WMI_10_2_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
+	WMI_10_2_REQUEST_STATS_CMDID,
+	WMI_10_2_GPIO_CONFIG_CMDID,
+	WMI_10_2_GPIO_OUTPUT_CMDID,
+	WMI_10_2_VDEV_RATEMASK_CMDID,
+	WMI_10_2_PDEV_SMART_ANT_ENABLE_CMDID,
+	WMI_10_2_PDEV_SMART_ANT_SET_RX_ANTENNA_CMDID,
+	WMI_10_2_PEER_SMART_ANT_SET_TX_ANTENNA_CMDID,
+	WMI_10_2_PEER_SMART_ANT_SET_TRAIN_INFO_CMDID,
+	WMI_10_2_PEER_SMART_ANT_SET_NODE_CONFIG_OPS_CMDID,
+	WMI_10_2_FORCE_FW_HANG_CMDID,
+	WMI_10_2_PDEV_SET_ANTENNA_SWITCH_TABLE_CMDID,
+	WMI_10_2_PDEV_SET_CTL_TABLE_CMDID,
+	WMI_10_2_PDEV_SET_MIMOGAIN_TABLE_CMDID,
+	WMI_10_2_PDEV_RATEPWR_TABLE_CMDID,
+	WMI_10_2_PDEV_RATEPWR_CHAINMSK_TABLE_CMDID,
+	WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1,
+};
+
+enum wmi_10_2_event_id {
+	WMI_10_2_SERVICE_READY_EVENTID = 0x8000,
+	WMI_10_2_READY_EVENTID,
+	WMI_10_2_DEBUG_MESG_EVENTID,
+	WMI_10_2_START_EVENTID = 0x9000,
+	WMI_10_2_END_EVENTID = 0x9FFF,
+	WMI_10_2_SCAN_EVENTID = WMI_10_2_START_EVENTID,
+	WMI_10_2_ECHO_EVENTID,
+	WMI_10_2_UPDATE_STATS_EVENTID,
+	WMI_10_2_INST_RSSI_STATS_EVENTID,
+	WMI_10_2_VDEV_START_RESP_EVENTID,
+	WMI_10_2_VDEV_STANDBY_REQ_EVENTID,
+	WMI_10_2_VDEV_RESUME_REQ_EVENTID,
+	WMI_10_2_VDEV_STOPPED_EVENTID,
+	WMI_10_2_PEER_STA_KICKOUT_EVENTID,
+	WMI_10_2_HOST_SWBA_EVENTID,
+	WMI_10_2_TBTTOFFSET_UPDATE_EVENTID,
+	WMI_10_2_MGMT_RX_EVENTID,
+	WMI_10_2_CHAN_INFO_EVENTID,
+	WMI_10_2_PHYERR_EVENTID,
+	WMI_10_2_ROAM_EVENTID,
+	WMI_10_2_PROFILE_MATCH,
+	WMI_10_2_DEBUG_PRINT_EVENTID,
+	WMI_10_2_PDEV_QVIT_EVENTID,
+	WMI_10_2_WLAN_PROFILE_DATA_EVENTID,
+	WMI_10_2_RTT_MEASUREMENT_REPORT_EVENTID,
+	WMI_10_2_TSF_MEASUREMENT_REPORT_EVENTID,
+	WMI_10_2_RTT_ERROR_REPORT_EVENTID,
+	WMI_10_2_RTT_KEEPALIVE_EVENTID,
+	WMI_10_2_WOW_WAKEUP_HOST_EVENTID,
+	WMI_10_2_DCS_INTERFERENCE_EVENTID,
+	WMI_10_2_PDEV_TPC_CONFIG_EVENTID,
+	WMI_10_2_GPIO_INPUT_EVENTID,
+	WMI_10_2_PEER_RATECODE_LIST_EVENTID,
+	WMI_10_2_GENERIC_BUFFER_EVENTID,
+	WMI_10_2_MCAST_BUF_RELEASE_EVENTID,
+	WMI_10_2_MCAST_LIST_AGEOUT_EVENTID,
+	WMI_10_2_WDS_PEER_EVENTID,
+	WMI_10_2_PDEV_UTF_EVENTID = WMI_10_2_END_EVENTID - 1,
+};
+
 enum wmi_phy_mode {
 	MODE_11A        = 0,   /* 11a Mode */
 	MODE_11G        = 1,   /* 11b/g Mode */
@@ -1551,6 +1704,16 @@ struct wmi_resource_config_10x {
 	__le32 max_frag_entries;
 } __packed;
 
+struct wmi_resource_config_10_2 {
+	struct wmi_resource_config_10x common;
+	__le32 max_peer_ext_stats;
+	__le32 smart_ant_cap; /* 0-disable, 1-enable */
+	__le32 bk_min_free;
+	__le32 be_min_free;
+	__le32 vi_min_free;
+	__le32 vo_min_free;
+	__le32 rx_batchmode; /* 0-disable, 1-enable */
+} __packed;
 
 #define NUM_UNITS_IS_NUM_VDEVS   0x1
 #define NUM_UNITS_IS_NUM_PEERS   0x2
@@ -1588,11 +1751,28 @@ struct wmi_init_cmd_10x {
 	struct host_memory_chunk host_mem_chunks[1];
 } __packed;
 
+struct wmi_init_cmd_10_2 {
+	struct wmi_resource_config_10_2 resource_config;
+	__le32 num_host_mem_chunks;
+
+	/*
+	 * variable number of host memory chunks.
+	 * This should be the last element in the structure
+	 */
+	struct host_memory_chunk host_mem_chunks[1];
+} __packed;
+
+struct wmi_chan_list_entry {
+	__le16 freq;
+	u8 phy_mode; /* valid for 10.2 only */
+	u8 reserved;
+} __packed;
+
 /* TLV for channel list */
 struct wmi_chan_list {
 	__le32 tag; /* WMI_CHAN_LIST_TAG */
 	__le32 num_chan;
-	__le32 channel_list[0];
+	struct wmi_chan_list_entry channel_list[0];
 } __packed;
 
 struct wmi_bssid_list {
@@ -1821,7 +2001,7 @@ struct wmi_start_scan_arg {
 	u32 n_bssids;
 
 	u8 ie[WLAN_SCAN_PARAMS_MAX_IE_LEN];
-	u32 channels[64];
+	u16 channels[64];
 	struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID];
 	struct wmi_bssid_arg bssids[WLAN_SCAN_PARAMS_MAX_BSSID];
 };
@@ -2515,6 +2695,19 @@ enum wmi_10x_pdev_param {
 	WMI_10X_PDEV_PARAM_BURST_DUR,
 	/* Set Bursting Enable*/
 	WMI_10X_PDEV_PARAM_BURST_ENABLE,
+
+	/* following are available as of firmware 10.2 */
+	WMI_10X_PDEV_PARAM_SMART_ANTENNA_DEFAULT_ANTENNA,
+	WMI_10X_PDEV_PARAM_IGMPMLD_OVERRIDE,
+	WMI_10X_PDEV_PARAM_IGMPMLD_TID,
+	WMI_10X_PDEV_PARAM_ANTENNA_GAIN,
+	WMI_10X_PDEV_PARAM_RX_DECAP_MODE,
+	WMI_10X_PDEV_PARAM_RX_FILTER,
+	WMI_10X_PDEV_PARAM_SET_MCAST_TO_UCAST_TID,
+	WMI_10X_PDEV_PARAM_PROXY_STA_MODE,
+	WMI_10X_PDEV_PARAM_SET_MCAST2UCAST_MODE,
+	WMI_10X_PDEV_PARAM_SET_MCAST2UCAST_BUFFER,
+	WMI_10X_PDEV_PARAM_REMOVE_MCAST2UCAST_BUFFER,
 };
 
 struct wmi_pdev_set_param_cmd {
@@ -3387,6 +3580,14 @@ enum wmi_10x_vdev_param {
 	WMI_10X_VDEV_PARAM_ENABLE_RTSCTS,
 
 	WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
+
+	/* following are available as of firmware 10.2 */
+	WMI_10X_VDEV_PARAM_TX_ENCAP_TYPE,
+	WMI_10X_VDEV_PARAM_CABQ_MAXDUR,
+	WMI_10X_VDEV_PARAM_MFPTEST_SET,
+	WMI_10X_VDEV_PARAM_RTS_FIXED_RATE,
+	WMI_10X_VDEV_PARAM_VHT_SGIMASK,
+	WMI_10X_VDEV_PARAM_VHT80_RATEMASK,
 };
 
 /* slot time long */
@@ -3470,6 +3671,11 @@ enum wmi_bcn_tx_ref_flags {
 	WMI_BCN_TX_REF_FLAG_DELIVER_CAB = 0x2,
 };
 
+/* TODO: It is unclear why "no antenna" works while any other seemingly valid
+ * chainmask yields no beacons on the air at all.
+ */
+#define WMI_BCN_TX_REF_DEF_ANTENNA 0
+
 struct wmi_bcn_tx_ref_cmd {
 	__le32 vdev_id;
 	__le32 data_len;
@@ -3481,6 +3687,8 @@ struct wmi_bcn_tx_ref_cmd {
 	__le32 frame_control;
 	/* to control CABQ traffic: WMI_BCN_TX_REF_FLAG_ */
 	__le32 flags;
+	/* introduced in 10.2 */
+	__le32 antenna_mask;
 } __packed;
 
 /* Beacon filter */
@@ -4053,7 +4261,7 @@ struct wmi_peer_set_q_empty_callback_cmd {
 /* Maximum listen interval supported by hw in units of beacon interval */
 #define ATH10K_MAX_HW_LISTEN_INTERVAL 5
 
-struct wmi_peer_assoc_complete_cmd {
+struct wmi_common_peer_assoc_complete_cmd {
 	struct wmi_mac_addr peer_macaddr;
 	__le32 vdev_id;
 	__le32 peer_new_assoc; /* 1=assoc, 0=reassoc */
@@ -4071,11 +4279,30 @@ struct wmi_peer_assoc_complete_cmd {
 	__le32 peer_vht_caps;
 	__le32 peer_phymode;
 	struct wmi_vht_rate_set peer_vht_rates;
+};
+
+struct wmi_main_636_peer_assoc_complete_cmd {
+	struct wmi_common_peer_assoc_complete_cmd cmd;
+
 	/* HT Operation Element of the peer. Five bytes packed in 2
 	 *  INT32 array and filled from lsb to msb. */
 	__le32 peer_ht_info[2];
 } __packed;
 
+struct wmi_10_1_peer_assoc_complete_cmd {
+	struct wmi_common_peer_assoc_complete_cmd cmd;
+} __packed;
+
+#define WMI_PEER_ASSOC_INFO0_MAX_MCS_IDX_LSB 0
+#define WMI_PEER_ASSOC_INFO0_MAX_MCS_IDX_MASK 0x0f
+#define WMI_PEER_ASSOC_INFO0_MAX_NSS_LSB 4
+#define WMI_PEER_ASSOC_INFO0_MAX_NSS_MASK 0xf0
+
+struct wmi_10_2_peer_assoc_complete_cmd {
+	struct wmi_common_peer_assoc_complete_cmd cmd;
+	__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
+} __packed;
+
 struct wmi_peer_assoc_complete_arg {
 	u8 addr[ETH_ALEN];
 	u32 vdev_id;
-- 
1.8.5.3



From vh.nguyen at actiasodielec.fr  Fri Jul 25 05:22:06 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Fri, 25 Jul 2014 14:22:06 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>,
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>,
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>

>>>So probably the air condition you have forces the rate control to pick
>>>MCS7 as the most suitable rates.

>> What could I do to improve this? (Change the air conditioner LOL?)

>Heh, he meant the RF environment in the location you are. :)
>And ugh - this is why we need an open source ART already.

My 2 devices have an ARM processor 1200MHz.
If I connect these two devices by an Ethernet cable and doing iperf (in TCP)
I can obtain 880 Mbps, it means that my processor can deal with that speed 
of data transfer. But if I use Wi-fi instead of Ethernet to test rate between these
devices, my processor is exhausted, I run command top and see that 0~1% 
idle only,  ksoftirqd and kworker take most of my processor resource. 

Last week I discovered by chance that the module loaded in kernel can create 
effects to performance of rate, in my case it is "iptables". If I unload all module 
that related to iptables I can improve the performance. 
So I wonder if I can do some thing with the Wi-fi driver to  improve rate? 
Or the only solution is overclock/change my processor?

NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE





From greearb at candelatech.com  Fri Jul 25 05:51:00 2014
From: greearb at candelatech.com (Ben Greear)
Date: Fri, 25 Jul 2014 05:51:00 -0700
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>,
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>,
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>
Message-ID: <53D252B4.9070704@candelatech.com>



On 07/25/2014 05:22 AM, Vu Hai NGUYEN wrote:
>>>> So probably the air condition you have forces the rate control to pick
>>>> MCS7 as the most suitable rates.
>
>>> What could I do to improve this? (Change the air conditioner LOL?)
>
>> Heh, he meant the RF environment in the location you are. :)
>> And ugh - this is why we need an open source ART already.
>
> My 2 devices have an ARM processor 1200MHz.
> If I connect these two devices by an Ethernet cable and doing iperf (in TCP)
> I can obtain 880 Mbps, it means that my processor can deal with that speed
> of data transfer. But if I use Wi-fi instead of Ethernet to test rate between these
> devices, my processor is exhausted, I run command top and see that 0~1%
> idle only,  ksoftirqd and kworker take most of my processor resource.
>
> Last week I discovered by chance that the module loaded in kernel can create
> effects to performance of rate, in my case it is "iptables". If I unload all module
> that related to iptables I can improve the performance.
> So I wonder if I can do some thing with the Wi-fi driver to  improve rate?
> Or the only solution is overclock/change my processor?

Can you run 'perf top' on your system when it is under load so we can
see where the CPU is being used the most?

Thanks,
Ben

>
> NGUYEN Vu Hai
> Acita-Sodielec
> Route de Mayres - B.P. 9
> 12100 St GEORGES DE LUZENCON
> FRANCE
>
>
>
>
> _______________________________________________
> ath10k mailing list
> ath10k at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/ath10k
>

-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


From kvalo at qca.qualcomm.com  Fri Jul 25 07:18:40 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 25 Jul 2014 17:18:40 +0300
Subject: [PATCH] ath10k: add support for 10.2 firmware
In-Reply-To: <1406287937-26507-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Fri, 25 Jul 2014 13:32:17 +0200")
References: <1406287937-26507-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87y4vhmshr.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> The 10.2 firmware is a successor of 10.1 firmware
> (formerly identified as 10.x). Both share a lot
> but have some slight ABI differences that need to
> be taken care of.
>
> The 10.2 firmware introduces some new features but
> those can be added in subsequent patches. This
> patch makes ath10k boot and work with 10.2 with
> comparable functionality to 10.1.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Anyone who wants to test this, the firmware image is here:

https://github.com/kvalo/ath10k-firmware/tree/master/10.2

Because of backwards compatibility the firmware image name needs to be
firmware-3.bin for 10.2 branch.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Fri Jul 25 11:19:05 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 25 Jul 2014 21:19:05 +0300
Subject: [PATCH v4 0/2] ath10k spectral scan support
Message-ID: <20140725181753.10809.84231.stgit@potku.adurom.net>

This is patchset iteration the ath10k spectral scan feature.

To view the samples, please have a look at the fft_eval tool [1] which
now supports both ath9k and ath10k formats.

The count issue is still open: Even when a count is specified, the
hardware seems to send endless samples. It seems to work most of the
time in VHT80 mode though, but in HT20 and HT40 the count value seems
to be ignored. To reproduce this, start hostapd with the desired
channel width and do:

echo 8 > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_count
echo manual > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
echo trigger > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 >> /tmp/fft.dump

Repeating the last line and checking the filesize will easily show
whether ath10k still sends samples or not. We would expect 8 samples in
this configuration.

[1] https://github.com/simonwunderlich/FFT_eval

v4:

* CPTCFG_ fixes
* rework spectral.c initialisation (ath10k_spectral_start() etc)
* only run a simple test

---

Simon Wunderlich (1):
      ath10k: add spectral scan feature

Sven Eckelmann (1):
      ath: Move spectral debugfs structs to shared header


 drivers/net/wireless/ath/ath10k/Kconfig    |    1 
 drivers/net/wireless/ath/ath10k/Makefile   |    1 
 drivers/net/wireless/ath/ath10k/core.c     |   10 
 drivers/net/wireless/ath/ath10k/core.h     |   11 +
 drivers/net/wireless/ath/ath10k/mac.c      |    8 
 drivers/net/wireless/ath/ath10k/spectral.c |  561 ++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |   90 ++++
 drivers/net/wireless/ath/ath10k/wmi.c      |  105 +++++
 drivers/net/wireless/ath/ath10k/wmi.h      |   97 +++++
 drivers/net/wireless/ath/ath9k/spectral.h  |   71 ----
 drivers/net/wireless/ath/spectral_common.h |  113 ++++++
 11 files changed, 998 insertions(+), 70 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h
 create mode 100644 drivers/net/wireless/ath/spectral_common.h



From kvalo at qca.qualcomm.com  Fri Jul 25 11:19:12 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 25 Jul 2014 21:19:12 +0300
Subject: [PATCH v4 1/2] ath: Move spectral debugfs structs to shared header
In-Reply-To: <20140725181753.10809.84231.stgit@potku.adurom.net>
References: <20140725181753.10809.84231.stgit@potku.adurom.net>
Message-ID: <20140725181912.10809.4781.stgit@potku.adurom.net>

From: Sven Eckelmann <sven at narfation.org>

The ath9k and ath10k will share the definitions of the debugfs spectral
structures and enums. Having them in the same place helps to avoid conflicts.

Signed-off-by: Sven Eckelmann <sven at narfation.org>
Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/spectral.h  |   71 +----------------------
 drivers/net/wireless/ath/spectral_common.h |   88 ++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 69 deletions(-)
 create mode 100644 drivers/net/wireless/ath/spectral_common.h

diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h
index ead63412ee1a..7b410c6858b0 100644
--- a/drivers/net/wireless/ath/ath9k/spectral.h
+++ b/drivers/net/wireless/ath/ath9k/spectral.h
@@ -17,6 +17,8 @@
 #ifndef SPECTRAL_H
 #define SPECTRAL_H
 
+#include "../spectral_common.h"
+
 /* enum spectral_mode:
  *
  * @SPECTRAL_DISABLED: spectral mode is disabled
@@ -54,8 +56,6 @@ struct ath_ht20_mag_info {
 	u8 max_exp;
 } __packed;
 
-#define SPECTRAL_HT20_NUM_BINS		56
-
 /* WARNING: don't actually use this struct! MAC may vary the amount of
  * data by -1/+2. This struct is for reference only.
  */
@@ -83,8 +83,6 @@ struct ath_ht20_40_mag_info {
 	u8 max_exp;
 } __packed;
 
-#define SPECTRAL_HT20_40_NUM_BINS		128
-
 /* WARNING: don't actually use this struct! MAC may vary the amount of
  * data. This struct is for reference only.
  */
@@ -125,71 +123,6 @@ static inline u8 spectral_bitmap_weight(u8 *bins)
 	return bins[0] & 0x3f;
 }
 
-/* FFT sample format given to userspace via debugfs.
- *
- * Please keep the type/length at the front position and change
- * other fields after adding another sample type
- *
- * TODO: this might need rework when switching to nl80211-based
- * interface.
- */
-enum ath_fft_sample_type {
-	ATH_FFT_SAMPLE_HT20 = 1,
-	ATH_FFT_SAMPLE_HT20_40,
-};
-
-struct fft_sample_tlv {
-	u8 type;	/* see ath_fft_sample */
-	__be16 length;
-	/* type dependent data follows */
-} __packed;
-
-struct fft_sample_ht20 {
-	struct fft_sample_tlv tlv;
-
-	u8 max_exp;
-
-	__be16 freq;
-	s8 rssi;
-	s8 noise;
-
-	__be16 max_magnitude;
-	u8 max_index;
-	u8 bitmap_weight;
-
-	__be64 tsf;
-
-	u8 data[SPECTRAL_HT20_NUM_BINS];
-} __packed;
-
-struct fft_sample_ht20_40 {
-	struct fft_sample_tlv tlv;
-
-	u8 channel_type;
-	__be16 freq;
-
-	s8 lower_rssi;
-	s8 upper_rssi;
-
-	__be64 tsf;
-
-	s8 lower_noise;
-	s8 upper_noise;
-
-	__be16 lower_max_magnitude;
-	__be16 upper_max_magnitude;
-
-	u8 lower_max_index;
-	u8 upper_max_index;
-
-	u8 lower_bitmap_weight;
-	u8 upper_bitmap_weight;
-
-	u8 max_exp;
-
-	u8 data[SPECTRAL_HT20_40_NUM_BINS];
-} __packed;
-
 void ath9k_spectral_init_debug(struct ath_softc *sc);
 void ath9k_spectral_deinit_debug(struct ath_softc *sc);
 
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
new file mode 100644
index 000000000000..b9ab722747bd
--- /dev/null
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_COMMON_H
+#define SPECTRAL_COMMON_H
+
+#define SPECTRAL_HT20_NUM_BINS		56
+#define SPECTRAL_HT20_40_NUM_BINS		128
+
+/* FFT sample format given to userspace via debugfs.
+ *
+ * Please keep the type/length at the front position and change
+ * other fields after adding another sample type
+ *
+ * TODO: this might need rework when switching to nl80211-based
+ * interface.
+ */
+enum ath_fft_sample_type {
+	ATH_FFT_SAMPLE_HT20 = 1,
+	ATH_FFT_SAMPLE_HT20_40,
+};
+
+struct fft_sample_tlv {
+	u8 type;	/* see ath_fft_sample */
+	__be16 length;
+	/* type dependent data follows */
+} __packed;
+
+struct fft_sample_ht20 {
+	struct fft_sample_tlv tlv;
+
+	u8 max_exp;
+
+	__be16 freq;
+	s8 rssi;
+	s8 noise;
+
+	__be16 max_magnitude;
+	u8 max_index;
+	u8 bitmap_weight;
+
+	__be64 tsf;
+
+	u8 data[SPECTRAL_HT20_NUM_BINS];
+} __packed;
+
+struct fft_sample_ht20_40 {
+	struct fft_sample_tlv tlv;
+
+	u8 channel_type;
+	__be16 freq;
+
+	s8 lower_rssi;
+	s8 upper_rssi;
+
+	__be64 tsf;
+
+	s8 lower_noise;
+	s8 upper_noise;
+
+	__be16 lower_max_magnitude;
+	__be16 upper_max_magnitude;
+
+	u8 lower_max_index;
+	u8 upper_max_index;
+
+	u8 lower_bitmap_weight;
+	u8 upper_bitmap_weight;
+
+	u8 max_exp;
+
+	u8 data[SPECTRAL_HT20_40_NUM_BINS];
+} __packed;
+
+#endif /* SPECTRAL_COMMON_H */



From kvalo at qca.qualcomm.com  Fri Jul 25 11:19:18 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 25 Jul 2014 21:19:18 +0300
Subject: [PATCH v4 2/2] ath10k: add spectral scan feature
In-Reply-To: <20140725181753.10809.84231.stgit@potku.adurom.net>
References: <20140725181753.10809.84231.stgit@potku.adurom.net>
Message-ID: <20140725181918.10809.60403.stgit@potku.adurom.net>

From: Simon Wunderlich <sw at simonwunderlich.de>

Adds the spectral scan feature for ath10k. The spectral scan is triggered by
configuring a mode through a debugfs control file. Samples can be gathered via
another relay debugfs file.

Essentially, to try it out:

ip link set dev wlan0 up
echo background > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
echo trigger > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
iw dev wlan0 scan
echo disable > /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath10k/spectral_scan0 > samples

This feature is still experimental. Based on the original RFC patch of
Sven Eckelmann.

kvalo: CPTCFG_ -> CONFIG_, rework how spectral.c is initialised

Signed-off-by: Simon Wunderlich <sw at simonwunderlich.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer at fokus.fraunhofer.de>
Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/Kconfig    |    1 
 drivers/net/wireless/ath/ath10k/Makefile   |    1 
 drivers/net/wireless/ath/ath10k/core.c     |   10 
 drivers/net/wireless/ath/ath10k/core.h     |   11 +
 drivers/net/wireless/ath/ath10k/mac.c      |    8 
 drivers/net/wireless/ath/ath10k/spectral.c |  561 ++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/spectral.h |   90 ++++
 drivers/net/wireless/ath/ath10k/wmi.c      |  105 +++++
 drivers/net/wireless/ath/ath10k/wmi.h      |   97 +++++
 drivers/net/wireless/ath/spectral_common.h |   25 +
 10 files changed, 908 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.c
 create mode 100644 drivers/net/wireless/ath/ath10k/spectral.h

diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index a6f5285235af..1053bb5f2cdc 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -25,6 +25,7 @@ config ATH10K_DEBUG
 config ATH10K_DEBUGFS
 	bool "Atheros ath10k debugfs support"
 	depends on ATH10K
+	select RELAY
 	---help---
 	  Enabled debugfs support
 
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index a4179f49ee1f..2cfb63ca9327 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -10,6 +10,7 @@ ath10k_core-y += mac.o \
 		 wmi.o \
 		 bmi.o
 
+ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
 ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
 
 obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 93adb8c58969..8071f0e408f9 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -986,9 +986,17 @@ static void ath10k_core_register_work(struct work_struct *work)
 		goto err_unregister_mac;
 	}
 
+	status = ath10k_spectral_create(ar);
+	if (status) {
+		ath10k_err("failed to initialize spectral\n");
+		goto err_debug_destroy;
+	}
+
 	set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
 	return;
 
+err_debug_destroy:
+	ath10k_debug_destroy(ar);
 err_unregister_mac:
 	ath10k_mac_unregister(ar);
 err_release_fw:
@@ -1032,6 +1040,8 @@ void ath10k_core_unregister(struct ath10k *ar)
 
 	ath10k_core_free_firmware_files(ar);
 
+	ath10k_spectral_destroy(ar);
+
 	ath10k_debug_destroy(ar);
 }
 EXPORT_SYMBOL(ath10k_core_unregister);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 83a5fa91531d..e18ab7f54a2f 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -31,6 +31,7 @@
 #include "../ath.h"
 #include "../regd.h"
 #include "../dfs_pattern_detector.h"
+#include "spectral.h"
 
 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -237,6 +238,7 @@ struct ath10k_vif {
 
 	bool is_started;
 	bool is_up;
+	bool spectral_enabled;
 	u32 aid;
 	u8 bssid[ETH_ALEN];
 
@@ -494,6 +496,15 @@ struct ath10k {
 #ifdef CONFIG_ATH10K_DEBUGFS
 	struct ath10k_debug debug;
 #endif
+
+	struct {
+		/* relay(fs) channel for spectral scan */
+		struct rchan *rfs_chan_spec_scan;
+
+		/* spectral_mode and spec_config are protected by conf_mutex */
+		enum ath10k_spectral_mode mode;
+		struct ath10k_spec_scan config;
+	} spectral;
 };
 
 struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 9d61bb157189..d14f1425d285 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2485,6 +2485,8 @@ static int ath10k_start(struct ieee80211_hw *hw)
 	ar->num_started_vdevs = 0;
 	ath10k_regd_update(ar);
 
+	ath10k_spectral_start(ar);
+
 	mutex_unlock(&ar->conf_mutex);
 	return 0;
 
@@ -2892,8 +2894,14 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 		dev_kfree_skb_any(arvif->beacon);
 		arvif->beacon = NULL;
 	}
+
 	spin_unlock_bh(&ar->data_lock);
 
+	ret = ath10k_spectral_vif_stop(arvif);
+	if (ret)
+		ath10k_warn("failed to stop spectral for vdev %i: %d\n",
+			    arvif->vdev_id, ret);
+
 	ar->free_vdev_map |= 1 << (arvif->vdev_id);
 	list_del(&arvif->list);
 
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
new file mode 100644
index 000000000000..0444dc53bb84
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/relay.h>
+#include "core.h"
+#include "debug.h"
+
+static void send_fft_sample(struct ath10k *ar,
+			    const struct fft_sample_tlv *fft_sample_tlv)
+{
+	int length;
+
+	if (!ar->spectral.rfs_chan_spec_scan)
+		return;
+
+	length = __be16_to_cpu(fft_sample_tlv->length) +
+		 sizeof(*fft_sample_tlv);
+	relay_write(ar->spectral.rfs_chan_spec_scan, fft_sample_tlv, length);
+}
+
+static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
+			   u8 *data)
+{
+	int dc_pos;
+	u8 max_exp;
+
+	dc_pos = bin_len / 2;
+
+	/* peak index outside of bins */
+	if (dc_pos < max_index || -dc_pos >= max_index)
+		return 0;
+
+	for (max_exp = 0; max_exp < 8; max_exp++) {
+		if (data[dc_pos + max_index] == (max_magnitude >> max_exp))
+			break;
+	}
+
+	/* max_exp not found */
+	if (data[dc_pos + max_index] != (max_magnitude >> max_exp))
+		return 0;
+
+	return max_exp;
+}
+
+int ath10k_spectral_process_fft(struct ath10k *ar,
+				struct wmi_single_phyerr_rx_event *event,
+				struct phyerr_fft_report *fftr,
+				size_t bin_len, u64 tsf)
+{
+	struct fft_sample_ath10k *fft_sample;
+	u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
+	u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag;
+	u32 reg0, reg1, nf_list1, nf_list2;
+	u8 chain_idx, *bins;
+	int dc_pos;
+
+	fft_sample = (struct fft_sample_ath10k *)&buf;
+
+	if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
+		return -EINVAL;
+
+	reg0 = __le32_to_cpu(fftr->reg0);
+	reg1 = __le32_to_cpu(fftr->reg1);
+
+	length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + bin_len;
+	fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH10K;
+	fft_sample->tlv.length = __cpu_to_be16(length);
+
+	/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
+	 * but the results/plots suggest that its actually 22/44/88 MHz.
+	 */
+	switch (event->hdr.chan_width_mhz) {
+	case 20:
+		fft_sample->chan_width_mhz = 22;
+		break;
+	case 40:
+		fft_sample->chan_width_mhz = 44;
+		break;
+	case 80:
+		/* TODO: As experiments with an analogue sender and various
+		 * configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
+		 * show, the particular configuration of 80 MHz/64 bins does
+		 * not match with the other smaples at all. Until the reason
+		 * for that is found, don't report these samples.
+		 */
+		if (bin_len == 64)
+			return -EINVAL;
+		fft_sample->chan_width_mhz = 88;
+		break;
+	default:
+		fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
+	}
+
+	fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
+	fft_sample->avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
+
+	peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
+	fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
+	fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
+	fft_sample->rssi = event->hdr.rssi_combined;
+
+	total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
+	base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
+	fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
+	fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
+
+	freq1 = __le16_to_cpu(event->hdr.freq1);
+	freq2 = __le16_to_cpu(event->hdr.freq2);
+	fft_sample->freq1 = __cpu_to_be16(freq1);
+	fft_sample->freq2 = __cpu_to_be16(freq2);
+
+	nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
+	nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
+	chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
+
+	switch (chain_idx) {
+	case 0:
+		fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
+		break;
+	case 1:
+		fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
+		break;
+	case 2:
+		fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
+		break;
+	case 3:
+		fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
+		break;
+	}
+
+	bins = (u8 *)fftr;
+	bins += sizeof(*fftr);
+
+	fft_sample->tsf = __cpu_to_be64(tsf);
+
+	/* max_exp has been directly reported by previous hardware (ath9k),
+	 * maybe its possible to get it by other means?
+	 */
+	fft_sample->max_exp = get_max_exp(fft_sample->max_index, peak_mag,
+					  bin_len, bins);
+
+	memcpy(fft_sample->data, bins, bin_len);
+
+	/* DC value (value in the middle) is the blind spot of the spectral
+	 * sample and invalid, interpolate it.
+	 */
+	dc_pos = bin_len / 2;
+	fft_sample->data[dc_pos] = (fft_sample->data[dc_pos + 1] +
+				    fft_sample->data[dc_pos - 1]) / 2;
+
+	send_fft_sample(ar, &fft_sample->tlv);
+
+	return 0;
+}
+
+static struct ath10k_vif *ath10k_get_spectral_vdev(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	if (list_empty(&ar->arvifs))
+		return NULL;
+
+	/* if there already is a vif doing spectral, return that. */
+	list_for_each_entry(arvif, &ar->arvifs, list)
+		if (arvif->spectral_enabled)
+			return arvif;
+
+	/* otherwise, return the first vif. */
+	return list_first_entry(&ar->arvifs, typeof(*arvif), list);
+}
+
+static int ath10k_spectral_scan_trigger(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+	int res;
+	int vdev_id;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	arvif = ath10k_get_spectral_vdev(ar);
+	if (!arvif)
+		return -ENODEV;
+	vdev_id = arvif->vdev_id;
+
+	if (ar->spectral.mode == SPECTRAL_DISABLED)
+		return 0;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (res < 0)
+		return res;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
+					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
+	if (res < 0)
+		return res;
+
+	return 0;
+}
+
+static int ath10k_spectral_scan_config(struct ath10k *ar,
+				       enum ath10k_spectral_mode mode)
+{
+	struct wmi_vdev_spectral_conf_arg arg;
+	struct ath10k_vif *arvif;
+	int vdev_id, count, res = 0;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	arvif = ath10k_get_spectral_vdev(ar);
+	if (!arvif)
+		return -ENODEV;
+
+	vdev_id = arvif->vdev_id;
+
+	arvif->spectral_enabled = (mode != SPECTRAL_DISABLED);
+	ar->spectral.mode = mode;
+
+	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
+					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
+					      WMI_SPECTRAL_ENABLE_CMD_DISABLE);
+	if (res < 0) {
+		ath10k_warn("failed to enable spectral scan: %d\n", res);
+		return res;
+	}
+
+	if (mode == SPECTRAL_DISABLED)
+		return 0;
+
+	if (mode == SPECTRAL_BACKGROUND)
+		count = WMI_SPECTRAL_COUNT_DEFAULT;
+	else
+		count = max_t(u8, 1, ar->spectral.config.count);
+
+	arg.vdev_id = vdev_id;
+	arg.scan_count = count;
+	arg.scan_period = WMI_SPECTRAL_PERIOD_DEFAULT;
+	arg.scan_priority = WMI_SPECTRAL_PRIORITY_DEFAULT;
+	arg.scan_fft_size = ar->spectral.config.fft_size;
+	arg.scan_gc_ena = WMI_SPECTRAL_GC_ENA_DEFAULT;
+	arg.scan_restart_ena = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
+	arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
+	arg.scan_init_delay = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
+	arg.scan_nb_tone_thr = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
+	arg.scan_str_bin_thr = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
+	arg.scan_wb_rpt_mode = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
+	arg.scan_rssi_rpt_mode = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
+	arg.scan_rssi_thr = WMI_SPECTRAL_RSSI_THR_DEFAULT;
+	arg.scan_pwr_format = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
+	arg.scan_rpt_mode = WMI_SPECTRAL_RPT_MODE_DEFAULT;
+	arg.scan_bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	arg.scan_dbm_adj = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
+	arg.scan_chn_mask = WMI_SPECTRAL_CHN_MASK_DEFAULT;
+
+	res = ath10k_wmi_vdev_spectral_conf(ar, &arg);
+	if (res < 0) {
+		ath10k_warn("failed to configure spectral scan: %d\n", res);
+		return res;
+	}
+
+	return 0;
+}
+
+static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char *mode = "";
+	unsigned int len;
+	enum ath10k_spectral_mode spectral_mode;
+
+	mutex_lock(&ar->conf_mutex);
+	spectral_mode = ar->spectral.mode;
+	mutex_unlock(&ar->conf_mutex);
+
+	switch (spectral_mode) {
+	case SPECTRAL_DISABLED:
+		mode = "disable";
+		break;
+	case SPECTRAL_BACKGROUND:
+		mode = "background";
+		break;
+	case SPECTRAL_MANUAL:
+		mode = "manual";
+		break;
+	}
+
+	len = strlen(mode);
+	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
+}
+
+static ssize_t write_file_spec_scan_ctl(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	ssize_t len;
+	int res;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (strncmp("trigger", buf, 7) == 0) {
+		if (ar->spectral.mode == SPECTRAL_MANUAL ||
+		    ar->spectral.mode == SPECTRAL_BACKGROUND) {
+			/* reset the configuration to adopt possibly changed
+			 * debugfs parameters
+			 */
+			res = ath10k_spectral_scan_config(ar,
+							  ar->spectral.mode);
+			if (res < 0) {
+				ath10k_warn("failed to reconfigure spectral scan: %d\n",
+					    res);
+			}
+			res = ath10k_spectral_scan_trigger(ar);
+			if (res < 0) {
+				ath10k_warn("failed to trigger spectral scan: %d\n",
+					    res);
+			}
+		} else {
+			res = -EINVAL;
+		}
+	} else if (strncmp("background", buf, 9) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
+	} else if (strncmp("manual", buf, 6) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
+	} else if (strncmp("disable", buf, 7) == 0) {
+		res = ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
+	} else {
+		res = -EINVAL;
+	}
+
+	mutex_unlock(&ar->conf_mutex);
+
+	if (res < 0)
+		return res;
+
+	return count;
+}
+
+static const struct file_operations fops_spec_scan_ctl = {
+	.read = read_file_spec_scan_ctl,
+	.write = write_file_spec_scan_ctl,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static ssize_t read_file_spectral_count(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len;
+	u8 spectral_count;
+
+	mutex_lock(&ar->conf_mutex);
+	spectral_count = ar->spectral.config.count;
+	mutex_unlock(&ar->conf_mutex);
+
+	len = sprintf(buf, "%d\n", spectral_count);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_count(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 0 || val > 255)
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+	ar->spectral.config.count = val;
+	mutex_unlock(&ar->conf_mutex);
+
+	return count;
+}
+
+static const struct file_operations fops_spectral_count = {
+	.read = read_file_spectral_count,
+	.write = write_file_spectral_count,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static ssize_t read_file_spectral_bins(struct file *file,
+				       char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	unsigned int len, bins, fft_size, bin_scale;
+
+	mutex_lock(&ar->conf_mutex);
+
+	fft_size = ar->spectral.config.fft_size;
+	bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	bins = 1 << (fft_size - bin_scale);
+
+	mutex_unlock(&ar->conf_mutex);
+
+	len = sprintf(buf, "%d\n", bins);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_spectral_bins(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	unsigned long val;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
+		return -EINVAL;
+
+	if (!is_power_of_2(val))
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+	ar->spectral.config.fft_size = ilog2(val);
+	ar->spectral.config.fft_size += WMI_SPECTRAL_BIN_SCALE_DEFAULT;
+	mutex_unlock(&ar->conf_mutex);
+
+	return count;
+}
+
+static const struct file_operations fops_spectral_bins = {
+	.read = read_file_spectral_bins,
+	.write = write_file_spectral_bins,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static struct dentry *create_buf_file_handler(const char *filename,
+					      struct dentry *parent,
+					      umode_t mode,
+					      struct rchan_buf *buf,
+					      int *is_global)
+{
+	struct dentry *buf_file;
+
+	buf_file = debugfs_create_file(filename, mode, parent, buf,
+				       &relay_file_operations);
+	*is_global = 1;
+	return buf_file;
+}
+
+static int remove_buf_file_handler(struct dentry *dentry)
+{
+	debugfs_remove(dentry);
+
+	return 0;
+}
+
+static struct rchan_callbacks rfs_spec_scan_cb = {
+	.create_buf_file = create_buf_file_handler,
+	.remove_buf_file = remove_buf_file_handler,
+};
+
+int ath10k_spectral_start(struct ath10k *ar)
+{
+	struct ath10k_vif *arvif;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	list_for_each_entry(arvif, &ar->arvifs, list)
+		arvif->spectral_enabled = 0;
+
+	return 0;
+}
+
+int ath10k_spectral_vif_stop(struct ath10k_vif *arvif)
+{
+	if (!arvif->spectral_enabled)
+		return 0;
+
+	return ath10k_spectral_scan_config(arvif->ar, SPECTRAL_DISABLED);
+}
+
+int ath10k_spectral_create(struct ath10k *ar)
+{
+	ar->spectral.mode = SPECTRAL_DISABLED;
+	ar->spectral.config.count = WMI_SPECTRAL_COUNT_DEFAULT;
+	ar->spectral.config.fft_size = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
+
+	ar->spectral.rfs_chan_spec_scan = relay_open("spectral_scan",
+						     ar->debug.debugfs_phy,
+						     1024, 256,
+						     &rfs_spec_scan_cb, NULL);
+	debugfs_create_file("spectral_scan_ctl",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spec_scan_ctl);
+	debugfs_create_file("spectral_count",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_count);
+	debugfs_create_file("spectral_bins",
+			    S_IRUSR | S_IWUSR,
+			    ar->debug.debugfs_phy, ar,
+			    &fops_spectral_bins);
+
+	return 0;
+}
+
+void ath10k_spectral_destroy(struct ath10k *ar)
+{
+	if (ar->spectral.rfs_chan_spec_scan) {
+		relay_close(ar->spectral.rfs_chan_spec_scan);
+		ar->spectral.rfs_chan_spec_scan = NULL;
+	}
+}
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
new file mode 100644
index 000000000000..ddc57c557272
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SPECTRAL_H
+#define SPECTRAL_H
+
+#include "../spectral_common.h"
+
+/**
+ * struct ath10k_spec_scan - parameters for Atheros spectral scan
+ *
+ * @count: number of scan results requested for manual mode
+ * @fft_size: number of bins to be requested = 2^(fft_size - bin_scale)
+ */
+struct ath10k_spec_scan {
+	u8 count;
+	u8 fft_size;
+};
+
+/* enum ath10k_spectral_mode:
+ *
+ * @SPECTRAL_DISABLED: spectral mode is disabled
+ * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
+ *	something else.
+ * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
+ *	is performed manually.
+ */
+enum ath10k_spectral_mode {
+	SPECTRAL_DISABLED = 0,
+	SPECTRAL_BACKGROUND,
+	SPECTRAL_MANUAL,
+};
+
+#ifdef CONFIG_ATH10K_DEBUGFS
+
+int ath10k_spectral_process_fft(struct ath10k *ar,
+				struct wmi_single_phyerr_rx_event *event,
+				struct phyerr_fft_report *fftr,
+				size_t bin_len, u64 tsf);
+int ath10k_spectral_start(struct ath10k *ar);
+int ath10k_spectral_vif_stop(struct ath10k_vif *arvif);
+int ath10k_spectral_create(struct ath10k *ar);
+void ath10k_spectral_destroy(struct ath10k *ar);
+
+#else
+
+static inline int
+ath10k_spectral_process_fft(struct ath10k *ar,
+			    struct wmi_single_phyerr_rx_event *event,
+			    struct phyerr_fft_report *fftr,
+			    size_t bin_len, u64 tsf)
+{
+	return 0;
+}
+
+static inline int ath10k_spectral_start(struct ath10k *ar)
+{
+	return 0;
+}
+
+static inline int ath10k_spectral_vif_stop(struct ath10k_vif *arvif)
+{
+	return 0;
+}
+
+static inline int ath10k_spectral_create(struct ath10k *ar)
+{
+	return 0;
+}
+
+static inline void ath10k_spectral_destroy(struct ath10k *ar)
+{
+}
+
+#endif /* CONFIG_ATH10K_DEBUGFS */
+
+#endif /* SPECTRAL_H */
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index c2c87c916b5a..7e4f975e7a51 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1659,7 +1659,54 @@ static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
 				struct wmi_single_phyerr_rx_event *event,
 				u64 tsf)
 {
-	ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n");
+	int buf_len, tlv_len, res, i = 0;
+	struct phyerr_tlv *tlv;
+	u8 *tlv_buf;
+	struct phyerr_fft_report *fftr;
+	size_t fftr_len;
+
+	buf_len = __le32_to_cpu(event->hdr.buf_len);
+
+	while (i < buf_len) {
+		if (i + sizeof(*tlv) > buf_len) {
+			ath10k_warn("failed to parse phyerr tlv header at byte %d\n",
+				    i);
+			return;
+		}
+
+		tlv = (struct phyerr_tlv *)&event->bufp[i];
+		tlv_len = __le16_to_cpu(tlv->len);
+		tlv_buf = &event->bufp[i + sizeof(*tlv)];
+
+		if (i + sizeof(*tlv) + tlv_len > buf_len) {
+			ath10k_warn("failed to parse phyerr tlv payload at byte %d\n",
+				    i);
+			return;
+		}
+
+		switch (tlv->tag) {
+		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
+			if (sizeof(*fftr) > tlv_len) {
+				ath10k_warn("failed to parse fft report at byte %d\n",
+					    i);
+				return;
+			}
+
+			fftr_len = tlv_len - sizeof(*fftr);
+			fftr = (struct phyerr_fft_report *)tlv_buf;
+			res = ath10k_spectral_process_fft(ar, event,
+							  fftr, fftr_len,
+							  tsf);
+			if (res < 0) {
+				ath10k_warn("failed to process fft report: %d\n",
+					    res);
+				return;
+			}
+			break;
+		}
+
+		i += sizeof(*tlv) + tlv_len;
+	}
 }
 
 static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
@@ -3236,6 +3283,62 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				   ar->wmi.cmd->vdev_install_key_cmdid);
 }
 
+int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
+				  const struct wmi_vdev_spectral_conf_arg *arg)
+{
+	struct wmi_vdev_spectral_conf_cmd *cmd;
+	struct sk_buff *skb;
+	u32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_conf_cmd *)skb->data;
+	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
+	cmd->scan_count = __cpu_to_le32(arg->scan_count);
+	cmd->scan_period = __cpu_to_le32(arg->scan_period);
+	cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
+	cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
+	cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
+	cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
+	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
+	cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
+	cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
+	cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
+	cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
+	cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
+	cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
+	cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
+	cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
+	cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
+	cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
+	cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_configure_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
+int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				    u32 enable)
+{
+	struct wmi_vdev_spectral_enable_cmd *cmd;
+	struct sk_buff *skb;
+	u32 cmdid;
+
+	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_spectral_enable_cmd *)skb->data;
+	cmd->vdev_id = __cpu_to_le32(vdev_id);
+	cmd->trigger_cmd = __cpu_to_le32(trigger);
+	cmd->enable_cmd = __cpu_to_le32(enable);
+
+	cmdid = ar->wmi.cmd->vdev_spectral_scan_enable_cmdid;
+	return ath10k_wmi_cmd_send(ar, skb, cmdid);
+}
+
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 			   const u8 peer_addr[ETH_ALEN])
 {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index e93df2c10413..ce940c8e4ca1 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2067,6 +2067,7 @@ struct wmi_comb_phyerr_rx_event {
 #define PHYERR_TLV_SIG				0xBB
 #define PHYERR_TLV_TAG_SEARCH_FFT_REPORT	0xFB
 #define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY	0xF8
+#define PHYERR_TLV_TAG_SPECTRAL_SUMMARY_REPORT	0xF9
 
 struct phyerr_radar_report {
 	__le32 reg0; /* RADAR_REPORT_REG0_* */
@@ -3444,6 +3445,98 @@ struct wmi_vdev_simple_event {
 /* unsupported VDEV combination */
 #define WMI_INIFIED_VDEV_START_RESPONSE_NOT_SUPPORTED	0x2
 
+/* TODO: please add more comments if you have in-depth information */
+struct wmi_vdev_spectral_conf_cmd {
+	__le32 vdev_id;
+
+	/* number of fft samples to send (0 for infinite) */
+	__le32 scan_count;
+	__le32 scan_period;
+	__le32 scan_priority;
+
+	/* number of bins in the FFT: 2^(fft_size - bin_scale) */
+	__le32 scan_fft_size;
+	__le32 scan_gc_ena;
+	__le32 scan_restart_ena;
+	__le32 scan_noise_floor_ref;
+	__le32 scan_init_delay;
+	__le32 scan_nb_tone_thr;
+	__le32 scan_str_bin_thr;
+	__le32 scan_wb_rpt_mode;
+	__le32 scan_rssi_rpt_mode;
+	__le32 scan_rssi_thr;
+	__le32 scan_pwr_format;
+
+	/* rpt_mode: Format of FFT report to software for spectral scan
+	 * triggered FFTs:
+	 *	0: No FFT report (only spectral scan summary report)
+	 *	1: 2-dword summary of metrics for each completed FFT + spectral
+	 *	   scan	summary report
+	 *	2: 2-dword summary of metrics for each completed FFT +
+	 *	   1x- oversampled bins(in-band) per FFT + spectral scan summary
+	 *	   report
+	 *	3: 2-dword summary of metrics for each completed FFT +
+	 *	   2x- oversampled bins	(all) per FFT + spectral scan summary
+	 */
+	__le32 scan_rpt_mode;
+	__le32 scan_bin_scale;
+	__le32 scan_dbm_adj;
+	__le32 scan_chn_mask;
+} __packed;
+
+struct wmi_vdev_spectral_conf_arg {
+	u32 vdev_id;
+	u32 scan_count;
+	u32 scan_period;
+	u32 scan_priority;
+	u32 scan_fft_size;
+	u32 scan_gc_ena;
+	u32 scan_restart_ena;
+	u32 scan_noise_floor_ref;
+	u32 scan_init_delay;
+	u32 scan_nb_tone_thr;
+	u32 scan_str_bin_thr;
+	u32 scan_wb_rpt_mode;
+	u32 scan_rssi_rpt_mode;
+	u32 scan_rssi_thr;
+	u32 scan_pwr_format;
+	u32 scan_rpt_mode;
+	u32 scan_bin_scale;
+	u32 scan_dbm_adj;
+	u32 scan_chn_mask;
+};
+
+#define WMI_SPECTRAL_ENABLE_DEFAULT              0
+#define WMI_SPECTRAL_COUNT_DEFAULT               0
+#define WMI_SPECTRAL_PERIOD_DEFAULT             35
+#define WMI_SPECTRAL_PRIORITY_DEFAULT            1
+#define WMI_SPECTRAL_FFT_SIZE_DEFAULT            7
+#define WMI_SPECTRAL_GC_ENA_DEFAULT              1
+#define WMI_SPECTRAL_RESTART_ENA_DEFAULT         0
+#define WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT   -96
+#define WMI_SPECTRAL_INIT_DELAY_DEFAULT         80
+#define WMI_SPECTRAL_NB_TONE_THR_DEFAULT        12
+#define WMI_SPECTRAL_STR_BIN_THR_DEFAULT         8
+#define WMI_SPECTRAL_WB_RPT_MODE_DEFAULT         0
+#define WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT       0
+#define WMI_SPECTRAL_RSSI_THR_DEFAULT         0xf0
+#define WMI_SPECTRAL_PWR_FORMAT_DEFAULT          0
+#define WMI_SPECTRAL_RPT_MODE_DEFAULT            2
+#define WMI_SPECTRAL_BIN_SCALE_DEFAULT           1
+#define WMI_SPECTRAL_DBM_ADJ_DEFAULT             1
+#define WMI_SPECTRAL_CHN_MASK_DEFAULT            1
+
+struct wmi_vdev_spectral_enable_cmd {
+	__le32 vdev_id;
+	__le32 trigger_cmd;
+	__le32 enable_cmd;
+} __packed;
+
+#define WMI_SPECTRAL_TRIGGER_CMD_TRIGGER  1
+#define WMI_SPECTRAL_TRIGGER_CMD_CLEAR    2
+#define WMI_SPECTRAL_ENABLE_CMD_ENABLE    1
+#define WMI_SPECTRAL_ENABLE_CMD_DISABLE   2
+
 /* Beacon processing related command and event structures */
 struct wmi_bcn_tx_hdr {
 	__le32 vdev_id;
@@ -4290,6 +4383,10 @@ int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id,
 			      u32 param_id, u32 param_value);
 int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 				const struct wmi_vdev_install_key_arg *arg);
+int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
+				  const struct wmi_vdev_spectral_conf_arg *arg);
+int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
+				    u32 enable);
 int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 		    const u8 peer_addr[ETH_ALEN]);
 int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
diff --git a/drivers/net/wireless/ath/spectral_common.h b/drivers/net/wireless/ath/spectral_common.h
index b9ab722747bd..0d742acb1599 100644
--- a/drivers/net/wireless/ath/spectral_common.h
+++ b/drivers/net/wireless/ath/spectral_common.h
@@ -20,6 +20,11 @@
 #define SPECTRAL_HT20_NUM_BINS		56
 #define SPECTRAL_HT20_40_NUM_BINS		128
 
+/* TODO: could possibly be 512, but no samples this large
+ * could be acquired so far.
+ */
+#define SPECTRAL_ATH10K_MAX_NUM_BINS		256
+
 /* FFT sample format given to userspace via debugfs.
  *
  * Please keep the type/length at the front position and change
@@ -31,6 +36,7 @@
 enum ath_fft_sample_type {
 	ATH_FFT_SAMPLE_HT20 = 1,
 	ATH_FFT_SAMPLE_HT20_40,
+	ATH_FFT_SAMPLE_ATH10K,
 };
 
 struct fft_sample_tlv {
@@ -85,4 +91,23 @@ struct fft_sample_ht20_40 {
 	u8 data[SPECTRAL_HT20_40_NUM_BINS];
 } __packed;
 
+struct fft_sample_ath10k {
+	struct fft_sample_tlv tlv;
+	u8 chan_width_mhz;
+	__be16 freq1;
+	__be16 freq2;
+	__be16 noise;
+	__be16 max_magnitude;
+	__be16 total_gain_db;
+	__be16 base_pwr_db;
+	__be64 tsf;
+	s8 max_index;
+	u8 rssi;
+	u8 relpwr_db;
+	u8 avgpwr_db;
+	u8 max_exp;
+
+	u8 data[0];
+} __packed;
+
 #endif /* SPECTRAL_COMMON_H */



From greearb at candelatech.com  Fri Jul 25 16:15:26 2014
From: greearb at candelatech.com (Ben Greear)
Date: Fri, 25 Jul 2014 16:15:26 -0700
Subject: Performance v/s signal quality graph.
Message-ID: <53D2E50E.5010205@candelatech.com>

Some time back, I ran some tests, and someone (sorry, can't remember or find the email)
suggested my signal might be too hot.  I was using a 30 db fixed attenuator inline with the SMA
cables.

I set up a test today with E5 processor system as station, and a fast i7 processor
system as AP, with the two systems cabled through our variable attenuator.  Open authentication,
channel 149, other wifi equipment in area on 5ghz was (mostly) idle or powered down.
Kernel is 3.14.13+, latest ath10k CT (10.1.467 based) firmware on both systems
(though I don't think that matters much for throughput tests).  10 virtual stations
configured on station machine, but only one was actively doing traffic.

Here is a udp download v/s rx-signal graph as the attenuator is stepped from 0 to 95.5
db attenuation in .5 db steps.

http://www.candelatech.com/pdfs/ath10k_atten_vs_throughput.pdf

The rx-signal axis is the left hand side.  The green graph is the station's (ie netdev)
rx bps, the black is UDP goodput.

It seems ath10k (WLE900VX) has no real trouble with hot signals, and runs best between
-15 and -52 rx signal level (as reported by the station device).

Our systems are not perfectly isolated, so the maximum attenuation is around -85.

Enjoy,
Ben

-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From denton.gentry at gmail.com  Sun Jul 27 10:51:01 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Sun, 27 Jul 2014 10:51:01 -0700
Subject: [RFC] extract seqno from sta->last_seq_ctrl
Message-ID: <CABnBrYV27yNECG6PPWp2Gsz5w3azbEzGc4n5TcfavvUBbN8U_g@mail.gmail.com>

[Sending to ath10k list as I think ath10k is the only impacted driver right now]

I believe there is a minor problem in
[PATCH v2] mac80211: add support for Rx reordering offloading
http://www.spinics.net/lists/linux-wireless/msg124812.html

sta->last_seq_ctrl is the seq_ctrl field from the last seen packet. To
get the sequence number it needs to be byteswapped and shifted 4 bits;
patch below.

This mostly impacts Windows clients, because Windows sends 100-200
frames before sending ADDBA. This results in a starting seqno which is
quite large due to the 4 bit shift, and the ieee80211_sn_less() check
at the top of ieee80211_sta_manage_reorder_buf drops subsequent frames
until the sequence number catches up.


>From d0647db58d13533e5441c07f95b23e912976c87b Mon Sep 17 00:00:00 2001
From: Denton Gentry <denton.gentry at gmail.com>
Date: Sun, 27 Jul 2014 08:24:36 -0700
Subject: [PATCH] extract seqno from sta->last_seq_ctrl

This depends on:
* [PATCH v2] mac80211: add support for Rx reordering offloading

sta->last_seq_ctrl is the seq_ctrl field from the last
header seen, need to byteswap and shift it 4 bits to
extract the sequence number.

 net/mac80211/iface.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 77cd025..1903220 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1171,7 +1171,7 @@ static void ieee80211_iface_work(struct work_struct *work)
                        mutex_lock(&local->sta_mtx);
                        sta = sta_info_get_bss(sdata, rx_agg->addr);
                        if (sta) {
-                               u16 last_seq = sta->last_seq_ctrl[rx_agg->tid];
+                               u16 last_seq =
le16_to_cpu(sta->last_seq_ctrl[rx_agg->tid]) >> 4;

                                __ieee80211_start_rx_ba_session(sta,
                                                0, 0,
-- 
2.0.0.526.g5318336


From janusz.dziedzic at tieto.com  Sun Jul 27 23:26:05 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Mon, 28 Jul 2014 08:26:05 +0200
Subject: [PATCH v2] ath10k: extend debug code for RX path
Message-ID: <1406528765-4669-1-git-send-email-janusz.dziedzic@tieto.com>

Print sequence number, AMSDU_MORE flag and AC when additional
debug enabled in RX path. This is usefull for debugging purpose.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c |   41 ++++++++++++++++++++++++++++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index d80fcda..f7c8021 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -818,19 +818,55 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
 	return true;
 }
 
+static const char * const tid_to_ac[] = {
+	"BE",
+	"BK",
+	"BK",
+	"BE",
+	"VI",
+	"VI",
+	"VO",
+	"VO",
+};
+
+static char *ath10k_get_tid(struct ieee80211_hdr *hdr, char *out, size_t size)
+{
+	u8 *qc;
+	int tid;
+
+	if (!ieee80211_is_data_qos(hdr->frame_control))
+		return "";
+
+	qc = ieee80211_get_qos_ctl(hdr);
+	tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
+	if (tid < 8)
+		snprintf(out, size, "tid %d (%s)", tid, tid_to_ac[tid]);
+	else
+		snprintf(out, size, "tid %d", tid);
+
+	return out;
+}
+
 static void ath10k_process_rx(struct ath10k *ar,
 			      struct ieee80211_rx_status *rx_status,
 			      struct sk_buff *skb)
 {
 	struct ieee80211_rx_status *status;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	char tid[32];
 
 	status = IEEE80211_SKB_RXCB(skb);
 	*status = *rx_status;
 
 	ath10k_dbg(ATH10K_DBG_DATA,
-		   "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %imic-err %i\n",
+		   "rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
 		   skb,
 		   skb->len,
+		   ieee80211_get_SA(hdr),
+		   ath10k_get_tid(hdr, tid, sizeof(tid)),
+		   is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
+							"mcast" : "ucast",
+		   (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4,
 		   status->flag == 0 ? "legacy" : "",
 		   status->flag & RX_FLAG_HT ? "ht" : "",
 		   status->flag & RX_FLAG_VHT ? "vht" : "",
@@ -842,7 +878,8 @@ static void ath10k_process_rx(struct ath10k *ar,
 		   status->freq,
 		   status->band, status->flag,
 		   !!(status->flag & RX_FLAG_FAILED_FCS_CRC),
-		   !!(status->flag & RX_FLAG_MMIC_ERROR));
+		   !!(status->flag & RX_FLAG_MMIC_ERROR),
+		   !!(status->flag & RX_FLAG_AMSDU_MORE));
 	ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
 			skb->data, skb->len);
 
-- 
1.7.9.5



From varkabhadram at gmail.com  Sun Jul 27 23:35:31 2014
From: varkabhadram at gmail.com (Varka Bhadram)
Date: Mon, 28 Jul 2014 12:05:31 +0530
Subject: [PATCH v2] ath10k: extend debug code for RX path
In-Reply-To: <1406528765-4669-1-git-send-email-janusz.dziedzic@tieto.com>
References: <1406528765-4669-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <53D5EF33.1080208@gmail.com>

On 07/28/2014 11:56 AM, Janusz Dziedzic wrote:
> Print sequence number, AMSDU_MORE flag and AC when additional
> debug enabled in RX path. This is usefull for debugging purpose.
>
> Signed-off-by: Janusz Dziedzic<janusz.dziedzic at tieto.com>
> ---
>   drivers/net/wireless/ath/ath10k/htt_rx.c |   41 ++++++++++++++++++++++++++++--
>   1 file changed, 39 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
> index d80fcda..f7c8021 100644
> --- a/drivers/net/wireless/ath/ath10k/htt_rx.c
> +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
> @@ -818,19 +818,55 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
>   	return true;
>   }
>   
> +static const char * const tid_to_ac[] = {

No space required '*' and const.

static const char *const tid_to_ac[] = {


> +	"BE",
> +	"BK",
> +	"BK",
> +	"BE",
> +	"VI",
> +	"VI",
> +	"VO",
> +	"VO",
> +};
> +
> +static char *ath10k_get_tid(struct ieee80211_hdr *hdr, char *out, size_t size)
> +{
> +	u8 *qc;
> +	int tid;
> +
> +	if (!ieee80211_is_data_qos(hdr->frame_control))
> +		return "";

return NULL would be more readable...?

> +
> +	qc = ieee80211_get_qos_ctl(hdr);
> +	tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
> +	if (tid < 8)
> +		snprintf(out, size, "tid %d (%s)", tid, tid_to_ac[tid]);
> +	else
> +		snprintf(out, size, "tid %d", tid);
> +
> +	return out;
> +}
> +
>   static void ath10k_process_rx(struct ath10k *ar,
>   			      struct ieee80211_rx_status *rx_status,
>   			      struct sk_buff *skb)
>   {
>   	struct ieee80211_rx_status *status;
> +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
> +	char tid[32];
>   
>   	status = IEEE80211_SKB_RXCB(skb);
>   	*status = *rx_status;
>   
>   	ath10k_dbg(ATH10K_DBG_DATA,
> -		   "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %imic-err %i\n",
> +		   "rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
>   		   skb,
>   		   skb->len,
> +		   ieee80211_get_SA(hdr),
> +		   ath10k_get_tid(hdr, tid, sizeof(tid)),
> +		   is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
> +							"mcast" : "ucast",

should match open paranthesis...

is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
			"mcast" : "ucast",

> +		   (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4,
>   		   status->flag == 0 ? "legacy" : "",
>   		   status->flag & RX_FLAG_HT ? "ht" : "",
>   		   status->flag & RX_FLAG_VHT ? "vht" : "",
> @@ -842,7 +878,8 @@ static void ath10k_process_rx(struct ath10k *ar,
>   		   status->freq,
>   		   status->band, status->flag,
>   		   !!(status->flag & RX_FLAG_FAILED_FCS_CRC),
> -		   !!(status->flag & RX_FLAG_MMIC_ERROR));
> +		   !!(status->flag & RX_FLAG_MMIC_ERROR),
> +		   !!(status->flag & RX_FLAG_AMSDU_MORE));
>   	ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
>   			skb->data, skb->len);
>   


-- 
Regards,
Varka Bhadram.



From vh.nguyen at actiasodielec.fr  Mon Jul 28 00:32:50 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Mon, 28 Jul 2014 09:32:50 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <53D252B4.9070704@candelatech.com>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>,
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>,
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>,
 <53D252B4.9070704@candelatech.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7F6@srvexch01.SODIELEC.local>

>> My 2 devices have an ARM processor 1200MHz.
>> If I connect these two devices by an Ethernet cable and doing iperf (in TCP)
>> I can obtain 880 Mbps, it means that my processor can deal with that speed
>> of data transfer. But if I use Wi-fi instead of Ethernet to test rate between these
>> devices, my processor is exhausted, I run command top and see that 0~1%
>> idle only,  ksoftirqd and kworker take most of my processor resource.
>>
>> Last week I discovered by chance that the module loaded in kernel can create
>> effects to performance of rate, in my case it is "iptables". If I unload all module
>> that related to iptables I can improve the performance.
>> So I wonder if I can do some thing with the Wi-fi driver to  improve rate?
>> Or the only solution is overclock/change my processor?

>Can you run 'perf top' on your system when it is under load so we can
>see where the CPU is being used the most?

It's complicated for me to install "perf" cause it depends on the package linux-tools (please
correct me if I'm wrong :D)and our linux kernel is provided from the processor's producer.
I don't see the option to build "perf" form the menuconfig of our linux. I've enabled these parameters
but still when I run perf from shell there is no program found.

CONFIG_HAVE_PERF_EVENTS=y   
CONFIG_EVENT_TRACING=y     
CONFIG_PERF_EVENTS=y       
CONFIG_PERF_COUNTERS=y     

I can only run "top" to see what process used most of out CPU, they are  ksoftirqd and kworker.

NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE




From janusz.dziedzic at tieto.com  Mon Jul 28 00:52:30 2014
From: janusz.dziedzic at tieto.com (Janusz Dziedzic)
Date: Mon, 28 Jul 2014 09:52:30 +0200
Subject: [PATCH v2] ath10k: extend debug code for RX path
In-Reply-To: <53D5EF33.1080208@gmail.com>
References: <1406528765-4669-1-git-send-email-janusz.dziedzic@tieto.com>
 <53D5EF33.1080208@gmail.com>
Message-ID: <CALhHN=rOF+-8gJCM4tBNk39ksd_F_w_h2GB=njP6N6PXqkZiXg@mail.gmail.com>

On 28 July 2014 08:35, Varka Bhadram <varkabhadram at gmail.com> wrote:
> On 07/28/2014 11:56 AM, Janusz Dziedzic wrote:
>>
>> Print sequence number, AMSDU_MORE flag and AC when additional
>> debug enabled in RX path. This is usefull for debugging purpose.
>>
>> Signed-off-by: Janusz Dziedzic<janusz.dziedzic at tieto.com>
>> ---
>>   drivers/net/wireless/ath/ath10k/htt_rx.c |   41
>> ++++++++++++++++++++++++++++--
>>   1 file changed, 39 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c
>> b/drivers/net/wireless/ath/ath10k/htt_rx.c
>> index d80fcda..f7c8021 100644
>> --- a/drivers/net/wireless/ath/ath10k/htt_rx.c
>> +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
>> @@ -818,19 +818,55 @@ static bool ath10k_htt_rx_h_channel(struct ath10k
>> *ar,
>>         return true;
>>   }
>>   +static const char * const tid_to_ac[] = {
>
>
> No space required '*' and const.
>
Seems checkpatch didn't find this.

> static const char *const tid_to_ac[] = {
>
>
>
>> +       "BE",
>> +       "BK",
>> +       "BK",
>> +       "BE",
>> +       "VI",
>> +       "VI",
>> +       "VO",
>> +       "VO",
>> +};
>> +
>> +static char *ath10k_get_tid(struct ieee80211_hdr *hdr, char *out, size_t
>> size)
>> +{
>> +       u8 *qc;
>> +       int tid;
>> +
>> +       if (!ieee80211_is_data_qos(hdr->frame_control))
>> +               return "";
>
>
> return NULL would be more readable...?
>
We don't need extra "(null)" in printf, empty string is what I expect
here (same as other params in this dbg info).
Anyway I can return "out" here and initialize as empty before calling
ath10k_get_tid().

>
>> +
>> +       qc = ieee80211_get_qos_ctl(hdr);
>> +       tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
>> +       if (tid < 8)
>> +               snprintf(out, size, "tid %d (%s)", tid, tid_to_ac[tid]);
>> +       else
>> +               snprintf(out, size, "tid %d", tid);
>> +
>> +       return out;
>> +}
>> +
>>   static void ath10k_process_rx(struct ath10k *ar,
>>                               struct ieee80211_rx_status *rx_status,
>>                               struct sk_buff *skb)
>>   {
>>         struct ieee80211_rx_status *status;
>> +       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
>> +       char tid[32];
>>         status = IEEE80211_SKB_RXCB(skb);
>>         *status = *rx_status;
>>         ath10k_dbg(ATH10K_DBG_DATA,
>> -                  "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u
>> freq %u band %u flag 0x%x fcs-err %imic-err %i\n",
>> +                  "rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s
>> %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i
>> amsdu-more %i\n",
>>                    skb,
>>                    skb->len,
>> +                  ieee80211_get_SA(hdr),
>> +                  ath10k_get_tid(hdr, tid, sizeof(tid)),
>> +                  is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
>> +                                                       "mcast" : "ucast",
>
>
> should match open paranthesis...
>
> is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
>
>                         "mcast" : "ucast",
>
Could you describe this more (I didn't find clear description about this)?

BR
Janusz


From kvalo at qca.qualcomm.com  Mon Jul 28 01:07:12 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 28 Jul 2014 11:07:12 +0300
Subject: [PATCH v2] ath10k: extend debug code for RX path
In-Reply-To: <CALhHN=rOF+-8gJCM4tBNk39ksd_F_w_h2GB=njP6N6PXqkZiXg@mail.gmail.com>
 (Janusz Dziedzic's message of "Mon, 28 Jul 2014 09:52:30 +0200")
References: <1406528765-4669-1-git-send-email-janusz.dziedzic@tieto.com>
 <53D5EF33.1080208@gmail.com>
 <CALhHN=rOF+-8gJCM4tBNk39ksd_F_w_h2GB=njP6N6PXqkZiXg@mail.gmail.com>
Message-ID: <87ppgplxe7.fsf@kamboji.qca.qualcomm.com>

Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:

> On 28 July 2014 08:35, Varka Bhadram <varkabhadram at gmail.com> wrote:
>> On 07/28/2014 11:56 AM, Janusz Dziedzic wrote:
>>>
>>> Print sequence number, AMSDU_MORE flag and AC when additional
>>> debug enabled in RX path. This is usefull for debugging purpose.
>>>
>>> Signed-off-by: Janusz Dziedzic<janusz.dziedzic at tieto.com>
>>> ---
>>>   drivers/net/wireless/ath/ath10k/htt_rx.c |   41
>>> ++++++++++++++++++++++++++++--
>>>   1 file changed, 39 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c
>>> b/drivers/net/wireless/ath/ath10k/htt_rx.c
>>> index d80fcda..f7c8021 100644
>>> --- a/drivers/net/wireless/ath/ath10k/htt_rx.c
>>> +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
>>> @@ -818,19 +818,55 @@ static bool ath10k_htt_rx_h_channel(struct ath10k
>>> *ar,
>>>         return true;
>>>   }
>>>   +static const char * const tid_to_ac[] = {
>>
>>
>> No space required '*' and const.
>
> Seems checkpatch didn't find this.

>From a quick grep I saw that kernel has both "* const" and "*const". I
would say keep it as it is.

>>> +static char *ath10k_get_tid(struct ieee80211_hdr *hdr, char *out, size_t
>>> size)
>>> +{
>>> +       u8 *qc;
>>> +       int tid;
>>> +
>>> +       if (!ieee80211_is_data_qos(hdr->frame_control))
>>> +               return "";
>>
>>
>> return NULL would be more readable...?
>>
> We don't need extra "(null)" in printf, empty string is what I expect
> here (same as other params in this dbg info).
> Anyway I can return "out" here and initialize as empty before calling
> ath10k_get_tid().

IMHO return "" is more readable here.

>>> +                  is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
>>> +                                                       "mcast" : "ucast",
>>
>>
>> should match open paranthesis...
>>
>> is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
>>
>>                         "mcast" : "ucast",
>>
> Could you describe this more (I didn't find clear description about this)?

AFAICS there is no open parenthesis here to which align the indentation.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Jul 28 01:12:52 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 28 Jul 2014 11:12:52 +0300
Subject: [RFC] extract seqno from sta->last_seq_ctrl
In-Reply-To: <CABnBrYV27yNECG6PPWp2Gsz5w3azbEzGc4n5TcfavvUBbN8U_g@mail.gmail.com>
 (Denton Gentry's message of "Sun, 27 Jul 2014 10:51:01 -0700")
References: <CABnBrYV27yNECG6PPWp2Gsz5w3azbEzGc4n5TcfavvUBbN8U_g@mail.gmail.com>
Message-ID: <87lhrdlx4r.fsf@kamboji.qca.qualcomm.com>

Denton Gentry <denton.gentry at gmail.com> writes:

>>From d0647db58d13533e5441c07f95b23e912976c87b Mon Sep 17 00:00:00 2001
> From: Denton Gentry <denton.gentry at gmail.com>
> Date: Sun, 27 Jul 2014 08:24:36 -0700
> Subject: [PATCH] extract seqno from sta->last_seq_ctrl
>
> This depends on:
> * [PATCH v2] mac80211: add support for Rx reordering offloading
>
> sta->last_seq_ctrl is the seq_ctrl field from the last
> header seen, need to byteswap and shift it 4 bits to
> extract the sequence number.

I'll let Michal comment on the bug, but I cannot do anything with this
patch as it doesn't have the Signed-off-by tag. Can you resend, please?

-- 
Kalle Valo


From michal.kazior at tieto.com  Mon Jul 28 03:13:43 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 28 Jul 2014 12:13:43 +0200
Subject: [RFC] extract seqno from sta->last_seq_ctrl
In-Reply-To: <CABnBrYV27yNECG6PPWp2Gsz5w3azbEzGc4n5TcfavvUBbN8U_g@mail.gmail.com>
References: <CABnBrYV27yNECG6PPWp2Gsz5w3azbEzGc4n5TcfavvUBbN8U_g@mail.gmail.com>
Message-ID: <CA+BoTQm9VXKki+st5A5cVOA-yjrVhLw+gZ6cKPNPPAUtzWFo5Q@mail.gmail.com>

On 27 July 2014 19:51, Denton Gentry <denton.gentry at gmail.com> wrote:
> [Sending to ath10k list as I think ath10k is the only impacted driver right now]
>
> I believe there is a minor problem in
> [PATCH v2] mac80211: add support for Rx reordering offloading
> http://www.spinics.net/lists/linux-wireless/msg124812.html
>
> sta->last_seq_ctrl is the seq_ctrl field from the last seen packet. To
> get the sequence number it needs to be byteswapped and shifted 4 bits;
> patch below.

Good catch!


> This mostly impacts Windows clients, because Windows sends 100-200
> frames before sending ADDBA. This results in a starting seqno which is
> quite large due to the 4 bit shift, and the ieee80211_sn_less() check
> at the top of ieee80211_sta_manage_reorder_buf drops subsequent frames
> until the sequence number catches up.
>
>
> From d0647db58d13533e5441c07f95b23e912976c87b Mon Sep 17 00:00:00 2001
> From: Denton Gentry <denton.gentry at gmail.com>
> Date: Sun, 27 Jul 2014 08:24:36 -0700
> Subject: [PATCH] extract seqno from sta->last_seq_ctrl

You're missing "mac80211: " prefix. Also this message doesn't seem to
tell much. I'd probably entitle it "mac80211: fix start_seq_num in Rx
reorder offload" and then follow that with details (what/why).


>
> This depends on:
> * [PATCH v2] mac80211: add support for Rx reordering offloading

This shouldn't be in the commit log.


>
> sta->last_seq_ctrl is the seq_ctrl field from the last
> header seen, need to byteswap and shift it 4 bits to
> extract the sequence number.
>
>  net/mac80211/iface.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
> index 77cd025..1903220 100644
> --- a/net/mac80211/iface.c
> +++ b/net/mac80211/iface.c
> @@ -1171,7 +1171,7 @@ static void ieee80211_iface_work(struct work_struct *work)
>                         mutex_lock(&local->sta_mtx);
>                         sta = sta_info_get_bss(sdata, rx_agg->addr);
>                         if (sta) {
> -                               u16 last_seq = sta->last_seq_ctrl[rx_agg->tid];
> +                               u16 last_seq =
> le16_to_cpu(sta->last_seq_ctrl[rx_agg->tid]) >> 4;

The byteswap is already in place (Johannes fixed it).

The bitshift should be done with IEEE80211_SEQ_TO_SN macro.

Once you fix the commit log and rebase your patch you should submit
this to linux-wireless mailing list.


Micha?


From vh.nguyen at actiasodielec.fr  Mon Jul 28 04:53:18 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Mon, 28 Jul 2014 13:53:18 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <53D252B4.9070704@candelatech.com>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>,
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>,
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>,
 <53D252B4.9070704@candelatech.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7F8@srvexch01.SODIELEC.local>

>> My 2 devices have an ARM processor 1200MHz.
>> If I connect these two devices by an Ethernet cable and doing iperf (in TCP)
>> I can obtain 880 Mbps, it means that my processor can deal with that speed
>> of data transfer. But if I use Wi-fi instead of Ethernet to test rate between these
>> devices, my processor is exhausted, I run command top and see that 0~1%
>> idle only,  ksoftirqd and kworker take most of my processor resource.
>>
>> Last week I discovered by chance that the module loaded in kernel can create
>> effects to performance of rate, in my case it is "iptables". If I unload all module
>> that related to iptables I can improve the performance.
>> So I wonder if I can do some thing with the Wi-fi driver to  improve rate?
>> Or the only solution is overclock/change my processor?

>Can you run 'perf top' on your system when it is under load so we can
>see where the CPU is being used the most?

I follow a tutorial to cross compile perf so here is my result


PerfTop:      70 irqs/sec  kernel:98.6%  exact:  0.0% [1000Hz cycles],  (all, 1 CPU)
-------------------------------------------------------------------------------

    39.43%  [kernel]       [k] csum_partial_copy_nocheck
     5.54%  [kernel]       [k] __kmalloc_track_caller
     4.93%  [kernel]       [k] kfree
     4.31%  [mac80211]     [k] ieee80211_tx_status
     4.31%  [kernel]       [k] memcpy
     3.49%  [kernel]       [k] __memzero
     3.29%  [kernel]       [k] mv_eth_poll
     3.29%  [kernel]       [k] __kfree_skb
     2.05%  [ath10k_pci]   [k] ath10k_ce_send_nolock
     1.44%  [mac80211]     [k] $a
     1.44%  [kernel]       [k] dev_gro_receive
     1.44%  [kernel]       [k] napi_gro_receive
     1.44%  [kernel]       [k] eth_type_trans
     1.44%  [kernel]       [k] inet_gro_receive
     1.44%  [kernel]       [k] skb_copy_and_csum_bits
     1.44%  [kernel]       [k] skb_segment
     1.44%  [ath10k_core]  [k] ath10k_htt_rx_amsdu_pop
     1.44%  [ath10k_core]  [k] ath10k_txrx_tx_unref
     1.23%  [kernel]       [k] local_bh_enable                                  
     1.23%  [kernel]       [k] kmem_cache_alloc                                 
     1.23%  [kernel]       [k] dev_hard_start_xmit 


Thank you in advance for your response,

NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE



Thanks,
Ben

>
> NGUYEN Vu Hai
> Acita-Sodielec
> Route de Mayres - B.P. 9
> 12100 St GEORGES DE LUZENCON
> FRANCE
>
>
>
>
> _______________________________________________
> ath10k mailing list
> ath10k at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/ath10k
>

--
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


From michal.kazior at tieto.com  Mon Jul 28 06:28:52 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 28 Jul 2014 15:28:52 +0200
Subject: [PATCH] ath10k: improve channel switching
Message-ID: <1406554132-17264-1-git-send-email-michal.kazior@tieto.com>

In some cases during heavy tx vdev stop-start
would timeout on vdev synchronization causing
traffic to stall for a few seconds.

Instead of stop-starting use a dedicated vdev
restart command and down vdevs explicitly before
doing so.

This gets rid of the synchronization
warnings/timeouts and makes channel switching
smoother during traffic.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 9d61bb1..b76efe2 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -796,7 +796,7 @@ static void ath10k_recalc_radar_detection(struct ath10k *ar)
 	}
 }
 
-static int ath10k_vdev_start(struct ath10k_vif *arvif)
+static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, bool restart)
 {
 	struct ath10k *ar = arvif->ar;
 	struct cfg80211_chan_def *chandef = &ar->chandef;
@@ -838,7 +838,11 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif)
 		   arg.vdev_id, arg.channel.freq,
 		   ath10k_wmi_phymode_str(arg.channel.mode));
 
-	ret = ath10k_wmi_vdev_start(ar, &arg);
+	if (restart)
+		ret = ath10k_wmi_vdev_restart(ar, &arg);
+	else
+		ret = ath10k_wmi_vdev_start(ar, &arg);
+
 	if (ret) {
 		ath10k_warn("failed to start WMI vdev %i: %d\n",
 			    arg.vdev_id, ret);
@@ -858,6 +862,16 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif)
 	return ret;
 }
 
+static int ath10k_vdev_start(struct ath10k_vif *arvif)
+{
+	return ath10k_vdev_start_restart(arvif, false);
+}
+
+static int ath10k_vdev_restart(struct ath10k_vif *arvif)
+{
+	return ath10k_vdev_start_restart(arvif, true);
+}
+
 static int ath10k_vdev_stop(struct ath10k_vif *arvif)
 {
 	struct ath10k *ar = arvif->ar;
@@ -2582,18 +2596,21 @@ static void ath10k_config_chan(struct ath10k *ar)
 		if (!arvif->is_started)
 			continue;
 
+		if (!arvif->is_up)
+			continue;
+
 		if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
 			continue;
 
-		ret = ath10k_vdev_stop(arvif);
+		ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
 		if (ret) {
-			ath10k_warn("failed to stop vdev %d: %d\n",
+			ath10k_warn("failed to down vdev %d: %d\n",
 				    arvif->vdev_id, ret);
 			continue;
 		}
 	}
 
-	/* all vdevs are now stopped - now attempt to restart them */
+	/* all vdevs are downed now - attempt to restart and re-up them */
 
 	list_for_each_entry(arvif, &ar->arvifs, list) {
 		if (!arvif->is_started)
@@ -2602,9 +2619,9 @@ static void ath10k_config_chan(struct ath10k *ar)
 		if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
 			continue;
 
-		ret = ath10k_vdev_start(arvif);
+		ret = ath10k_vdev_restart(arvif);
 		if (ret) {
-			ath10k_warn("failed to start vdev %d: %d\n",
+			ath10k_warn("failed to restart vdev %d: %d\n",
 				    arvif->vdev_id, ret);
 			continue;
 		}
-- 
1.8.5.3



From greearb at candelatech.com  Mon Jul 28 09:08:26 2014
From: greearb at candelatech.com (Ben Greear)
Date: Mon, 28 Jul 2014 09:08:26 -0700
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D7F8@srvexch01.SODIELEC.local>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>,
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>,
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>,
 <53D252B4.9070704@candelatech.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F8@srvexch01.SODIELEC.local>
Message-ID: <53D6757A.8040803@candelatech.com>

On 07/28/2014 04:53 AM, Vu Hai NGUYEN wrote:
>>> My 2 devices have an ARM processor 1200MHz.
>>> If I connect these two devices by an Ethernet cable and doing iperf (in TCP)
>>> I can obtain 880 Mbps, it means that my processor can deal with that speed
>>> of data transfer. But if I use Wi-fi instead of Ethernet to test rate between these
>>> devices, my processor is exhausted, I run command top and see that 0~1%
>>> idle only,  ksoftirqd and kworker take most of my processor resource.
>>>
>>> Last week I discovered by chance that the module loaded in kernel can create
>>> effects to performance of rate, in my case it is "iptables". If I unload all module
>>> that related to iptables I can improve the performance.
>>> So I wonder if I can do some thing with the Wi-fi driver to  improve rate?
>>> Or the only solution is overclock/change my processor?
> 
>> Can you run 'perf top' on your system when it is under load so we can
>> see where the CPU is being used the most?
> 
> I follow a tutorial to cross compile perf so here is my result
> 
> 
> PerfTop:      70 irqs/sec  kernel:98.6%  exact:  0.0% [1000Hz cycles],  (all, 1 CPU)
> -------------------------------------------------------------------------------
> 
>     39.43%  [kernel]       [k] csum_partial_copy_nocheck

Looks like your ethernet driver is not doing checksum offloading?

I am pretty sure ath10k does support this unless you have managed
to disabled it somehow?

Thanks,
Ben

>      5.54%  [kernel]       [k] __kmalloc_track_caller
>      4.93%  [kernel]       [k] kfree
>      4.31%  [mac80211]     [k] ieee80211_tx_status
>      4.31%  [kernel]       [k] memcpy
>      3.49%  [kernel]       [k] __memzero
>      3.29%  [kernel]       [k] mv_eth_poll
>      3.29%  [kernel]       [k] __kfree_skb
>      2.05%  [ath10k_pci]   [k] ath10k_ce_send_nolock
>      1.44%  [mac80211]     [k] $a
>      1.44%  [kernel]       [k] dev_gro_receive
>      1.44%  [kernel]       [k] napi_gro_receive
>      1.44%  [kernel]       [k] eth_type_trans
>      1.44%  [kernel]       [k] inet_gro_receive
>      1.44%  [kernel]       [k] skb_copy_and_csum_bits
>      1.44%  [kernel]       [k] skb_segment
>      1.44%  [ath10k_core]  [k] ath10k_htt_rx_amsdu_pop
>      1.44%  [ath10k_core]  [k] ath10k_txrx_tx_unref
>      1.23%  [kernel]       [k] local_bh_enable                                  
>      1.23%  [kernel]       [k] kmem_cache_alloc                                 
>      1.23%  [kernel]       [k] dev_hard_start_xmit 
> 
> 
> Thank you in advance for your response,
> 
> NGUYEN Vu Hai
> Acita-Sodielec
> Route de Mayres - B.P. 9
> 12100 St GEORGES DE LUZENCON
> FRANCE
> 
> 
> 
> Thanks,
> Ben
> 
>>
>> NGUYEN Vu Hai
>> Acita-Sodielec
>> Route de Mayres - B.P. 9
>> 12100 St GEORGES DE LUZENCON
>> FRANCE
>>
>>
>>
>>
>> _______________________________________________
>> ath10k mailing list
>> ath10k at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/ath10k
>>
> 
> --
> Ben Greear <greearb at candelatech.com>
> Candela Technologies Inc  http://www.candelatech.com
> 


-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From kvalo at qca.qualcomm.com  Mon Jul 28 12:39:20 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 28 Jul 2014 22:39:20 +0300
Subject: [PATCH] ath10k:  Improve 'hard' simulate fw crash.
In-Reply-To: <1406070004-6238-1-git-send-email-greearb@candelatech.com>
 (greearb@candelatech.com's message of "Tue, 22 Jul 2014 16:00:04
 -0700")
References: <1406070004-6238-1-git-send-email-greearb@candelatech.com>
Message-ID: <874my1l1cn.fsf@kamboji.qca.qualcomm.com>

greearb at candelatech.com writes:

> From: Ben Greear <greearb at candelatech.com>
>
> Different firmware may support different numbers of
> vdevs.  Use value that is always out of range for all
> firmware.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Jul 28 13:59:15 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 28 Jul 2014 23:59:15 +0300
Subject: [PATCH] ath10k: add support for 10.2 firmware
In-Reply-To: <1406287937-26507-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Fri, 25 Jul 2014 13:32:17 +0200")
References: <1406287937-26507-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87oaw9jj30.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> The 10.2 firmware is a successor of 10.1 firmware
> (formerly identified as 10.x). Both share a lot
> but have some slight ABI differences that need to
> be taken care of.
>
> The 10.2 firmware introduces some new features but
> those can be added in subsequent patches. This
> patch makes ath10k boot and work with 10.2 with
> comparable functionality to 10.1.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied with minor changes:

> +static void ath10k_wmi_10_2_process_rx(struct ath10k *ar, struct sk_buff *skb)
> +{
> +	struct wmi_cmd_hdr *cmd_hdr;
> +	enum wmi_10_2_event_id id;
> +
> +	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
> +	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
> +
> +	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
> +		return;
> +
> +	trace_ath10k_wmi_event(id, skb->data, skb->len);
> +
> +	switch (id) {
> +
> +
> +	case WMI_10_2_MGMT_RX_EVENTID:

checkpatch warned about extra newlines here.

> +static void
> +ath10k_wmi_peer_assoc_fill_main_636(struct ath10k *ar, void *buf,
> +				    const struct wmi_peer_assoc_complete_arg *arg)
> +{

And this was too long. I "fixed" it by s/main_636/main/. I think the 636
part was a bit redundant anyway.

-- 
Kalle Valo


From michal.kazior at tieto.com  Mon Jul 28 23:26:22 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 29 Jul 2014 08:26:22 +0200
Subject: ath10k tx to a Macbook Pro stalls
In-Reply-To: <CALCETrXtvTyFbc0RM0kHcW_UiX+eurRTdp0vdQER2ysUrd4FcQ@mail.gmail.com>
References: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>
 <87vbqqwoks.fsf@kamboji.qca.qualcomm.com>
 <CALCETrXtvTyFbc0RM0kHcW_UiX+eurRTdp0vdQER2ysUrd4FcQ@mail.gmail.com>
Message-ID: <CA+BoTQ=q-Xfk6+FwcT7yLd+YpcZobNVhszfwhLHeyL3XExps4w@mail.gmail.com>

On 22 July 2014 06:12, Andy Lutomirski <luto at amacapital.net> wrote:
> On Mon, Jul 21, 2014 at 11:31 AM, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> Andy Lutomirski <luto at amacapital.net> writes:
>>
>>> On my Archer C7 v2, as soon as the MBP tries to do something like
>>> playing a video, it seems like frames *to* the MBP no longer get
>>> there.  At the very least, arp replies don't get there.
>>
>> A multicast problem? Can you run for example 'arping -b <macbook's ip>'
>> to check if multicast stops working at some point? What if you hardcode
>> the ARP address, do unicast packets go to the macbook still?
>
> It's a unicast problem, actually.  arping -b works.  arping w/o -b
> gets one reply.
>
> arp -s <IP> ff:ff:ff:ff:ff:ff allows me to ping the MBP (with
> moderately high loss).  (I'm actually a bit surprised that Linux is
> okay with that.)
>
> Does this mean that the MBP is failing to notice TIM entries, or that
> ath10k somehow stops buffering packets to power-saving stations?

Do you have u-APSD enabled in your OpenWRT configuration by any chance?


Micha?


From vh.nguyen at actiasodielec.fr  Tue Jul 29 01:02:34 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Tue, 29 Jul 2014 10:02:34 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <53D6757A.8040803@candelatech.com>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>,
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>,
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>,
 <53D252B4.9070704@candelatech.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F8@srvexch01.SODIELEC.local>,
 <53D6757A.8040803@candelatech.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D7FE@srvexch01.SODIELEC.local>

>> I follow a tutorial to cross compile perf so here is my result
>>
>>
>> PerfTop:      70 irqs/sec  kernel:98.6%  exact:  0.0% [1000Hz cycles],  (all, 1 CPU)
>> -------------------------------------------------------------------------------
>>
>>     39.43%  [kernel]       [k] csum_partial_copy_nocheck

>Looks like your ethernet driver is not doing checksum offloading?

>I am pretty sure ath10k does support this unless you have managed
>to disabled it somehow?

I'm using ath10k from master branch (generated by backport), My only hack is changing the default country of regulatory domain from US to France.
The checksum patch is implemented by Michal Kazior since july 2013 and I also check that there is function checksum state in htt_rx.c file so it should be in my 
driver module.
But I install ethtool and here is the ouput of my interface wlan0:
#ethtool --show-offload  wlan0 
Features for wlan0:
rx-checksumming: off [fixed]
tx-checksumming: on
	tx-checksum-ipv4: off [fixed]
	tx-checksum-unneeded: off [fixed]
	tx-checksum-ip-generic: on [fixed]
	tx-checksum-ipv6: off [fixed]
	tx-checksum-fcoe-crc: off [fixed]
	tx-checksum-sctp: off [fixed]
scatter-gather: off
	tx-scatter-gather: off [fixed]
	tx-scatter-gather-fraglist: off [fixed]
tcp-segmentation-offload: off
	tx-tcp-segmentation: off [fixed]
	tx-tcp-ecn-segmentation: off [fixed]
	tx-tcp6-segmentation: off [fixed]
udp-fragmentation-offload: off [fixed]
generic-segmentation-offload: off [requested on]
generic-receive-offload: on
large-receive-offload: off [fixed]
rx-vlan-offload: off [fixed]
tx-vlan-offload: off [fixed]
ntuple-filters: off [fixed]
receive-hashing: off [fixed]
highdma: off [fixed]
rx-vlan-filter: off [fixed]
vlan-challenged: off [fixed]
tx-lockless: off [fixed]
netns-local: on [fixed]
tx-gso-robust: off [fixed]
tx-fcoe-segmentation: off [fixed]
fcoe-mtu: off [fixed]
tx-nocache-copy: on
loopback: off [fixed]

And I cannot enable these function, as it show [fixed] like above.
# ethtool --offload  wlan0  rx on  tx on
Cannot change rx-checksumming
Cannot change tx-checksumming


>>      5.54%  [kernel]       [k] __kmalloc_track_caller
>>      4.93%  [kernel]       [k] kfree
>>      4.31%  [mac80211]     [k] ieee80211_tx_status
>>      4.31%  [kernel]       [k] memcpy
>>      3.49%  [kernel]       [k] __memzero
>>      3.29%  [kernel]       [k] mv_eth_poll
>>      3.29%  [kernel]       [k] __kfree_skb
>>      2.05%  [ath10k_pci]   [k] ath10k_ce_send_nolock
>>      1.44%  [mac80211]     [k] $a
>>      1.44%  [kernel]       [k] dev_gro_receive
>>      1.44%  [kernel]       [k] napi_gro_receive
>>      1.44%  [kernel]       [k] eth_type_trans
>>      1.44%  [kernel]       [k] inet_gro_receive
>>      1.44%  [kernel]       [k] skb_copy_and_csum_bits
>>      1.44%  [kernel]       [k] skb_segment
>>      1.44%  [ath10k_core]  [k] ath10k_htt_rx_amsdu_pop
>>      1.44%  [ath10k_core]  [k] ath10k_txrx_tx_unref
>>      1.23%  [kernel]       [k] local_bh_enable
>>      1.23%  [kernel]       [k] kmem_cache_alloc
>>      1.23%  [kernel]       [k] dev_hard_start_xmit
>>
>>
>> Thank you in advance for your response,


NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE




From kvalo at qca.qualcomm.com  Tue Jul 29 02:20:02 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 29 Jul 2014 12:20:02 +0300
Subject: [PATCH 1/2] ath10k: introduce a stricter scan state machine
In-Reply-To: <1405941081-17359-2-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Mon, 21 Jul 2014 13:11:20 +0200")
References: <1405941081-17359-1-git-send-email-michal.kazior@tieto.com>
 <1405941081-17359-2-git-send-email-michal.kazior@tieto.com>
Message-ID: <87egx4iksd.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> This aims at fixing some rare scan bugs related to
> firmware reporting unexpected scan event
> sequences.
>
> One such bug was if spectral scan phyerr reporting
> prevented firmware from properly propagating scan
> events to host. This leadsl to scan timeout. After
> that next scan would trigger scan completed event
> first (before scan started event) leading to
> ar->scan.in_progress and timeout timer states to
> be overwritten incorrectly and making the very
> next scan to hang forever.
>
> Reported-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

> +enum ath10k_scan_state {
> +	ATH10K_SCAN_IDLE,
> +	ATH10K_SCAN_STARTING,
> +	ATH10K_SCAN_RUNNING,
> +	ATH10K_SCAN_RUNNING_AND_ABORTING,
> +};

Can't we just call the last state just as ATH10K_SCAN_ABORTING? I think
I understand why you added the word "running" there but IMHO that's not
needed.

> @@ -2323,8 +2348,6 @@ void ath10k_halt(struct ath10k *ar)
>  		ath10k_monitor_stop(ar);
>  	}
>  
> -	del_timer_sync(&ar->scan.timeout);
> -	ath10k_reset_scan((unsigned long)ar);
>  	ath10k_peer_cleanup_all(ar);
>  	ath10k_core_stop(ar);
>  	ath10k_hif_power_down(ar);

Why you don't call ath10k_scan_reset() here? I would have assumed that
you do that.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Jul 29 02:44:36 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 29 Jul 2014 12:44:36 +0300
Subject: [PATCH] ath10k: fix aggregated 4addr Rx
In-Reply-To: <1406205374-24858-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 24 Jul 2014 14:36:14 +0200")
References: <1406205374-24858-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <8761igijnf.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

> A-MSDU 4addr frames weren't reconstructed properly
> and in some cases this resulted in a warning:
>
>  br0: received packet on wlan0.sta1 with own address as source address
>
> Since this was only related to A-MSDU it would
> trigger when more intense traffic was generated.
>
> Reported-by: Vu Hai NGUYEN <vh.nguyen at actiasodielec.fr>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From michal.kazior at tieto.com  Tue Jul 29 02:46:48 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 29 Jul 2014 11:46:48 +0200
Subject: [PATCH 1/2] ath10k: introduce a stricter scan state machine
In-Reply-To: <87egx4iksd.fsf@kamboji.qca.qualcomm.com>
References: <1405941081-17359-1-git-send-email-michal.kazior@tieto.com>
 <1405941081-17359-2-git-send-email-michal.kazior@tieto.com>
 <87egx4iksd.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQnMKDCPTOZswZTg8s-_hmaKBiwDT_Rj4tt=ReR7RUWQ3w@mail.gmail.com>

On 29 July 2014 11:20, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
>
>> This aims at fixing some rare scan bugs related to
>> firmware reporting unexpected scan event
>> sequences.
>>
>> One such bug was if spectral scan phyerr reporting
>> prevented firmware from properly propagating scan
>> events to host. This leadsl to scan timeout. After
>> that next scan would trigger scan completed event
>> first (before scan started event) leading to
>> ar->scan.in_progress and timeout timer states to
>> be overwritten incorrectly and making the very
>> next scan to hang forever.
>>
>> Reported-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
>> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
>
>> +enum ath10k_scan_state {
>> +     ATH10K_SCAN_IDLE,
>> +     ATH10K_SCAN_STARTING,
>> +     ATH10K_SCAN_RUNNING,
>> +     ATH10K_SCAN_RUNNING_AND_ABORTING,
>> +};
>
> Can't we just call the last state just as ATH10K_SCAN_ABORTING? I think
> I understand why you added the word "running" there but IMHO that's not
> needed.

I'll change that.


>> @@ -2323,8 +2348,6 @@ void ath10k_halt(struct ath10k *ar)
>>               ath10k_monitor_stop(ar);
>>       }
>>
>> -     del_timer_sync(&ar->scan.timeout);
>> -     ath10k_reset_scan((unsigned long)ar);
>>       ath10k_peer_cleanup_all(ar);
>>       ath10k_core_stop(ar);
>>       ath10k_hif_power_down(ar);
>
> Why you don't call ath10k_scan_reset() here? I would have assumed that
> you do that.

Hmm.. Good catch.

Anyway I need to work on this patch a little bit more and fix another
corner case.


Micha?


From kvalo at qca.qualcomm.com  Tue Jul 29 02:48:46 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 29 Jul 2014 12:48:46 +0300
Subject: [PATCH v2] ath10k: extend debug code for RX path
In-Reply-To: <1406528765-4669-1-git-send-email-janusz.dziedzic@tieto.com>
 (Janusz Dziedzic's message of "Mon, 28 Jul 2014 08:26:05 +0200")
References: <1406528765-4669-1-git-send-email-janusz.dziedzic@tieto.com>
Message-ID: <871tt4ijgh.fsf@kamboji.qca.qualcomm.com>

Janusz Dziedzic <janusz.dziedzic at tieto.com> writes:

> Print sequence number, AMSDU_MORE flag and AC when additional
> debug enabled in RX path. This is usefull for debugging purpose.
>
> Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Jul 29 02:51:17 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 29 Jul 2014 12:51:17 +0300
Subject: [PATCH 1/2] ath10k: introduce a stricter scan state machine
In-Reply-To: <CA+BoTQnMKDCPTOZswZTg8s-_hmaKBiwDT_Rj4tt=ReR7RUWQ3w@mail.gmail.com>
 (Michal Kazior's message of "Tue, 29 Jul 2014 11:46:48 +0200")
References: <1405941081-17359-1-git-send-email-michal.kazior@tieto.com>
 <1405941081-17359-2-git-send-email-michal.kazior@tieto.com>
 <87egx4iksd.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQnMKDCPTOZswZTg8s-_hmaKBiwDT_Rj4tt=ReR7RUWQ3w@mail.gmail.com>
Message-ID: <87wqawh4ru.fsf@kamboji.qca.qualcomm.com>

Michal Kazior <michal.kazior at tieto.com> writes:

>>> @@ -2323,8 +2348,6 @@ void ath10k_halt(struct ath10k *ar)
>>>               ath10k_monitor_stop(ar);
>>>       }
>>>
>>> -     del_timer_sync(&ar->scan.timeout);
>>> -     ath10k_reset_scan((unsigned long)ar);
>>>       ath10k_peer_cleanup_all(ar);
>>>       ath10k_core_stop(ar);
>>>       ath10k_hif_power_down(ar);
>>
>> Why you don't call ath10k_scan_reset() here? I would have assumed that
>> you do that.
>
> Hmm.. Good catch.
>
> Anyway I need to work on this patch a little bit more and fix another
> corner case.

Ok, I'll drop this patch and wait for the next version.

-- 
Kalle Valo


From michal.kazior at tieto.com  Tue Jul 29 03:03:59 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 29 Jul 2014 12:03:59 +0200
Subject: [PATCH] ath10k: fix wmi service bitmap debug
Message-ID: <1406628239-31322-1-git-send-email-michal.kazior@tieto.com>

The 10.x and main firmware branches have
conflicting WMI service bitmap definitions.

This also fixes WMI services parsing on big-endian
hosts and changes debugfs output to be more human
friendly.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h  |   2 +-
 drivers/net/wireless/ath/ath10k/debug.c |  26 ++-
 drivers/net/wireless/ath/ath10k/wmi.c   |  14 +-
 drivers/net/wireless/ath/ath10k/wmi.h   | 367 +++++++++++++++++++++++---------
 4 files changed, 290 insertions(+), 119 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index ded3af2..d8141fe 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -280,7 +280,7 @@ struct ath10k_debug {
 	struct dentry *debugfs_phy;
 
 	struct ath10k_target_stats target_stats;
-	u32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE];
+	DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_BM_SIZE);
 
 	struct completion event_stats_compl;
 
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index c9e35c87e..df1abe7 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -115,9 +115,10 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
 {
 	struct ath10k *ar = file->private_data;
 	char *buf;
-	unsigned int len = 0, buf_len = 1500;
-	const char *status;
+	unsigned int len = 0, buf_len = 4096;
+	const char *name;
 	ssize_t ret_cnt;
+	bool enabled;
 	int i;
 
 	buf = kzalloc(buf_len, GFP_KERNEL);
@@ -129,15 +130,22 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
 	if (len > buf_len)
 		len = buf_len;
 
-	for (i = 0; i < WMI_SERVICE_LAST; i++) {
-		if (WMI_SERVICE_IS_ENABLED(ar->debug.wmi_service_bitmap, i))
-			status = "enabled";
-		else
-			status = "disabled";
+	for (i = 0; i < WMI_MAX_SERVICE; i++) {
+		enabled = test_bit(i, ar->debug.wmi_service_bitmap);
+		name = wmi_service_name(i);
+
+		if (!name) {
+			if (enabled)
+				len += scnprintf(buf + len, buf_len - len,
+						 "%-40s %s (bit %d)\n",
+						 "unknown", "enabled", i);
+
+			continue;
+		}
 
 		len += scnprintf(buf + len, buf_len - len,
-				 "0x%02x - %20s - %s\n",
-				 i, wmi_service_name(i), status);
+				 "%-40s %s\n",
+				 name, enabled ? "enabled" : "-");
 	}
 
 	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index b09661d..94e534a 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2033,6 +2033,7 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
 					      struct sk_buff *skb)
 {
 	struct wmi_service_ready_event *ev = (void *)skb->data;
+	DECLARE_BITMAP(svc_bmap, WMI_SERVICE_BM_SIZE) = {};
 
 	if (skb->len < sizeof(*ev)) {
 		ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
@@ -2066,8 +2067,10 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
 	ar->ath_common.regulatory.current_rd =
 		__le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
 
-	ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap,
-				      sizeof(ev->wmi_service_bitmap));
+	wmi_main_svc_map(ev->wmi_service_bitmap, svc_bmap);
+	ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
+	ath10k_dbg_dump(ATH10K_DBG_WMI, NULL, "ath10k: wmi svc: ",
+			ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap));
 
 	if (strlen(ar->hw->wiphy->fw_version) == 0) {
 		snprintf(ar->hw->wiphy->fw_version,
@@ -2107,6 +2110,7 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
 	u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
 	int ret;
 	struct wmi_service_ready_event_10x *ev = (void *)skb->data;
+	DECLARE_BITMAP(svc_bmap, WMI_SERVICE_BM_SIZE) = {};
 
 	if (skb->len < sizeof(*ev)) {
 		ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
@@ -2133,8 +2137,10 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
 	ar->ath_common.regulatory.current_rd =
 		__le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
 
-	ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap,
-				      sizeof(ev->wmi_service_bitmap));
+	wmi_10x_svc_map(ev->wmi_service_bitmap, svc_bmap);
+	ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
+	ath10k_dbg_dump(ATH10K_DBG_WMI, NULL, "ath10k: wmi svc: ",
+			ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap));
 
 	if (strlen(ar->hw->wiphy->fw_version) == 0) {
 		snprintf(ar->hw->wiphy->fw_version,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index c9ac11c..c197012 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -73,116 +73,277 @@ struct wmi_cmd_hdr {
 #define HTC_PROTOCOL_VERSION    0x0002
 #define WMI_PROTOCOL_VERSION    0x0002
 
-enum wmi_service_id {
-	WMI_SERVICE_BEACON_OFFLOAD = 0,   /* beacon offload */
-	WMI_SERVICE_SCAN_OFFLOAD,	  /* scan offload */
-	WMI_SERVICE_ROAM_OFFLOAD,	  /* roam offload */
-	WMI_SERVICE_BCN_MISS_OFFLOAD,     /* beacon miss offload */
-	WMI_SERVICE_STA_PWRSAVE,	  /* fake sleep + basic power save */
-	WMI_SERVICE_STA_ADVANCED_PWRSAVE, /* uapsd, pspoll, force sleep */
-	WMI_SERVICE_AP_UAPSD,		  /* uapsd on AP */
-	WMI_SERVICE_AP_DFS,		  /* DFS on AP */
-	WMI_SERVICE_11AC,		  /* supports 11ac */
-	WMI_SERVICE_BLOCKACK,	/* Supports triggering ADDBA/DELBA from host*/
-	WMI_SERVICE_PHYERR,		  /* PHY error */
-	WMI_SERVICE_BCN_FILTER,		  /* Beacon filter support */
-	WMI_SERVICE_RTT,		  /* RTT (round trip time) support */
-	WMI_SERVICE_RATECTRL,		  /* Rate-control */
-	WMI_SERVICE_WOW,		  /* WOW Support */
-	WMI_SERVICE_RATECTRL_CACHE,       /* Rate-control caching */
-	WMI_SERVICE_IRAM_TIDS,            /* TIDs in IRAM */
-	WMI_SERVICE_ARPNS_OFFLOAD,	  /* ARP NS Offload support */
-	WMI_SERVICE_NLO,		  /* Network list offload service */
-	WMI_SERVICE_GTK_OFFLOAD,	  /* GTK offload */
-	WMI_SERVICE_SCAN_SCH,		  /* Scan Scheduler Service */
-	WMI_SERVICE_CSA_OFFLOAD,	  /* CSA offload service */
-	WMI_SERVICE_CHATTER,		  /* Chatter service */
-	WMI_SERVICE_COEX_FREQAVOID,	  /* FW report freq range to avoid */
-	WMI_SERVICE_PACKET_POWER_SAVE,	  /* packet power save service */
-	WMI_SERVICE_FORCE_FW_HANG,        /* To test fw recovery mechanism */
-	WMI_SERVICE_GPIO,                 /* GPIO service */
-	WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM, /* Modulated DTIM support */
-	WMI_STA_UAPSD_BASIC_AUTO_TRIG,    /* UAPSD AC Trigger Generation  */
-	WMI_STA_UAPSD_VAR_AUTO_TRIG,      /* -do- */
-	WMI_SERVICE_STA_KEEP_ALIVE,       /* STA keep alive mechanism support */
-	WMI_SERVICE_TX_ENCAP,             /* Packet type for TX encapsulation */
-
-	WMI_SERVICE_LAST,
-	WMI_MAX_SERVICE = 64		  /* max service */
+enum wmi_service {
+	WMI_SERVICE_BEACON_OFFLOAD = 0,
+	WMI_SERVICE_SCAN_OFFLOAD,
+	WMI_SERVICE_ROAM_OFFLOAD,
+	WMI_SERVICE_BCN_MISS_OFFLOAD,
+	WMI_SERVICE_STA_PWRSAVE,
+	WMI_SERVICE_STA_ADVANCED_PWRSAVE,
+	WMI_SERVICE_AP_UAPSD,
+	WMI_SERVICE_AP_DFS,
+	WMI_SERVICE_11AC,
+	WMI_SERVICE_BLOCKACK,
+	WMI_SERVICE_PHYERR,
+	WMI_SERVICE_BCN_FILTER,
+	WMI_SERVICE_RTT,
+	WMI_SERVICE_RATECTRL,
+	WMI_SERVICE_WOW,
+	WMI_SERVICE_RATECTRL_CACHE,
+	WMI_SERVICE_IRAM_TIDS,
+	WMI_SERVICE_ARPNS_OFFLOAD,
+	WMI_SERVICE_NLO,
+	WMI_SERVICE_GTK_OFFLOAD,
+	WMI_SERVICE_SCAN_SCH,
+	WMI_SERVICE_CSA_OFFLOAD,
+	WMI_SERVICE_CHATTER,
+	WMI_SERVICE_COEX_FREQAVOID,
+	WMI_SERVICE_PACKET_POWER_SAVE,
+	WMI_SERVICE_FORCE_FW_HANG,
+	WMI_SERVICE_GPIO,
+	WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
+	WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
+	WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
+	WMI_SERVICE_STA_KEEP_ALIVE,
+	WMI_SERVICE_TX_ENCAP,
+	WMI_SERVICE_BURST,
+	WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT,
+	WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT,
+};
+
+enum wmi_10x_service {
+	WMI_10X_SERVICE_BEACON_OFFLOAD = 0,
+	WMI_10X_SERVICE_SCAN_OFFLOAD,
+	WMI_10X_SERVICE_ROAM_OFFLOAD,
+	WMI_10X_SERVICE_BCN_MISS_OFFLOAD,
+	WMI_10X_SERVICE_STA_PWRSAVE,
+	WMI_10X_SERVICE_STA_ADVANCED_PWRSAVE,
+	WMI_10X_SERVICE_AP_UAPSD,
+	WMI_10X_SERVICE_AP_DFS,
+	WMI_10X_SERVICE_11AC,
+	WMI_10X_SERVICE_BLOCKACK,
+	WMI_10X_SERVICE_PHYERR,
+	WMI_10X_SERVICE_BCN_FILTER,
+	WMI_10X_SERVICE_RTT,
+	WMI_10X_SERVICE_RATECTRL,
+	WMI_10X_SERVICE_WOW,
+	WMI_10X_SERVICE_RATECTRL_CACHE,
+	WMI_10X_SERVICE_IRAM_TIDS,
+	WMI_10X_SERVICE_BURST,
+
+	/* introduced in 10.2 */
+	WMI_10X_SERVICE_SMART_ANTENNA_SW_SUPPORT,
+	WMI_10X_SERVICE_FORCE_FW_HANG,
+	WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
+};
+
+enum wmi_main_service {
+	WMI_MAIN_SERVICE_BEACON_OFFLOAD = 0,
+	WMI_MAIN_SERVICE_SCAN_OFFLOAD,
+	WMI_MAIN_SERVICE_ROAM_OFFLOAD,
+	WMI_MAIN_SERVICE_BCN_MISS_OFFLOAD,
+	WMI_MAIN_SERVICE_STA_PWRSAVE,
+	WMI_MAIN_SERVICE_STA_ADVANCED_PWRSAVE,
+	WMI_MAIN_SERVICE_AP_UAPSD,
+	WMI_MAIN_SERVICE_AP_DFS,
+	WMI_MAIN_SERVICE_11AC,
+	WMI_MAIN_SERVICE_BLOCKACK,
+	WMI_MAIN_SERVICE_PHYERR,
+	WMI_MAIN_SERVICE_BCN_FILTER,
+	WMI_MAIN_SERVICE_RTT,
+	WMI_MAIN_SERVICE_RATECTRL,
+	WMI_MAIN_SERVICE_WOW,
+	WMI_MAIN_SERVICE_RATECTRL_CACHE,
+	WMI_MAIN_SERVICE_IRAM_TIDS,
+	WMI_MAIN_SERVICE_ARPNS_OFFLOAD,
+	WMI_MAIN_SERVICE_NLO,
+	WMI_MAIN_SERVICE_GTK_OFFLOAD,
+	WMI_MAIN_SERVICE_SCAN_SCH,
+	WMI_MAIN_SERVICE_CSA_OFFLOAD,
+	WMI_MAIN_SERVICE_CHATTER,
+	WMI_MAIN_SERVICE_COEX_FREQAVOID,
+	WMI_MAIN_SERVICE_PACKET_POWER_SAVE,
+	WMI_MAIN_SERVICE_FORCE_FW_HANG,
+	WMI_MAIN_SERVICE_GPIO,
+	WMI_MAIN_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
+	WMI_MAIN_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
+	WMI_MAIN_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
+	WMI_MAIN_SERVICE_STA_KEEP_ALIVE,
+	WMI_MAIN_SERVICE_TX_ENCAP,
 };
 
 static inline char *wmi_service_name(int service_id)
 {
+#define SVCSTR(x) { case x: return #x; }
 	switch (service_id) {
-	case WMI_SERVICE_BEACON_OFFLOAD:
-		return "BEACON_OFFLOAD";
-	case WMI_SERVICE_SCAN_OFFLOAD:
-		return "SCAN_OFFLOAD";
-	case WMI_SERVICE_ROAM_OFFLOAD:
-		return "ROAM_OFFLOAD";
-	case WMI_SERVICE_BCN_MISS_OFFLOAD:
-		return "BCN_MISS_OFFLOAD";
-	case WMI_SERVICE_STA_PWRSAVE:
-		return "STA_PWRSAVE";
-	case WMI_SERVICE_STA_ADVANCED_PWRSAVE:
-		return "STA_ADVANCED_PWRSAVE";
-	case WMI_SERVICE_AP_UAPSD:
-		return "AP_UAPSD";
-	case WMI_SERVICE_AP_DFS:
-		return "AP_DFS";
-	case WMI_SERVICE_11AC:
-		return "11AC";
-	case WMI_SERVICE_BLOCKACK:
-		return "BLOCKACK";
-	case WMI_SERVICE_PHYERR:
-		return "PHYERR";
-	case WMI_SERVICE_BCN_FILTER:
-		return "BCN_FILTER";
-	case WMI_SERVICE_RTT:
-		return "RTT";
-	case WMI_SERVICE_RATECTRL:
-		return "RATECTRL";
-	case WMI_SERVICE_WOW:
-		return "WOW";
-	case WMI_SERVICE_RATECTRL_CACHE:
-		return "RATECTRL CACHE";
-	case WMI_SERVICE_IRAM_TIDS:
-		return "IRAM TIDS";
-	case WMI_SERVICE_ARPNS_OFFLOAD:
-		return "ARPNS_OFFLOAD";
-	case WMI_SERVICE_NLO:
-		return "NLO";
-	case WMI_SERVICE_GTK_OFFLOAD:
-		return "GTK_OFFLOAD";
-	case WMI_SERVICE_SCAN_SCH:
-		return "SCAN_SCH";
-	case WMI_SERVICE_CSA_OFFLOAD:
-		return "CSA_OFFLOAD";
-	case WMI_SERVICE_CHATTER:
-		return "CHATTER";
-	case WMI_SERVICE_COEX_FREQAVOID:
-		return "COEX_FREQAVOID";
-	case WMI_SERVICE_PACKET_POWER_SAVE:
-		return "PACKET_POWER_SAVE";
-	case WMI_SERVICE_FORCE_FW_HANG:
-		return "FORCE FW HANG";
-	case WMI_SERVICE_GPIO:
-		return "GPIO";
-	case WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM:
-		return "MODULATED DTIM";
-	case WMI_STA_UAPSD_BASIC_AUTO_TRIG:
-		return "BASIC UAPSD";
-	case WMI_STA_UAPSD_VAR_AUTO_TRIG:
-		return "VAR UAPSD";
-	case WMI_SERVICE_STA_KEEP_ALIVE:
-		return "STA KEEP ALIVE";
-	case WMI_SERVICE_TX_ENCAP:
-		return "TX ENCAP";
+	SVCSTR(WMI_SERVICE_BEACON_OFFLOAD)
+	SVCSTR(WMI_SERVICE_SCAN_OFFLOAD)
+	SVCSTR(WMI_SERVICE_ROAM_OFFLOAD)
+	SVCSTR(WMI_SERVICE_BCN_MISS_OFFLOAD)
+	SVCSTR(WMI_SERVICE_STA_PWRSAVE)
+	SVCSTR(WMI_SERVICE_STA_ADVANCED_PWRSAVE)
+	SVCSTR(WMI_SERVICE_AP_UAPSD)
+	SVCSTR(WMI_SERVICE_AP_DFS)
+	SVCSTR(WMI_SERVICE_11AC)
+	SVCSTR(WMI_SERVICE_BLOCKACK)
+	SVCSTR(WMI_SERVICE_PHYERR)
+	SVCSTR(WMI_SERVICE_BCN_FILTER)
+	SVCSTR(WMI_SERVICE_RTT)
+	SVCSTR(WMI_SERVICE_RATECTRL)
+	SVCSTR(WMI_SERVICE_WOW)
+	SVCSTR(WMI_SERVICE_RATECTRL_CACHE)
+	SVCSTR(WMI_SERVICE_IRAM_TIDS)
+	SVCSTR(WMI_SERVICE_ARPNS_OFFLOAD)
+	SVCSTR(WMI_SERVICE_NLO)
+	SVCSTR(WMI_SERVICE_GTK_OFFLOAD)
+	SVCSTR(WMI_SERVICE_SCAN_SCH)
+	SVCSTR(WMI_SERVICE_CSA_OFFLOAD)
+	SVCSTR(WMI_SERVICE_CHATTER)
+	SVCSTR(WMI_SERVICE_COEX_FREQAVOID)
+	SVCSTR(WMI_SERVICE_PACKET_POWER_SAVE)
+	SVCSTR(WMI_SERVICE_FORCE_FW_HANG)
+	SVCSTR(WMI_SERVICE_GPIO)
+	SVCSTR(WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM)
+	SVCSTR(WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG)
+	SVCSTR(WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG)
+	SVCSTR(WMI_SERVICE_STA_KEEP_ALIVE)
+	SVCSTR(WMI_SERVICE_TX_ENCAP)
+	SVCSTR(WMI_SERVICE_BURST)
+	SVCSTR(WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT)
+	SVCSTR(WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT)
 	default:
-		return "UNKNOWN SERVICE\n";
+		return NULL;
 	}
+#undef SVCSTR
+}
+
+#define WMI_MAX_SERVICE 64
+
+#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id) \
+	(__le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
+	 BIT((svc_id)%(sizeof(u32))))
+
+#define SVCMAP(x, y) \
+	do { \
+		if (WMI_SERVICE_IS_ENABLED((in), (x))) \
+			__set_bit(y, out); \
+	} while (0)
+
+static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out)
+{
+	SVCMAP(WMI_10X_SERVICE_BEACON_OFFLOAD,
+	       WMI_SERVICE_BEACON_OFFLOAD);
+	SVCMAP(WMI_10X_SERVICE_SCAN_OFFLOAD,
+	       WMI_SERVICE_SCAN_OFFLOAD);
+	SVCMAP(WMI_10X_SERVICE_ROAM_OFFLOAD,
+	       WMI_SERVICE_ROAM_OFFLOAD);
+	SVCMAP(WMI_10X_SERVICE_BCN_MISS_OFFLOAD,
+	       WMI_SERVICE_BCN_MISS_OFFLOAD);
+	SVCMAP(WMI_10X_SERVICE_STA_PWRSAVE,
+	       WMI_SERVICE_STA_PWRSAVE);
+	SVCMAP(WMI_10X_SERVICE_STA_ADVANCED_PWRSAVE,
+	       WMI_SERVICE_STA_ADVANCED_PWRSAVE);
+	SVCMAP(WMI_10X_SERVICE_AP_UAPSD,
+	       WMI_SERVICE_AP_UAPSD);
+	SVCMAP(WMI_10X_SERVICE_AP_DFS,
+	       WMI_SERVICE_AP_DFS);
+	SVCMAP(WMI_10X_SERVICE_11AC,
+	       WMI_SERVICE_11AC);
+	SVCMAP(WMI_10X_SERVICE_BLOCKACK,
+	       WMI_SERVICE_BLOCKACK);
+	SVCMAP(WMI_10X_SERVICE_PHYERR,
+	       WMI_SERVICE_PHYERR);
+	SVCMAP(WMI_10X_SERVICE_BCN_FILTER,
+	       WMI_SERVICE_BCN_FILTER);
+	SVCMAP(WMI_10X_SERVICE_RTT,
+	       WMI_SERVICE_RTT);
+	SVCMAP(WMI_10X_SERVICE_RATECTRL,
+	       WMI_SERVICE_RATECTRL);
+	SVCMAP(WMI_10X_SERVICE_WOW,
+	       WMI_SERVICE_WOW);
+	SVCMAP(WMI_10X_SERVICE_RATECTRL_CACHE,
+	       WMI_SERVICE_RATECTRL_CACHE);
+	SVCMAP(WMI_10X_SERVICE_IRAM_TIDS,
+	       WMI_SERVICE_IRAM_TIDS);
+	SVCMAP(WMI_10X_SERVICE_BURST,
+	       WMI_SERVICE_BURST);
+	SVCMAP(WMI_10X_SERVICE_SMART_ANTENNA_SW_SUPPORT,
+	       WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT);
+	SVCMAP(WMI_10X_SERVICE_FORCE_FW_HANG,
+	       WMI_SERVICE_FORCE_FW_HANG);
+	SVCMAP(WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
+	       WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT);
 }
 
+static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out)
+{
+	SVCMAP(WMI_MAIN_SERVICE_BEACON_OFFLOAD,
+	       WMI_SERVICE_BEACON_OFFLOAD);
+	SVCMAP(WMI_MAIN_SERVICE_SCAN_OFFLOAD,
+	       WMI_SERVICE_SCAN_OFFLOAD);
+	SVCMAP(WMI_MAIN_SERVICE_ROAM_OFFLOAD,
+	       WMI_SERVICE_ROAM_OFFLOAD);
+	SVCMAP(WMI_MAIN_SERVICE_BCN_MISS_OFFLOAD,
+	       WMI_SERVICE_BCN_MISS_OFFLOAD);
+	SVCMAP(WMI_MAIN_SERVICE_STA_PWRSAVE,
+	       WMI_SERVICE_STA_PWRSAVE);
+	SVCMAP(WMI_MAIN_SERVICE_STA_ADVANCED_PWRSAVE,
+	       WMI_SERVICE_STA_ADVANCED_PWRSAVE);
+	SVCMAP(WMI_MAIN_SERVICE_AP_UAPSD,
+	       WMI_SERVICE_AP_UAPSD);
+	SVCMAP(WMI_MAIN_SERVICE_AP_DFS,
+	       WMI_SERVICE_AP_DFS);
+	SVCMAP(WMI_MAIN_SERVICE_11AC,
+	       WMI_SERVICE_11AC);
+	SVCMAP(WMI_MAIN_SERVICE_BLOCKACK,
+	       WMI_SERVICE_BLOCKACK);
+	SVCMAP(WMI_MAIN_SERVICE_PHYERR,
+	       WMI_SERVICE_PHYERR);
+	SVCMAP(WMI_MAIN_SERVICE_BCN_FILTER,
+	       WMI_SERVICE_BCN_FILTER);
+	SVCMAP(WMI_MAIN_SERVICE_RTT,
+	       WMI_SERVICE_RTT);
+	SVCMAP(WMI_MAIN_SERVICE_RATECTRL,
+	       WMI_SERVICE_RATECTRL);
+	SVCMAP(WMI_MAIN_SERVICE_WOW,
+	       WMI_SERVICE_WOW);
+	SVCMAP(WMI_MAIN_SERVICE_RATECTRL_CACHE,
+	       WMI_SERVICE_RATECTRL_CACHE);
+	SVCMAP(WMI_MAIN_SERVICE_IRAM_TIDS,
+	       WMI_SERVICE_IRAM_TIDS);
+	SVCMAP(WMI_MAIN_SERVICE_ARPNS_OFFLOAD,
+	       WMI_SERVICE_ARPNS_OFFLOAD);
+	SVCMAP(WMI_MAIN_SERVICE_NLO,
+	       WMI_SERVICE_NLO);
+	SVCMAP(WMI_MAIN_SERVICE_GTK_OFFLOAD,
+	       WMI_SERVICE_GTK_OFFLOAD);
+	SVCMAP(WMI_MAIN_SERVICE_SCAN_SCH,
+	       WMI_SERVICE_SCAN_SCH);
+	SVCMAP(WMI_MAIN_SERVICE_CSA_OFFLOAD,
+	       WMI_SERVICE_CSA_OFFLOAD);
+	SVCMAP(WMI_MAIN_SERVICE_CHATTER,
+	       WMI_SERVICE_CHATTER);
+	SVCMAP(WMI_MAIN_SERVICE_COEX_FREQAVOID,
+	       WMI_SERVICE_COEX_FREQAVOID);
+	SVCMAP(WMI_MAIN_SERVICE_PACKET_POWER_SAVE,
+	       WMI_SERVICE_PACKET_POWER_SAVE);
+	SVCMAP(WMI_MAIN_SERVICE_FORCE_FW_HANG,
+	       WMI_SERVICE_FORCE_FW_HANG);
+	SVCMAP(WMI_MAIN_SERVICE_GPIO,
+	       WMI_SERVICE_GPIO);
+	SVCMAP(WMI_MAIN_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
+	       WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM);
+	SVCMAP(WMI_MAIN_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
+	       WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG);
+	SVCMAP(WMI_MAIN_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
+	       WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG);
+	SVCMAP(WMI_MAIN_SERVICE_STA_KEEP_ALIVE,
+	       WMI_SERVICE_STA_KEEP_ALIVE);
+	SVCMAP(WMI_MAIN_SERVICE_TX_ENCAP,
+	       WMI_SERVICE_TX_ENCAP);
+}
+
+#undef SVCMAP
 
 #define WMI_SERVICE_BM_SIZE \
 	((WMI_MAX_SERVICE + sizeof(u32) - 1)/sizeof(u32))
@@ -1229,10 +1390,6 @@ struct wlan_host_mem_req {
 	__le32 num_units;
 } __packed;
 
-#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id) \
-	((((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
-	(1 << ((svc_id)%(sizeof(u32))))) != 0)
-
 /*
  * The following struct holds optional payload for
  * wmi_service_ready_event,e.g., 11ac pass some of the
-- 
1.8.5.3



From linville at tuxdriver.com  Tue Jul 29 07:23:31 2014
From: linville at tuxdriver.com (John W. Linville)
Date: Tue, 29 Jul 2014 10:23:31 -0400
Subject: Pull request: ath 20140725
In-Reply-To: <87wqb1pzvi.fsf@kamboji.qca.qualcomm.com>
References: <87wqb1pzvi.fsf@kamboji.qca.qualcomm.com>
Message-ID: <20140729142331.GC13090@tuxdriver.com>

On Fri, Jul 25, 2014 at 12:10:57PM +0300, Kalle Valo wrote:
> Hi John,
> 
> here's an ath10k pull request which I'm still hoping to get to 3.17,
> especially because of the rx reordering and IBSS advertisement fixes.
> But if we don't get these to 3.17 it won't be the end of the world
> either :)
> 
> Please let me know if there are any problems.
> 
> The changelog:
> 
> Michal and Janusz did some important RX aggregation fixes, basically we
> were missing RX reordering altogether. The 10.1 firmware doesn't support
> Ad-Hoc mode and Michal fixed ath10k so that it doesn't advertise Ad-Hoc
> support with that firmware. Also he implemented a workaround for a KVM
> issue.
> 
> 
> The following changes since commit bac9832076ee3b134bc859e07698c99276fc9459:
> 
>   b43: enable 5 GHz support for N-PHY devices (2014-07-23 13:08:36 -0400)
> 
> are available in the git repository at:
> 
>   git://github.com/kvalo/ath.git tags/for-linville-20140725
> 
> for you to fetch changes up to 0ccb7a3485e5526dca69f036b0d6c5148c78b3f8:
> 
>   ath10k: handle attention flags correctly when using A-MSDU (2014-07-25 11:51:07 +0300)

Pulling now...

-- 
John W. Linville		Someday the world will need a hero, and you
linville at tuxdriver.com			might be all we have.  Be ready.


From vh.nguyen at actiasodielec.fr  Tue Jul 29 08:04:18 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Tue, 29 Jul 2014 17:04:18 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D7FE@srvexch01.SODIELEC.local>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>,
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>,
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>,
 <53D252B4.9070704@candelatech.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F8@srvexch01.SODIELEC.local>,
 <53D6757A.8040803@candelatech.com>,
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7FE@srvexch01.SODIELEC.local>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D800@srvexch01.SODIELEC.local>

>>> I follow a tutorial to cross compile perf so here is my result
>>>
>>>
>>> PerfTop:      70 irqs/sec  kernel:98.6%  exact:  0.0% [1000Hz cycles],  (all, 1 CPU)
>>> -------------------------------------------------------------------------------
>>>
>>>     39.43%  [kernel]       [k] csum_partial_copy_nocheck

>>Looks like your ethernet driver is not doing checksum offloading?

>>I am pretty sure ath10k does support this unless you have managed
>>to disabled it somehow?

>I'm using ath10k from master branch (generated by backport), My only hack is changing the default country of regulatory domain from US to France.
>The checksum patch is implemented by Michal Kazior since july 2013 and I also check that there is function checksum state in htt_rx.c file so it should be in my
>driver module.
>But I install ethtool and here is the ouput of my interface wlan0:
>#ethtool --show-offload  wlan0
>Features for wlan0:
>rx-checksumming: off [fixed]
>tx-checksumming: on
>        tx-checksum-ipv4: off [fixed]
>        tx-checksum-unneeded: off [fixed]
>        tx-checksum-ip-generic: on [fixed]
>        tx-checksum-ipv6: off [fixed]
>        tx-checksum-fcoe-crc: off [fixed]
>        tx-checksum-sctp: off [fixed]
>scatter-gather: off
>        tx-scatter-gather: off [fixed]
>        tx-scatter-gather-fraglist: off [fixed]
>tcp-segmentation-offload: off
>        tx-tcp-segmentation: off [fixed]
>        tx-tcp-ecn-segmentation: off [fixed]
>        tx-tcp6-segmentation: off [fixed]
>udp-fragmentation-offload: off [fixed]
>generic-segmentation-offload: off [requested on]
>generic-receive-offload: on
>large-receive-offload: off [fixed]
>rx-vlan-offload: off [fixed]
>tx-vlan-offload: off [fixed]
>ntuple-filters: off [fixed]
>receive-hashing: off [fixed]
>highdma: off [fixed]
>rx-vlan-filter: off [fixed]
>vlan-challenged: off [fixed]
>tx-lockless: off [fixed]
>netns-local: on [fixed]
>tx-gso-robust: off [fixed]
>tx-fcoe-segmentation: off [fixed]
>fcoe-mtu: off [fixed]
>tx-nocache-copy: on
>loopback: off [fixed]
>
>And I cannot enable these function, as it show [fixed] like above.
># ethtool --offload  wlan0  rx on  tx on
>Cannot change rx-checksumming
>Cannot change tx-checksumming

I used ethtool to disable Checksum offloading on my Ethernet interface and increase rate from
400 Mbps to 500 Mbps, now the thread "csum_partial_copy_nocheck" has disappeared and there
is no more particular thread which takes most of the processor resource. But my processor is 
always exhausted. 
I notice some warning when starting perf top
[ath10k_core] with build id f31b98301ddea35e320bacaef048e4adbae00a6d not found, continuing without symbols
[ath10k_pci] with build id a1303b5587ceef676d03d5a68fa5c7d717861c5d not found, continuing without symbols
[mac80211] with build id f73251a940dedf51ac599141e5edefe05da2cb6f not found, continuing without symbols
[cfg80211] with build id 94dd0809b98902252ce78cc3bc4ae385dd5e8fdf not found, continuing without symbols
This may cause some unknown thread like the 2nd thread $a below of [mac80211]?
 
PerfTop:      51 irqs/sec  kernel:98.0%  exact:  0.0% [1000Hz cycles],  (all, 1 CPU)
-------------------------------------------------------------------------------

     8.79%  [mac80211]     [k] ieee80211_tx_status
     5.02%  [mac80211]     [k] $a
     5.02%  [kernel]       [k] __memzero
     4.60%  [kernel]       [k] memcpy
     4.60%  [kernel]       [k] mv_eth_poll
     4.18%  [kernel]       [k] dev_queue_xmit
     4.18%  [kernel]       [k] br_parse_ip_options
     3.77%  [kernel]       [k] dev_hard_start_xmit
     3.77%  [kernel]       [k] nf_hook_slow
     3.35%  [kernel]       [k] local_bh_enable
     3.35%  [kernel]       [k] nf_iterate
     3.35%  [kernel]       [k] br_nf_forward_ip
     2.93%  [kernel]       [k] kfree
     2.93%  [kernel]       [k] br_nf_pre_routing
     2.93%  [kernel]       [k] mv_eth_tx
     2.93%  [kernel]       [k] br_handle_frame_finish
     2.93%  [ath10k_pci]   [k] ath10k_ce_send_nolock
     2.93%  [ath10k_core]  [k] ath10k_txrx_tx_unref
     2.51%  [kernel]       [k] eth_type_trans
     2.51%  [ath10k_core]  [k] ath10k_htt_rx_amsdu_pop

I notice that ieee80211_tx_status takes much of resource too, but because of firmware
issue we don't get true information from tx_status, should we deactivate it to improve
the performance?

NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE




NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE



_______________________________________________
ath10k mailing list
ath10k at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k


From greearb at candelatech.com  Tue Jul 29 08:55:12 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 29 Jul 2014 08:55:12 -0700
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D800@srvexch01.SODIELEC.local>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>,
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>,
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>,
 <53D252B4.9070704@candelatech.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F8@srvexch01.SODIELEC.local>,
 <53D6757A.8040803@candelatech.com>,
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7FE@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D800@srvexch01.SODIELEC.loc
 al>
Message-ID: <53D7C3E0.7030400@candelatech.com>

On 07/29/2014 08:04 AM, Vu Hai NGUYEN wrote:
>>>> I follow a tutorial to cross compile perf so here is my result
>>>>
>>>>
>>>> PerfTop:      70 irqs/sec  kernel:98.6%  exact:  0.0% [1000Hz cycles],  (all, 1 CPU)
>>>> -------------------------------------------------------------------------------
>>>>
>>>>     39.43%  [kernel]       [k] csum_partial_copy_nocheck
> 
>>> Looks like your ethernet driver is not doing checksum offloading?
> 
>>> I am pretty sure ath10k does support this unless you have managed
>>> to disabled it somehow?
> 
>> I'm using ath10k from master branch (generated by backport), My only hack is changing the default country of regulatory domain from US to France.
>> The checksum patch is implemented by Michal Kazior since july 2013 and I also check that there is function checksum state in htt_rx.c file so it should be in my
>> driver module.
>> But I install ethtool and here is the ouput of my interface wlan0:
>> #ethtool --show-offload  wlan0
>> Features for wlan0:
>> rx-checksumming: off [fixed]
>> tx-checksumming: on
>>        tx-checksum-ipv4: off [fixed]
>>        tx-checksum-unneeded: off [fixed]
>>        tx-checksum-ip-generic: on [fixed]
>>        tx-checksum-ipv6: off [fixed]
>>        tx-checksum-fcoe-crc: off [fixed]
>>        tx-checksum-sctp: off [fixed]
>> scatter-gather: off
>>        tx-scatter-gather: off [fixed]
>>        tx-scatter-gather-fraglist: off [fixed]
>> tcp-segmentation-offload: off
>>        tx-tcp-segmentation: off [fixed]
>>        tx-tcp-ecn-segmentation: off [fixed]
>>        tx-tcp6-segmentation: off [fixed]
>> udp-fragmentation-offload: off [fixed]
>> generic-segmentation-offload: off [requested on]
>> generic-receive-offload: on
>> large-receive-offload: off [fixed]
>> rx-vlan-offload: off [fixed]
>> tx-vlan-offload: off [fixed]
>> ntuple-filters: off [fixed]
>> receive-hashing: off [fixed]
>> highdma: off [fixed]
>> rx-vlan-filter: off [fixed]
>> vlan-challenged: off [fixed]
>> tx-lockless: off [fixed]
>> netns-local: on [fixed]
>> tx-gso-robust: off [fixed]
>> tx-fcoe-segmentation: off [fixed]
>> fcoe-mtu: off [fixed]
>> tx-nocache-copy: on
>> loopback: off [fixed]
>>
>> And I cannot enable these function, as it show [fixed] like above.
>> # ethtool --offload  wlan0  rx on  tx on
>> Cannot change rx-checksumming
>> Cannot change tx-checksumming
> 
> I used ethtool to disable Checksum offloading on my Ethernet interface and increase rate from
> 400 Mbps to 500 Mbps, now the thread "csum_partial_copy_nocheck" has disappeared and there
> is no more particular thread which takes most of the processor resource. But my processor is 
> always exhausted. 

Strange that disabling checksum helped things.  Maybe your ethernet driver
has issues?

Looks like removing netfilter (and maybe ebtables?) would
also help your performance...

tx status is needed for bookkeping at least, even if you don't
get useful status info in stock firmware.

CT firmware will give you proper status if you apply some of the
ath10k driver patches from my tree, but that is unlikely to help
performance.

Thanks,
Ben

> I notice some warning when starting perf top
> [ath10k_core] with build id f31b98301ddea35e320bacaef048e4adbae00a6d not found, continuing without symbols
> [ath10k_pci] with build id a1303b5587ceef676d03d5a68fa5c7d717861c5d not found, continuing without symbols
> [mac80211] with build id f73251a940dedf51ac599141e5edefe05da2cb6f not found, continuing without symbols
> [cfg80211] with build id 94dd0809b98902252ce78cc3bc4ae385dd5e8fdf not found, continuing without symbols
> This may cause some unknown thread like the 2nd thread $a below of [mac80211]?
>  
> PerfTop:      51 irqs/sec  kernel:98.0%  exact:  0.0% [1000Hz cycles],  (all, 1 CPU)
> -------------------------------------------------------------------------------
> 
>      8.79%  [mac80211]     [k] ieee80211_tx_status
>      5.02%  [mac80211]     [k] $a
>      5.02%  [kernel]       [k] __memzero
>      4.60%  [kernel]       [k] memcpy
>      4.60%  [kernel]       [k] mv_eth_poll
>      4.18%  [kernel]       [k] dev_queue_xmit
>      4.18%  [kernel]       [k] br_parse_ip_options
>      3.77%  [kernel]       [k] dev_hard_start_xmit
>      3.77%  [kernel]       [k] nf_hook_slow
>      3.35%  [kernel]       [k] local_bh_enable
>      3.35%  [kernel]       [k] nf_iterate
>      3.35%  [kernel]       [k] br_nf_forward_ip
>      2.93%  [kernel]       [k] kfree
>      2.93%  [kernel]       [k] br_nf_pre_routing
>      2.93%  [kernel]       [k] mv_eth_tx
>      2.93%  [kernel]       [k] br_handle_frame_finish
>      2.93%  [ath10k_pci]   [k] ath10k_ce_send_nolock
>      2.93%  [ath10k_core]  [k] ath10k_txrx_tx_unref
>      2.51%  [kernel]       [k] eth_type_trans
>      2.51%  [ath10k_core]  [k] ath10k_htt_rx_amsdu_pop
> 
> I notice that ieee80211_tx_status takes much of resource too, but because of firmware
> issue we don't get true information from tx_status, should we deactivate it to improve
> the performance?
> 
> NGUYEN Vu Hai
> Acita-Sodielec
> Route de Mayres - B.P. 9
> 12100 St GEORGES DE LUZENCON
> FRANCE
> 
> 
> 
> 
> NGUYEN Vu Hai
> Acita-Sodielec
> Route de Mayres - B.P. 9
> 12100 St GEORGES DE LUZENCON
> FRANCE
> 
> 
> 
> _______________________________________________
> ath10k mailing list
> ath10k at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/ath10k
> 


-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From luto at amacapital.net  Tue Jul 29 10:52:11 2014
From: luto at amacapital.net (Andy Lutomirski)
Date: Tue, 29 Jul 2014 10:52:11 -0700
Subject: ath10k tx to a Macbook Pro stalls
In-Reply-To: <CA+BoTQ=q-Xfk6+FwcT7yLd+YpcZobNVhszfwhLHeyL3XExps4w@mail.gmail.com>
References: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>
 <87vbqqwoks.fsf@kamboji.qca.qualcomm.com>
 <CALCETrXtvTyFbc0RM0kHcW_UiX+eurRTdp0vdQER2ysUrd4FcQ@mail.gmail.com>
 <CA+BoTQ=q-Xfk6+FwcT7yLd+YpcZobNVhszfwhLHeyL3XExps4w@mail.gmail.com>
Message-ID: <CALCETrUrqGzGvzbjyc2uMo0cA3HWZi=roPx0vFJRxEY7ii_PBA@mail.gmail.com>

On Mon, Jul 28, 2014 at 11:26 PM, Michal Kazior <michal.kazior at tieto.com> wrote:
> On 22 July 2014 06:12, Andy Lutomirski <luto at amacapital.net> wrote:
>> On Mon, Jul 21, 2014 at 11:31 AM, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>>> Andy Lutomirski <luto at amacapital.net> writes:
>>>
>>>> On my Archer C7 v2, as soon as the MBP tries to do something like
>>>> playing a video, it seems like frames *to* the MBP no longer get
>>>> there.  At the very least, arp replies don't get there.
>>>
>>> A multicast problem? Can you run for example 'arping -b <macbook's ip>'
>>> to check if multicast stops working at some point? What if you hardcode
>>> the ARP address, do unicast packets go to the macbook still?
>>
>> It's a unicast problem, actually.  arping -b works.  arping w/o -b
>> gets one reply.
>>
>> arp -s <IP> ff:ff:ff:ff:ff:ff allows me to ping the MBP (with
>> moderately high loss).  (I'm actually a bit surprised that Linux is
>> okay with that.)
>>
>> Does this mean that the MBP is failing to notice TIM entries, or that
>> ath10k somehow stops buffering packets to power-saving stations?
>
> Do you have u-APSD enabled in your OpenWRT configuration by any chance?

How do I tell?  The docs seem out of date here.  I have:

config wifi-device 'radio0'
    option type 'mac80211'
    option hwmode '11a'
    option path 'pci0000:01/0000:01:00.0'
    option htmode 'VHT80'
    #option htmode 'HT40'
    option disabled '0'
    option channel '149'

The relevant part (I think) of /var/run/hostapd.conf is:

ieee80211n=1
ht_capab=[HT40+][LDPC][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][DSSS_CCK-40
]
vht_oper_chwidth=1
vht_oper_centr_freq_seg0_idx=155
ieee80211ac=1
vht_capab=[RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-ANTENNA-PATTERN][TX-ANTENNA-PA
TTERN][RX-STBC1][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP7]

--Andy


From michal.kazior at tieto.com  Tue Jul 29 23:15:55 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 30 Jul 2014 08:15:55 +0200
Subject: ath10k tx to a Macbook Pro stalls
In-Reply-To: <CALCETrUrqGzGvzbjyc2uMo0cA3HWZi=roPx0vFJRxEY7ii_PBA@mail.gmail.com>
References: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>
 <87vbqqwoks.fsf@kamboji.qca.qualcomm.com>
 <CALCETrXtvTyFbc0RM0kHcW_UiX+eurRTdp0vdQER2ysUrd4FcQ@mail.gmail.com>
 <CA+BoTQ=q-Xfk6+FwcT7yLd+YpcZobNVhszfwhLHeyL3XExps4w@mail.gmail.com>
 <CALCETrUrqGzGvzbjyc2uMo0cA3HWZi=roPx0vFJRxEY7ii_PBA@mail.gmail.com>
Message-ID: <CA+BoTQkq9N6uGRYSh=T_8Wrv7XgiGtzjG3fQwOE_B69ayF==Zw@mail.gmail.com>

On 29 July 2014 19:52, Andy Lutomirski <luto at amacapital.net> wrote:
> On Mon, Jul 28, 2014 at 11:26 PM, Michal Kazior <michal.kazior at tieto.com> wrote:
>> On 22 July 2014 06:12, Andy Lutomirski <luto at amacapital.net> wrote:
>>> On Mon, Jul 21, 2014 at 11:31 AM, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>>>> Andy Lutomirski <luto at amacapital.net> writes:
[...]
>>> Does this mean that the MBP is failing to notice TIM entries, or that
>>> ath10k somehow stops buffering packets to power-saving stations?
>>
>> Do you have u-APSD enabled in your OpenWRT configuration by any chance?
>
> How do I tell?  The docs seem out of date here.  I have:
>
> config wifi-device 'radio0'
>     option type 'mac80211'
>     option hwmode '11a'
>     option path 'pci0000:01/0000:01:00.0'
>     option htmode 'VHT80'
>     #option htmode 'HT40'
>     option disabled '0'
>     option channel '149'
>
> The relevant part (I think) of /var/run/hostapd.conf is:
>
> ieee80211n=1
> ht_capab=[HT40+][LDPC][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][DSSS_CCK-40
> ]
> vht_oper_chwidth=1
> vht_oper_centr_freq_seg0_idx=155
> ieee80211ac=1
> vht_capab=[RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-ANTENNA-PATTERN][TX-ANTENNA-PA
> TTERN][RX-STBC1][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP7]

Do you have `uapsd_advertisement_enabled=1` set in /var/run/hostapd.conf?


Micha?


From michal.kazior at tieto.com  Tue Jul 29 23:26:17 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 30 Jul 2014 08:26:17 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D800@srvexch01.SODIELEC.local>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>
 <53D252B4.9070704@candelatech.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F8@srvexch01.SODIELEC.local>
 <53D6757A.8040803@candelatech.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7FE@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D800@srvexch01.SODIELEC.local>
Message-ID: <CA+BoTQ=QscHgrk5bbWugjdnVGh=T_L-psEPKToYHOdKGcQZi7A@mail.gmail.com>

On 29 July 2014 17:04, Vu Hai NGUYEN <vh.nguyen at actiasodielec.fr> wrote:
[...]
> I used ethtool to disable Checksum offloading on my Ethernet interface and increase rate from
> 400 Mbps to 500 Mbps, now the thread "csum_partial_copy_nocheck" has disappeared and there
> is no more particular thread which takes most of the processor resource. But my processor is
> always exhausted.
> I notice some warning when starting perf top
> [ath10k_core] with build id f31b98301ddea35e320bacaef048e4adbae00a6d not found, continuing without symbols
> [ath10k_pci] with build id a1303b5587ceef676d03d5a68fa5c7d717861c5d not found, continuing without symbols
> [mac80211] with build id f73251a940dedf51ac599141e5edefe05da2cb6f not found, continuing without symbols
> [cfg80211] with build id 94dd0809b98902252ce78cc3bc4ae385dd5e8fdf not found, continuing without symbols
> This may cause some unknown thread like the 2nd thread $a below of [mac80211]?
>
> PerfTop:      51 irqs/sec  kernel:98.0%  exact:  0.0% [1000Hz cycles],  (all, 1 CPU)
> -------------------------------------------------------------------------------
>
>      8.79%  [mac80211]     [k] ieee80211_tx_status
>      5.02%  [mac80211]     [k] $a
>      5.02%  [kernel]       [k] __memzero
>      4.60%  [kernel]       [k] memcpy
>      4.60%  [kernel]       [k] mv_eth_poll
>      4.18%  [kernel]       [k] dev_queue_xmit
>      4.18%  [kernel]       [k] br_parse_ip_options
>      3.77%  [kernel]       [k] dev_hard_start_xmit
>      3.77%  [kernel]       [k] nf_hook_slow
>      3.35%  [kernel]       [k] local_bh_enable
>      3.35%  [kernel]       [k] nf_iterate
>      3.35%  [kernel]       [k] br_nf_forward_ip
>      2.93%  [kernel]       [k] kfree
>      2.93%  [kernel]       [k] br_nf_pre_routing
>      2.93%  [kernel]       [k] mv_eth_tx
>      2.93%  [kernel]       [k] br_handle_frame_finish
>      2.93%  [ath10k_pci]   [k] ath10k_ce_send_nolock
>      2.93%  [ath10k_core]  [k] ath10k_txrx_tx_unref
>      2.51%  [kernel]       [k] eth_type_trans
>      2.51%  [ath10k_core]  [k] ath10k_htt_rx_amsdu_pop

This accounts for 76.58% of CPU usage. You've most likely trimmed down
the remaining entries accounting for 24% before posting.

By the looks of it you might be able to strip down netfilter
(iptables) rules to none on all chains and tables if you just want to
max out the performance at the cost of having no firewall whatsoever.

You also might want to change qdisc (`tc` command) on all interfaces
involved to pfifo in case you're using codel to further reduce CPU
load at the cost of buffer bloating the system.


> I notice that ieee80211_tx_status takes much of resource too, but because of firmware
> issue we don't get true information from tx_status, should we deactivate it to improve
> the performance?

Even though tx rate isn't reported by ath10k it is still necessary to
report ack/no ack for frames and allow mac80211 to further process
frame completion.


Micha?


From greearb at candelatech.com  Wed Jul 30 08:46:54 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 30 Jul 2014 08:46:54 -0700
Subject: Crash in hacked kernel with CT firmware.
Message-ID: <53D9136E.8050908@candelatech.com>

Not sure how relevant this is to upstream, but just in case someone
wants to look at it:

Kernel is modified 3.14.14+, with a good bit of backported ath10k and some
patches of my own to help stabilize ath10k with my workload and to support
CT firmware features.

http://dmz2.candelatech.com/git/gitweb.cgi?p=linux-3.14.dev.y/.git;a=summary

Firmware is CT firmware, and it has a bug in this test case where it crashes
fairly often upon removal of a vdev after some traffic tests have been
running.  Likely this firmware bug is something that I have added or
at least exacerbated, and I am working on fixing it.

But, when it crashes, it takes the kernel down shortly afterwards
in a reliable manner:

[firmware crashes]

ath10k: failed with wmi_cmd_timeout 4 times, attempting hardware reset.
sta2: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta3: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta4: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta5: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta12: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta13: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta15: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta16: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta17: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta18: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta21: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta22: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta23: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta30: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta31: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta32: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta33: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta34: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta35: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta36: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta37: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta38: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta39: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta40: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta41: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta42: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta43: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta44: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta45: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta46: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta47: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta48: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta49: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta50: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta51: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta52: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta53: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta54: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta55: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta56: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta57: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta58: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta59: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta60: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta61: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta62: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting
sta63: Failed to send nullfunc to AP 04:f0:21:37:e3:2e after 1000ms, disconnecting


BUG: unable to handle kernel NULL pointer dereference at 0000000000000068
IP: [<ffffffffa06a318d>] ath10k_txrx_tx_unref+0x91/0x3c7 [ath10k_core]
PGD 44cf64067 PUD 449c87067 PMD 0
Oops: 0000 [#1] PREEMPT SMP
Modules linked in: nf_conntrack_netlink nfnetlink nf_nat_ipv4 nf_nat 8021q garp stp mrp llc m]
CPU: 0 PID: 5945 Comm: ip Tainted: G        WC O 3.14.14+ #38
Hardware name: Supermicro X9SRL-F/X9SRL-F, BIOS 3.0a 12/05/2013
task: ffff88043675c2a0 ti: ffff88043e4d4000 task.ti: ffff88043e4d4000
RIP: 0010:[<ffffffffa06a318d>]  [<ffffffffa06a318d>] ath10k_txrx_tx_unref+0x91/0x3c7 [ath10k_]
RSP: 0018:ffff88043e4d54b8  EFLAGS: 00010282
RAX: 0000000000000007 RBX: 0000000000000000 RCX: 0000000000000001
RDX: ffff880449e7c000 RSI: 0000000000000007 RDI: 0000000000000008
RBP: ffff88043e4d54e8 R08: 0000000000000000 R09: ffffffffa06a24b7
R10: ffffffffa06a24b7 R11: 0000000000000000 R12: ffff88043e4d5502
R13: ffff88046b02b428 R14: ffff88046c74e098 R15: ffff88046b02bc78
FS:  00007fe6c9271740(0000) GS:ffff88047fc00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000068 CR3: 0000000443978000 CR4: 00000000001407f0
Stack:
 0000000000000007 ffff88046b02b428 0000000000000007 ffff88046b02b568
 ffff88046b02b908 ffff88046b02bc78 ffff88043e4d5528 ffffffffa06a28b4
 ffff88043e4d5528 0001000000071c28 ffff88046b02b428 ffff88046b02b428
Call Trace:
 [<ffffffffa06a28b4>] ath10k_htt_tx_detach+0x70/0xd1 [ath10k_core]
 [<ffffffffa06a04cf>] ath10k_htt_detach+0x16/0x1b [ath10k_core]
 [<ffffffffa069eab3>] ath10k_core_stop+0x4f/0x70 [ath10k_core]
 [<ffffffffa069ae32>] ath10k_halt+0xde/0x161 [ath10k_core]
 [<ffffffffa069aeed>] ath10k_stop+0x38/0x89 [ath10k_core]
 [<ffffffffa05b0ae6>] ieee80211_stop_device+0x58/0x84 [mac80211]
 [<ffffffffa069541c>] ? spin_lock_bh+0x9/0xb [ath10k_core]
 [<ffffffffa059d0d3>] ieee80211_do_stop+0x625/0x67d [mac80211]
 [<ffffffff810fdf6a>] ? trace_hardirqs_on+0xd/0xf
 [<ffffffff810c6d42>] ? __local_bh_enable_ip+0xaf/0xd9
 [<ffffffff815d8156>] ? _raw_spin_unlock_bh+0x31/0x35
 [<ffffffff8153a693>] ? dev_deactivate_many+0x129/0x172
 [<ffffffffa059d140>] ieee80211_stop+0x15/0x19 [mac80211]
 [<ffffffff8151beff>] __dev_close_many+0x95/0xba
 [<ffffffff8151bfa5>] __dev_close+0x48/0x67
 [<ffffffff81522696>] __dev_change_flags+0xa6/0x14a
 [<ffffffff8152276d>] dev_change_flags+0x23/0x59
 [<ffffffff8152c318>] do_setlink+0x2d7/0x793
 [<ffffffff8152ef6e>] rtnl_newlink+0x36f/0x5a7
 [<ffffffff8152ed0a>] ? rtnl_newlink+0x10b/0x5a7


(gdb) l *(ath10k_txrx_tx_unref+0x91)
0xe18d is in ath10k_txrx_tx_unref (/mnt/sda/home/greearb/git/linux-3.14.dev.y/drivers/net/wireless/ath/ath10k/txrx.c:109).
104		}
105	
106		msdu = htt->pending_tx[tx_done->msdu_id];
107		skb_cb = ATH10K_SKB_CB(msdu);
108	
109		dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
110	
111		if (skb_cb->htt.txbuf)
112			dma_pool_free(htt->tx_pool,
113				      skb_cb->htt.txbuf,
(gdb)


Thanks,
Ben

-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From luto at amacapital.net  Wed Jul 30 15:37:30 2014
From: luto at amacapital.net (Andy Lutomirski)
Date: Wed, 30 Jul 2014 15:37:30 -0700
Subject: ath10k tx to a Macbook Pro stalls
In-Reply-To: <CA+BoTQkq9N6uGRYSh=T_8Wrv7XgiGtzjG3fQwOE_B69ayF==Zw@mail.gmail.com>
References: <CALCETrUXvbhkKDAvEw+643mKZtJzcJtPGhxbo35r3h=rCMOWwA@mail.gmail.com>
 <87vbqqwoks.fsf@kamboji.qca.qualcomm.com>
 <CALCETrXtvTyFbc0RM0kHcW_UiX+eurRTdp0vdQER2ysUrd4FcQ@mail.gmail.com>
 <CA+BoTQ=q-Xfk6+FwcT7yLd+YpcZobNVhszfwhLHeyL3XExps4w@mail.gmail.com>
 <CALCETrUrqGzGvzbjyc2uMo0cA3HWZi=roPx0vFJRxEY7ii_PBA@mail.gmail.com>
 <CA+BoTQkq9N6uGRYSh=T_8Wrv7XgiGtzjG3fQwOE_B69ayF==Zw@mail.gmail.com>
Message-ID: <CALCETrX+NczOb=U2QOf9Bqoh0ECVM=GSXwPDH=rAW+d5XQePHA@mail.gmail.com>

On Tue, Jul 29, 2014 at 11:15 PM, Michal Kazior <michal.kazior at tieto.com> wrote:
> On 29 July 2014 19:52, Andy Lutomirski <luto at amacapital.net> wrote:
>> On Mon, Jul 28, 2014 at 11:26 PM, Michal Kazior <michal.kazior at tieto.com> wrote:
>>> On 22 July 2014 06:12, Andy Lutomirski <luto at amacapital.net> wrote:
>>>> On Mon, Jul 21, 2014 at 11:31 AM, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>>>>> Andy Lutomirski <luto at amacapital.net> writes:
> [...]
>>>> Does this mean that the MBP is failing to notice TIM entries, or that
>>>> ath10k somehow stops buffering packets to power-saving stations?
>>>
>>> Do you have u-APSD enabled in your OpenWRT configuration by any chance?
>>
>> How do I tell?  The docs seem out of date here.  I have:
>>
>> config wifi-device 'radio0'
>>     option type 'mac80211'
>>     option hwmode '11a'
>>     option path 'pci0000:01/0000:01:00.0'
>>     option htmode 'VHT80'
>>     #option htmode 'HT40'
>>     option disabled '0'
>>     option channel '149'
>>
>> The relevant part (I think) of /var/run/hostapd.conf is:
>>
>> ieee80211n=1
>> ht_capab=[HT40+][LDPC][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][DSSS_CCK-40
>> ]
>> vht_oper_chwidth=1
>> vht_oper_centr_freq_seg0_idx=155
>> ieee80211ac=1
>> vht_capab=[RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-ANTENNA-PATTERN][TX-ANTENNA-PA
>> TTERN][RX-STBC1][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP7]
>
> Do you have `uapsd_advertisement_enabled=1` set in /var/run/hostapd.conf?
>

Here's the whole file, with the obvious redactions:

driver=nl80211
logger_syslog=127
logger_syslog_level=2
logger_stdout=127
logger_stdout_level=2
hw_mode=a
channel=149

ieee80211n=1
ht_capab=[HT40+][LDPC][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][DSSS_CCK-40]
vht_oper_chwidth=1
vht_oper_centr_freq_seg0_idx=155
ieee80211ac=1
vht_capab=[RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][RX-STBC1][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP7]

interface=wlan0
ctrl_interface=/var/run/hostapd
disassoc_low_ack=1
preamble=1
wmm_enabled=1
ignore_broadcast_ssid=0
wpa_passphrase=PASSPHRASE
auth_algs=1
wpa=2
wpa_pairwise=CCMP
ssid=Aether Wind
bridge=br-lan
okc=0
disable_pmksa_caching=1
macaddr_acl=0
deny_mac_file=/var/run/hostapd-wlan0.maclist
bssid=BSSID

--Andy


From yeohchunyeow at gmail.com  Wed Jul 30 20:46:07 2014
From: yeohchunyeow at gmail.com (Yeoh Chun-Yeow)
Date: Thu, 31 Jul 2014 11:46:07 +0800
Subject: [PATCH] ath10k: add support for 10.2 firmware
In-Reply-To: <87y4vhmshr.fsf@kamboji.qca.qualcomm.com>
References: <1406287937-26507-1-git-send-email-michal.kazior@tieto.com>
 <87y4vhmshr.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CAEFj98698nmqwou0PV0v8qV6==MPk=Y0pj18_kiHrRUXgQ4VEw@mail.gmail.com>

> Anyone who wants to test this, the firmware image is here:
>
> https://github.com/kvalo/ath10k-firmware/tree/master/10.2
>

So, 10.x firmware won't have IBSS support?

-----
Chun-Yeow


From michal.kazior at tieto.com  Thu Jul 31 00:58:49 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 31 Jul 2014 09:58:49 +0200
Subject: Crash in hacked kernel with CT firmware.
In-Reply-To: <53D9136E.8050908@candelatech.com>
References: <53D9136E.8050908@candelatech.com>
Message-ID: <CA+BoTQk7MNoD_PcbhaLxhtknQiORbW3ak6f=go31csif2JMAsQ@mail.gmail.com>

On 30 July 2014 17:46, Ben Greear <greearb at candelatech.com> wrote:
> Not sure how relevant this is to upstream, but just in case someone
> wants to look at it:
>
> Kernel is modified 3.14.14+, with a good bit of backported ath10k and some
> patches of my own to help stabilize ath10k with my workload and to support
> CT firmware features.
>
> http://dmz2.candelatech.com/git/gitweb.cgi?p=linux-3.14.dev.y/.git;a=summary
>
> Firmware is CT firmware, and it has a bug in this test case where it crashes
> fairly often upon removal of a vdev after some traffic tests have been
> running.  Likely this firmware bug is something that I have added or
> at least exacerbated, and I am working on fixing it.
>
> But, when it crashes, it takes the kernel down shortly afterwards
> in a reliable manner:
[...]
> BUG: unable to handle kernel NULL pointer dereference at 0000000000000068
> IP: [<ffffffffa06a318d>] ath10k_txrx_tx_unref+0x91/0x3c7 [ath10k_core]
[...]
> Call Trace:
>  [<ffffffffa06a28b4>] ath10k_htt_tx_detach+0x70/0xd1 [ath10k_core]
>  [<ffffffffa06a04cf>] ath10k_htt_detach+0x16/0x1b [ath10k_core]
>  [<ffffffffa069eab3>] ath10k_core_stop+0x4f/0x70 [ath10k_core]
>  [<ffffffffa069ae32>] ath10k_halt+0xde/0x161 [ath10k_core]
>  [<ffffffffa069aeed>] ath10k_stop+0x38/0x89 [ath10k_core]
>  [<ffffffffa05b0ae6>] ieee80211_stop_device+0x58/0x84 [mac80211]
>  [<ffffffffa069541c>] ? spin_lock_bh+0x9/0xb [ath10k_core]
>  [<ffffffffa059d0d3>] ieee80211_do_stop+0x625/0x67d [mac80211]
>  [<ffffffff810fdf6a>] ? trace_hardirqs_on+0xd/0xf
>  [<ffffffff810c6d42>] ? __local_bh_enable_ip+0xaf/0xd9
>  [<ffffffff815d8156>] ? _raw_spin_unlock_bh+0x31/0x35
>  [<ffffffff8153a693>] ? dev_deactivate_many+0x129/0x172
>  [<ffffffffa059d140>] ieee80211_stop+0x15/0x19 [mac80211]
[...]
> (gdb) l *(ath10k_txrx_tx_unref+0x91)
> 0xe18d is in ath10k_txrx_tx_unref (/mnt/sda/home/greearb/git/linux-3.14.dev.y/drivers/net/wireless/ath/ath10k/txrx.c:109).
> 104             }
> 105
> 106             msdu = htt->pending_tx[tx_done->msdu_id];
> 107             skb_cb = ATH10K_SKB_CB(msdu);
> 108
> 109             dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);

Okay.. So `msdu` is NULL. I can't seem to find unpaired used_msdu_ids
and pending_tx accesses. This suggests htt->pending_tx itself is
invalid (as well as used_msdu_ids) - perhaps use-after-free (both
pointers aren't NULLed). This in turn suggests ath10k_htt_tx_detach()
was called before and this is the second call. Stack trace suggests
the (allegadly second) call originates from drv_stop(). When ath10k
crashes ath10k_core_start() worker calls ath10k_halt() directly, sets
RESTARTING state and queues mac80211 hw restart. ath10k_stop() calls
ath10k_halt() only if state is ON, RESTARTED or WEDGED. RESTARTING
isn't one of them, but since you have more than 1 entry point for hw
recovery (pci indication, wmi_send, flush) you can trigger
ath10k_core_start() worker with RESTARTING state (i.e. crash within a
crash before ath10k_start() is called) which changes state to WEDGED.
WEDGED allows ath10k_halt() to be called in ath10k_stop(). QED.

The following (it has been in upstream for some time now) should fix
the problem:

commit c5058f5b82f226b236dc5a65015152ed3c23efff
Author: Michal Kazior <michal.kazior at tieto.com>
Date:   Mon May 26 12:46:03 2014 +0300

    ath10k: perform hw restart lazily

    This reduces risk of races and prepares for more
    hw restart fixes.

    It also makes sense to perform teardown after
    mac80211 starts its restart routine as it
    guarantees it has stopped itself by then
    (including tx queues).

    Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
    Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>

This probably makes your ieee80211_stop_queues() in ath10k_halt() obsolete too.


Micha?


From michal.kazior at tieto.com  Thu Jul 31 01:07:35 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 31 Jul 2014 10:07:35 +0200
Subject: [PATCH] ath10k: add support for 10.2 firmware
In-Reply-To: <CAEFj98698nmqwou0PV0v8qV6==MPk=Y0pj18_kiHrRUXgQ4VEw@mail.gmail.com>
References: <1406287937-26507-1-git-send-email-michal.kazior@tieto.com>
 <87y4vhmshr.fsf@kamboji.qca.qualcomm.com>
 <CAEFj98698nmqwou0PV0v8qV6==MPk=Y0pj18_kiHrRUXgQ4VEw@mail.gmail.com>
Message-ID: <CA+BoTQnaic6AwL=1=5FrP7hw_bUL4dburFP3StqERc9Yj4Lo+g@mail.gmail.com>

On 31 July 2014 05:46, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
>> Anyone who wants to test this, the firmware image is here:
>>
>> https://github.com/kvalo/ath10k-firmware/tree/master/10.2
>>
>
> So, 10.x firmware won't have IBSS support?

I don't think anyone can answer you that with certainty. 10.2 doesn't
seem to support IBSS just like 10.1.

Perhaps 10.3 (or later) will support it, but I wouldn't get my hopes
up since the 10.x branch seems to focus on AP only.


Micha?


From vh.nguyen at actiasodielec.fr  Thu Jul 31 03:02:09 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Thu, 31 Jul 2014 12:02:09 +0200
Subject: Trouble shooting low rate MCS9 in 802.11ac
In-Reply-To: <CA+BoTQ=QscHgrk5bbWugjdnVGh=T_L-psEPKToYHOdKGcQZi7A@mail.gmail.com>
References: <30258C2D-7A80-42C1-8AE7-713C490ABF05@st-andrews.ac.uk>
 <53C6A1C7.5060004@intec.ugent.be>
 <CA+BoTQ==9HQrPxp3qZGwEm_a3wQY_wMW5ckrbSRu+MkxU1HRgw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EB@srvexch01.SODIELEC.local>
 <CACKGw+HM-VYpotQGcTsanebvfU-4iGocOpbbGak7iUDb7sUURA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EC@srvexch01.SODIELEC.local>
 <CACKGw+HraUvPSVprRQCEh0=MRaiahpGde9wUj-w5pbDtXSj8Yw@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EE@srvexch01.SODIELEC.local>
 <CAJ-Vmon+TC_TouvoAX3kZT5x+crrStHLmcjCfOeGHvC5eszbTA@mail.gmail.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7EF@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F5@srvexch01.SODIELEC.local>
 <53D252B4.9070704@candelatech.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7F8@srvexch01.SODIELEC.local>
 <53D6757A.8040803@candelatech.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D7FE@srvexch01.SODIELEC.local>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D800@srvexch01.SODIELEC.local>,
 <CA+BoTQ=QscHgrk5bbWugjdnVGh=T_L-psEPKToYHOdKGcQZi7A@mail.gmail.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D803@srvexch01.SODIELEC.local>

>Strange that disabling checksum helped things.  Maybe your ethernet driver
>has issues?

I've no idea about this. Do you have any suggest how to check it? :D

>Looks like removing netfilter (and maybe ebtables?) would
>also help your performance...

I don't enable ebtables in my kernel config, so it shoud not be built in my kernel

>tx status is needed for bookkeping at least, even if you don't
>get useful status info in stock firmware.
>
>CT firmware will give you proper status if you apply some of the
>ath10k driver patches from my tree, but that is unlikely to help
>performance.

>This accounts for 76.58% of CPU usage. You've most likely trimmed down
>the remaining entries accounting for 24% before posting.

I saw there is option -a when running perf top but I did it and still, it doesn't 
print all processes :(

>By the looks of it you might be able to strip down netfilter
>(iptables) rules to none on all chains and tables if you just want to
>max out the performance at the cost of having no firewall whatsoever.

I'd cleaned all rules of iptables and removed all modules of iptables from kernel by command modprobe -r
But there's still some process of netfilter process running. I disabled netfilter on bridge interface by writing 0 to these files:
/proc/sys/net/bridge/bridge-nf-call-arptables
/proc/sys/net/bridge/bridge-nf-call-iptables
/proc/sys/net/bridge/bridge-nf-call-ip6tables

and the performance increases from 500 to 550 Mbps (iperf in tcp reports between 530 ~ 570Mbps). 
There is no more process like  "br_nf_pre_routing" and "br_nf_forward_ip".
Do you think I can do anything more to strip down netfilter?
Now the processor of my AP (about 20% idle)  is no more exhausted but not the same on STA (about 4.5 % idle)
Here is my perf top result on AP:

PerfTop:      99 irqs/sec  kernel:96.0%  exact:  0.0% [1000Hz cycles],  (all, 1 CPU)
-------------------------------------------------------------------------------

    24.40%  [kernel]       [k] armadaxp_enter_idle
     6.04%  [mac80211]     [k] ieee80211_tx_status
     5.07%  [kernel]       [k] memcpy
     3.38%  [kernel]       [k] mv_eth_poll
     3.38%  [mac80211]     [k] $a
     2.66%  [kernel]       [k] __memzero
     2.54%  [ath10k_pci]   [k] ath10k_ce_send_nolock
     2.17%  [ath10k_core]  [k] ath10k_txrx_tx_unref
     2.05%  [kernel]       [k] dev_queue_xmit
     2.05%  [kernel]       [k] br_handle_frame
     1.69%  [kernel]       [k] local_bh_enable
     1.69%  [kernel]       [k] eth_type_trans
     1.69%  [ath10k_core]  [k] ath10k_htt_tx
     1.69%  ld-2.13.so     [.] 0xf120  
     1.69%  [ath10k_pci]   [k] ath10k_ce_completed_send_next
     1.57%  [kernel]       [k] __netif_receive_skb
     1.45%  [kernel]       [k] dev_hard_start_xmit
     1.45%  [kernel]       [k] nf_iterate
     1.33%  [kernel]       [k] dev_gro_receive                                  
     1.21%  [kernel]       [k] kfree                                            
     1.21%  [kernel]       [k] __kfree_skb 

And on STA:

PerfTop:      51 irqs/sec  kernel:94.1%  exact:  0.0% [1000Hz cycles],  (all, 1 CPU)
-------------------------------------------------------------------------------

     7.51%  [kernel]       [k] memcpy
     6.65%  [ath10k_core]  [k] ath10k_htt_rx_amsdu_pop
     5.49%  [kernel]       [k] mv_eth_tx
     4.91%  [kernel]       [k] kfree
     4.91%  [kernel]       [k] __memzero
     4.05%  [kernel]       [k] armadaxp_enter_idle
     4.05%  [kernel]       [k] __kmalloc_track_caller
     4.05%  [kernel]       [k] dev_queue_xmit
     4.05%  [kernel]       [k] ip_rcv
     3.76%  [mac80211]     [k] ieee80211_rx
     3.76%  [kernel]       [k] __kfree_skb
     3.76%  [ath10k_core]  [k] $a
     2.89%  [mac80211]     [k] ieee80211_rx_handlers
     2.60%  [mac80211]     [k] $a
     2.60%  [kernel]       [k] ip_forward
     2.60%  [cfg80211]     [k] ieee80211_data_to_8023
     2.60%  [ath10k_pci]   [k] ath10k_ce_completed_send_next
     2.31%  ld-2.13.so     [.] 0x9d8c  
     2.31%  [cfg80211]     [k] ieee80211_hdrlen
     2.02%  [mac80211]     [k] $a

>You also might want to change qdisc (`tc` command) on all interfaces
>involved to pfifo in case you're using codel to further reduce CPU
>load at the cost of buffer bloating the system.

I installed tc from package iproute2 and did : tc qdisc but it doesn't improve the performance :D

NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE

From vh.nguyen at actiasodielec.fr  Thu Jul 31 08:49:49 2014
From: vh.nguyen at actiasodielec.fr (Vu Hai NGUYEN)
Date: Thu, 31 Jul 2014 17:49:49 +0200
Subject: [PATCH] ath10k: fix aggregated 4addr Rx
In-Reply-To: <1406205374-24858-1-git-send-email-michal.kazior@tieto.com>
References: <1406205374-24858-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <EE97821C81277E459BEA5C6384C6F241012F15C1D805@srvexch01.SODIELEC.local>

Thank you for the patch. I applied it (manually not automatically, the patch is not based on ath-master branch?)
The warning msg: br0: received packet on wlan0.sta1 with own address as source address disappeared on the console of my AP.
But the performance of my bridged STA (using CT firmware) is still lower than non-bridged STA (10.1-467 firmware).
(520 vs 550 Mbps)

The processor of my AP is not exhausted (about 15-20% idle) but perf top on my bridged STA show that there is this thread: br_fdb_update.
I didn't see it on non-bridged STA, it takes 5% resource of the processor
I look for it on google and this thread is related to the warning message br0:received packet on wlan0.sta1 with own address as source address
Do you guy have any suggestion?

Thanks,
NGUYEN Vu Hai
Acita-Sodielec
Route de Mayres - B.P. 9
12100 St GEORGES DE LUZENCON
FRANCE

________________________________________
De : Michal Kazior [michal.kazior at tieto.com]
Date d'envoi : jeudi 24 juillet 2014 14:36
? : ath10k at lists.infradead.org
Cc : linux-wireless at vger.kernel.org; Vu Hai NGUYEN; Michal Kazior
Objet : [PATCH] ath10k: fix aggregated 4addr Rx

A-MSDU 4addr frames weren't reconstructed properly
and in some cases this resulted in a warning:

 br0: received packet on wlan0.sta1 with own address as source address

Since this was only related to A-MSDU it would
trigger when more intense traffic was generated.

Reported-by: Vu Hai NGUYEN <vh.nguyen at actiasodielec.fr>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 318efc3..a8328f9 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -859,7 +859,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
        enum rx_msdu_decap_format fmt;
        enum htt_rx_mpdu_encrypt_type enctype;
        struct ieee80211_hdr *hdr;
-       u8 hdr_buf[64], addr[ETH_ALEN], *qos;
+       u8 hdr_buf[64], da[ETH_ALEN], sa[ETH_ALEN], *qos;
        unsigned int hdr_len;

        rxd = (void *)skb->data - sizeof(*rxd);
@@ -897,10 +897,11 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
                        skb_trim(skb, skb->len - FCS_LEN);
                        break;
                case RX_MSDU_DECAP_NATIVE_WIFI:
-                       /* pull decapped header and copy DA */
+                       /* pull decapped header and copy SA & DA */
                        hdr = (struct ieee80211_hdr *)skb->data;
                        hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
-                       memcpy(addr, ieee80211_get_DA(hdr), ETH_ALEN);
+                       memcpy(da, ieee80211_get_DA(hdr), ETH_ALEN);
+                       memcpy(sa, ieee80211_get_SA(hdr), ETH_ALEN);
                        skb_pull(skb, hdr_len);

                        /* push original 802.11 header */
@@ -914,8 +915,11 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
                        qos = ieee80211_get_qos_ctl(hdr);
                        qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;

-                       /* original 802.11 header has a different DA */
-                       memcpy(ieee80211_get_DA(hdr), addr, ETH_ALEN);
+                       /* original 802.11 header has a different DA and in
+                        * case of 4addr it may also have different SA
+                        */
+                       memcpy(ieee80211_get_DA(hdr), da, ETH_ALEN);
+                       memcpy(ieee80211_get_SA(hdr), sa, ETH_ALEN);
                        break;
                case RX_MSDU_DECAP_ETHERNET2_DIX:
                        /* strip ethernet header and insert decapped 802.11
--
1.8.5.3



From greearb at candelatech.com  Thu Jul 31 10:22:02 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 31 Jul 2014 10:22:02 -0700
Subject: [PATCH] ath10k: fix aggregated 4addr Rx
In-Reply-To: <EE97821C81277E459BEA5C6384C6F241012F15C1D805@srvexch01.SODIELEC.local>
References: <1406205374-24858-1-git-send-email-michal.kazior@tieto.com>
 <EE97821C81277E459BEA5C6384C6F241012F15C1D805@srvexch01.SODIELEC.local>
Message-ID: <53DA7B3A.7000403@candelatech.com>

On 07/31/2014 08:49 AM, Vu Hai NGUYEN wrote:
> Thank you for the patch. I applied it (manually not automatically, the patch is not based on ath-master branch?)
> The warning msg: br0: received packet on wlan0.sta1 with own address as source address disappeared on the console of my AP.
> But the performance of my bridged STA (using CT firmware) is still lower than non-bridged STA (10.1-467 firmware).
> (520 vs 550 Mbps)
> 
> The processor of my AP is not exhausted (about 15-20% idle) but perf top on my bridged STA show that there is this thread: br_fdb_update.
> I didn't see it on non-bridged STA, it takes 5% resource of the processor
> I look for it on google and this thread is related to the warning message br0:received packet on wlan0.sta1 with own address as source address
> Do you guy have any suggestion?

Is there any way at all to make the standard firmware do bridged mode?  I am curious if
the slow-down is due to my firmware or to bridging in general...

Thanks,
Ben

-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



From greearb at candelatech.com  Thu Jul 31 14:29:43 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 31 Jul 2014 14:29:43 -0700
Subject: New CT firmware release is uploaded.
In-Reply-To: <53CD9C08.9090908@candelatech.com>
References: <53CD9C08.9090908@candelatech.com>
Message-ID: <53DAB547.3030700@candelatech.com>

I've put up a new version (010) that fixes a crash bug in the 009
release.  64 stations (vdevs) have been fairly well tested at
this point (using my 3.14.14+ kernel).

http://www.candelatech.com/ath10k.php

Thanks,
Ben


On 07/21/2014 04:02 PM, Ben Greear wrote:
> Release notes:
> 
>       Improve RAM usage:  Re-organized, trimmed, and otherwise made better use
>       of RAM.  Allow compiling out swbmiss, beacon filtering, roaming code.
>       Images with 'full' in their name do NOT have the previously mentioned features
>       compiled out.
> 
>       Over-all, freed up about 80k of extra RAM, which can be used for more vdevs,
>       peers, buffers, etc.
> 
>       Supports 64 vdevs (one should be reserved for monitor interface, so
>       effectively 63 vdevs for current kernels.)
> 
> I have only lightly tested this on my 3.14 kernel so far.
> 
> A lot of these changes could potentially introduce run-time
> crashes due to extensive use of a different type of RAM for
> storing many structures.  Should be a quick fix should problems
> arise.
> 
> As always, let me know if you find any problems.
> 
> Thanks,
> Ben
> 


-- 
Ben Greear <greearb at candelatech.com>
Candela Technologies Inc  http://www.candelatech.com



