From kvalo at qca.qualcomm.com  Tue Sep  2 00:15:57 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 2 Sep 2014 10:15:57 +0300
Subject: [PATCH] ath10k: re-enable interrupts properly in hw recovery
In-Reply-To: <1409144989-17934-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Wed, 27 Aug 2014 15:09:49 +0200")
References: <1409144989-17934-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <871trupk5u.fsf@kamboji.qca.qualcomm.com>

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

> Recent changes done to start/restart sequences
> broke hw recovery in some hw configurations. The
> pci transport was stopped twice however due to a
> workaround in the pci disabling code the
> disable/enable for first msi interrupt was not
> balanced. This ended up with irqs not being
> properly re-enabled and the following print out
> during recovery:
>
>  ath10k: failed to receive control response completion, polling..
>  ath10k: Service connect timeout: -110
>  ath10k: Could not init core: -110
>
> Legacy interrupt mode was unaffected while msi
> ranged mode would be partially crippled (it would
> miss fw indication interrupts but otherwise it
> worked fine).
>
> This fixes completely broken fw recovery for a
> single msi interrupt mode and fixes subsequent fw
> crash reports for msi range interrupt mode.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep  2 00:17:45 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 2 Sep 2014 10:17:45 +0300
Subject: [PATCH] ath10k: fix num_legacy_stations tracking
In-Reply-To: <1409212779-5212-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 28 Aug 2014 09:59:39 +0200")
References: <1409212779-5212-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87wq9mo5ie.fsf@kamboji.qca.qualcomm.com>

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

> If a station was reassociated, i.e. due to change
> of supported rates update via sta_rc_update() the
> num_legacy_stations would be (incorrectly) bumped
> up leading to unbalanced usage of the var. This in
> turn could lock rtscts protection up as enabled.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep  2 00:19:15 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 2 Sep 2014 10:19:15 +0300
Subject: [PATCH] ath10k: kill tasklets after free_irq
In-Reply-To: <1409214280-6492-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 28 Aug 2014 10:24:40 +0200")
References: <1409214280-6492-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87sikao5fw.fsf@kamboji.qca.qualcomm.com>

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

> Commit 5c771e7454d148af35e8b4297d00f880de79ea49
> introduced a regression. On some systems spurious
> interrupts could schedule a tasklet while tearing
> down leading to, e.g.:
>
>  BUG: unable to handle kernel paging request at fe589030
>  IP: [<c1316fb0>] ioread32+0x30/0x40
>  ...
>  Call Trace:
>   [<fe576c1b>] ath10k_pci_tasklet+0x1b/0x60 [ath10k_pci]
>   [<c1053fbe>] tasklet_action+0x9e/0xb0
>   [<c10534f1>] __do_softirq+0xf1/0x3f0
>   [<c1053400>] ? ftrace_raw_event_irq_handler_entry+0xa0/0xa0
>   [<c1004999>] do_softirq_own_stack+0x29/0x40
>   <IRQ>
>   [<c1053a76>] irq_exit+0x86/0xb0
>  ...
>   [<c132d522>] do_pci_disable_device+0x52/0x60
>   [<c132d57f>] pci_disable_device+0x4f/0xb0
>   [<c132a961>] ? __pci_set_master+0x51/0x80
>   [<fe5740b3>] ath10k_pci_release+0x33/0x40 [ath10k_pci]
>   [<fe575d4b>] ath10k_pci_remove+0x7b/0x90 [ath10k_pci]
>
> Reported-by: Kalle Valo <kvalo at qca.qualcomm.com>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied. I also added a "Tested-by: Kalle" line.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep  2 00:29:05 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 2 Sep 2014 10:29:05 +0300
Subject: [PATCH 0/2] ath10k: monitor fixes
In-Reply-To: <1409223497-19946-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 28 Aug 2014 12:58:15 +0200")
References: <1409223497-19946-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87lhq2o4zi.fsf@kamboji.qca.qualcomm.com>

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

> Hi,
>
> This cleans up the monitor code a bit and
> introduces a workaround for a fw bug (leading to a
> fw crash) when station interface associates while
> a monitor vdev is running.
>
> People have been complaining about the fw crash
> for some time now. I guess we have no choice but
> to make a workaround in ath10k. The most common
> usecase that will benefit from this fix is
> probably 4addr sta briding.
>
>
> Michal Kazior (2):
>   ath10k: fix monitor start/stop sequences
>   ath10k: stop monitor vdev for sta assoc

Thanks, both patches applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep  2 06:13:31 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 2 Sep 2014 16:13:31 +0300
Subject: [PATCH] ath10k: remove diag_*_access functions
In-Reply-To: <1409231036-16137-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 28 Aug 2014 15:03:56 +0200")
References: <1409231036-16137-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87iol6mah0.fsf@kamboji.qca.qualcomm.com>

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

> Remove the ugly _access functions. Being explicit
> is a good thing.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep  2 06:17:52 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 2 Sep 2014 16:17:52 +0300
Subject: [PATCH] ath10k: add device/driver strings to tracepoints
In-Reply-To: <1409231135-16233-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 28 Aug 2014 15:05:35 +0200")
References: <1409231135-16233-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87bnqyma9r.fsf@kamboji.qca.qualcomm.com>

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

> This makes it easier to log and debug via tracing
> with more than 1 ath10k device on a system.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep  2 06:19:37 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 2 Sep 2014 16:19:37 +0300
Subject: [PATCH] ath10k: don't access tx_info while overwriting it
In-Reply-To: <1409303943-1452-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Fri, 29 Aug 2014 11:19:03 +0200")
References: <1409303943-1452-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <877g1mma6u.fsf@kamboji.qca.qualcomm.com>

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

> Nothing important was being overwritten so it
> didn't yield any bugs yet.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep  2 06:38:09 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 2 Sep 2014 16:38:09 +0300
Subject: [PATCH v5] ath10k:  save firmware debug log messages.
In-Reply-To: <1409239441-4878-1-git-send-email-greearb@candelatech.com>
 (greearb@candelatech.com's message of "Thu, 28 Aug 2014 08:24:01
 -0700")
References: <1409239441-4878-1-git-send-email-greearb@candelatech.com>
Message-ID: <8738cam9by.fsf@kamboji.qca.qualcomm.com>

(Dropping linux-wireless)

greearb at candelatech.com writes:

> 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>

Before I start looking at this in detail: this looks fragile and
complicated from ath10k point of view. Why not just take a dump of the
whole firmware memory and postprocess this, with whatever else we might
need from the firmware? That's a lot easier to maintain.

-- 
Kalle Valo


From michal.kazior at tieto.com  Tue Sep  2 06:48:42 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 2 Sep 2014 15:48:42 +0200
Subject: ath10k: kernel panic on 8f975e16cd2b456ee40a796e9c61797b58670706
Message-ID: <CA+BoTQmW+mz8=NKi-CABmdYYw+YaHi2ZwHQkYp7h0+tPxVcsFw@mail.gmail.com>

Hi,

While playing with some stuff I managed to crash the device very early
during wait_for_device and I've hit the following:

[  171.259328] ath10k_pci 0000:00:05.0: device has crashed during init
[  171.264129] BUG: unable to handle kernel NULL pointer dereference
at           (null)
[  171.265095] IP: [<ffffffffa0058005>]
ath10k_debug_get_new_fw_crash_data+0x15/0x30 [ath10k_core]
[  171.265095] PGD 0
[  171.265095] Oops: 0002 [#1] SMP
[  171.265095] Modules linked in: ath10k_pci(O) ath10k_core(O) ath
[last unloaded: ath]
[  171.265095] CPU: 3 PID: 29 Comm: kworker/u8:1 Tainted: G
O   3.17.0-rc2-wl-ath+ #447
[  171.265095] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
BIOS Bochs 01/01/2011
[  171.265095] Workqueue: ath10k_wq ath10k_core_register_work [ath10k_core]
[  171.265095] task: ffff88001eb01ad0 ti: ffff88001eb60000 task.ti:
ffff88001eb60000
[  171.265095] RIP: 0010:[<ffffffffa0058005>]  [<ffffffffa0058005>]
ath10k_debug_get_new_fw_crash_data+0x15/0x30 [ath10k_core]
[  171.265095] RSP: 0018:ffff88001eb63ce8  EFLAGS: 00010246
[  171.265095] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[  171.265095] RDX: 0000000000000000 RSI: ffffc90001a09030 RDI: 0000000000000001
[  171.265095] RBP: ffff88001eb63cf0 R08: 0000000000000000 R09: ffff8800000bb200
[  171.265095] R10: 00000000000001e2 R11: ffff88001eb638de R12: ffff88001d7459a0
[  171.265095] R13: ffff88001d746ab0 R14: 00000000fffe14d4 R15: ffff88001d747c60
[  171.265095] FS:  0000000000000000(0000) GS:ffff88001fd80000(0000)
knlGS:0000000000000000
[  171.265095] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[  171.265095] CR2: 0000000000000000 CR3: 000000001df34000 CR4: 00000000000006e0
[  171.265095] Stack:
[  171.265095]  ffff88001d7459a0 ffff88001eb63d58 ffffffffa0083bbe
ffff880000000010
[  171.265095]  ffff88001eb63d68 ffff88001eb63d18 0000000000000002
0000000000059010
[  171.265095]  ffffffffa0086fef 00000000deadbeef ffff88001d747a28
ffff88001d7459a0
[  171.265095] Call Trace:
[  171.265095]  [<ffffffffa0083bbe>]
ath10k_pci_fw_crashed_dump+0x2e/0xd0 [ath10k_pci]
[  171.265095]  [<ffffffffa0085410>]
__ath10k_pci_hif_power_up+0x5f0/0x700 [ath10k_pci]
[  171.265095]  [<ffffffffa0085550>] ath10k_pci_hif_power_up+0x30/0xe0
[ath10k_pci]
[  171.265095]  [<ffffffffa005bc7b>]
ath10k_core_register_work+0x2b/0x520 [ath10k_core]
[  171.265095]  [<ffffffff810689cc>] process_one_work+0x18c/0x3f0
[  171.265095]  [<ffffffff81069011>] worker_thread+0x121/0x4a0
[  171.265095]  [<ffffffff81068ef0>] ? rescuer_thread+0x2c0/0x2c0
[  171.265095]  [<ffffffff8106daf2>] kthread+0xd2/0xf0
[  171.265095]  [<ffffffff8106da20>] ? kthread_create_on_node+0x170/0x170
[  171.265095]  [<ffffffff81857cfc>] ret_from_fork+0x7c/0xb0
[  171.265095]  [<ffffffff8106da20>] ? kthread_create_on_node+0x170/0x170
[  171.265095] Code: 8b 40 38 48 c7 80 00 01 00 00 00 00 00 00 5b 5d
c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 53 48 8b 9f 90 1d 00 00
48 8d 7b 01 <c6> 03 01 e8 e3 ec 2b e1 48 8d 7b 18 e8 6a 4f 05 e1 48 89
d8 5b
[  171.265095] RIP  [<ffffffffa0058005>]
ath10k_debug_get_new_fw_crash_data+0x15/0x30 [ath10k_core]
[  171.265095]  RSP <ffff88001eb63ce8>
[  171.265095] CR2: 0000000000000000
[  171.265095] ---[ end trace 5d0ed15b050bcc1f ]---
[  171.265095] Kernel panic - not syncing: Fatal exception in interrupt
[  171.265095] Kernel Offset: 0x0 from 0xffffffff81000000 (relocation
range: 0xffffffff80000000-0xffffffff9fffffff)
[  171.265095] ---[ end Kernel panic - not syncing: Fatal exception in interrupt

The reason is ath10k_debug_create() is called during core_register
*after* probe_fw. If firmware crashes during probe_fw (and I suppose
it doesn't need to be the "early" one) then ath10k ends up
dereferencing crash_data (which is NULL).

So we either add an extra check for the NULL case or we re-work debug
lifecycle. Currently debug attaches to mac80211/wiphy debugfs so part
of it has to be done after probing fw anyway (crash_data could be done
earlier). Thoughts?


Micha?


From michal.kazior at tieto.com  Tue Sep  2 06:51:58 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 2 Sep 2014 15:51:58 +0200
Subject: [PATCH v5] ath10k: save firmware debug log messages.
In-Reply-To: <8738cam9by.fsf@kamboji.qca.qualcomm.com>
References: <1409239441-4878-1-git-send-email-greearb@candelatech.com>
 <8738cam9by.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQk2CkmaZtZQ9iQyqU_9K3E_TYwetGNbsKpxYjbUvdL43g@mail.gmail.com>

On 2 September 2014 15:38, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> (Dropping linux-wireless)
>
> greearb at candelatech.com writes:
>
>> 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>
>
> Before I start looking at this in detail: this looks fragile and
> complicated from ath10k point of view. Why not just take a dump of the
> whole firmware memory and postprocess this, with whatever else we might
> need from the firmware? That's a lot easier to maintain.

I like the idea although it still makes sense to keep some sort of a
circular buffer for the debug mesg events delivered via wmi, does it
not?


Micha?


From kvalo at qca.qualcomm.com  Tue Sep  2 07:25:14 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 2 Sep 2014 17:25:14 +0300
Subject: [PATCH v5] ath10k: save firmware debug log messages.
In-Reply-To: <CA+BoTQk2CkmaZtZQ9iQyqU_9K3E_TYwetGNbsKpxYjbUvdL43g@mail.gmail.com>
 (Michal Kazior's message of "Tue, 2 Sep 2014 15:51:58 +0200")
References: <1409239441-4878-1-git-send-email-greearb@candelatech.com>
 <8738cam9by.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQk2CkmaZtZQ9iQyqU_9K3E_TYwetGNbsKpxYjbUvdL43g@mail.gmail.com>
Message-ID: <87y4u2ksl1.fsf@kamboji.qca.qualcomm.com>

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

> On 2 September 2014 15:38, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> (Dropping linux-wireless)
>>
>> greearb at candelatech.com writes:
>>
>>> 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>
>>
>> Before I start looking at this in detail: this looks fragile and
>> complicated from ath10k point of view. Why not just take a dump of the
>> whole firmware memory and postprocess this, with whatever else we might
>> need from the firmware? That's a lot easier to maintain.
>
> I like the idea although it still makes sense to keep some sort of a
> circular buffer for the debug mesg events delivered via wmi, does it
> not?

How would ath10k use those stored debug mesg events? Attach them to the
firmare crash dump file? Or did you have something else in mind?

But most importantly, would that be useful? Does the firmware send debug
events now? Or would it require the user to change the firmware log
level through fw_dbglog debugfs file before the crash?

I want to avoid a situation where we have to maintain a feature which
nobody uses.

-- 
Kalle Valo


From greearb at candelatech.com  Tue Sep  2 07:52:27 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 02 Sep 2014 07:52:27 -0700
Subject: [PATCH v5] ath10k: save firmware debug log messages.
In-Reply-To: <CA+BoTQk2CkmaZtZQ9iQyqU_9K3E_TYwetGNbsKpxYjbUvdL43g@mail.gmail.com>
References: <1409239441-4878-1-git-send-email-greearb@candelatech.com>	<8738cam9by.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQk2CkmaZtZQ9iQyqU_9K3E_TYwetGNbsKpxYjbUvdL43g@mail.gmail.com>
Message-ID: <5405D9AB.60002@candelatech.com>



On 09/02/2014 06:51 AM, Michal Kazior wrote:
> On 2 September 2014 15:38, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> (Dropping linux-wireless)
>>
>> greearb at candelatech.com writes:
>>
>>> 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>
>>
>> Before I start looking at this in detail: this looks fragile and
>> complicated from ath10k point of view. Why not just take a dump of the
>> whole firmware memory and postprocess this, with whatever else we might
>> need from the firmware? That's a lot easier to maintain.
>
> I like the idea although it still makes sense to keep some sort of a
> circular buffer for the debug mesg events delivered via wmi, does it
> not?

Upstream firmware already creates and sends dbglog messages, and it is nice to see
a history.  It sends them to host fairly often, so just grabbing the log
on crash could miss useful info.

For that matter, I'd like to read firmware debuglog ids not just on crash,
which I could easily do with this patch as the basis by creating a new
debugfs file that just dumps the debuglog ids.

I'm not sure what I could do with a full ram dump, but perhaps QCA devs
have something.  It would at a minimum use a lot more RAM to store it.
I just need (know how to decode) the BSS regions, debug-logs, and registers.

Thanks,
Ben

>
>
> Micha?
>

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


From yanbol at qti.qualcomm.com  Tue Sep  2 07:58:50 2014
From: yanbol at qti.qualcomm.com (Li, Yanbo)
Date: Tue, 2 Sep 2014 14:58:50 +0000
Subject: [PATCH v5] ath10k: save firmware debug log messages.
In-Reply-To: <5405D9AB.60002@candelatech.com>
References: <1409239441-4878-1-git-send-email-greearb@candelatech.com>
 <8738cam9by.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQk2CkmaZtZQ9iQyqU_9K3E_TYwetGNbsKpxYjbUvdL43g@mail.gmail.com>
 <5405D9AB.60002@candelatech.com>
Message-ID: <8F62F6322D7B2E46AD0AB51C2C2A02FD2305CF61@NASANEXD01D.na.qualcomm.com>

Hi Ben,

I just start to investigate about how to get the full dump from target.  It can utilization the debugfs framework you have done, 
We can work together and figure out more detail about how to implement it. 

Thanks 
BR /Yanbo

-----Original Message-----
From: ath10k [mailto:ath10k-bounces at lists.infradead.org] On Behalf Of Ben Greear
Sent: Tuesday, September 02, 2014 10:52 PM
To: michal.kazior at tieto.com; Valo, Kalle
Cc: ath10k at lists.infradead.org
Subject: Re: [PATCH v5] ath10k: save firmware debug log messages.



On 09/02/2014 06:51 AM, Michal Kazior wrote:
> On 2 September 2014 15:38, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> (Dropping linux-wireless)
>>
>> greearb at candelatech.com writes:
>>
>>> 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>
>>
>> Before I start looking at this in detail: this looks fragile and 
>> complicated from ath10k point of view. Why not just take a dump of 
>> the whole firmware memory and postprocess this, with whatever else we 
>> might need from the firmware? That's a lot easier to maintain.
>
> I like the idea although it still makes sense to keep some sort of a 
> circular buffer for the debug mesg events delivered via wmi, does it 
> not?

Upstream firmware already creates and sends dbglog messages, and it is nice to see a history.  It sends them to host fairly often, so just grabbing the log on crash could miss useful info.

For that matter, I'd like to read firmware debuglog ids not just on crash, which I could easily do with this patch as the basis by creating a new debugfs file that just dumps the debuglog ids.

I'm not sure what I could do with a full ram dump, but perhaps QCA devs have something.  It would at a minimum use a lot more RAM to store it.
I just need (know how to decode) the BSS regions, debug-logs, and registers.

Thanks,
Ben

>
>
> Micha?
>

--
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 greearb at candelatech.com  Tue Sep  2 08:50:23 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 02 Sep 2014 08:50:23 -0700
Subject: [PATCH v5] ath10k: save firmware debug log messages.
In-Reply-To: <8F62F6322D7B2E46AD0AB51C2C2A02FD2305CF61@NASANEXD01D.na.qualcomm.com>
References: <1409239441-4878-1-git-send-email-greearb@candelatech.com>
 <8738cam9by.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQk2CkmaZtZQ9iQyqU_9K3E_TYwetGNbsKpxYjbUvdL43g@mail.gmail.com>
 <5405D9AB.60002@candelatech.com>
 <8F62F6322D7B2E46AD0AB51C2C2A02FD2305CF61@NASANEXD01D.na.qualcomm.com>
Message-ID: <5405E73F.6000605@candelatech.com>

On 09/02/2014 07:58 AM, Li, Yanbo wrote:
> Hi Ben,
> 
> I just start to investigate about how to get the full dump from target.  It can utilization the debugfs framework you have done, 
> We can work together and figure out more detail about how to implement it. 

Sounds good.  I have patches to deal with dumping debug-log, ROM and RAM bss regions,
and a proprietary tool to decode all of this that QCA can have access to.

My patches are similar to what has been posted before, but tweaked
slightly and tested.  I am trying to get the debug-log patch
in acceptable form before posting the rest of the patches, but I
can make them available earlier if someone wants to see them.

Please let me know what you have in mind.

Thanks,
Ben

> 
> Thanks 
> BR /Yanbo
> 
> -----Original Message-----
> From: ath10k [mailto:ath10k-bounces at lists.infradead.org] On Behalf Of Ben Greear
> Sent: Tuesday, September 02, 2014 10:52 PM
> To: michal.kazior at tieto.com; Valo, Kalle
> Cc: ath10k at lists.infradead.org
> Subject: Re: [PATCH v5] ath10k: save firmware debug log messages.
> 
> 
> 
> On 09/02/2014 06:51 AM, Michal Kazior wrote:
>> On 2 September 2014 15:38, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>>> (Dropping linux-wireless)
>>>
>>> greearb at candelatech.com writes:
>>>
>>>> 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>
>>>
>>> Before I start looking at this in detail: this looks fragile and 
>>> complicated from ath10k point of view. Why not just take a dump of 
>>> the whole firmware memory and postprocess this, with whatever else we 
>>> might need from the firmware? That's a lot easier to maintain.
>>
>> I like the idea although it still makes sense to keep some sort of a 
>> circular buffer for the debug mesg events delivered via wmi, does it 
>> not?
> 
> Upstream firmware already creates and sends dbglog messages, and it is nice to see a history.  It sends them to host fairly often, so just grabbing the log on crash could miss useful info.
> 
> For that matter, I'd like to read firmware debuglog ids not just on crash, which I could easily do with this patch as the basis by creating a new debugfs file that just dumps the debuglog ids.
> 
> I'm not sure what I could do with a full ram dump, but perhaps QCA devs have something.  It would at a minimum use a lot more RAM to store it.
> I just need (know how to decode) the BSS regions, debug-logs, and registers.
> 
> Thanks,
> Ben
> 
>>
>>
>> Micha?
>>
> 
> --
> 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
> 


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



From greearb at candelatech.com  Tue Sep  2 09:03:57 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 02 Sep 2014 09:03:57 -0700
Subject: [PATCH v5] ath10k: save firmware debug log messages.
In-Reply-To: <87y4u2ksl1.fsf@kamboji.qca.qualcomm.com>
References: <1409239441-4878-1-git-send-email-greearb@candelatech.com>
 <8738cam9by.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQk2CkmaZtZQ9iQyqU_9K3E_TYwetGNbsKpxYjbUvdL43g@mail.gmail.com>
 <87y4u2ksl1.fsf@kamboji.qca.qualcomm.com>
Message-ID: <5405EA6D.2040803@candelatech.com>

On 09/02/2014 07:25 AM, Kalle Valo wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
> 
>> On 2 September 2014 15:38, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>>> (Dropping linux-wireless)
>>>
>>> greearb at candelatech.com writes:
>>>
>>>> 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>
>>>
>>> Before I start looking at this in detail: this looks fragile and
>>> complicated from ath10k point of view. Why not just take a dump of the
>>> whole firmware memory and postprocess this, with whatever else we might
>>> need from the firmware? That's a lot easier to maintain.
>>
>> I like the idea although it still makes sense to keep some sort of a
>> circular buffer for the debug mesg events delivered via wmi, does it
>> not?
> 
> How would ath10k use those stored debug mesg events? Attach them to the
> firmare crash dump file? Or did you have something else in mind?

It can log them to /var/log/messages as hex for ongoing firmware logging.
It can allow dumping snapshots through debugfs for similar reasons.
Using the above, it can allow firmware devs to insert the equivalent of printf in their
firmware around crash sites and get some debug info in the logs to
aid debugging firmware crashes or other strange things w/out having
a serial console attached to the ath10k NIC.  That is how I debug and fix
crashes in firmware that are not obvious from the initial dump.
Surely your firmware guys could use similar tools.

You have no guarantee when debug log messages are delivered to the host,
so without storing them as received from the target, you may not have anything
useful to dump/decode at crash time.

> But most importantly, would that be useful? Does the firmware send debug
> events now? Or would it require the user to change the firmware log
> level through fw_dbglog debugfs file before the crash?

Standard firmware sends some info with un-modifed ath10k driver,
and modified firmware can provide much more as needed.  There is
no need to twiddle firmware debug log levels for basic use, though
that may give added benefit in some cases.

> I want to avoid a situation where we have to maintain a feature which
> nobody uses.

Anyone that cares about fixing firmware bugs and making the firmware
stable can make good use of this feature.

Thanks,
Ben

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



From psidhu at gateworks.com  Tue Sep  2 11:51:53 2014
From: psidhu at gateworks.com (Pushpal Sidhu)
Date: Tue, 2 Sep 2014 11:51:53 -0700
Subject: Timeout Issues
In-Reply-To: <CA+BoTQn1EiwajmmymkLSM6Nm0pJFOKqo89L4ZUiw6TGbQ-Cv_w@mail.gmail.com>
References: <CAD1M062MNW7y_hf+5btNA14xt9K69TqQy=Q-rCm+2xuHCZDEsA@mail.gmail.com>
 <53F39AB3.10601@candelatech.com>
 <CAD1M062FPxZyj86LvvaomwR3z2KeScnYDCNT_g6zMQzK10+vxA@mail.gmail.com>
 <87zjez7m7t.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQn1EiwajmmymkLSM6Nm0pJFOKqo89L4ZUiw6TGbQ-Cv_w@mail.gmail.com>
Message-ID: <CAD1M060R0x021Rw=mviL54PVH=KS5vnTZBHpUog=fJX007r7Gw@mail.gmail.com>

Sorry for the amazingly late reply, other things crept into my schedule.

Kalle Valo <kvalo at qca.qualcomm.com> writes:
>Have you verified that with this kernel version the PCI bus works
>correctly on your ARM board? Especially check that interrupts work.

Michal Kazior <michal.kazior at tieto.com> writes:
>Note the:
>
>[    7.704403] ath10k: failed to receive control response completion, polling..
>
>This suggests interrupts aren't delivered to the host system for some
>reason although firmware is operational (control response itself was
>delivered to the host).
>
>This particular warning was introduced as part of a workaround for a
>virtual machine PCI passthrough (with the suspicion iomem writes
>aren't propagated properly in the VM). However only control response
>was the subject of the missing interrupt. In your case subsequent
>communication is missing interrupts.
>
>Can you check if the interrupt line is shared with any other devices, please:
>
> lspci -vv | grep -e '..:..\..' -e IRQ
>  cat /proc/interrupts
>
>
>>
>> This causes the card to not be registered, and thus is unusable (there
>>is no wlanX)
>>
>> I am able to use the Intel 7260 card (another AC card) with their
>> firmware binary blob, so I don't believe this is a hardware
>> configuration issue with mini-pcie.
>
>I assume you have only 1 mini-pcie slot on the board and you've used
>it when testing both intel and ath devices or does it have more than 1
>slot and you've used different slots when testing both devices?
>
>
>Micha?

The board has 9 port PCI-e switch behind the RC. I did, however, use
the same slot. I found that there was always 1 interrupt, but never
any more. This made me think a bit more and found that if I set
PCI_MSI=n in the kernel config, the problem 'goes away' and I see
increasing number of interrupts and do not see anymore of the '-110'
error messages. This issue, for me, is solved as I don't necessary
need mixed signaled interrupts, but I'm unsure of why this is
happening and what is different about the Intel 7260HMW card from the
Atheros cards or in their respective drivers.

- Pushpal


From adrian at freebsd.org  Tue Sep  2 12:16:20 2014
From: adrian at freebsd.org (Adrian Chadd)
Date: Tue, 2 Sep 2014 12:16:20 -0700
Subject: Timeout Issues
In-Reply-To: <CAD1M060R0x021Rw=mviL54PVH=KS5vnTZBHpUog=fJX007r7Gw@mail.gmail.com>
References: <CAD1M062MNW7y_hf+5btNA14xt9K69TqQy=Q-rCm+2xuHCZDEsA@mail.gmail.com>
 <53F39AB3.10601@candelatech.com>
 <CAD1M062FPxZyj86LvvaomwR3z2KeScnYDCNT_g6zMQzK10+vxA@mail.gmail.com>
 <87zjez7m7t.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQn1EiwajmmymkLSM6Nm0pJFOKqo89L4ZUiw6TGbQ-Cv_w@mail.gmail.com>
 <CAD1M060R0x021Rw=mviL54PVH=KS5vnTZBHpUog=fJX007r7Gw@mail.gmail.com>
Message-ID: <CAJ-VmokfCnNVDwGks0jdew6K4kPHFot=fmMLpnNTnD2+x+ZXRw@mail.gmail.com>

.. wasn't there some odd-ness with the QCA988x MSI stuff anyway?

I recall driver WAR's in the 1.0 world; I haven't checked what 2.0 fixed.


-a


From kvalo at qca.qualcomm.com  Tue Sep  2 23:14:47 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 3 Sep 2014 09:14:47 +0300
Subject: WMI version handling
In-Reply-To: <1407261537-11308-1-git-send-email-greearb@candelatech.com>
 (greearb@candelatech.com's message of "Tue, 5 Aug 2014 10:58:57
 -0700")
References: <1407261537-11308-1-git-send-email-greearb@candelatech.com>
Message-ID: <87zjehjkmg.fsf@kamboji.qca.qualcomm.com>

Hi,

This was "[PATCH] ath10k: Support 32+ stations." but I'll change the
subject as this a bigger discussion. I'll also drop linux-wireless for
now, I assume they are not interested about our discussion how to manage
firmware interfaces.

greearb at candelatech.com writes:

> From: Ben Greear <greearb at candelatech.com>
>
> Implement 64-bit vdev map to support larger numbers
> of virtual devices.  Support up to 32 stations
> (actual limit will be determined when loading firmware,
> as different firmwares have different limits)
>
> Enable larger limits when using Candela Technologies
> firmware.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>

So what this firmware does is that it changes these values:

> +/* Over-rides for Candela Technologies firmware */
> +#define TARGET_10X_NUM_VDEVS_CT			32
> +#define TARGET_10X_NUM_PEERS_CT			(32 + (TARGET_10X_NUM_VDEVS_CT))
> +#define TARGET_10X_AST_SKID_LIMIT_CT		(TARGET_10X_NUM_PEERS_CT * TARGET_10X_NUM_PEER_AST)

I think it would be better to provide these through FW IEs, one u32 for
each. I guess we need one also for the skid limit? That way it's easier
to maintain this in ath10k.

Of course that would mean we have to create struct ieee80211_iface_limit
and struct ieee80211_iface_combination runtime, instead of statically
how it's done now. But shouldn't be a problem, right?

Also I have been thinking that using firmware feature bits (for example
ATH10K_FW_FEATURE_WMI_10_2 and ATH10K_FW_FEATURE_WMI_10X) for WMI
version is not the best way. I think it's easier to manage all this if
we have a u32 FW IE to provide WMI version. IIRC Ben was suggesting this
at some point.

Example:

enum ath10k_fw_wmi_version {
	ATH10K_FW_WMI_VERSION_MAIN = 0,
	ATH10K_FW_WMI_VERSION_10_1 = 1,
	ATH10K_FW_WMI_VERSION_10_2 = 2,
}

And then wmi.c would set correct interface based on this version.

We would still use feature bits to enable and disable smaller changes
like ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX does. But for bigger WMI changes
we would change the WMI version, for example if we have a new firmware
branch with significant changes or similar.

And for backwards comptability we need to do so that
ATH10K_FW_FEATURE_WMI_10X sets ATH10K_FW_WMI_VERSION_10_1 and
ATH10K_FW_FEATURE_WMI_10_2 sets ATH10K_FW_WMI_VERSION_10_2.

Thoughts?

-- 
Kalle Valo


From greearb at candelatech.com  Wed Sep  3 08:00:41 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 03 Sep 2014 08:00:41 -0700
Subject: WMI version handling
In-Reply-To: <87zjehjkmg.fsf@kamboji.qca.qualcomm.com>
References: <1407261537-11308-1-git-send-email-greearb@candelatech.com>
 <87zjehjkmg.fsf@kamboji.qca.qualcomm.com>
Message-ID: <54072D19.7010809@candelatech.com>

On 09/02/2014 11:14 PM, Kalle Valo wrote:
> Hi,
> 
> This was "[PATCH] ath10k: Support 32+ stations." but I'll change the
> subject as this a bigger discussion. I'll also drop linux-wireless for
> now, I assume they are not interested about our discussion how to manage
> firmware interfaces.
> 
> greearb at candelatech.com writes:
> 
>> From: Ben Greear <greearb at candelatech.com>
>>
>> Implement 64-bit vdev map to support larger numbers
>> of virtual devices.  Support up to 32 stations
>> (actual limit will be determined when loading firmware,
>> as different firmwares have different limits)
>>
>> Enable larger limits when using Candela Technologies
>> firmware.
>>
>> Signed-off-by: Ben Greear <greearb at candelatech.com>
> 
> So what this firmware does is that it changes these values:
> 
>> +/* Over-rides for Candela Technologies firmware */
>> +#define TARGET_10X_NUM_VDEVS_CT			32
>> +#define TARGET_10X_NUM_PEERS_CT			(32 + (TARGET_10X_NUM_VDEVS_CT))
>> +#define TARGET_10X_AST_SKID_LIMIT_CT		(TARGET_10X_NUM_PEERS_CT * TARGET_10X_NUM_PEER_AST)

My firmware really makes better use of resources and is able to deal better with
a wider range of configured values.

For a full list of ath10k patches that I hope to someday submit, see:

http://dmz2.candelatech.com/git/gitweb.cgi?p=linux.ath/.git;a=summary

Towards the end, I have patches to configure number of stations with
kernel module variable.  I think at a minimum, should be able to configure
peer count as well.

> I think it would be better to provide these through FW IEs, one u32 for
> each. I guess we need one also for the skid limit? That way it's easier
> to maintain this in ath10k.

Skid limit should depend on the others.  If you get unlucky with hashes,
or an attacker figures out how to do so artificially, then you can crash
upstream ath10k firmware by associating more than skid-limit stations.

> Of course that would mean we have to create struct ieee80211_iface_limit
> and struct ieee80211_iface_combination runtime, instead of statically
> how it's done now. But shouldn't be a problem, right?

Yes, I do that later in my patch series.  It works, my patches as written
may need some changes as I had to remove some const markings that might not
be acceptable upstream.

> Also I have been thinking that using firmware feature bits (for example
> ATH10K_FW_FEATURE_WMI_10_2 and ATH10K_FW_FEATURE_WMI_10X) for WMI
> version is not the best way. I think it's easier to manage all this if
> we have a u32 FW IE to provide WMI version. IIRC Ben was suggesting this
> at some point.
> 
> Example:
> 
> enum ath10k_fw_wmi_version {
> 	ATH10K_FW_WMI_VERSION_MAIN = 0,
> 	ATH10K_FW_WMI_VERSION_10_1 = 1,
> 	ATH10K_FW_WMI_VERSION_10_2 = 2,
> }
> 
> And then wmi.c would set correct interface based on this version.

I am happy with the current flags, it seems to work well enough.
I'd leave policy out of the IEs as much as possible, as normal users
cannot modify it, and certainly it would be a problem if you wanted
different policy with different NICs in same system.
IEs should describe the minimum needed for the
ath10k to enforce policy as best as it can.  We have to assume that
users tweaking station and peer count can deal with fw crashes until
they get the settings right.

My CT firmware will print out available RAM once booted, so it is
fairly easy to utilize maximum amount of resources with a bit of
trial and error.  It would be trivial to make upstream firmware do
the same, of course, but upstream firmware may crash for other
reasons as you change resource config...

> We would still use feature bits to enable and disable smaller changes
> like ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX does. But for bigger WMI changes
> we would change the WMI version, for example if we have a new firmware
> branch with significant changes or similar.
> 
> And for backwards comptability we need to do so that
> ATH10K_FW_FEATURE_WMI_10X sets ATH10K_FW_WMI_VERSION_10_1 and
> ATH10K_FW_FEATURE_WMI_10_2 sets ATH10K_FW_WMI_VERSION_10_2.

I was able to do all of my changes w/out needing new a new WMI version,
and I think that is the right approach.  I do not like large amounts of
duplicated code and table lookups, which is what new WMI versions appear
to imply.

I'd prefer to keep IEs generally as they are now (in my firmware,
at least), and allow changing number of peers, stations, etc through debugfs
and/or kernel modules.  Just restart the firmware when users have completed
the config changes.  Don't assume ath10k can properly limit all configurables
to keep firmware from crashing, but give users enough info (ie, RAM usage),
that they can deal with it themselves.  Normal users will never need to know
about or change the configurables anyway, but those building APs can tweak
as needed.

If QCA goes to more of a rolling release for firmware, like I do for CT
firmware, then we may want to add IEs a bit more often, to notify things like
"can-support-feature-foo".  10.2 v/s 10.1 can still determine the
over-all WMI api, perhaps, but at specific points we can take advantage of
specific firmware features based on IE flag.

Thanks,
Ben

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



From michal.kazior at tieto.com  Wed Sep  3 23:56:15 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 4 Sep 2014 08:56:15 +0200
Subject: WMI version handling
In-Reply-To: <54072D19.7010809@candelatech.com>
References: <1407261537-11308-1-git-send-email-greearb@candelatech.com>
 <87zjehjkmg.fsf@kamboji.qca.qualcomm.com>
 <54072D19.7010809@candelatech.com>
Message-ID: <CA+BoTQkbLRpAvmjVEvjCqwTnk9XqFeWOxhr1cpQSuvtVm898tw@mail.gmail.com>

On 3 September 2014 17:00, Ben Greear <greearb at candelatech.com> wrote:
> On 09/02/2014 11:14 PM, Kalle Valo wrote:
>> Hi,
[...]
>> Also I have been thinking that using firmware feature bits (for example
>> ATH10K_FW_FEATURE_WMI_10_2 and ATH10K_FW_FEATURE_WMI_10X) for WMI
>> version is not the best way. I think it's easier to manage all this if
>> we have a u32 FW IE to provide WMI version. IIRC Ben was suggesting this
>> at some point.
>>
>> Example:
>>
>> enum ath10k_fw_wmi_version {
>>       ATH10K_FW_WMI_VERSION_MAIN = 0,
>>       ATH10K_FW_WMI_VERSION_10_1 = 1,
>>       ATH10K_FW_WMI_VERSION_10_2 = 2,
>> }
>>
>> And then wmi.c would set correct interface based on this version.
>
> I am happy with the current flags, it seems to work well enough.

I'm actually okay with this but I'd actually throw out the "wmi"
string from it and leave out just "ath10k_fw_version". I've recently
discovered some minor HTT discrepancies between fw branches so we
might want to use the version tag to pick HTT "backend" as well..


> I'd leave policy out of the IEs as much as possible, as normal users
> cannot modify it, and certainly it would be a problem if you wanted
> different policy with different NICs in same system.
> IEs should describe the minimum needed for the
> ath10k to enforce policy as best as it can.  We have to assume that
> users tweaking station and peer count can deal with fw crashes until
> they get the settings right.
>
> My CT firmware will print out available RAM once booted, so it is
> fairly easy to utilize maximum amount of resources with a bit of
> trial and error.  It would be trivial to make upstream firmware do
> the same, of course, but upstream firmware may crash for other
> reasons as you change resource config...

IOW You're okay if ath10k applies default/hardcoded configuration
values of 10.1 for your firmware (as your firmware is going to
advertise as a 10.1) - is that correct? You just want to be able to
tune these values per-device in runtime. I think debugfs is the best
candidate here then.

ath10k would need to have a separate debugfs entry for that then, i.e.
one that is independent from wiphy. You could have, e.g.
/sys/kernel/debug/ath10k/pci/0000:04:00.0/num_peers which re-registers
to mac80211 upon modification.


>> We would still use feature bits to enable and disable smaller changes
>> like ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX does. But for bigger WMI changes
>> we would change the WMI version, for example if we have a new firmware
>> branch with significant changes or similar.
>>
>> And for backwards comptability we need to do so that
>> ATH10K_FW_FEATURE_WMI_10X sets ATH10K_FW_WMI_VERSION_10_1 and
>> ATH10K_FW_FEATURE_WMI_10_2 sets ATH10K_FW_WMI_VERSION_10_2.
>
> I was able to do all of my changes w/out needing new a new WMI version,
> and I think that is the right approach.  I do not like large amounts of
> duplicated code and table lookups, which is what new WMI versions appear
> to imply.

It's actually really simple to update WMI in an ABI-safe way.
Unfortunately official firmware updates break it fairly often and we
have to deal with that. Aaand there's going to be another WMI backend
soon most likely.


[...]
> If QCA goes to more of a rolling release for firmware, like I do for CT
> firmware, then we may want to add IEs a bit more often, to notify things like
> "can-support-feature-foo".  10.2 v/s 10.1 can still determine the
> over-all WMI api, perhaps, but at specific points we can take advantage of
> specific firmware features based on IE flag.

This is what WMI bitmap service is actually for. ath10k is ignoring
this now and exposes it via debugfs only. It's possible to, e.g. pick
"max num of stations" configuration values based on the "iram tids"
being set or not.


Micha?


From michal.kazior at tieto.com  Thu Sep  4 00:13:08 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu,  4 Sep 2014 09:13:08 +0200
Subject: [PATCH] ath10k: move fw_crash_dump allocation
Message-ID: <1409814788-1661-1-git-send-email-michal.kazior@tieto.com>

The fw_crash_data was allocated too late. Upon
early firmware crash, before registering to
mac80211, it was possible to crash the whole
system:

 ath10k_pci 0000:00:05.0: device has crashed during init
 BUG: unable to handle kernel NULL pointer dereference at           (null)
 IP: [<ffffffffa0058005>] ath10k_debug_get_new_fw_crash_data+0x15/0x30 [ath10k_core]
 PGD 0
 Oops: 0002 [#1] SMP
 Modules linked in: ath10k_pci(O) ath10k_core(O) ath [last unloaded: ath]
 CPU: 3 PID: 29 Comm: kworker/u8:1 Tainted: G           O   3.17.0-rc2-wl-ath+ #447
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
 Workqueue: ath10k_wq ath10k_core_register_work [ath10k_core]
 task: ffff88001eb01ad0 ti: ffff88001eb60000 task.ti: ffff88001eb60000
 RIP: 0010:[<ffffffffa0058005>]  [<ffffffffa0058005>] ath10k_debug_get_new_fw_crash_data+0x15/0x30 [ath10k_core]
 RSP: 0018:ffff88001eb63ce8  EFLAGS: 00010246
 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
 RDX: 0000000000000000 RSI: ffffc90001a09030 RDI: 0000000000000001
 RBP: ffff88001eb63cf0 R08: 0000000000000000 R09: ffff8800000bb200
 R10: 00000000000001e2 R11: ffff88001eb638de R12: ffff88001d7459a0
 R13: ffff88001d746ab0 R14: 00000000fffe14d4 R15: ffff88001d747c60
 FS:  0000000000000000(0000) GS:ffff88001fd80000(0000) knlGS:0000000000000000
 CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
 CR2: 0000000000000000 CR3: 000000001df34000 CR4: 00000000000006e0
 Stack:
  ffff88001d7459a0 ffff88001eb63d58 ffffffffa0083bbe ffff880000000010
  ffff88001eb63d68 ffff88001eb63d18 0000000000000002 0000000000059010
  ffffffffa0086fef 00000000deadbeef ffff88001d747a28 ffff88001d7459a0
 Call Trace:
  [<ffffffffa0083bbe>] ath10k_pci_fw_crashed_dump+0x2e/0xd0 [ath10k_pci]
  [<ffffffffa0085410>] __ath10k_pci_hif_power_up+0x5f0/0x700 [ath10k_pci]
  [<ffffffffa0085550>] ath10k_pci_hif_power_up+0x30/0xe0 [ath10k_pci]
  [<ffffffffa005bc7b>] ath10k_core_register_work+0x2b/0x520 [ath10k_core]
  [<ffffffff810689cc>] process_one_work+0x18c/0x3f0
  [<ffffffff81069011>] worker_thread+0x121/0x4a0
  [<ffffffff81068ef0>] ? rescuer_thread+0x2c0/0x2c0
  [<ffffffff8106daf2>] kthread+0xd2/0xf0
  [<ffffffff8106da20>] ? kthread_create_on_node+0x170/0x170
  [<ffffffff81857cfc>] ret_from_fork+0x7c/0xb0
  [<ffffffff8106da20>] ? kthread_create_on_node+0x170/0x170
 Code: 8b 40 38 48 c7 80 00 01 00 00 00 00 00 00 5b 5d c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 53 48 8b 9f 90 1d 00 00 48 8d 7b 01 <c6> 03 01 e8 e3 ec 2b e1 48 8d 7b 18 e8 6a 4f 05 e1 48 89 d8 5b
 RIP  [<ffffffffa0058005>] ath10k_debug_get_new_fw_crash_data+0x15/0x30 [ath10k_core]
  RSP <ffff88001eb63ce8>
 CR2: 0000000000000000
 ---[ end trace 5d0ed15b050bcc1f ]---
 Kernel panic - not syncing: Fatal exception in interrupt
 Kernel Offset: 0x0 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffff9fffffff)
 ---[ end Kernel panic - not syncing: Fatal exception in interrupt

To prevent that split debug functions and allocate
fw_crash_data earlier.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.c  | 18 +++++++++++++----
 drivers/net/wireless/ath/ath10k/debug.c | 34 ++++++++++++++++-----------------
 drivers/net/wireless/ath/ath10k/debug.h | 11 +++++++++++
 3 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 651a6da..eadb225 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -977,7 +977,7 @@ static void ath10k_core_register_work(struct work_struct *work)
 		goto err_release_fw;
 	}
 
-	status = ath10k_debug_create(ar);
+	status = ath10k_debug_register(ar);
 	if (status) {
 		ath10k_err(ar, "unable to initialize debugfs\n");
 		goto err_unregister_mac;
@@ -1043,7 +1043,7 @@ void ath10k_core_unregister(struct ath10k *ar)
 
 	ath10k_core_free_firmware_files(ar);
 
-	ath10k_debug_destroy(ar);
+	ath10k_debug_unregister(ar);
 }
 EXPORT_SYMBOL(ath10k_core_unregister);
 
@@ -1051,6 +1051,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 				  const struct ath10k_hif_ops *hif_ops)
 {
 	struct ath10k *ar;
+	int ret;
 
 	ar = ath10k_mac_create(priv_size);
 	if (!ar)
@@ -1076,7 +1077,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 
 	ar->workqueue = create_singlethread_workqueue("ath10k_wq");
 	if (!ar->workqueue)
-		goto err_wq;
+		goto err_free_mac;
 
 	mutex_init(&ar->conf_mutex);
 	spin_lock_init(&ar->data_lock);
@@ -1094,10 +1095,18 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 	INIT_WORK(&ar->register_work, ath10k_core_register_work);
 	INIT_WORK(&ar->restart_work, ath10k_core_restart);
 
+	ret = ath10k_debug_create(ar);
+	if (ret)
+		goto err_free_wq;
+
 	return ar;
 
-err_wq:
+err_free_wq:
+	destroy_workqueue(ar->workqueue);
+
+err_free_mac:
 	ath10k_mac_destroy(ar);
+
 	return NULL;
 }
 EXPORT_SYMBOL(ath10k_core_create);
@@ -1107,6 +1116,7 @@ void ath10k_core_destroy(struct ath10k *ar)
 	flush_workqueue(ar->workqueue);
 	destroy_workqueue(ar->workqueue);
 
+	ath10k_debug_destroy(ar);
 	ath10k_mac_destroy(ar);
 }
 EXPORT_SYMBOL(ath10k_core_destroy);
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index d922ef4..966784a 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1132,20 +1132,25 @@ static const struct file_operations fops_dfs_stats = {
 
 int ath10k_debug_create(struct ath10k *ar)
 {
-	int ret;
-
 	ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
-	if (!ar->debug.fw_crash_data) {
-		ret = -ENOMEM;
-		goto err;
-	}
+	if (!ar->debug.fw_crash_data)
+		return -ENOMEM;
 
+	return 0;
+}
+
+void ath10k_debug_destroy(struct ath10k *ar)
+{
+	vfree(ar->debug.fw_crash_data);
+	ar->debug.fw_crash_data = NULL;
+}
+
+int ath10k_debug_register(struct ath10k *ar)
+{
 	ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
 						   ar->hw->wiphy->debugfsdir);
-	if (!ar->debug.debugfs_phy) {
-		ret = -ENOMEM;
-		goto err_free_fw_crash_data;
-	}
+	if (!ar->debug.debugfs_phy)
+		return -ENOMEM;
 
 	INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
 			  ath10k_debug_htt_stats_dwork);
@@ -1192,17 +1197,10 @@ int ath10k_debug_create(struct ath10k *ar)
 	}
 
 	return 0;
-
-err_free_fw_crash_data:
-	vfree(ar->debug.fw_crash_data);
-
-err:
-	return ret;
 }
 
-void ath10k_debug_destroy(struct ath10k *ar)
+void ath10k_debug_unregister(struct ath10k *ar)
 {
-	vfree(ar->debug.fw_crash_data);
 	cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 5674653..71c8084 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -49,6 +49,8 @@ int ath10k_debug_start(struct ath10k *ar);
 void ath10k_debug_stop(struct ath10k *ar);
 int ath10k_debug_create(struct ath10k *ar);
 void ath10k_debug_destroy(struct ath10k *ar);
+int ath10k_debug_register(struct ath10k *ar);
+void ath10k_debug_unregister(struct ath10k *ar);
 void ath10k_debug_read_service_map(struct ath10k *ar,
 				   void *service_map,
 				   size_t map_size);
@@ -80,6 +82,15 @@ static inline void ath10k_debug_destroy(struct ath10k *ar)
 {
 }
 
+static inline int ath10k_debug_register(struct ath10k *ar)
+{
+	return 0;
+}
+
+static inline void ath10k_debug_unregister(struct ath10k *ar)
+{
+}
+
 static inline void ath10k_debug_read_service_map(struct ath10k *ar,
 						 void *service_map,
 						 size_t map_size)
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep  4 01:16:40 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 4 Sep 2014 10:16:40 +0200
Subject: Timeout Issues
In-Reply-To: <CAD1M060R0x021Rw=mviL54PVH=KS5vnTZBHpUog=fJX007r7Gw@mail.gmail.com>
References: <CAD1M062MNW7y_hf+5btNA14xt9K69TqQy=Q-rCm+2xuHCZDEsA@mail.gmail.com>
 <53F39AB3.10601@candelatech.com>
 <CAD1M062FPxZyj86LvvaomwR3z2KeScnYDCNT_g6zMQzK10+vxA@mail.gmail.com>
 <87zjez7m7t.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQn1EiwajmmymkLSM6Nm0pJFOKqo89L4ZUiw6TGbQ-Cv_w@mail.gmail.com>
 <CAD1M060R0x021Rw=mviL54PVH=KS5vnTZBHpUog=fJX007r7Gw@mail.gmail.com>
Message-ID: <CA+BoTQnr5R+shHJ0ikXKbhVfhJ_92J_3Db8tNE8+U1kChpQgEg@mail.gmail.com>

On 2 September 2014 20:51, Pushpal Sidhu <psidhu at gateworks.com> wrote:
> Sorry for the amazingly late reply, other things crept into my schedule.
[...]
>
> The board has 9 port PCI-e switch behind the RC. I did, however, use
> the same slot. I found that there was always 1 interrupt, but never
> any more. This made me think a bit more and found that if I set
> PCI_MSI=n in the kernel config, the problem 'goes away' and I see
> increasing number of interrupts and do not see anymore of the '-110'
> error messages. This issue, for me, is solved as I don't necessary
> need mixed signaled interrupts, but I'm unsure of why this is
> happening and what is different about the Intel 7260HMW card from the
> Atheros cards or in their respective drivers.

Hmm.. Your original logs suggest ath10k was already running in
legacy/shared irq mode before which means it already tried MSI and
failed:

> [    5.233469] ath10k_pci 0000:09:00.0: enabling device (0140 -> 0142)
> [    5.575954] ath10k: pci irq legacy irq_mode 0 reset_mode 0

I wonder if the Intel card succeeds to pci_enable_msi(). Perhaps this
is a bug with QCA988X failing to recover from a failed MSI negotiation
with the PCI-E controller?

You could try adding irq_mode=1 parameter to ath10k_pci module. This
way you'll force ath10k to use shared interrupts without even trying
to go through MSI->shared failover and if I'm right you won't need the
PCI_MSI=n in your kernel.


Micha?


From michal.kazior at tieto.com  Thu Sep  4 01:18:32 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu,  4 Sep 2014 10:18:32 +0200
Subject: [PATCH] ath10k: use proper service bitmap size
Message-ID: <1409818712-7493-1-git-send-email-michal.kazior@tieto.com>

On 32bit systems the bitmap was too small and it
was overwritten partially by the stat completion
structure. This was visible with 10.2 firmware
only due to it using a few of the last service
ids.

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 |  2 +-
 drivers/net/wireless/ath/ath10k/wmi.c   |  4 ++--
 drivers/net/wireless/ath/ath10k/wmi.h   | 12 +++++-------
 4 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 797741d..a2695e3 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -293,7 +293,7 @@ struct ath10k_debug {
 	struct dentry *debugfs_phy;
 
 	struct ath10k_target_stats target_stats;
-	DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_BM_SIZE);
+	DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
 
 	struct completion event_stats_compl;
 
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index d922ef4..e487064 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -208,7 +208,7 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
 	if (len > buf_len)
 		len = buf_len;
 
-	for (i = 0; i < WMI_MAX_SERVICE; i++) {
+	for (i = 0; i < WMI_SERVICE_MAX; i++) {
 		enabled = test_bit(i, ar->debug.wmi_service_bitmap);
 		name = wmi_service_name(i);
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index b13ccf6..e7edc89 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2164,7 +2164,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) = {};
+	DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
 
 	if (skb->len < sizeof(*ev)) {
 		ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
@@ -2241,7 +2241,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) = {};
+	DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
 
 	if (skb->len < sizeof(*ev)) {
 		ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index e708365..bdb2e6c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -109,6 +109,9 @@ enum wmi_service {
 	WMI_SERVICE_BURST,
 	WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT,
 	WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT,
+
+	/* keep last */
+	WMI_SERVICE_MAX,
 };
 
 enum wmi_10x_service {
@@ -219,8 +222,6 @@ static inline char *wmi_service_name(int service_id)
 #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))))
@@ -347,9 +348,6 @@ static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out)
 
 #undef SVCMAP
 
-#define WMI_SERVICE_BM_SIZE \
-	((WMI_MAX_SERVICE + sizeof(u32) - 1)/sizeof(u32))
-
 /* 2 word representation of MAC addr */
 struct wmi_mac_addr {
 	union {
@@ -1405,7 +1403,7 @@ struct wmi_service_ready_event {
 	__le32 phy_capability;
 	/* Maximum number of frag table entries that SW will populate less 1 */
 	__le32 max_frag_entry;
-	__le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE];
+	__le32 wmi_service_bitmap[16];
 	__le32 num_rf_chains;
 	/*
 	 * The following field is only valid for service type
@@ -1444,7 +1442,7 @@ struct wmi_service_ready_event_10x {
 
 	/* Maximum number of frag table entries that SW will populate less 1 */
 	__le32 max_frag_entry;
-	__le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE];
+	__le32 wmi_service_bitmap[16];
 	__le32 num_rf_chains;
 
 	/*
-- 
1.8.5.3



From matteo at openwrt.org  Thu Sep  4 01:50:39 2014
From: matteo at openwrt.org (Matteo Croce)
Date: Thu, 4 Sep 2014 10:50:39 +0200
Subject: [PATCH] ath10k: ATH10K_DEBUGFS depends on DEBUG_FS
Message-ID: <CAFnufp1Rg2JOLM4d6g_=uF+Nrydt0Wy_4DK85bnqNHkthD9zQw@mail.gmail.com>

enable ath10k debugfs only when debugfs is enabled,
fixes an invalid pointer on module insert

--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -24,7 +24,7 @@ config ATH10K_DEBUG

 config ATH10K_DEBUGFS
  bool "Atheros ath10k debugfs support"
- depends on ATH10K
+ depends on ATH10K && DEBUG_FS
  select RELAY
  ---help---
   Enabled debugfs support


From kvalo at qca.qualcomm.com  Thu Sep  4 03:04:38 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 4 Sep 2014 13:04:38 +0300
Subject: [PATCH] ath10k: ATH10K_DEBUGFS depends on DEBUG_FS
In-Reply-To: <CAFnufp1Rg2JOLM4d6g_=uF+Nrydt0Wy_4DK85bnqNHkthD9zQw@mail.gmail.com>
 (Matteo Croce's message of "Thu, 4 Sep 2014 10:50:39 +0200")
References: <CAFnufp1Rg2JOLM4d6g_=uF+Nrydt0Wy_4DK85bnqNHkthD9zQw@mail.gmail.com>
Message-ID: <87iol3k8g9.fsf@kamboji.qca.qualcomm.com>

Matteo Croce <matteo at openwrt.org> writes:

> enable ath10k debugfs only when debugfs is enabled,
> fixes an invalid pointer on module insert
>
> --- a/drivers/net/wireless/ath/ath10k/Kconfig
> +++ b/drivers/net/wireless/ath/ath10k/Kconfig

This is missing Signed-off-by, so I cannot take this. Please check
Documentation/SubmittingPatches and please resend.

The safest way to submit a patch is to commit with 'git commit -s' and
then submit the commit with 'git send-email'. But first do a trial run
by submitting it to yourself.

-- 
Kalle Valo


From michal.kazior at tieto.com  Thu Sep  4 03:30:46 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu,  4 Sep 2014 12:30:46 +0200
Subject: [PATCH] amenth10k: fix debugfs_create_dir() checking
Message-ID: <1409826646-23269-1-git-send-email-michal.kazior@tieto.com>

The function may return an -ENODEV if debugfs is
disabled in kernel. This should originally be
guarded by ath10k's Kconfig but it still makes
sense to check for the non-NULL errno return
value.

Either this or a Kconfig patch prevents from a
kernel oops due to invalid pointer dereference:

 BUG: unable to handle kernel NULL pointer dereference at 000000000000001d
 IP: [<ffffffff810d4423>] relay_open_buf.part.9+0x1a3/0x2d0
 PGD 0
 Oops: 0000 [#1] SMP
 Modules linked in: ath10k_pci ath10k_core ath
 CPU: 1 PID: 6 Comm: kworker/u8:0 Tainted: G        W      3.17.0-rc2-wl-ath+ #448
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
 Workqueue: ath10k_wq ath10k_core_register_work [ath10k_core]
 task: ffff88001e94abc0 ti: ffff88001e988000 task.ti: ffff88001e988000
 RIP: 0010:[<ffffffff810d4423>]  [<ffffffff810d4423>] relay_open_buf.part.9+0x1a3/0x2d0
 RSP: 0018:ffff88001e98bd40  EFLAGS: 00010286
 RAX: ffffffffffffffed RBX: ffffc90000a01000 RCX: 0000000000001473
 RDX: 0000000000000000 RSI: ffffffffffffffed RDI: ffff88001d4b1d00
 RBP: ffff88001e98bd80 R08: 0000000000014860 R09: ffff88001fc94860
 R10: ffffea0000752c40 R11: ffff88001e801700 R12: 0000000000000040
 R13: 0000000000000200 R14: ffff88001d5b8800 R15: ffff88001d4b1e00
 FS:  0000000000000000(0000) GS:ffff88001fc80000(0000) knlGS:0000000000000000
 CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
 CR2: 000000000000001d CR3: 000000001d4bd000 CR4: 00000000000006e0
 Stack:
  000000001e98bda8 0000000000000040 ffff88001d5b8800 ffff88001d5b8800
  0000000000000000 0000000000000000 ffffffff81c96690 ffffffffa0025997
  ffff88001e98bdc8 ffffffff810d47bf 0000000000000000 ffffffffffffffed
 Call Trace:
  [<ffffffff810d47bf>] relay_open+0x17f/0x2c0
  [<ffffffffa001ea0f>] ath10k_spectral_create+0x2f/0x40 [ath10k_core]
  [<ffffffffa0012ff8>] ath10k_core_register_work+0x318/0x520 [ath10k_core]
  [<ffffffff810619d9>] process_one_work+0x169/0x390
  [<ffffffff810626a9>] worker_thread+0x119/0x490
  [<ffffffff81062590>] ? rescuer_thread+0x2b0/0x2b0
  [<ffffffff81066efd>] kthread+0xcd/0xf0
  [<ffffffff81066e30>] ? kthread_create_on_node+0x170/0x170
  [<ffffffff8179137c>] ret_from_fork+0x7c/0xb0
  [<ffffffff81066e30>] ? kthread_create_on_node+0x170/0x170
 Code: 00 85 c0 74 2e 8b 55 c4 48 8b 7d d0 4c 89 fe e8 d4 fd ff ff 48 85 c0 0f 84 12 01 00 00 49 89 87 98 00 00 00 49 8b 97 d0 00 00 00 <48> 8b 40 30 48 89 50 50 8b 45 c4 be 01 00 00 00 4c 89 ff 41 89
 RIP  [<ffffffff810d4423>] relay_open_buf.part.9+0x1a3/0x2d0
  RSP <ffff88001e98bd40>
 CR2: 000000000000001d
 ---[ end trace 2eafd3e96c41b8e2 ]---

Note: Without a Kconfig patch ath10k with
ATH10K_DEBUGFS && !DEBUG_FS will fail and refuse
to register to mac80211.

Reported-by: Matteo Croce <matteo at openwrt.org>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
@Kalle:

 - this patch prevents kernel oops but ath10k will
   fail to load

 - Matteo's patch prevents kernel oops and ath10k
   will load fine

Since mine is just an extra precaution feel free
to drop all but the first paragraph of my commit
message if you want to.

 drivers/net/wireless/ath/ath10k/debug.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index d922ef4..ed192a5 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1142,8 +1142,12 @@ int ath10k_debug_create(struct ath10k *ar)
 
 	ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
 						   ar->hw->wiphy->debugfsdir);
-	if (!ar->debug.debugfs_phy) {
-		ret = -ENOMEM;
+	if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
+		if (IS_ERR(ar->debug.debugfs_phy))
+			ret = PTR_ERR(ar->debug.debugfs_phy);
+		else
+			ret = -ENOMEM;
+
 		goto err_free_fw_crash_data;
 	}
 
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep  4 03:32:36 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu,  4 Sep 2014 12:32:36 +0200
Subject: [PATCH v2] ath10k: fix debugfs_create_dir() checking
Message-ID: <1409826756-3609-1-git-send-email-michal.kazior@tieto.com>

The function may return an -ENODEV if debugfs is
disabled in kernel. This should originally be
guarded by ath10k's Kconfig but it still makes
sense to check for the non-NULL errno return
value.

Either this or a Kconfig patch prevents from a
kernel oops due to invalid pointer dereference:

 BUG: unable to handle kernel NULL pointer dereference at 000000000000001d
 IP: [<ffffffff810d4423>] relay_open_buf.part.9+0x1a3/0x2d0
 PGD 0
 Oops: 0000 [#1] SMP
 Modules linked in: ath10k_pci ath10k_core ath
 CPU: 1 PID: 6 Comm: kworker/u8:0 Tainted: G        W      3.17.0-rc2-wl-ath+ #448
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
 Workqueue: ath10k_wq ath10k_core_register_work [ath10k_core]
 task: ffff88001e94abc0 ti: ffff88001e988000 task.ti: ffff88001e988000
 RIP: 0010:[<ffffffff810d4423>]  [<ffffffff810d4423>] relay_open_buf.part.9+0x1a3/0x2d0
 RSP: 0018:ffff88001e98bd40  EFLAGS: 00010286
 RAX: ffffffffffffffed RBX: ffffc90000a01000 RCX: 0000000000001473
 RDX: 0000000000000000 RSI: ffffffffffffffed RDI: ffff88001d4b1d00
 RBP: ffff88001e98bd80 R08: 0000000000014860 R09: ffff88001fc94860
 R10: ffffea0000752c40 R11: ffff88001e801700 R12: 0000000000000040
 R13: 0000000000000200 R14: ffff88001d5b8800 R15: ffff88001d4b1e00
 FS:  0000000000000000(0000) GS:ffff88001fc80000(0000) knlGS:0000000000000000
 CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
 CR2: 000000000000001d CR3: 000000001d4bd000 CR4: 00000000000006e0
 Stack:
  000000001e98bda8 0000000000000040 ffff88001d5b8800 ffff88001d5b8800
  0000000000000000 0000000000000000 ffffffff81c96690 ffffffffa0025997
  ffff88001e98bdc8 ffffffff810d47bf 0000000000000000 ffffffffffffffed
 Call Trace:
  [<ffffffff810d47bf>] relay_open+0x17f/0x2c0
  [<ffffffffa001ea0f>] ath10k_spectral_create+0x2f/0x40 [ath10k_core]
  [<ffffffffa0012ff8>] ath10k_core_register_work+0x318/0x520 [ath10k_core]
  [<ffffffff810619d9>] process_one_work+0x169/0x390
  [<ffffffff810626a9>] worker_thread+0x119/0x490
  [<ffffffff81062590>] ? rescuer_thread+0x2b0/0x2b0
  [<ffffffff81066efd>] kthread+0xcd/0xf0
  [<ffffffff81066e30>] ? kthread_create_on_node+0x170/0x170
  [<ffffffff8179137c>] ret_from_fork+0x7c/0xb0
  [<ffffffff81066e30>] ? kthread_create_on_node+0x170/0x170
 Code: 00 85 c0 74 2e 8b 55 c4 48 8b 7d d0 4c 89 fe e8 d4 fd ff ff 48 85 c0 0f 84 12 01 00 00 49 89 87 98 00 00 00 49 8b 97 d0 00 00 00 <48> 8b 40 30 48 89 50 50 8b 45 c4 be 01 00 00 00 4c 89 ff 41 89
 RIP  [<ffffffff810d4423>] relay_open_buf.part.9+0x1a3/0x2d0
  RSP <ffff88001e98bd40>
 CR2: 000000000000001d
 ---[ end trace 2eafd3e96c41b8e2 ]---

Note: Without a Kconfig patch ath10k with
ATH10K_DEBUGFS && !DEBUG_FS will fail and refuse
to register to mac80211.

Reported-by: Matteo Croce <matteo at openwrt.org>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---

Notes:
    v2:
     * fix commit subject (sorry for the noise!)

@Kalle:

 - this patch prevents kernel oops but ath10k will
   fail to load

 - Matteo's patch prevents kernel oops and ath10k
   will load fine

Since mine is just an extra precaution feel free
to drop all but the first paragraph of my commit
message if you want to.


 drivers/net/wireless/ath/ath10k/Kconfig | 2 +-
 drivers/net/wireless/ath/ath10k/debug.c | 8 ++++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index 1053bb5..72acb82 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -24,7 +24,7 @@ config ATH10K_DEBUG
 
 config ATH10K_DEBUGFS
 	bool "Atheros ath10k debugfs support"
-	depends on ATH10K
+	depends on ATH10K && DEBUG_FS
 	select RELAY
 	---help---
 	  Enabled debugfs support
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index d922ef4..ed192a5 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1142,8 +1142,12 @@ int ath10k_debug_create(struct ath10k *ar)
 
 	ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
 						   ar->hw->wiphy->debugfsdir);
-	if (!ar->debug.debugfs_phy) {
-		ret = -ENOMEM;
+	if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
+		if (IS_ERR(ar->debug.debugfs_phy))
+			ret = PTR_ERR(ar->debug.debugfs_phy);
+		else
+			ret = -ENOMEM;
+
 		goto err_free_fw_crash_data;
 	}
 
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep  4 03:36:45 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu,  4 Sep 2014 12:36:45 +0200
Subject: [PATCH v3] ath10k: fix debugfs_create_dir() checking
Message-ID: <1409827005-3777-1-git-send-email-michal.kazior@tieto.com>

The function may return an -ENODEV if debugfs is
disabled in kernel. This should originally be
guarded by ath10k's Kconfig but it still makes
sense to check for the non-NULL errno return
value.

Either this or a Kconfig patch prevents from a
kernel oops due to invalid pointer dereference:

 BUG: unable to handle kernel NULL pointer dereference at 000000000000001d
 IP: [<ffffffff810d4423>] relay_open_buf.part.9+0x1a3/0x2d0
 PGD 0
 Oops: 0000 [#1] SMP
 Modules linked in: ath10k_pci ath10k_core ath
 CPU: 1 PID: 6 Comm: kworker/u8:0 Tainted: G        W      3.17.0-rc2-wl-ath+ #448
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
 Workqueue: ath10k_wq ath10k_core_register_work [ath10k_core]
 task: ffff88001e94abc0 ti: ffff88001e988000 task.ti: ffff88001e988000
 RIP: 0010:[<ffffffff810d4423>]  [<ffffffff810d4423>] relay_open_buf.part.9+0x1a3/0x2d0
 RSP: 0018:ffff88001e98bd40  EFLAGS: 00010286
 RAX: ffffffffffffffed RBX: ffffc90000a01000 RCX: 0000000000001473
 RDX: 0000000000000000 RSI: ffffffffffffffed RDI: ffff88001d4b1d00
 RBP: ffff88001e98bd80 R08: 0000000000014860 R09: ffff88001fc94860
 R10: ffffea0000752c40 R11: ffff88001e801700 R12: 0000000000000040
 R13: 0000000000000200 R14: ffff88001d5b8800 R15: ffff88001d4b1e00
 FS:  0000000000000000(0000) GS:ffff88001fc80000(0000) knlGS:0000000000000000
 CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
 CR2: 000000000000001d CR3: 000000001d4bd000 CR4: 00000000000006e0
 Stack:
  000000001e98bda8 0000000000000040 ffff88001d5b8800 ffff88001d5b8800
  0000000000000000 0000000000000000 ffffffff81c96690 ffffffffa0025997
  ffff88001e98bdc8 ffffffff810d47bf 0000000000000000 ffffffffffffffed
 Call Trace:
  [<ffffffff810d47bf>] relay_open+0x17f/0x2c0
  [<ffffffffa001ea0f>] ath10k_spectral_create+0x2f/0x40 [ath10k_core]
  [<ffffffffa0012ff8>] ath10k_core_register_work+0x318/0x520 [ath10k_core]
  [<ffffffff810619d9>] process_one_work+0x169/0x390
  [<ffffffff810626a9>] worker_thread+0x119/0x490
  [<ffffffff81062590>] ? rescuer_thread+0x2b0/0x2b0
  [<ffffffff81066efd>] kthread+0xcd/0xf0
  [<ffffffff81066e30>] ? kthread_create_on_node+0x170/0x170
  [<ffffffff8179137c>] ret_from_fork+0x7c/0xb0
  [<ffffffff81066e30>] ? kthread_create_on_node+0x170/0x170
 Code: 00 85 c0 74 2e 8b 55 c4 48 8b 7d d0 4c 89 fe e8 d4 fd ff ff 48 85 c0 0f 84 12 01 00 00 49 89 87 98 00 00 00 49 8b 97 d0 00 00 00 <48> 8b 40 30 48 89 50 50 8b 45 c4 be 01 00 00 00 4c 89 ff 41 89
 RIP  [<ffffffff810d4423>] relay_open_buf.part.9+0x1a3/0x2d0
  RSP <ffff88001e98bd40>
 CR2: 000000000000001d
 ---[ end trace 2eafd3e96c41b8e2 ]---

Note: Without a Kconfig patch ath10k with
ATH10K_DEBUGFS && !DEBUG_FS will fail and refuse
to register to mac80211.

Reported-by: Matteo Croce <matteo at openwrt.org>
Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---

Notes:
    v2:
     * fix commit subject (sorry for the noise!)
    
    v3:
     * remove Kconfig patch (I accidentally amended something I shouldn't have,
       sorry for the noise again! I guess I need a break..)

@Kalle:

 - this patch prevents kernel oops but ath10k will
   fail to load

 - Matteo's patch prevents kernel oops and ath10k
   will load fine

Since mine is just an extra precaution feel free
to drop all but the first paragraph of my commit
message if you want to.


 drivers/net/wireless/ath/ath10k/debug.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index d922ef4..ed192a5 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1142,8 +1142,12 @@ int ath10k_debug_create(struct ath10k *ar)
 
 	ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
 						   ar->hw->wiphy->debugfsdir);
-	if (!ar->debug.debugfs_phy) {
-		ret = -ENOMEM;
+	if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
+		if (IS_ERR(ar->debug.debugfs_phy))
+			ret = PTR_ERR(ar->debug.debugfs_phy);
+		else
+			ret = -ENOMEM;
+
 		goto err_free_fw_crash_data;
 	}
 
-- 
1.8.5.3



From matteo at openwrt.org  Thu Sep  4 05:51:09 2014
From: matteo at openwrt.org (Matteo Croce)
Date: Thu,  4 Sep 2014 14:51:09 +0200
Subject: [PATCH] ath10k: ATH10K_DEBUGFS depends on DEBUG_FS
Message-ID: <1409835069-2246-1-git-send-email-matteo@openwrt.org>

ATH10K_DEBUGFS must depend on DEBUG_FS, otherwise
ath10k will generate an invalid pointer on module load

Signed-off-by: Matteo Croce <matteo at openwrt.org>
---
 drivers/net/wireless/ath/ath10k/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index 1053bb5..72acb82 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -24,7 +24,7 @@ config ATH10K_DEBUG
 
 config ATH10K_DEBUGFS
 	bool "Atheros ath10k debugfs support"
-	depends on ATH10K
+	depends on ATH10K && DEBUG_FS
 	select RELAY
 	---help---
 	  Enabled debugfs support
-- 
2.1.0



From kvalo at qca.qualcomm.com  Thu Sep  4 06:56:41 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 04 Sep 2014 16:56:41 +0300
Subject: [PATCH v3 0/2] ath10k: testmode support
Message-ID: <20140904135447.26750.52873.stgit@potku.adurom.net>

Hi,

new version of ath10k testmode support. Only functionality changes were in
ath10k_tm_cmd_utf_start(). The user space interface didn't change from v2.

v3:

* remove false "fall through" comment in ath10k_start() (Michal)

* fix multiline comment style (Michal)

* put testmode interface definitions to testmode_uapi.h (or similar) (Johannes)

* document __set_bit(ar->fw_features) better (Michal)

* ath10k_tm_cmd_utf_start(): return ar->fw_feature value if there's an error

* free firmware in ath10k_tm_cmd_utf_start() when an error happens (Michal)

* ath10k_tm_cmd_utf_start(): move hif_power_down() to err_power_down label


v2:

* check error from ath10k_wmi_alloc_skb() (Michal)

* int err -> int ret (Michal)

* fix conflicts in core.c

* add ar->testmode.utf_monitor to check if ath10k_tm_event_wmi()
  should deliver WMI events or not

* print mode in ath10k_download_fw() log messages

* set ar->testmode.utf to NULL after it's released (Michal)

* release ar->testmode.utf also in ath10k_tm_cmd_utf_stop()

* rename ath10k_testmode_unregister() to ath10k_testmode_destroy()

* call ath10k_core_stop() in ath10k_testmode_destroy() (Michal)

* document wmi packet format in testmode commands (Michal)

* consume WMI packets so that mac80211 calls are not made in UTF mode (Michal)

* force to use 10x WMI interface with UTF firmware

* API change: remove ATH10K_TM_CMD_EVENT_WMI, use ATH10K_TM_CMD_WMI also for events

* API change: add major and minor version numbers to
  ATH10K_TM_CMD_GET_VERSION for the user space more easily to detect
  interface changes

* use conf_mutex in ath10k_tm_cmd_wmi()

* print "UTF firmware started" and "UTF firmware stopped"

* print "testmode %d" in ath10k_print_driver_info()

* don't call ath10k_wait_for_suspend() in UTF mode


---

Kalle Valo (2):
      ath10k: make ath10k_wmi_cmd_send() public
      ath10k: add testmode


 drivers/net/wireless/ath/ath10k/Makefile     |    1 
 drivers/net/wireless/ath/ath10k/core.c       |   88 ++++--
 drivers/net/wireless/ath/ath10k/core.h       |   22 +-
 drivers/net/wireless/ath/ath10k/debug.c      |    5 
 drivers/net/wireless/ath/ath10k/debug.h      |    1 
 drivers/net/wireless/ath/ath10k/hw.h         |    2 
 drivers/net/wireless/ath/ath10k/mac.c        |    9 +
 drivers/net/wireless/ath/ath10k/testmode.c   |  375 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/testmode.h   |   46 +++
 drivers/net/wireless/ath/ath10k/testmode_i.h |   70 +++++
 drivers/net/wireless/ath/ath10k/wmi.c        |   22 +-
 drivers/net/wireless/ath/ath10k/wmi.h        |    4 
 12 files changed, 612 insertions(+), 33 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode.c
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode.h
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode_i.h



From kvalo at qca.qualcomm.com  Thu Sep  4 06:56:48 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 04 Sep 2014 16:56:48 +0300
Subject: [PATCH v3 1/2] ath10k: make ath10k_wmi_cmd_send() public
In-Reply-To: <20140904135447.26750.52873.stgit@potku.adurom.net>
References: <20140904135447.26750.52873.stgit@potku.adurom.net>
Message-ID: <20140904135648.26750.54412.stgit@potku.adurom.net>

We need this function to send wmi packets from testmode.c.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/wmi.c |    5 ++---
 drivers/net/wireless/ath/ath10k/wmi.h |    4 ++++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index b13ccf6778c3..f80959419525 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -624,7 +624,7 @@ int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar)
 	return ret;
 }
 
-static struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len)
+struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len)
 {
 	struct sk_buff *skb;
 	u32 round_len = roundup(len, 4);
@@ -725,8 +725,7 @@ static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar)
 	wake_up(&ar->wmi.tx_credits_wq);
 }
 
-static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
-			       u32 cmd_id)
+int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
 {
 	int ret = -EOPNOTSUPP;
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index e70836586756..8019a0f1edd1 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -4739,6 +4739,10 @@ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
 int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
 
 int ath10k_wmi_connect(struct ath10k *ar);
+
+struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
+int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
+
 int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
 				const struct wmi_channel_arg *);
 int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);



From kvalo at qca.qualcomm.com  Thu Sep  4 06:56:54 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 04 Sep 2014 16:56:54 +0300
Subject: [PATCH v3 2/2] ath10k: add testmode
In-Reply-To: <20140904135447.26750.52873.stgit@potku.adurom.net>
References: <20140904135447.26750.52873.stgit@potku.adurom.net>
Message-ID: <20140904135654.26750.69133.stgit@potku.adurom.net>

Add testmode interface for starting and using UTF firmware which is used to run
factory tests. This is implemented by adding new state ATH10K_STATE_UTF and user
space can enable this state with ATH10K_TM_CMD_UTF_START command. To go back to
normal mode user space can send ATH10K_TM_CMD_UTF_STOP.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/Makefile     |    1 
 drivers/net/wireless/ath/ath10k/core.c       |   88 ++++--
 drivers/net/wireless/ath/ath10k/core.h       |   22 +-
 drivers/net/wireless/ath/ath10k/debug.c      |    5 
 drivers/net/wireless/ath/ath10k/debug.h      |    1 
 drivers/net/wireless/ath/ath10k/hw.h         |    2 
 drivers/net/wireless/ath/ath10k/mac.c        |    9 +
 drivers/net/wireless/ath/ath10k/testmode.c   |  375 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/testmode.h   |   46 +++
 drivers/net/wireless/ath/ath10k/testmode_i.h |   70 +++++
 drivers/net/wireless/ath/ath10k/wmi.c        |   17 +
 11 files changed, 606 insertions(+), 30 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode.c
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode.h
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode_i.h

diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index 2cfb63ca9327..8b1b1adb477a 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -11,6 +11,7 @@ ath10k_core-y += mac.o \
 		 bmi.o
 
 ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
+ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.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 651a6da8adf5..c01a37526ad5 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -26,6 +26,7 @@
 #include "bmi.h"
 #include "debug.h"
 #include "htt.h"
+#include "testmode.h"
 
 unsigned int ath10k_debug_mask;
 static bool uart_print;
@@ -257,21 +258,42 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
 	return 0;
 }
 
-static int ath10k_download_fw(struct ath10k *ar)
+static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
 {
-	u32 address;
+	u32 address, data_len;
+	const char *mode_name;
+	const void *data;
 	int ret;
 
 	address = ar->hw_params.patch_load_addr;
 
-	ret = ath10k_bmi_fast_download(ar, address, ar->firmware_data,
-				       ar->firmware_len);
+	switch (mode) {
+	case ATH10K_FIRMWARE_MODE_NORMAL:
+		data = ar->firmware_data;
+		data_len = ar->firmware_len;
+		mode_name = "normal";
+		break;
+	case ATH10K_FIRMWARE_MODE_UTF:
+		data = ar->testmode.utf->data;
+		data_len = ar->testmode.utf->size;
+		mode_name = "utf";
+		break;
+	default:
+		ath10k_err(ar, "unknown firmware mode: %d\n", mode);
+		return -EINVAL;
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_BOOT,
+		   "boot uploading firmware image %p len %d mode %s\n",
+		   data, data_len, mode_name);
+
+	ret = ath10k_bmi_fast_download(ar, address, data, data_len);
 	if (ret) {
-		ath10k_err(ar, "could not write fw (%d)\n", ret);
-		goto exit;
+		ath10k_err(ar, "failed to download %s firmware: %d\n",
+			   mode_name, ret);
+		return ret;
 	}
 
-exit:
 	return ret;
 }
 
@@ -567,7 +589,8 @@ success:
 	return 0;
 }
 
-static int ath10k_init_download_firmware(struct ath10k *ar)
+static int ath10k_init_download_firmware(struct ath10k *ar,
+					 enum ath10k_firmware_mode mode)
 {
 	int ret;
 
@@ -583,7 +606,7 @@ static int ath10k_init_download_firmware(struct ath10k *ar)
 		return ret;
 	}
 
-	ret = ath10k_download_fw(ar);
+	ret = ath10k_download_fw(ar, mode);
 	if (ret) {
 		ath10k_err(ar, "failed to download firmware: %d\n", ret);
 		return ret;
@@ -685,12 +708,15 @@ static void ath10k_core_restart(struct work_struct *work)
 	case ATH10K_STATE_WEDGED:
 		ath10k_warn(ar, "device is wedged, will not restart\n");
 		break;
+	case ATH10K_STATE_UTF:
+		ath10k_warn(ar, "firmware restart in UTF mode not supported\n");
+		break;
 	}
 
 	mutex_unlock(&ar->conf_mutex);
 }
 
-int ath10k_core_start(struct ath10k *ar)
+int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
 {
 	int status;
 
@@ -703,7 +729,7 @@ int ath10k_core_start(struct ath10k *ar)
 		goto err;
 	}
 
-	status = ath10k_init_download_firmware(ar);
+	status = ath10k_init_download_firmware(ar, mode);
 	if (status)
 		goto err;
 
@@ -760,10 +786,12 @@ int ath10k_core_start(struct ath10k *ar)
 		goto err_hif_stop;
 	}
 
-	status = ath10k_htt_connect(&ar->htt);
-	if (status) {
-		ath10k_err(ar, "failed to connect htt (%d)\n", status);
-		goto err_hif_stop;
+	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+		status = ath10k_htt_connect(&ar->htt);
+		if (status) {
+			ath10k_err(ar, "failed to connect htt (%d)\n", status);
+			goto err_hif_stop;
+		}
 	}
 
 	status = ath10k_wmi_connect(ar);
@@ -778,11 +806,13 @@ int ath10k_core_start(struct ath10k *ar)
 		goto err_hif_stop;
 	}
 
-	status = ath10k_wmi_wait_for_service_ready(ar);
-	if (status <= 0) {
-		ath10k_warn(ar, "wmi service ready event not received");
-		status = -ETIMEDOUT;
-		goto err_hif_stop;
+	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+		status = ath10k_wmi_wait_for_service_ready(ar);
+		if (status <= 0) {
+			ath10k_warn(ar, "wmi service ready event not received");
+			status = -ETIMEDOUT;
+			goto err_hif_stop;
+		}
 	}
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
@@ -802,10 +832,13 @@ int ath10k_core_start(struct ath10k *ar)
 		goto err_hif_stop;
 	}
 
-	status = ath10k_htt_setup(&ar->htt);
-	if (status) {
-		ath10k_err(ar, "failed to setup htt: %d\n", status);
-		goto err_hif_stop;
+	/* we don't care about HTT in UTF mode */
+	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+		status = ath10k_htt_setup(&ar->htt);
+		if (status) {
+			ath10k_err(ar, "failed to setup htt: %d\n", status);
+			goto err_hif_stop;
+		}
 	}
 
 	status = ath10k_debug_start(ar);
@@ -861,7 +894,8 @@ void ath10k_core_stop(struct ath10k *ar)
 	lockdep_assert_held(&ar->conf_mutex);
 
 	/* try to suspend target */
-	if (ar->state != ATH10K_STATE_RESTARTING)
+	if (ar->state != ATH10K_STATE_RESTARTING &&
+	    ar->state != ATH10K_STATE_UTF)
 		ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
 
 	ath10k_debug_stop(ar);
@@ -914,7 +948,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 
 	mutex_lock(&ar->conf_mutex);
 
-	ret = ath10k_core_start(ar);
+	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
 	if (ret) {
 		ath10k_err(ar, "could not init core (%d)\n", ret);
 		ath10k_core_free_firmware_files(ar);
@@ -1041,6 +1075,8 @@ void ath10k_core_unregister(struct ath10k *ar)
 	 * unhappy about callback failures. */
 	ath10k_mac_unregister(ar);
 
+	ath10k_testmode_destroy(ar);
+
 	ath10k_core_free_firmware_files(ar);
 
 	ath10k_debug_destroy(ar);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 797741d762be..30b53aa7a2d3 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -330,6 +330,17 @@ enum ath10k_state {
 	 * prevents completion timeouts and makes the driver more responsive to
 	 * userspace commands. This is also prevents recursive recovery. */
 	ATH10K_STATE_WEDGED,
+
+	/* factory tests */
+	ATH10K_STATE_UTF,
+};
+
+enum ath10k_firmware_mode {
+	/* the default mode, standard 802.11 functionality */
+	ATH10K_FIRMWARE_MODE_NORMAL,
+
+	/* factory tests etc */
+	ATH10K_FIRMWARE_MODE_UTF,
 };
 
 enum ath10k_fw_features {
@@ -543,6 +554,15 @@ struct ath10k {
 		struct ath10k_spec_scan config;
 	} spectral;
 
+	struct {
+		/* protected by conf_mutex */
+		const struct firmware *utf;
+		DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
+
+		/* protected by data_lock */
+		bool utf_monitor;
+	} testmode;
+
 	/* must be last */
 	u8 drv_priv[0] __aligned(sizeof(void *));
 };
@@ -551,7 +571,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 				  const struct ath10k_hif_ops *hif_ops);
 void ath10k_core_destroy(struct ath10k *ar);
 
-int ath10k_core_start(struct ath10k *ar);
+int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode);
 int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
 void ath10k_core_stop(struct ath10k *ar);
 int ath10k_core_register(struct ath10k *ar, u32 chip_id);
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index d922ef457498..570dce3902ae 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -134,11 +134,12 @@ void ath10k_print_driver_info(struct ath10k *ar)
 		    ar->fw_api,
 		    ar->htt.target_version_major,
 		    ar->htt.target_version_minor);
-	ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d\n",
+	ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
 		    config_enabled(CONFIG_ATH10K_DEBUG),
 		    config_enabled(CONFIG_ATH10K_DEBUGFS),
 		    config_enabled(CONFIG_ATH10K_TRACING),
-		    config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
+		    config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
+		    config_enabled(CONFIG_NL80211_TESTMODE));
 }
 EXPORT_SYMBOL(ath10k_print_driver_info);
 
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 56746539bea2..fdc8ba23301a 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -34,6 +34,7 @@ enum ath10k_debug_mask {
 	ATH10K_DBG_DATA		= 0x00000200,
 	ATH10K_DBG_BMI		= 0x00000400,
 	ATH10K_DBG_REGULATORY	= 0x00000800,
+	ATH10K_DBG_TESTMODE	= 0x00001000,
 	ATH10K_DBG_ANY		= 0xffffffff,
 };
 
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 13568b01de9f..3cf5702c1e7e 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -36,6 +36,8 @@
 #define ATH10K_FW_API2_FILE		"firmware-2.bin"
 #define ATH10K_FW_API3_FILE		"firmware-3.bin"
 
+#define ATH10K_FW_UTF_FILE		"utf.bin"
+
 /* includes also the null byte */
 #define ATH10K_FIRMWARE_MAGIC               "QCA-ATH10K"
 
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index f80eeed16cb6..5b35fff8127f 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -26,6 +26,7 @@
 #include "wmi.h"
 #include "htt.h"
 #include "txrx.h"
+#include "testmode.h"
 
 /**********/
 /* Crypto */
@@ -2480,6 +2481,9 @@ static int ath10k_start(struct ieee80211_hw *hw)
 		WARN_ON(1);
 		ret = -EINVAL;
 		goto err;
+	case ATH10K_STATE_UTF:
+		ret = -EBUSY;
+		goto err;
 	}
 
 	ret = ath10k_hif_power_up(ar);
@@ -2488,7 +2492,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
 		goto err_off;
 	}
 
-	ret = ath10k_core_start(ar);
+	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
 	if (ret) {
 		ath10k_err(ar, "Could not init core: %d\n", ret);
 		goto err_power_down;
@@ -4456,6 +4460,9 @@ static const struct ieee80211_ops ath10k_ops = {
 	.sta_rc_update			= ath10k_sta_rc_update,
 	.get_tsf			= ath10k_get_tsf,
 	.ampdu_action			= ath10k_ampdu_action,
+
+	CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
+
 #ifdef CONFIG_PM
 	.suspend			= ath10k_suspend,
 	.resume				= ath10k_resume,
diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c
new file mode 100644
index 000000000000..da9a924beff6
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2014 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 "testmode.h"
+
+#include <net/netlink.h>
+#include <linux/firmware.h>
+
+#include "debug.h"
+#include "wmi.h"
+#include "hif.h"
+#include "hw.h"
+
+#include "testmode_i.h"
+
+static const struct nla_policy ath10k_tm_policy[ATH10K_TM_ATTR_MAX + 1] = {
+	[ATH10K_TM_ATTR_CMD]		= { .type = NLA_U32 },
+	[ATH10K_TM_ATTR_DATA]		= { .type = NLA_BINARY,
+					    .len = ATH10K_TM_DATA_MAX_LEN },
+	[ATH10K_TM_ATTR_WMI_CMDID]	= { .type = NLA_U32 },
+	[ATH10K_TM_ATTR_VERSION_MAJOR]	= { .type = NLA_U32 },
+	[ATH10K_TM_ATTR_VERSION_MINOR]	= { .type = NLA_U32 },
+};
+
+/* Returns true if callee consumes the skb and the skb should be discarded.
+ * Returns false if skb is not used. Does not sleep.
+ */
+bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
+{
+	struct sk_buff *nl_skb;
+	bool consumed;
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+		   "testmode event wmi cmd_id %d skb %p skb->len %d\n",
+		   cmd_id, skb, skb->len);
+
+	ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
+
+	spin_lock_bh(&ar->data_lock);
+
+	if (!ar->testmode.utf_monitor) {
+		consumed = false;
+		goto out;
+	}
+
+	/* Only testmode.c should be handling events from utf firmware,
+	 * otherwise all sort of problems will arise as mac80211 operations
+	 * are not initialised. */
+	consumed = true;
+
+	nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
+						   2 * sizeof(u32) + skb->len,
+						   GFP_ATOMIC);
+	if (!nl_skb) {
+		ath10k_warn(ar,
+			    "failed to allocate skb for testmode wmi event\n");
+		goto out;
+	}
+
+	ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_CMD, ATH10K_TM_CMD_WMI);
+	if (ret) {
+		ath10k_warn(ar,
+			    "failed to to put testmode wmi event cmd attribute: %d\n",
+			    ret);
+		kfree_skb(nl_skb);
+		goto out;
+	}
+
+	ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_WMI_CMDID, cmd_id);
+	if (ret) {
+		ath10k_warn(ar,
+			    "failed to to put testmode wmi even cmd_id: %d\n",
+			    ret);
+		kfree_skb(nl_skb);
+		goto out;
+	}
+
+	ret = nla_put(nl_skb, ATH10K_TM_ATTR_DATA, skb->len, skb->data);
+	if (ret) {
+		ath10k_warn(ar,
+			    "failed to copy skb to testmode wmi event: %d\n",
+			    ret);
+		kfree_skb(nl_skb);
+		goto out;
+	}
+
+	cfg80211_testmode_event(nl_skb, GFP_ATOMIC);
+
+out:
+	spin_unlock_bh(&ar->data_lock);
+
+	return consumed;
+}
+
+static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
+{
+	struct sk_buff *skb;
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+		   "testmode cmd get version_major %d version_minor %d\n",
+		   ATH10K_TESTMODE_VERSION_MAJOR,
+		   ATH10K_TESTMODE_VERSION_MINOR);
+
+	skb = cfg80211_testmode_alloc_reply_skb(ar->hw->wiphy,
+						nla_total_size(sizeof(u32)));
+	if (!skb)
+		return -ENOMEM;
+
+	ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MAJOR,
+			  ATH10K_TESTMODE_VERSION_MAJOR);
+	if (ret) {
+		kfree_skb(skb);
+		return ret;
+	}
+
+	ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MINOR,
+			  ATH10K_TESTMODE_VERSION_MINOR);
+	if (ret) {
+		kfree_skb(skb);
+		return ret;
+	}
+
+	return cfg80211_testmode_reply(skb);
+}
+
+static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
+{
+	char filename[100];
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state == ATH10K_STATE_UTF) {
+		ret = -EALREADY;
+		goto err;
+	}
+
+	/* start utf only when the driver is not in use  */
+	if (ar->state != ATH10K_STATE_OFF) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	if (ar->testmode.utf != NULL)
+		/* utf image is already downloaded */
+		goto power_up;
+
+	snprintf(filename, sizeof(filename), "%s/%s",
+		 ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
+
+	/* load utf firmware image */
+	ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
+	if (ret) {
+		ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
+			    filename, ret);
+		goto err;
+	}
+
+power_up:
+	spin_lock_bh(&ar->data_lock);
+
+	ar->testmode.utf_monitor = true;
+
+	spin_unlock_bh(&ar->data_lock);
+
+	BUILD_BUG_ON(sizeof(ar->fw_features) !=
+		     sizeof(ar->testmode.orig_fw_features));
+
+	memcpy(ar->testmode.orig_fw_features, ar->fw_features,
+	       sizeof(ar->fw_features));
+
+	/* utf.bin firmware image does not advertise firmware features. Do
+	 * an ugly hack where we force the firmware features so that wmi.c
+	 * will use the correct WMI interface.
+	 */
+	memset(ar->fw_features, 0, sizeof(ar->fw_features));
+	__set_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features);
+
+	ret = ath10k_hif_power_up(ar);
+	if (ret) {
+		ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret);
+		ar->state = ATH10K_STATE_OFF;
+		goto err_fw_features;
+	}
+
+	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF);
+	if (ret) {
+		ath10k_err(ar, "failed to start core (testmode): %d\n", ret);
+		ar->state = ATH10K_STATE_OFF;
+		goto err_power_down;
+	}
+
+	ar->state = ATH10K_STATE_UTF;
+
+	ath10k_info(ar, "UTF firmware started\n");
+
+	mutex_unlock(&ar->conf_mutex);
+
+	return 0;
+
+err_power_down:
+	ath10k_hif_power_down(ar);
+
+err_fw_features:
+	/* return the original firmware features */
+	memcpy(ar->fw_features, ar->testmode.orig_fw_features,
+	       sizeof(ar->fw_features));
+
+	release_firmware(ar->testmode.utf);
+	ar->testmode.utf = NULL;
+
+err:
+	mutex_unlock(&ar->conf_mutex);
+
+	return ret;
+}
+
+static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
+{
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf stop\n");
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_UTF) {
+		ret = -ENETDOWN;
+		goto out;
+	}
+
+	ath10k_core_stop(ar);
+	ath10k_hif_power_down(ar);
+
+	spin_lock_bh(&ar->data_lock);
+
+	ar->testmode.utf_monitor = false;
+
+	spin_unlock_bh(&ar->data_lock);
+
+	/* return the original firmware features */
+	memcpy(ar->fw_features, ar->testmode.orig_fw_features,
+	       sizeof(ar->fw_features));
+
+	release_firmware(ar->testmode.utf);
+	ar->testmode.utf = NULL;
+
+	ar->state = ATH10K_STATE_OFF;
+	ret = 0;
+
+	ath10k_info(ar, "UTF firmware stopped\n");
+
+out:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
+}
+
+static int ath10k_tm_cmd_wmi(struct ath10k *ar, struct nlattr *tb[])
+{
+	struct sk_buff *skb;
+	int ret, buf_len;
+	u32 cmd_id;
+	void *buf;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_UTF) {
+		ret = -ENETDOWN;
+		goto out;
+	}
+
+	if (!tb[ATH10K_TM_ATTR_DATA]) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (!tb[ATH10K_TM_ATTR_WMI_CMDID]) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	buf = nla_data(tb[ATH10K_TM_ATTR_DATA]);
+	buf_len = nla_len(tb[ATH10K_TM_ATTR_DATA]);
+	cmd_id = nla_get_u32(tb[ATH10K_TM_ATTR_WMI_CMDID]);
+
+	ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+		   "testmode cmd wmi cmd_id %d buf %p buf_len %d\n",
+		   cmd_id, buf, buf_len);
+
+	ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", buf, buf_len);
+
+	skb = ath10k_wmi_alloc_skb(ar, buf_len);
+	if (!skb) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(skb->data, buf, buf_len);
+
+	ret = ath10k_wmi_cmd_send(ar, skb, cmd_id);
+	if (ret) {
+		ath10k_warn(ar, "failed to transmit wmi command (testmode): %d\n",
+			    ret);
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
+}
+
+int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		  void *data, int len)
+{
+	struct ath10k *ar = hw->priv;
+	struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1];
+	int ret;
+
+	ret = nla_parse(tb, ATH10K_TM_ATTR_MAX, data, len,
+			ath10k_tm_policy);
+	if (ret)
+		return ret;
+
+	if (!tb[ATH10K_TM_ATTR_CMD])
+		return -EINVAL;
+
+	switch (nla_get_u32(tb[ATH10K_TM_ATTR_CMD])) {
+	case ATH10K_TM_CMD_GET_VERSION:
+		return ath10k_tm_cmd_get_version(ar, tb);
+	case ATH10K_TM_CMD_UTF_START:
+		return ath10k_tm_cmd_utf_start(ar, tb);
+	case ATH10K_TM_CMD_UTF_STOP:
+		return ath10k_tm_cmd_utf_stop(ar, tb);
+	case ATH10K_TM_CMD_WMI:
+		return ath10k_tm_cmd_wmi(ar, tb);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+void ath10k_testmode_destroy(struct ath10k *ar)
+{
+	mutex_lock(&ar->conf_mutex);
+
+	release_firmware(ar->testmode.utf);
+	ar->testmode.utf = NULL;
+
+	if (ar->state != ATH10K_STATE_UTF) {
+		/* utf firmware is not running, nothing to do */
+		goto out;
+	}
+
+	ath10k_core_stop(ar);
+
+out:
+	mutex_unlock(&ar->conf_mutex);
+}
diff --git a/drivers/net/wireless/ath/ath10k/testmode.h b/drivers/net/wireless/ath/ath10k/testmode.h
new file mode 100644
index 000000000000..9cdd150815db
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/testmode.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 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 "core.h"
+
+#ifdef CONFIG_NL80211_TESTMODE
+
+void ath10k_testmode_destroy(struct ath10k *ar);
+
+bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb);
+int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		  void *data, int len);
+
+#else
+
+static inline void ath10k_testmode_destroy(struct ath10k *ar)
+{
+}
+
+static inline bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id,
+				       struct sk_buff *skb)
+{
+	return false;
+}
+
+static inline int ath10k_tm_cmd(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				void *data, int len)
+{
+	return 0;
+}
+
+#endif
diff --git a/drivers/net/wireless/ath/ath10k/testmode_i.h b/drivers/net/wireless/ath/ath10k/testmode_i.h
new file mode 100644
index 000000000000..ba81bf66ce85
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/testmode_i.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+/* "API" level of the ath10k testmode interface. Bump it after every
+ * incompatible interface change.
+ */
+#define ATH10K_TESTMODE_VERSION_MAJOR 1
+
+/* Bump this after every _compatible_ interface change, for example
+ * addition of a new command or an attribute.
+ */
+#define ATH10K_TESTMODE_VERSION_MINOR 0
+
+#define ATH10K_TM_DATA_MAX_LEN		5000
+
+enum ath10k_tm_attr {
+	__ATH10K_TM_ATTR_INVALID	= 0,
+	ATH10K_TM_ATTR_CMD		= 1,
+	ATH10K_TM_ATTR_DATA		= 2,
+	ATH10K_TM_ATTR_WMI_CMDID	= 3,
+	ATH10K_TM_ATTR_VERSION_MAJOR	= 4,
+	ATH10K_TM_ATTR_VERSION_MINOR	= 5,
+
+	/* keep last */
+	__ATH10K_TM_ATTR_AFTER_LAST,
+	ATH10K_TM_ATTR_MAX		= __ATH10K_TM_ATTR_AFTER_LAST - 1,
+};
+
+/* All ath10k testmode interface commands specified in
+ * ATH10K_TM_ATTR_CMD
+ */
+enum ath10k_tm_cmd {
+	/* Returns the supported ath10k testmode interface version in
+	 * ATH10K_TM_ATTR_VERSION. Always guaranteed to work. User space
+	 * uses this to verify it's using the correct version of the
+	 * testmode interface
+	 */
+	ATH10K_TM_CMD_GET_VERSION = 0,
+
+	/* Boots the UTF firmware, the netdev interface must be down at the
+	 * time.
+	 */
+	ATH10K_TM_CMD_UTF_START = 1,
+
+	/* Shuts down the UTF firmware and puts the driver back into OFF
+	 * state.
+	 */
+	ATH10K_TM_CMD_UTF_STOP = 2,
+
+	/* The command used to transmit a WMI command to the firmware and
+	 * the event to receive WMI events from the firmware. Without
+	 * struct wmi_cmd_hdr header, only the WMI payload. Command id is
+	 * provided with ATH10K_TM_ATTR_WMI_CMDID and payload in
+	 * ATH10K_TM_ATTR_DATA.
+	 */
+	ATH10K_TM_CMD_WMI = 3,
+};
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index f80959419525..f3a366a26c93 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -23,6 +23,7 @@
 #include "debug.h"
 #include "wmi.h"
 #include "mac.h"
+#include "testmode.h"
 
 /* MAIN WMI cmd track */
 static struct wmi_cmd_map wmi_cmd_map = {
@@ -2479,6 +2480,7 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_cmd_hdr *cmd_hdr;
 	enum wmi_10x_event_id id;
+	bool consumed;
 
 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@@ -2488,6 +2490,17 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
 
 	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
 
+	consumed = ath10k_tm_event_wmi(ar, id, skb);
+
+	/* Ready event must be handled normally also in UTF mode so that we
+	 * know the UTF firmware has booted, others we are just bypass WMI
+	 * events to testmode. */
+	if (consumed && id != WMI_10X_READY_EVENTID) {
+		ath10k_dbg(ar, ATH10K_DBG_WMI,
+			   "wmi testmode consumed 0x%x\n", id);
+		goto out;
+	}
+
 	switch (id) {
 	case WMI_10X_MGMT_RX_EVENTID:
 		ath10k_wmi_event_mgmt_rx(ar, skb);
@@ -2574,11 +2587,15 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
 	case WMI_10X_READY_EVENTID:
 		ath10k_wmi_ready_event_rx(ar, skb);
 		break;
+	case WMI_10X_PDEV_UTF_EVENTID:
+		/* ignore utf events */
+		break;
 	default:
 		ath10k_warn(ar, "Unknown eventid: %d\n", id);
 		break;
 	}
 
+out:
 	dev_kfree_skb(skb);
 }
 



From greearb at candelatech.com  Thu Sep  4 07:04:21 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 04 Sep 2014 07:04:21 -0700
Subject: WMI version handling
In-Reply-To: <CA+BoTQkbLRpAvmjVEvjCqwTnk9XqFeWOxhr1cpQSuvtVm898tw@mail.gmail.com>
References: <1407261537-11308-1-git-send-email-greearb@candelatech.com>	<87zjehjkmg.fsf@kamboji.qca.qualcomm.com>	<54072D19.7010809@candelatech.com>
 <CA+BoTQkbLRpAvmjVEvjCqwTnk9XqFeWOxhr1cpQSuvtVm898tw@mail.gmail.com>
Message-ID: <54087165.1090305@candelatech.com>



On 09/03/2014 11:56 PM, Michal Kazior wrote:
> On 3 September 2014 17:00, Ben Greear <greearb at candelatech.com> wrote:
>> On 09/02/2014 11:14 PM, Kalle Valo wrote:
>>> Hi,
> [...]
>>> Also I have been thinking that using firmware feature bits (for example
>>> ATH10K_FW_FEATURE_WMI_10_2 and ATH10K_FW_FEATURE_WMI_10X) for WMI
>>> version is not the best way. I think it's easier to manage all this if
>>> we have a u32 FW IE to provide WMI version. IIRC Ben was suggesting this
>>> at some point.
>>>
>>> Example:
>>>
>>> enum ath10k_fw_wmi_version {
>>>        ATH10K_FW_WMI_VERSION_MAIN = 0,
>>>        ATH10K_FW_WMI_VERSION_10_1 = 1,
>>>        ATH10K_FW_WMI_VERSION_10_2 = 2,
>>> }
>>>
>>> And then wmi.c would set correct interface based on this version.
>>
>> I am happy with the current flags, it seems to work well enough.
>
> I'm actually okay with this but I'd actually throw out the "wmi"
> string from it and leave out just "ath10k_fw_version". I've recently
> discovered some minor HTT discrepancies between fw branches so we
> might want to use the version tag to pick HTT "backend" as well..
>
>
>> I'd leave policy out of the IEs as much as possible, as normal users
>> cannot modify it, and certainly it would be a problem if you wanted
>> different policy with different NICs in same system.
>> IEs should describe the minimum needed for the
>> ath10k to enforce policy as best as it can.  We have to assume that
>> users tweaking station and peer count can deal with fw crashes until
>> they get the settings right.
>>
>> My CT firmware will print out available RAM once booted, so it is
>> fairly easy to utilize maximum amount of resources with a bit of
>> trial and error.  It would be trivial to make upstream firmware do
>> the same, of course, but upstream firmware may crash for other
>> reasons as you change resource config...
>
> IOW You're okay if ath10k applies default/hardcoded configuration
> values of 10.1 for your firmware (as your firmware is going to
> advertise as a 10.1) - is that correct? You just want to be able to
> tune these values per-device in runtime. I think debugfs is the best
> candidate here then.
>
> ath10k would need to have a separate debugfs entry for that then, i.e.
> one that is independent from wiphy. You could have, e.g.
> /sys/kernel/debug/ath10k/pci/0000:04:00.0/num_peers which re-registers
> to mac80211 upon modification.

That would be fine for the number of stations and peers, but there are other
features more specific to my firmware that should be enabled by default
if my firmware is loaded.  These include better tx-status, for instance.
I figured might as well also auto-tune the stations higher at the same time.

Also, some of the logic that auto-calculates skid-len, for instance, really
should be done for all firmware that can handle it to protect against malicious
hashing attacks.


>>> We would still use feature bits to enable and disable smaller changes
>>> like ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX does. But for bigger WMI changes
>>> we would change the WMI version, for example if we have a new firmware
>>> branch with significant changes or similar.
>>>
>>> And for backwards comptability we need to do so that
>>> ATH10K_FW_FEATURE_WMI_10X sets ATH10K_FW_WMI_VERSION_10_1 and
>>> ATH10K_FW_FEATURE_WMI_10_2 sets ATH10K_FW_WMI_VERSION_10_2.
>>
>> I was able to do all of my changes w/out needing new a new WMI version,
>> and I think that is the right approach.  I do not like large amounts of
>> duplicated code and table lookups, which is what new WMI versions appear
>> to imply.
>
> It's actually really simple to update WMI in an ABI-safe way.
> Unfortunately official firmware updates break it fairly often and we
> have to deal with that. Aaand there's going to be another WMI backend
> soon most likely.
>
>
> [...]
>> If QCA goes to more of a rolling release for firmware, like I do for CT
>> firmware, then we may want to add IEs a bit more often, to notify things like
>> "can-support-feature-foo".  10.2 v/s 10.1 can still determine the
>> over-all WMI api, perhaps, but at specific points we can take advantage of
>> specific firmware features based on IE flag.
>
> This is what WMI bitmap service is actually for. ath10k is ignoring
> this now and exposes it via debugfs only. It's possible to, e.g. pick
> "max num of stations" configuration values based on the "iram tids"
> being set or not.

I guess I haven't looked into WMI bitmap, but I was hoping for minimal
code changes when adding my firmware, and I want to keep my firmware
backwards compat with existing kernels.  With regard to max-num-of-stations,
I don't think you will will be able to reliably calculate the exact resource
limits combinations from ath10k driver.
Every configurable (peers, tx-buffers, stations, skid-limit, etc)
affects RAM and/or IRAM and there are various
upper limits on various items in the firmware that may only be hit at
unlucky times during runtime.

Thanks,
Ben


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


From michal.kazior at tieto.com  Fri Sep  5 00:27:57 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Fri, 5 Sep 2014 09:27:57 +0200
Subject: [PATCH v3 2/2] ath10k: add testmode
In-Reply-To: <20140904135654.26750.69133.stgit@potku.adurom.net>
References: <20140904135447.26750.52873.stgit@potku.adurom.net>
 <20140904135654.26750.69133.stgit@potku.adurom.net>
Message-ID: <CA+BoTQmheuGLxicMCwVREkru5eh7FxV3T8qmsME4U5_2vi-iyA@mail.gmail.com>

(On 4 September 2014 15:56, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Add testmode interface for starting and using UTF firmware which is used to run
> factory tests. This is implemented by adding new state ATH10K_STATE_UTF and user
> space can enable this state with ATH10K_TM_CMD_UTF_START command. To go back to
> normal mode user space can send ATH10K_TM_CMD_UTF_STOP.
>
> Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
> ---
[...]
> +bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
> +{
> +       struct sk_buff *nl_skb;
> +       bool consumed;
> +       int ret;
> +
> +       ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
> +                  "testmode event wmi cmd_id %d skb %p skb->len %d\n",
> +                  cmd_id, skb, skb->len);
> +
> +       ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
> +
> +       spin_lock_bh(&ar->data_lock);
> +
> +       if (!ar->testmode.utf_monitor) {
> +               consumed = false;
> +               goto out;
> +       }
> +
> +       /* Only testmode.c should be handling events from utf firmware,
> +        * otherwise all sort of problems will arise as mac80211 operations
> +        * are not initialised. */

Comment style.


> +static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
> +{
> +       char filename[100];
> +       int ret;
> +
> +       ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
> +
> +       mutex_lock(&ar->conf_mutex);
> +
> +       if (ar->state == ATH10K_STATE_UTF) {
> +               ret = -EALREADY;
> +               goto err;
> +       }
> +
> +       /* start utf only when the driver is not in use  */
> +       if (ar->state != ATH10K_STATE_OFF) {
> +               ret = -EBUSY;
> +               goto err;
> +       }
> +
> +       if (ar->testmode.utf != NULL)
> +               /* utf image is already downloaded */
> +               goto power_up;

I believe this shouldn't happen with the current code. We should
probably treat it with a if (WARN_ON(utf != NULL)) goto err;


> +void ath10k_testmode_destroy(struct ath10k *ar)
> +{
> +       mutex_lock(&ar->conf_mutex);
> +
> +       release_firmware(ar->testmode.utf);
> +       ar->testmode.utf = NULL;
> +
> +       if (ar->state != ATH10K_STATE_UTF) {
> +               /* utf firmware is not running, nothing to do */
> +               goto out;
> +       }
> +
> +       ath10k_core_stop(ar);

Hmm, you don't call power_down here. This isn't a problem from a
practical point of view after my recent changes but hey.

How about we split out guts from ath10k_tm_cmd_utf_stop() to
__ath10k_tm_cmd_utf_stop() (which assumes conf_mutex is already held)
and call it here like this:

 mutex_lock(conf_mutex);
 if (ar->state==UTF)
   __ath10k_tm_cmd_utf_stop(ar);
 mutex_unlock(conf_mutex);


> @@ -2488,6 +2490,17 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
>
>         trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
>
> +       consumed = ath10k_tm_event_wmi(ar, id, skb);
> +
> +       /* Ready event must be handled normally also in UTF mode so that we
> +        * know the UTF firmware has booted, others we are just bypass WMI
> +        * events to testmode. */

Comment style.


Micha?


From kvalo at qca.qualcomm.com  Fri Sep  5 06:23:08 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 5 Sep 2014 16:23:08 +0300
Subject: WMI version handling
In-Reply-To: <54072D19.7010809@candelatech.com> (Ben Greear's message of "Wed, 
 3 Sep 2014 08:00:41 -0700")
References: <1407261537-11308-1-git-send-email-greearb@candelatech.com>
 <87zjehjkmg.fsf@kamboji.qca.qualcomm.com>
 <54072D19.7010809@candelatech.com>
Message-ID: <871trqgq0z.fsf@kamboji.qca.qualcomm.com>

Ben Greear <greearb at candelatech.com> writes:

>> Also I have been thinking that using firmware feature bits (for example
>> ATH10K_FW_FEATURE_WMI_10_2 and ATH10K_FW_FEATURE_WMI_10X) for WMI
>> version is not the best way. I think it's easier to manage all this if
>> we have a u32 FW IE to provide WMI version. IIRC Ben was suggesting this
>> at some point.
>> 
>> Example:
>> 
>> enum ath10k_fw_wmi_version {
>> 	ATH10K_FW_WMI_VERSION_MAIN = 0,
>> 	ATH10K_FW_WMI_VERSION_10_1 = 1,
>> 	ATH10K_FW_WMI_VERSION_10_2 = 2,
>> }
>> 
>> And then wmi.c would set correct interface based on this version.
>
> I am happy with the current flags, it seems to work well enough.

Yeah, there's no problem at the moment. But if we start adding more
interfaces handling them through feature flags will become more
difficult. That's why I think adding a separate enum will be better in
the long run.

> I'd leave policy out of the IEs as much as possible, as normal users
> cannot modify it, and certainly it would be a problem if you wanted
> different policy with different NICs in same system. IEs should
> describe the minimum needed for the ath10k to enforce policy as best
> as it can.

The firmware IEs are not about policy. They are about advertising the
capabilities of the firmware image so that ath10k can know how to
configure the firmare.

> We have to assume that users tweaking station and peer count can deal
> with fw crashes until they get the settings right.

No way. In no circumstances ath10k should configure firmware out of
bounds. If we do that, it's a bug in ath10k.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Fri Sep  5 06:32:15 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 5 Sep 2014 16:32:15 +0300
Subject: WMI version handling
In-Reply-To: <CA+BoTQkbLRpAvmjVEvjCqwTnk9XqFeWOxhr1cpQSuvtVm898tw@mail.gmail.com>
 (Michal Kazior's message of "Thu, 4 Sep 2014 08:56:15 +0200")
References: <1407261537-11308-1-git-send-email-greearb@candelatech.com>
 <87zjehjkmg.fsf@kamboji.qca.qualcomm.com>
 <54072D19.7010809@candelatech.com>
 <CA+BoTQkbLRpAvmjVEvjCqwTnk9XqFeWOxhr1cpQSuvtVm898tw@mail.gmail.com>
Message-ID: <87wq9ifb1c.fsf@kamboji.qca.qualcomm.com>

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

> On 3 September 2014 17:00, Ben Greear <greearb at candelatech.com> wrote:
>> On 09/02/2014 11:14 PM, Kalle Valo wrote:
>>> Hi,
> [...]
>>> Also I have been thinking that using firmware feature bits (for example
>>> ATH10K_FW_FEATURE_WMI_10_2 and ATH10K_FW_FEATURE_WMI_10X) for WMI
>>> version is not the best way. I think it's easier to manage all this if
>>> we have a u32 FW IE to provide WMI version. IIRC Ben was suggesting this
>>> at some point.
>>>
>>> Example:
>>>
>>> enum ath10k_fw_wmi_version {
>>>       ATH10K_FW_WMI_VERSION_MAIN = 0,
>>>       ATH10K_FW_WMI_VERSION_10_1 = 1,
>>>       ATH10K_FW_WMI_VERSION_10_2 = 2,
>>> }
>>>
>>> And then wmi.c would set correct interface based on this version.
>>
>> I am happy with the current flags, it seems to work well enough.
>
> I'm actually okay with this but I'd actually throw out the "wmi"
> string from it and leave out just "ath10k_fw_version". I've recently
> discovered some minor HTT discrepancies between fw branches so we
> might want to use the version tag to pick HTT "backend" as well..

I'm again thinking that we should have a separate enum for the HTT
version. So that the firmware interface is defined with WMI version, HTT
version and feature flags (which define smaller changes in the
interface).

-- 
Kalle Valo


From greearb at candelatech.com  Fri Sep  5 08:46:37 2014
From: greearb at candelatech.com (Ben Greear)
Date: Fri, 05 Sep 2014 08:46:37 -0700
Subject: WMI version handling
In-Reply-To: <871trqgq0z.fsf@kamboji.qca.qualcomm.com>
References: <1407261537-11308-1-git-send-email-greearb@candelatech.com>
 <87zjehjkmg.fsf@kamboji.qca.qualcomm.com> <54072D19.7010809@candelatech.com>
 <871trqgq0z.fsf@kamboji.qca.qualcomm.com>
Message-ID: <5409DADD.1050001@candelatech.com>



On 09/05/2014 06:23 AM, Kalle Valo wrote:
> Ben Greear <greearb at candelatech.com> writes:
>
>>> Also I have been thinking that using firmware feature bits (for example
>>> ATH10K_FW_FEATURE_WMI_10_2 and ATH10K_FW_FEATURE_WMI_10X) for WMI
>>> version is not the best way. I think it's easier to manage all this if
>>> we have a u32 FW IE to provide WMI version. IIRC Ben was suggesting this
>>> at some point.
>>>
>>> Example:
>>>
>>> enum ath10k_fw_wmi_version {
>>> 	ATH10K_FW_WMI_VERSION_MAIN = 0,
>>> 	ATH10K_FW_WMI_VERSION_10_1 = 1,
>>> 	ATH10K_FW_WMI_VERSION_10_2 = 2,
>>> }
>>>
>>> And then wmi.c would set correct interface based on this version.
>>
>> I am happy with the current flags, it seems to work well enough.
>
> Yeah, there's no problem at the moment. But if we start adding more
> interfaces handling them through feature flags will become more
> difficult. That's why I think adding a separate enum will be better in
> the long run.

Worry about the long run when it gets here.  Prematurely engineering for
possible scenarios just wastes time.  We can always go back and
reorganize code later as the re-use patterns become more clear.

>> I'd leave policy out of the IEs as much as possible, as normal users
>> cannot modify it, and certainly it would be a problem if you wanted
>> different policy with different NICs in same system. IEs should
>> describe the minimum needed for the ath10k to enforce policy as best
>> as it can.
>
> The firmware IEs are not about policy. They are about advertising the
> capabilities of the firmware image so that ath10k can know how to
> configure the firmare.

More stations means less peers, less tx-buffers means more of other things.
Disabling some firmware offload features frees ram for other things.
RAM usage per item increment is not even linear in some cases, and you
would have to have intimate knowledge of the firmware to understand the
limits.

Firmware can only tell you the maximum stations it can support, but if
you configure too many peers or too many tx-buffers, or enable roaming
offload, you would have to decrease the number of stations actually allocated.

Some users may want lots of stations, others lots of peers, other less tx-buffers,
and others more.  Some might want to ensure skid-length handles worst-case
scenarios at cost of fewer peers or stations.

>> We have to assume that users tweaking station and peer count can deal
>> with fw crashes until they get the settings right.
>
> No way. In no circumstances ath10k should configure firmware out of
> bounds. If we do that, it's a bug in ath10k.

You are either going to have to fix firmware, cripple your driver, or
accept some risk and let users configure settings that work best for them
if they care to.  Make sure the driver defaults work and do not crash,
but don't be so conservative that you decrease usability for those that
actually care to tinker.

If you are not swayed by my arguments, then just go ahead and implement
it how you want and I will attempt to make my patches work with your
methods.  I am frustrated with endless discussions and no upstream
patches.

Thanks,
Ben

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


From greearb at candelatech.com  Fri Sep  5 09:34:08 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Fri,  5 Sep 2014 09:34:08 -0700
Subject: [PATCH 1/2] ath10k: save firmware stacks upon firmware crash
Message-ID: <1409934849-23078-1-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>
Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---

This is a merge/rework of previously posted stack-dump patches.
This is on top of the debug-log dumping patch and the
firmware crash-by-assert patch.  It has been tested.

 drivers/net/wireless/ath/ath10k/core.h  |  4 +++
 drivers/net/wireless/ath/ath10k/debug.c | 29 +++++++++++++++++-
 drivers/net/wireless/ath/ath10k/hw.h    |  1 +
 drivers/net/wireless/ath/ath10k/pci.c   | 54 ++++++++++++++++++++++++++++++++-
 4 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index fc39995..0ca52e0 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -303,6 +303,10 @@ struct ath10k_fw_crash_data {
 	uuid_le uuid;
 	struct timespec timestamp;
 	__le32 registers[REG_DUMP_COUNT_QCA988X];
+	__le32 stack_buf[ATH10K_FW_STACK_SIZE / sizeof(__le32)];
+	__le32 exc_stack_buf[ATH10K_FW_STACK_SIZE / sizeof(__le32)];
+	__le32 stack_addr;
+	__le32 exc_stack_addr;
 };
 
 struct ath10k_debug {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 229573e..5c11966 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -33,10 +33,15 @@
  * enum ath10k_fw_crash_dump_type - types of data in the dump file
  * @ATH10K_FW_CRASH_DUMP_REGDUMP: Register crash dump in binary format
  * @ATH10K_FW_ERROR_DUMP_DBGLOG:  Recent firmware debug log entries
+ * @ATH10K_FW_CRASH_DUMP_STACK:   Stack memory contents.
+ * @ATH10K_FW_CRASH_DUMP_EXC_STACK:   Exception stack memory contents.
  */
 enum ath10k_fw_crash_dump_type {
 	ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
 	ATH10K_FW_CRASH_DUMP_DBGLOG = 1,
+	ATH10K_FW_CRASH_DUMP_STACK = 2,
+	ATH10K_FW_CRASH_DUMP_EXC_STACK = 3,
+
 	ATH10K_FW_CRASH_DUMP_MAX,
 };
 
@@ -100,8 +105,11 @@ struct ath10k_dump_file_data {
 	/* VERMAGIC_STRING */
 	char kernel_ver[64];
 
+	__le32 stack_addr;
+	__le32 exc_stack_addr;
+
 	/* room for growth w/out changing binary format */
-	u8 unused[128];
+	u8 unused[120];
 
 	/* struct ath10k_tlv_dump_data + more */
 	u8 data[0];
@@ -774,6 +782,8 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	len = hdr_len;
 	len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
 	len += sizeof(*dump_tlv) + sizeof(ar->debug.dbglog_entry_data);
+	len += sizeof(*dump_tlv) + sizeof(crash_data->stack_buf);
+	len += sizeof(*dump_tlv) + sizeof(crash_data->exc_stack_buf);
 
 	sofar += hdr_len;
 
@@ -813,6 +823,8 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
 	dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
 	dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
+	dump_data->stack_addr = cpu_to_le32(crash_data->stack_addr);
+	dump_data->exc_stack_addr = cpu_to_le32(crash_data->exc_stack_addr);
 
 	strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
 		sizeof(dump_data->fw_ver));
@@ -845,7 +857,22 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 		cpu_to_le32(ar->debug.dbglog_entry_data.head_idx);
 	dbglog_storage->tail_idx =
 		cpu_to_le32(ar->debug.dbglog_entry_data.tail_idx);
+	sofar += sizeof(*dump_tlv) + tmp;
 
+	/* Gather firmware stack dump */
+	tmp = sizeof(crash_data->stack_buf);
+	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+	dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_STACK);
+	dump_tlv->tlv_len = cpu_to_le32(tmp);
+	memcpy(dump_tlv->tlv_data, crash_data->stack_buf, tmp);
+	sofar += sizeof(*dump_tlv) + tmp;
+
+	/* Gather firmware exception stack dump */
+	tmp = sizeof(crash_data->exc_stack_buf);
+	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+	dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_EXC_STACK);
+	dump_tlv->tlv_len = cpu_to_le32(tmp);
+	memcpy(dump_tlv->tlv_data, crash_data->exc_stack_buf, tmp);
 	sofar += sizeof(*dump_tlv) + tmp;
 
 	ar->debug.fw_crash_data->crashed_since_read = false;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 28fedba..c7ec412 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -40,6 +40,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 09990f0..71d01fd 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -604,6 +604,22 @@ static int ath10k_pci_diag_read32(struct ath10k *ar, u32 address, u32 *value)
 	return ret;
 }
 
+static int __ath10k_pci_diag_read_hi_addr(struct ath10k *ar, __le32 *dest,
+					  u32 src)
+{
+	u32 host_addr;
+	int ret;
+
+	host_addr = host_interest_item_address(src);
+
+	ret = ath10k_pci_diag_read32(ar, host_addr, dest);
+	if (ret != 0) {
+		ath10k_warn(ar, "failed to get memcpy hi address for firmware address %d: %d\n",
+			    src, ret);
+	}
+	return ret;
+}
+
 static int __ath10k_pci_diag_read_hi(struct ath10k *ar, void *dest,
 				     u32 src, u32 len)
 {
@@ -630,7 +646,10 @@ static int __ath10k_pci_diag_read_hi(struct ath10k *ar, void *dest,
 }
 
 #define ath10k_pci_diag_read_hi(ar, dest, src, len)		\
-	__ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len);
+	__ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len)
+
+#define ath10k_pci_diag_read_hi_addr(ar, dest, src)		\
+	__ath10k_pci_diag_read_hi_addr(ar, dest, HI_ITEM(src))
 
 static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 				     const void *data, int nbytes)
@@ -944,6 +963,37 @@ 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);
 }
 
+/* Save the main firmware stack */
+static void ath10k_pci_dump_stack(struct ath10k *ar,
+				  struct ath10k_fw_crash_data *crash_data)
+{
+	if (!crash_data)
+		return;
+
+	lockdep_assert_held(&ar->data_lock);
+	BUILD_BUG_ON(ATH10K_FW_STACK_SIZE % 4);
+
+	ath10k_pci_diag_read_hi(ar, crash_data->stack_buf,
+				hi_stack, ATH10K_FW_STACK_SIZE);
+	ath10k_pci_diag_read_hi_addr(ar, &crash_data->stack_addr, hi_stack);
+}
+
+/* Save the exception firmware stack */
+static void ath10k_pci_dump_exc_stack(struct ath10k *ar,
+				      struct ath10k_fw_crash_data *crash_data)
+{
+	if (!crash_data)
+		return;
+
+	lockdep_assert_held(&ar->data_lock);
+
+	ath10k_pci_diag_read_hi(ar, crash_data->exc_stack_buf,
+				hi_err_stack, ATH10K_FW_STACK_SIZE);
+
+	ath10k_pci_diag_read_hi_addr(ar, &crash_data->exc_stack_addr,
+				     hi_err_stack);
+}
+
 static void ath10k_pci_dump_registers(struct ath10k *ar,
 				      struct ath10k_fw_crash_data *crash_data)
 {
@@ -1092,6 +1142,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
 	ath10k_print_driver_info(ar);
 	ath10k_pci_dump_registers(ar, crash_data);
 	ath10k_pci_dump_dbglog(ar);
+	ath10k_pci_dump_stack(ar, crash_data);
+	ath10k_pci_dump_exc_stack(ar, crash_data);
 	if (crash_data)
 		crash_data->crashed_since_read = true;
 
-- 
1.7.11.7



From greearb at candelatech.com  Fri Sep  5 09:34:09 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Fri,  5 Sep 2014 09:34:09 -0700
Subject: [PATCH 2/2] ath10k: save firmware RAM and ROM BSS sections on crash
In-Reply-To: <1409934849-23078-1-git-send-email-greearb@candelatech.com>
References: <1409934849-23078-1-git-send-email-greearb@candelatech.com>
Message-ID: <1409934849-23078-2-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>
Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---

This is a re-work and consolidation of previously posted patches.
It uses a single IE with 4 members:  My CT firmware already uses this,
and no other firmware has any support at all for this IE, so I would
like to be compatible.  I use a well-defined struct now, so hopefully
that is more acceptable than my first patches.

Using one IE decreases code and makes code easier to maintain.

Fix several bugs in earlier versions (copy-paste error in IE
handling, inversion of ROM v/s RAM bss sizes)

This has been tested.

 drivers/net/wireless/ath/ath10k/core.c  | 41 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/core.h  | 16 ++++++++++
 drivers/net/wireless/ath/ath10k/debug.c | 34 ++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/hw.h    |  1 +
 drivers/net/wireless/ath/ath10k/pci.c   | 52 +++++++++++++++++++++++++++++++++
 5 files changed, 143 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 651a6da..9828a79 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -360,6 +360,13 @@ err:
 	return ret;
 }
 
+struct ath10k_bss_rom_ie {
+	__le32 ram_addr;
+	__le32 ram_len;
+	__le32 rom_addr;
+	__le32 rom_len;
+} __packed;
+
 static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 {
 	size_t magic_len, len, ie_len;
@@ -367,6 +374,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 	struct ath10k_fw_ie *hdr;
 	const u8 *data;
 	__le32 *timestamp;
+	struct ath10k_bss_rom_ie *bss;
 
 	/* first fetch the firmware file (firmware-*.bin) */
 	ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
@@ -481,6 +489,39 @@ 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:
+			if (ie_len < sizeof(*bss)) {
+				ath10k_warn(ar, "invalid ie len for bss-info (%zd)\n",
+					    ie_len);
+				break;
+			}
+			bss = (struct ath10k_bss_rom_ie *)(data);
+
+			ar->fw.ram_bss_addr = le32_to_cpu(bss->ram_addr);
+			ar->fw.ram_bss_len = le32_to_cpu(bss->ram_len);
+			ath10k_dbg(ar, ATH10K_DBG_BOOT,
+				   "found RAM BSS addr 0x%x length %d\n",
+				   ar->fw.ram_bss_addr, ar->fw.ram_bss_len);
+
+			if (ar->fw.ram_bss_len > ATH10K_RAM_BSS_BUF_LEN) {
+				ath10k_warn(ar, "too long firmware RAM BSS length: %d\n",
+					    ar->fw.ram_bss_len);
+				ar->fw.ram_bss_len = 0;
+			}
+
+			ar->fw.rom_bss_addr = le32_to_cpu(bss->rom_addr);
+			ar->fw.rom_bss_len = le32_to_cpu(bss->rom_len);
+			ath10k_dbg(ar, ATH10K_DBG_BOOT,
+				   "found ROM BSS addr 0x%x length %d\n",
+				   ar->fw.rom_bss_addr, ar->fw.rom_bss_len);
+
+			if (ar->fw.rom_bss_len > ATH10K_ROM_BSS_BUF_LEN) {
+				ath10k_warn(ar, "too long firmware ROM BSS length: %d\n",
+					    ar->fw.rom_bss_len);
+				ar->fw.rom_bss_len = 0;
+			}
+
+			break;
 		default:
 			ath10k_warn(ar, "Unknown FW IE: %u\n",
 				    le32_to_cpu(hdr->id));
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 0ca52e0..b16c0c5 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -296,6 +296,10 @@ struct ath10k_dbglog_entry_storage {
 #define DBGLOG_NUM_ARGS_MASK             0xFC000000 /* Bit 26-31 */
 #define DBGLOG_NUM_ARGS_MAX              5 /* firmware tool chain limit */
 
+/* estimated values, hopefully these are enough */
+#define ATH10K_ROM_BSS_BUF_LEN 30000
+#define ATH10K_RAM_BSS_BUF_LEN 10000
+
 /* used for crash-dump storage, protected by data-lock */
 struct ath10k_fw_crash_data {
 	bool crashed_since_read;
@@ -307,6 +311,8 @@ struct ath10k_fw_crash_data {
 	__le32 exc_stack_buf[ATH10K_FW_STACK_SIZE / sizeof(__le32)];
 	__le32 stack_addr;
 	__le32 exc_stack_addr;
+	__le32 rom_bss_buf[ATH10K_ROM_BSS_BUF_LEN / sizeof(__le32)];
+	__le32 ram_bss_buf[ATH10K_RAM_BSS_BUF_LEN / sizeof(__le32)];
 };
 
 struct ath10k_debug {
@@ -455,6 +461,16 @@ struct ath10k {
 		} fw;
 	} hw_params;
 
+	/* These are written to only during first firmware load from user
+	 * space so no need for any locking.
+	 */
+	struct {
+		u32 ram_bss_addr;
+		u32 ram_bss_len;
+		u32 rom_bss_addr;
+		u32 rom_bss_len;
+	} fw;
+
 	const struct firmware *board;
 	const void *board_data;
 	size_t board_len;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 5c11966..4a5e2e1 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -35,12 +35,16 @@
  * @ATH10K_FW_ERROR_DUMP_DBGLOG:  Recent firmware debug log entries
  * @ATH10K_FW_CRASH_DUMP_STACK:   Stack memory contents.
  * @ATH10K_FW_CRASH_DUMP_EXC_STACK:   Exception stack memory contents.
+ * @ATH10K_FW_CRASH_DUMP_RAM_BSS:  BSS area for RAM code
+ * @ATH10K_FW_CRASH_DUMP_ROM_BSS:  BSS area for ROM code
  */
 enum ath10k_fw_crash_dump_type {
 	ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
 	ATH10K_FW_CRASH_DUMP_DBGLOG = 1,
 	ATH10K_FW_CRASH_DUMP_STACK = 2,
 	ATH10K_FW_CRASH_DUMP_EXC_STACK = 3,
+	ATH10K_FW_CRASH_DUMP_RAM_BSS = 4,
+	ATH10K_FW_CRASH_DUMP_ROM_BSS = 5,
 
 	ATH10K_FW_CRASH_DUMP_MAX,
 };
@@ -107,9 +111,11 @@ struct ath10k_dump_file_data {
 
 	__le32 stack_addr;
 	__le32 exc_stack_addr;
+	__le32 rom_bss_addr;
+	__le32 ram_bss_addr;
 
 	/* room for growth w/out changing binary format */
-	u8 unused[120];
+	u8 unused[112];
 
 	/* struct ath10k_tlv_dump_data + more */
 	u8 data[0];
@@ -785,6 +791,12 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	len += sizeof(*dump_tlv) + sizeof(crash_data->stack_buf);
 	len += sizeof(*dump_tlv) + sizeof(crash_data->exc_stack_buf);
 
+	if (ar->fw.ram_bss_addr && ar->fw.ram_bss_len)
+		len += sizeof(*dump_tlv) + ar->fw.ram_bss_len;
+
+	if (ar->fw.rom_bss_addr && ar->fw.rom_bss_len)
+		len += sizeof(*dump_tlv) + ar->fw.rom_bss_len;
+
 	sofar += hdr_len;
 
 	/* This is going to get big when we start dumping FW RAM and such,
@@ -825,6 +837,8 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
 	dump_data->stack_addr = cpu_to_le32(crash_data->stack_addr);
 	dump_data->exc_stack_addr = cpu_to_le32(crash_data->exc_stack_addr);
+	dump_data->rom_bss_addr = cpu_to_le32(ar->fw.rom_bss_addr);
+	dump_data->ram_bss_addr = cpu_to_le32(ar->fw.ram_bss_addr);
 
 	strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
 		sizeof(dump_data->fw_ver));
@@ -875,6 +889,24 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
 	memcpy(dump_tlv->tlv_data, crash_data->exc_stack_buf, tmp);
 	sofar += sizeof(*dump_tlv) + tmp;
 
+	if (ar->fw.ram_bss_addr && ar->fw.ram_bss_len) {
+		tmp = ar->fw.ram_bss_len;
+		dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+		dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_RAM_BSS);
+		dump_tlv->tlv_len = cpu_to_le32(tmp);
+		memcpy(dump_tlv->tlv_data, crash_data->ram_bss_buf, tmp);
+		sofar += sizeof(*dump_tlv) + tmp;
+	}
+
+	if (ar->fw.rom_bss_addr && ar->fw.rom_bss_len) {
+		tmp = ar->fw.rom_bss_len;
+		dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+		dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_ROM_BSS);
+		dump_tlv->tlv_len = cpu_to_le32(tmp);
+		memcpy(dump_tlv->tlv_data, crash_data->rom_bss_buf, tmp);
+		sofar += sizeof(*dump_tlv) + tmp;
+	}
+
 	ar->debug.fw_crash_data->crashed_since_read = false;
 
 	WARN_ON(sofar != len);
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index c7ec412..eb1a14b 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -54,6 +54,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 71d01fd..5f2523c4 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -963,6 +963,56 @@ 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_pci_dump_bss_ram(struct ath10k *ar,
+				    struct ath10k_fw_crash_data *crash_data)
+{
+	int ret;
+
+	if (!crash_data)
+		return;
+
+	lockdep_assert_held(&ar->data_lock);
+
+	if (!ar->fw.ram_bss_addr)
+		return;
+
+	if (!ar->fw.ram_bss_len)
+		return;
+
+	ret = ath10k_pci_diag_read_mem(ar, ar->fw.ram_bss_addr,
+				       crash_data->ram_bss_buf,
+				       ar->fw.ram_bss_len);
+	if (ret)
+		ath10k_warn(ar,
+			    "failed to read firmware RAM BSS memory from %d (%d B): %d\n",
+			    ar->fw.ram_bss_addr, ar->fw.ram_bss_len, ret);
+}
+
+static void ath10k_pci_dump_bss_rom(struct ath10k *ar,
+				    struct ath10k_fw_crash_data *crash_data)
+{
+	int ret;
+
+	if (!crash_data)
+		return;
+
+	lockdep_assert_held(&ar->data_lock);
+
+	if (!ar->fw.rom_bss_addr)
+		return;
+
+	if (!ar->fw.rom_bss_len)
+		return;
+
+	ret = ath10k_pci_diag_read_mem(ar, ar->fw.rom_bss_addr,
+				       crash_data->rom_bss_buf,
+				       ar->fw.rom_bss_len);
+	if (ret)
+		ath10k_warn(ar,
+			    "failed to read firmware ROM BSS memory from %d (%d B): %d\n",
+			    ar->fw.rom_bss_addr, ar->fw.rom_bss_len, ret);
+}
+
 /* Save the main firmware stack */
 static void ath10k_pci_dump_stack(struct ath10k *ar,
 				  struct ath10k_fw_crash_data *crash_data)
@@ -1144,6 +1194,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
 	ath10k_pci_dump_dbglog(ar);
 	ath10k_pci_dump_stack(ar, crash_data);
 	ath10k_pci_dump_exc_stack(ar, crash_data);
+	ath10k_pci_dump_bss_ram(ar, crash_data);
+	ath10k_pci_dump_bss_rom(ar, crash_data);
 	if (crash_data)
 		crash_data->crashed_since_read = true;
 
-- 
1.7.11.7



From denton.gentry at gmail.com  Fri Sep  5 13:56:45 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Fri, 5 Sep 2014 13:56:45 -0700
Subject: Firmware crash w/ 10.2 diagnosis?
Message-ID: <CABnBrYV4Lh7EF9xaEK6zkPk0HhU=iP283WhH+wA9=i7XfHroGg@mail.gmail.com>

Can anyone tell me what this firmware crash means?
I don't have steps to reproduce it, it seems to happen randomly. The
clients are mostly idle.

[Fri Sep  5 11:37:08 2014] ath10k: firmware crashed!
[Fri Sep  5 11:37:08 2014] ath10k: hardware name qca988x hw2.0 version
0x4100016c
[Fri Sep  5 11:37:08 2014] ath10k: firmware version: 10.2-00082-4-2
[Fri Sep  5 11:37:08 2014] ath10k: target register Dump Location: 0x0040AA34
[Fri Sep  5 11:37:08 2014] ath10k: target Register Dump
[Fri Sep  5 11:37:08 2014] ath10k: [00]: 0x4100016C 0x00000000
0x00949FF9 0x803044BE
[Fri Sep  5 11:37:08 2014] ath10k: [04]: 0x00949FF9 0x00060730
0x00000015 0x00000002
[Fri Sep  5 11:37:08 2014] ath10k: [08]: 0x00425BD0 0x803044BE
0x00000000 0x00000000
[Fri Sep  5 11:37:08 2014] ath10k: [12]: 0x00000009 0xFFFFFFFF
0x00958360 0x0095836B
[Fri Sep  5 11:37:08 2014] ath10k: [16]: 0x00958080 0x009BD000
0x00000000 0x00000000
[Fri Sep  5 11:37:08 2014] ath10k: [20]: 0x40949FF9 0x0040AB44
0x00000000 0x0043AC74
[Fri Sep  5 11:37:08 2014] ath10k: [24]: 0x8099519C 0x0040ABA4
0x00000F40 0xC0949FF9
[Fri Sep  5 11:37:08 2014] ath10k: [28]: 0x8099861D 0x0040ABC4
0x00424B2C 0x00439E64
[Fri Sep  5 11:37:08 2014] ath10k: [32]: 0x80998802 0x0040AD14
0x00000000 0x0042DD18
[Fri Sep  5 11:37:08 2014] ath10k: [36]: 0x80998704 0x0040AD44
0x0042DD18 0x00000002
[Fri Sep  5 11:37:08 2014] ath10k: [40]: 0x80998830 0x0040AD74
0x00439EC4 0x0042DD18
[Fri Sep  5 11:37:08 2014] ath10k: [44]: 0x809970B2 0x0040AD94
0x00439EC4 0x00000002
[Fri Sep  5 11:37:08 2014] ath10k: [48]: 0x80998EF5 0x0040ADB4
0x0041FA54 0x00425760
[Fri Sep  5 11:37:08 2014] ath10k: [52]: 0x809BCF0D 0x0040AEE4
0x004245FC 0x00000002
[Fri Sep  5 11:37:08 2014] ath10k: [56]: 0x80940F18 0x0040AF14
0x00000005 0x004039E4
[Fri Sep  5 11:37:13 2014] ath10k: failed to synchronise monitor vdev 1: -110
[Fri Sep  5 11:37:13 2014] ath10k: failed to stop monitor vdev: -110
[Fri Sep  5 11:37:16 2014] ath10k: failed to request wmi monitor vdev
1 removal: -11
[Fri Sep  5 11:37:16 2014] ath10k: failed to delete monitor vdev: -11
[Fri Sep  5 11:37:19 2014] ath10k_wmi_vdev_start_restart: dtim_period=0
[Fri Sep  5 11:37:19 2014] ath10k: peer 88:dc:96:XX:XX:XX on vdev 0
already exists
[Fri Sep  5 11:37:19 2014] ath10k: failed to add peer
88:dc:96:XX:XX:XX for vdev 0 when changing bssid: -22
[Fri Sep  5 11:37:19 2014] ath10k_wmi_vdev_start_restart: dtim_period=0
[Fri Sep  5 11:37:20 2014] ath10k: device successfully recovered


From michal.kazior at tieto.com  Sun Sep  7 23:28:58 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 8 Sep 2014 08:28:58 +0200
Subject: Firmware crash w/ 10.2 diagnosis?
In-Reply-To: <CABnBrYV4Lh7EF9xaEK6zkPk0HhU=iP283WhH+wA9=i7XfHroGg@mail.gmail.com>
References: <CABnBrYV4Lh7EF9xaEK6zkPk0HhU=iP283WhH+wA9=i7XfHroGg@mail.gmail.com>
Message-ID: <CA+BoTQ=tDMX4TKwmGcML4n-r-LPV3aici=X4Ms4rACoBhq2cKA@mail.gmail.com>

On 5 September 2014 22:56, Denton Gentry <denton.gentry at gmail.com> wrote:
> Can anyone tell me what this firmware crash means?
> I don't have steps to reproduce it, it seems to happen randomly. The
> clients are mostly idle.
>
> [Fri Sep  5 11:37:08 2014] ath10k: firmware crashed!
> [Fri Sep  5 11:37:08 2014] ath10k: hardware name qca988x hw2.0 version
> 0x4100016c
> [Fri Sep  5 11:37:08 2014] ath10k: firmware version: 10.2-00082-4-2
> [Fri Sep  5 11:37:08 2014] ath10k: target register Dump Location: 0x0040AA34
> [Fri Sep  5 11:37:08 2014] ath10k: target Register Dump
> [Fri Sep  5 11:37:08 2014] ath10k: [00]: 0x4100016C 0x00000000
> 0x00949FF9 0x803044BE
> [Fri Sep  5 11:37:08 2014] ath10k: [04]: 0x00949FF9 0x00060730
> 0x00000015 0x00000002
> [Fri Sep  5 11:37:08 2014] ath10k: [08]: 0x00425BD0 0x803044BE
> 0x00000000 0x00000000
> [Fri Sep  5 11:37:08 2014] ath10k: [12]: 0x00000009 0xFFFFFFFF
> 0x00958360 0x0095836B
> [Fri Sep  5 11:37:08 2014] ath10k: [16]: 0x00958080 0x009BD000
> 0x00000000 0x00000000
> [Fri Sep  5 11:37:08 2014] ath10k: [20]: 0x40949FF9 0x0040AB44
> 0x00000000 0x0043AC74
> [Fri Sep  5 11:37:08 2014] ath10k: [24]: 0x8099519C 0x0040ABA4
> 0x00000F40 0xC0949FF9
> [Fri Sep  5 11:37:08 2014] ath10k: [28]: 0x8099861D 0x0040ABC4
> 0x00424B2C 0x00439E64
> [Fri Sep  5 11:37:08 2014] ath10k: [32]: 0x80998802 0x0040AD14
> 0x00000000 0x0042DD18
> [Fri Sep  5 11:37:08 2014] ath10k: [36]: 0x80998704 0x0040AD44
> 0x0042DD18 0x00000002
> [Fri Sep  5 11:37:08 2014] ath10k: [40]: 0x80998830 0x0040AD74
> 0x00439EC4 0x0042DD18
> [Fri Sep  5 11:37:08 2014] ath10k: [44]: 0x809970B2 0x0040AD94
> 0x00439EC4 0x00000002
> [Fri Sep  5 11:37:08 2014] ath10k: [48]: 0x80998EF5 0x0040ADB4
> 0x0041FA54 0x00425760
> [Fri Sep  5 11:37:08 2014] ath10k: [52]: 0x809BCF0D 0x0040AEE4
> 0x004245FC 0x00000002
> [Fri Sep  5 11:37:08 2014] ath10k: [56]: 0x80940F18 0x0040AF14
> 0x00000005 0x004039E4
> [Fri Sep  5 11:37:13 2014] ath10k: failed to synchronise monitor vdev 1: -110
> [Fri Sep  5 11:37:13 2014] ath10k: failed to stop monitor vdev: -110
> [Fri Sep  5 11:37:16 2014] ath10k: failed to request wmi monitor vdev
> 1 removal: -11
> [Fri Sep  5 11:37:16 2014] ath10k: failed to delete monitor vdev: -11
> [Fri Sep  5 11:37:19 2014] ath10k_wmi_vdev_start_restart: dtim_period=0
> [Fri Sep  5 11:37:19 2014] ath10k: peer 88:dc:96:XX:XX:XX on vdev 0
> already exists
> [Fri Sep  5 11:37:19 2014] ath10k: failed to add peer
> 88:dc:96:XX:XX:XX for vdev 0 when changing bssid: -22
> [Fri Sep  5 11:37:19 2014] ath10k_wmi_vdev_start_restart: dtim_period=0

Hmm, you seem to be using some custom patches on ath10k. It seems you
were running a station interface and it roamed but for some reason it
tried to stop monitor vdev as well?

Can you share more details on what your setup is? What the custom patches are?


Micha?


From denton.gentry at gmail.com  Mon Sep  8 05:42:02 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Mon, 8 Sep 2014 05:42:02 -0700
Subject: Firmware crash w/ 10.2 diagnosis?
In-Reply-To: <CA+BoTQ=tDMX4TKwmGcML4n-r-LPV3aici=X4Ms4rACoBhq2cKA@mail.gmail.com>
References: <CABnBrYV4Lh7EF9xaEK6zkPk0HhU=iP283WhH+wA9=i7XfHroGg@mail.gmail.com>
 <CA+BoTQ=tDMX4TKwmGcML4n-r-LPV3aici=X4Ms4rACoBhq2cKA@mail.gmail.com>
Message-ID: <CABnBrYVb+BN4BFxrj82dj0KypxEy6GGYXtOitVW7twtzTeCArA@mail.gmail.com>

The ath10k is operating in AP mode.

Its using a base ath10k driver from a few months ago:

       git fetch git://github.com/kvalo/ath.git ath-next
       git checkout v3.15-rc1-237-gd9bc4b9

We've pulled in selected changes since. Notably:

warm reset
http://lists.infradead.org/pipermail/ath10k/2014-May/001992.html
http://lists.infradead.org/pipermail/ath10k/2014-May/001993.html

RX Reordering
http://lists.infradead.org/pipermail/ath10k/2014-July/002637.html
http://lists.infradead.org/pipermail/ath10k/2014-July/002621.html
http://lists.infradead.org/pipermail/ath10k/2014-July/002746.html
http://lists.infradead.org/pipermail/ath10k/2014-July/002784.html

Firmware 10.2
https://github.com/kvalo/ath/commit/24c88f7807fb7c723690474d0a5d3441468185d9

More recently, we pulled in TX credit and flushing changes
http://lists.infradead.org/pipermail/ath10k/2014-April/001765.html
http://lists.infradead.org/pipermail/ath10k/2014-April/001709.html
http://lists.infradead.org/pipermail/ath10k/2014-April/001706.html
http://lists.infradead.org/pipermail/ath10k/2014-April/001708.html


The data from the firmware shows something about a monitor vdev being
removed? hostapd does create a monitor interface, though I don't see
an indication that it was being removed at the time of the crash.
hostapd had exited and restarted well before though, is it possible
that removal of a monitor interface some time ago might be
contributing?

On Sun, Sep 7, 2014 at 11:28 PM, Michal Kazior <michal.kazior at tieto.com> wrote:
> On 5 September 2014 22:56, Denton Gentry <denton.gentry at gmail.com> wrote:
>> Can anyone tell me what this firmware crash means?
>> I don't have steps to reproduce it, it seems to happen randomly. The
>> clients are mostly idle.
>>
>> [Fri Sep  5 11:37:08 2014] ath10k: firmware crashed!
>> [Fri Sep  5 11:37:08 2014] ath10k: hardware name qca988x hw2.0 version
>> 0x4100016c
>> [Fri Sep  5 11:37:08 2014] ath10k: firmware version: 10.2-00082-4-2
>> [Fri Sep  5 11:37:08 2014] ath10k: target register Dump Location: 0x0040AA34
>> [Fri Sep  5 11:37:08 2014] ath10k: target Register Dump
>> [Fri Sep  5 11:37:08 2014] ath10k: [00]: 0x4100016C 0x00000000
>> 0x00949FF9 0x803044BE
>> [Fri Sep  5 11:37:08 2014] ath10k: [04]: 0x00949FF9 0x00060730
>> 0x00000015 0x00000002
>> [Fri Sep  5 11:37:08 2014] ath10k: [08]: 0x00425BD0 0x803044BE
>> 0x00000000 0x00000000
>> [Fri Sep  5 11:37:08 2014] ath10k: [12]: 0x00000009 0xFFFFFFFF
>> 0x00958360 0x0095836B
>> [Fri Sep  5 11:37:08 2014] ath10k: [16]: 0x00958080 0x009BD000
>> 0x00000000 0x00000000
>> [Fri Sep  5 11:37:08 2014] ath10k: [20]: 0x40949FF9 0x0040AB44
>> 0x00000000 0x0043AC74
>> [Fri Sep  5 11:37:08 2014] ath10k: [24]: 0x8099519C 0x0040ABA4
>> 0x00000F40 0xC0949FF9
>> [Fri Sep  5 11:37:08 2014] ath10k: [28]: 0x8099861D 0x0040ABC4
>> 0x00424B2C 0x00439E64
>> [Fri Sep  5 11:37:08 2014] ath10k: [32]: 0x80998802 0x0040AD14
>> 0x00000000 0x0042DD18
>> [Fri Sep  5 11:37:08 2014] ath10k: [36]: 0x80998704 0x0040AD44
>> 0x0042DD18 0x00000002
>> [Fri Sep  5 11:37:08 2014] ath10k: [40]: 0x80998830 0x0040AD74
>> 0x00439EC4 0x0042DD18
>> [Fri Sep  5 11:37:08 2014] ath10k: [44]: 0x809970B2 0x0040AD94
>> 0x00439EC4 0x00000002
>> [Fri Sep  5 11:37:08 2014] ath10k: [48]: 0x80998EF5 0x0040ADB4
>> 0x0041FA54 0x00425760
>> [Fri Sep  5 11:37:08 2014] ath10k: [52]: 0x809BCF0D 0x0040AEE4
>> 0x004245FC 0x00000002
>> [Fri Sep  5 11:37:08 2014] ath10k: [56]: 0x80940F18 0x0040AF14
>> 0x00000005 0x004039E4
>> [Fri Sep  5 11:37:13 2014] ath10k: failed to synchronise monitor vdev 1: -110
>> [Fri Sep  5 11:37:13 2014] ath10k: failed to stop monitor vdev: -110
>> [Fri Sep  5 11:37:16 2014] ath10k: failed to request wmi monitor vdev
>> 1 removal: -11
>> [Fri Sep  5 11:37:16 2014] ath10k: failed to delete monitor vdev: -11
>> [Fri Sep  5 11:37:19 2014] ath10k_wmi_vdev_start_restart: dtim_period=0
>> [Fri Sep  5 11:37:19 2014] ath10k: peer 88:dc:96:XX:XX:XX on vdev 0
>> already exists
>> [Fri Sep  5 11:37:19 2014] ath10k: failed to add peer
>> 88:dc:96:XX:XX:XX for vdev 0 when changing bssid: -22
>> [Fri Sep  5 11:37:19 2014] ath10k_wmi_vdev_start_restart: dtim_period=0
>
> Hmm, you seem to be using some custom patches on ath10k. It seems you
> were running a station interface and it roamed but for some reason it
> tried to stop monitor vdev as well?
>
> Can you share more details on what your setup is? What the custom patches are?
>
>
> Micha?


From greearb at candelatech.com  Mon Sep  8 08:51:47 2014
From: greearb at candelatech.com (Ben Greear)
Date: Mon, 08 Sep 2014 08:51:47 -0700
Subject: RTS threshold ignored in ath10k?
Message-ID: <540DD093.5070702@candelatech.com>

We did some tests using ath9k and ath10k.  It seems that ath10k
completely ignores RTS threshold settings.

I haven't had time to look into the code yet, but will try to
do so next week.

Thanks,
Ben

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



From s.gottschall at dd-wrt.com  Mon Sep  8 12:50:44 2014
From: s.gottschall at dd-wrt.com (Sebastian Gottschall)
Date: Mon, 08 Sep 2014 21:50:44 +0200
Subject: RTS threshold ignored in ath10k?
In-Reply-To: <540DD093.5070702@candelatech.com>
References: <540DD093.5070702@candelatech.com>
Message-ID: <540E0894.9080407@dd-wrt.com>

Am 08.09.2014 um 17:51 schrieb Ben Greear:
> We did some tests using ath9k and ath10k.  It seems that ath10k
> completely ignores RTS threshold settings.
>
> I haven't had time to look into the code yet, but will try to
> do so next week.
>
> Thanks,
> Ben
>
could you please also take a look into ack timing settings? right now 
its impossible for me to establish longer links with ath10k

Sebastian


From kvalo at qca.qualcomm.com  Tue Sep  9 05:08:21 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 9 Sep 2014 15:08:21 +0300
Subject: Firmware crash w/ 10.2 diagnosis?
In-Reply-To: <CABnBrYVb+BN4BFxrj82dj0KypxEy6GGYXtOitVW7twtzTeCArA@mail.gmail.com>
 (Denton Gentry's message of "Mon, 8 Sep 2014 05:42:02 -0700")
References: <CABnBrYV4Lh7EF9xaEK6zkPk0HhU=iP283WhH+wA9=i7XfHroGg@mail.gmail.com>
 <CA+BoTQ=tDMX4TKwmGcML4n-r-LPV3aici=X4Ms4rACoBhq2cKA@mail.gmail.com>
 <CABnBrYVb+BN4BFxrj82dj0KypxEy6GGYXtOitVW7twtzTeCArA@mail.gmail.com>
Message-ID: <87tx4h8096.fsf@kamboji.qca.qualcomm.com>

Denton Gentry <denton.gentry at gmail.com> writes:

> The ath10k is operating in AP mode.
>
> Its using a base ath10k driver from a few months ago:
>
>        git fetch git://github.com/kvalo/ath.git ath-next
>        git checkout v3.15-rc1-237-gd9bc4b9

What is the kernel version? Do you use backports?

> The data from the firmware shows something about a monitor vdev being
> removed? hostapd does create a monitor interface, though I don't see
> an indication that it was being removed at the time of the crash.
> hostapd had exited and restarted well before though, is it possible
> that removal of a monitor interface some time ago might be
> contributing?

So are you still using the old cooked monitor interface for management
frames? I strongly recommend switching to the new way of transmitting
and receiving management frames through nl80211 as then hostapd will not
a create monitor interface. This is what most people use and is most
extensively tested.

Commit 6e3e939f3b1bf8534b32ad09ff199d88800835a0 ('net: add wireless TX
status socket option') adds this capability to the kernel, first
released in Linux 3.3. There might be some dependencies in case you are
porting it to an older kernel, so be extra careful.

Please note that updating backports is not enough for SO_WIFI_STATUS
status, you need to update the kernel itself.

-- 
Kalle Valo


From michal.kazior at tieto.com  Tue Sep  9 05:48:13 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 9 Sep 2014 14:48:13 +0200
Subject: Firmware crash w/ 10.2 diagnosis?
In-Reply-To: <87tx4h8096.fsf@kamboji.qca.qualcomm.com>
References: <CABnBrYV4Lh7EF9xaEK6zkPk0HhU=iP283WhH+wA9=i7XfHroGg@mail.gmail.com>
 <CA+BoTQ=tDMX4TKwmGcML4n-r-LPV3aici=X4Ms4rACoBhq2cKA@mail.gmail.com>
 <CABnBrYVb+BN4BFxrj82dj0KypxEy6GGYXtOitVW7twtzTeCArA@mail.gmail.com>
 <87tx4h8096.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQnC0Px3gi6nK1MTjFMTr2cY0dTntCi+KBcvnEd31ELVZA@mail.gmail.com>

On 9 September 2014 14:08, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Denton Gentry <denton.gentry at gmail.com> writes:
>
>> The ath10k is operating in AP mode.
>>
>> Its using a base ath10k driver from a few months ago:
>>
>>        git fetch git://github.com/kvalo/ath.git ath-next
>>        git checkout v3.15-rc1-237-gd9bc4b9
>
> What is the kernel version? Do you use backports?
>
>> The data from the firmware shows something about a monitor vdev being
>> removed? hostapd does create a monitor interface, though I don't see
>> an indication that it was being removed at the time of the crash.
>> hostapd had exited and restarted well before though, is it possible
>> that removal of a monitor interface some time ago might be
>> contributing?
>
> So are you still using the old cooked monitor interface for management
> frames? I strongly recommend switching to the new way of transmitting
> and receiving management frames through nl80211 as then hostapd will not
> a create monitor interface. This is what most people use and is most
> extensively tested.

I don't think he's using cooked monitor. Instead his AP interface was
in a bridge which means it was promiscuous which means ath10k used
monitor vdev. That's perfectly normal.

Warnings I was concerned about are actually a result of recovery
procedure itself and do not seem to be related to the crash root
cause.


Micha?


From denton.gentry at gmail.com  Tue Sep  9 13:05:21 2014
From: denton.gentry at gmail.com (Denton Gentry)
Date: Tue, 9 Sep 2014 13:05:21 -0700
Subject: Firmware crash w/ 10.2 diagnosis?
In-Reply-To: <CA+BoTQnC0Px3gi6nK1MTjFMTr2cY0dTntCi+KBcvnEd31ELVZA@mail.gmail.com>
References: <CABnBrYV4Lh7EF9xaEK6zkPk0HhU=iP283WhH+wA9=i7XfHroGg@mail.gmail.com>
 <CA+BoTQ=tDMX4TKwmGcML4n-r-LPV3aici=X4Ms4rACoBhq2cKA@mail.gmail.com>
 <CABnBrYVb+BN4BFxrj82dj0KypxEy6GGYXtOitVW7twtzTeCArA@mail.gmail.com>
 <87tx4h8096.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQnC0Px3gi6nK1MTjFMTr2cY0dTntCi+KBcvnEd31ELVZA@mail.gmail.com>
Message-ID: <CABnBrYV6MSw1LgcgbL4O4sgR0K_P-9jCMEhOvMDmPt8yw2UeXQ@mail.gmail.com>

I'm using backports, and the kernel version is 3.2.
hostapd says it is indeed using the cooked monitor:

    monitor mode needed: 1 (poll_cmd=1 data_tx_status=0)

I'll look at updating the kernel, if not to 3.16 then at least to
something recent enough to stop using the monitor interface from
hostapd.

On Tue, Sep 9, 2014 at 5:48 AM, Michal Kazior <michal.kazior at tieto.com> wrote:
> On 9 September 2014 14:08, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> Denton Gentry <denton.gentry at gmail.com> writes:
>>
>>> The ath10k is operating in AP mode.
>>>
>>> Its using a base ath10k driver from a few months ago:
>>>
>>>        git fetch git://github.com/kvalo/ath.git ath-next
>>>        git checkout v3.15-rc1-237-gd9bc4b9
>>
>> What is the kernel version? Do you use backports?
>>
>>> The data from the firmware shows something about a monitor vdev being
>>> removed? hostapd does create a monitor interface, though I don't see
>>> an indication that it was being removed at the time of the crash.
>>> hostapd had exited and restarted well before though, is it possible
>>> that removal of a monitor interface some time ago might be
>>> contributing?
>>
>> So are you still using the old cooked monitor interface for management
>> frames? I strongly recommend switching to the new way of transmitting
>> and receiving management frames through nl80211 as then hostapd will not
>> a create monitor interface. This is what most people use and is most
>> extensively tested.
>
> I don't think he's using cooked monitor. Instead his AP interface was
> in a bridge which means it was promiscuous which means ath10k used
> monitor vdev. That's perfectly normal.
>
> Warnings I was concerned about are actually a result of recovery
> procedure itself and do not seem to be related to the crash root
> cause.
>
>
> Micha?


From Nick.Shu at spirent.com  Tue Sep  9 13:24:43 2014
From: Nick.Shu at spirent.com (Shu, Nick)
Date: Tue, 9 Sep 2014 20:24:43 +0000
Subject: How to set ath10k NIC to a specific wifi mode?
Message-ID: <153F35912E69C446A72CF7D6417EBADE13AFF2AD@SPCCOREXCMBX01.AD.SPIRENTCOM.COM>

Hi, All:
I have an ath10k PCIe NIC card that supports A/B/G/N/AC wifi modes.
Can somebody tell me that is there any way I can set it to work on a specific mode like wifiN mode? By using "iw" or any other tool under Linux OS?
Thanks!
Nick Shu
Spirent Communications e-mail confidentiality.
------------------------------------------------------------------------
This e-mail contains confidential and / or privileged information belonging to Spirent Communications plc, its affiliates and / or subsidiaries. If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution and / or the taking of any action based upon reliance on the contents of this transmission is strictly forbidden. If you have received this message in error please notify the sender by return e-mail and delete it from your system.

Spirent Communications plc
Northwood Park, Gatwick Road, Crawley, West Sussex, RH10 9XN, United Kingdom.
Tel No. +44 (0) 1293 767676
Fax No. +44 (0) 1293 767677

Registered in England Number 470893
Registered at Northwood Park, Gatwick Road, Crawley, West Sussex, RH10 9XN, United Kingdom.

Or if within the US,

Spirent Communications,
26750 Agoura Road, Calabasas, CA, 91302, USA.
Tel No. 1-818-676- 2300


From kvalo at qca.qualcomm.com  Wed Sep 10 04:14:23 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 14:14:23 +0300
Subject: [PATCH] ath10k: move fw_crash_dump allocation
In-Reply-To: <1409814788-1661-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 4 Sep 2014 09:13:08 +0200")
References: <1409814788-1661-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <878ulr9180.fsf@kamboji.qca.qualcomm.com>

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

> The fw_crash_data was allocated too late. Upon
> early firmware crash, before registering to
> mac80211, it was possible to crash the whole
> system:
>
>  ath10k_pci 0000:00:05.0: device has crashed during init
>  BUG: unable to handle kernel NULL pointer dereference at           (null)

[...]

>  ---[ end Kernel panic - not syncing: Fatal exception in interrupt
>
> To prevent that split debug functions and allocate
> fw_crash_data earlier.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Sep 10 04:17:27 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 14:17:27 +0300
Subject: [PATCH] ath10k: use proper service bitmap size
In-Reply-To: <1409818712-7493-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 4 Sep 2014 10:18:32 +0200")
References: <1409818712-7493-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <874mwf912w.fsf@kamboji.qca.qualcomm.com>

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

> On 32bit systems the bitmap was too small and it
> was overwritten partially by the stat completion
> structure. This was visible with 10.2 firmware
> only due to it using a few of the last service
> ids.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Sep 10 04:23:17 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 14:23:17 +0300
Subject: [PATCH] ath10k: ATH10K_DEBUGFS depends on DEBUG_FS
In-Reply-To: <1409835069-2246-1-git-send-email-matteo@openwrt.org> (Matteo
 Croce's message of "Thu, 4 Sep 2014 14:51:09 +0200")
References: <1409835069-2246-1-git-send-email-matteo@openwrt.org>
Message-ID: <87zje77m8q.fsf@kamboji.qca.qualcomm.com>

Matteo Croce <matteo at openwrt.org> writes:

> ATH10K_DEBUGFS must depend on DEBUG_FS, otherwise
> ath10k will generate an invalid pointer on module load
>
> Signed-off-by: Matteo Croce <matteo at openwrt.org>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Sep 10 07:49:04 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 17:49:04 +0300
Subject: [PATCH v3 2/2] ath10k: add testmode
In-Reply-To: <CA+BoTQmheuGLxicMCwVREkru5eh7FxV3T8qmsME4U5_2vi-iyA@mail.gmail.com>
 (Michal Kazior's message of "Fri, 5 Sep 2014 09:27:57 +0200")
References: <20140904135447.26750.52873.stgit@potku.adurom.net>
 <20140904135654.26750.69133.stgit@potku.adurom.net>
 <CA+BoTQmheuGLxicMCwVREkru5eh7FxV3T8qmsME4U5_2vi-iyA@mail.gmail.com>
Message-ID: <87egvj7cpr.fsf@kamboji.qca.qualcomm.com>

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

> (On 4 September 2014 15:56, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> Add testmode interface for starting and using UTF firmware which is used to run
>> factory tests. This is implemented by adding new state ATH10K_STATE_UTF and user
>> space can enable this state with ATH10K_TM_CMD_UTF_START command. To go back to
>> normal mode user space can send ATH10K_TM_CMD_UTF_STOP.
>>
>> Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
>> ---
> [...]
>> +bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
>> +{
>> +       struct sk_buff *nl_skb;
>> +       bool consumed;
>> +       int ret;
>> +
>> +       ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
>> +                  "testmode event wmi cmd_id %d skb %p skb->len %d\n",
>> +                  cmd_id, skb, skb->len);
>> +
>> +       ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
>> +
>> +       spin_lock_bh(&ar->data_lock);
>> +
>> +       if (!ar->testmode.utf_monitor) {
>> +               consumed = false;
>> +               goto out;
>> +       }
>> +
>> +       /* Only testmode.c should be handling events from utf firmware,
>> +        * otherwise all sort of problems will arise as mac80211 operations
>> +        * are not initialised. */
>
> Comment style.

Argh, will I ever learn :) Fixed now.

>> +static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
>> +{
>> +       char filename[100];
>> +       int ret;
>> +
>> +       ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
>> +
>> +       mutex_lock(&ar->conf_mutex);
>> +
>> +       if (ar->state == ATH10K_STATE_UTF) {
>> +               ret = -EALREADY;
>> +               goto err;
>> +       }
>> +
>> +       /* start utf only when the driver is not in use  */
>> +       if (ar->state != ATH10K_STATE_OFF) {
>> +               ret = -EBUSY;
>> +               goto err;
>> +       }
>> +
>> +       if (ar->testmode.utf != NULL)
>> +               /* utf image is already downloaded */
>> +               goto power_up;
>
> I believe this shouldn't happen with the current code. We should
> probably treat it with a if (WARN_ON(utf != NULL)) goto err;

Yeah, I'll add that.

>> +void ath10k_testmode_destroy(struct ath10k *ar)
>> +{
>> +       mutex_lock(&ar->conf_mutex);
>> +
>> +       release_firmware(ar->testmode.utf);
>> +       ar->testmode.utf = NULL;
>> +
>> +       if (ar->state != ATH10K_STATE_UTF) {
>> +               /* utf firmware is not running, nothing to do */
>> +               goto out;
>> +       }
>> +
>> +       ath10k_core_stop(ar);
>
> Hmm, you don't call power_down here. This isn't a problem from a
> practical point of view after my recent changes but hey.
>
> How about we split out guts from ath10k_tm_cmd_utf_stop() to
> __ath10k_tm_cmd_utf_stop() (which assumes conf_mutex is already held)
> and call it here like this:
>
>  mutex_lock(conf_mutex);
>  if (ar->state==UTF)
>    __ath10k_tm_cmd_utf_stop(ar);
>  mutex_unlock(conf_mutex);

Good idea, I'll do that.

>> @@ -2488,6 +2490,17 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
>>
>>         trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
>>
>> +       consumed = ath10k_tm_event_wmi(ar, id, skb);
>> +
>> +       /* Ready event must be handled normally also in UTF mode so that we
>> +        * know the UTF firmware has booted, others we are just bypass WMI
>> +        * events to testmode. */
>
> Comment style.

Fixed.

Thanks for the review! I'll send v4 soon.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Sep 10 08:23:16 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 18:23:16 +0300
Subject: [PATCH v4 0/2] ath10k: testmode support
Message-ID: <20140910152136.12610.18499.stgit@potku.adurom.net>

Hi,

latest version of my testmode patches. Getting closer, more or less cosmetic
changes this time :)

v4:

* fix comment style (Michal)

* add extra checks for at->testmode.utf (Michal)

* add __ath10k_tm_cmd_utf_stop() and call it from
  ath10k_testmode_destroy() (Michal)

v3:

* remove false "fall through" comment in ath10k_start() (Michal)

* fix multiline comment style (Michal)

* put testmode interface definitions to testmode_uapi.h (or similar) (Johannes)

* document __set_bit(ar->fw_features) better (Michal)

* ath10k_tm_cmd_utf_start(): return ar->fw_feature value if there's an error

* free firmware in ath10k_tm_cmd_utf_start() when an error happens (Michal)

* ath10k_tm_cmd_utf_start(): move hif_power_down() to err_power_down label


v2:

* check error from ath10k_wmi_alloc_skb() (Michal)

* int err -> int ret (Michal)

* fix conflicts in core.c

* add ar->testmode.utf_monitor to check if ath10k_tm_event_wmi()
  should deliver WMI events or not

* print mode in ath10k_download_fw() log messages

* set ar->testmode.utf to NULL after it's released (Michal)

* release ar->testmode.utf also in ath10k_tm_cmd_utf_stop()

* rename ath10k_testmode_unregister() to ath10k_testmode_destroy()

* call ath10k_core_stop() in ath10k_testmode_destroy() (Michal)

* document wmi packet format in testmode commands (Michal)

* consume WMI packets so that mac80211 calls are not made in UTF mode (Michal)

* force to use 10x WMI interface with UTF firmware

* API change: remove ATH10K_TM_CMD_EVENT_WMI, use ATH10K_TM_CMD_WMI also for events

* API change: add major and minor version numbers to
  ATH10K_TM_CMD_GET_VERSION for the user space more easily to detect
  interface changes

* use conf_mutex in ath10k_tm_cmd_wmi()

* print "UTF firmware started" and "UTF firmware stopped"

* print "testmode %d" in ath10k_print_driver_info()

* don't call ath10k_wait_for_suspend() in UTF mode

---

Kalle Valo (2):
      ath10k: make ath10k_wmi_cmd_send() public
      ath10k: add testmode


 drivers/net/wireless/ath/ath10k/Makefile     |    1 
 drivers/net/wireless/ath/ath10k/core.c       |   88 ++++--
 drivers/net/wireless/ath/ath10k/core.h       |   22 +-
 drivers/net/wireless/ath/ath10k/debug.c      |    5 
 drivers/net/wireless/ath/ath10k/debug.h      |    1 
 drivers/net/wireless/ath/ath10k/hw.h         |    2 
 drivers/net/wireless/ath/ath10k/mac.c        |    9 +
 drivers/net/wireless/ath/ath10k/testmode.c   |  381 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/testmode.h   |   46 +++
 drivers/net/wireless/ath/ath10k/testmode_i.h |   70 +++++
 drivers/net/wireless/ath/ath10k/wmi.c        |   23 +-
 drivers/net/wireless/ath/ath10k/wmi.h        |    4 
 12 files changed, 619 insertions(+), 33 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode.c
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode.h
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode_i.h



From kvalo at qca.qualcomm.com  Wed Sep 10 08:23:23 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 18:23:23 +0300
Subject: [PATCH v4 1/2] ath10k: make ath10k_wmi_cmd_send() public
In-Reply-To: <20140910152136.12610.18499.stgit@potku.adurom.net>
References: <20140910152136.12610.18499.stgit@potku.adurom.net>
Message-ID: <20140910152323.12610.46916.stgit@potku.adurom.net>

We need this function to send wmi packets from testmode.c.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/wmi.c |    5 ++---
 drivers/net/wireless/ath/ath10k/wmi.h |    4 ++++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index e7edc89cfcd0..67af370012f9 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -624,7 +624,7 @@ int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar)
 	return ret;
 }
 
-static struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len)
+struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len)
 {
 	struct sk_buff *skb;
 	u32 round_len = roundup(len, 4);
@@ -725,8 +725,7 @@ static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar)
 	wake_up(&ar->wmi.tx_credits_wq);
 }
 
-static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
-			       u32 cmd_id)
+int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
 {
 	int ret = -EOPNOTSUPP;
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index bdb2e6cc0f4c..f8c1afbdb442 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -4737,6 +4737,10 @@ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
 int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
 
 int ath10k_wmi_connect(struct ath10k *ar);
+
+struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
+int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
+
 int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
 				const struct wmi_channel_arg *);
 int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);



From kvalo at qca.qualcomm.com  Wed Sep 10 08:23:30 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 18:23:30 +0300
Subject: [PATCH v4 2/2] ath10k: add testmode
In-Reply-To: <20140910152136.12610.18499.stgit@potku.adurom.net>
References: <20140910152136.12610.18499.stgit@potku.adurom.net>
Message-ID: <20140910152329.12610.41409.stgit@potku.adurom.net>

Add testmode interface for starting and using UTF firmware which is used to run
factory tests. This is implemented by adding new state ATH10K_STATE_UTF and user
space can enable this state with ATH10K_TM_CMD_UTF_START command. To go back to
normal mode user space can send ATH10K_TM_CMD_UTF_STOP.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/Makefile     |    1 
 drivers/net/wireless/ath/ath10k/core.c       |   88 ++++--
 drivers/net/wireless/ath/ath10k/core.h       |   22 +-
 drivers/net/wireless/ath/ath10k/debug.c      |    5 
 drivers/net/wireless/ath/ath10k/debug.h      |    1 
 drivers/net/wireless/ath/ath10k/hw.h         |    2 
 drivers/net/wireless/ath/ath10k/mac.c        |    9 +
 drivers/net/wireless/ath/ath10k/testmode.c   |  381 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/testmode.h   |   46 +++
 drivers/net/wireless/ath/ath10k/testmode_i.h |   70 +++++
 drivers/net/wireless/ath/ath10k/wmi.c        |   18 +
 11 files changed, 613 insertions(+), 30 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode.c
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode.h
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode_i.h

diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index 2cfb63ca9327..8b1b1adb477a 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -11,6 +11,7 @@ ath10k_core-y += mac.o \
 		 bmi.o
 
 ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
+ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.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 eadb22519912..cee18c89d7f2 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -26,6 +26,7 @@
 #include "bmi.h"
 #include "debug.h"
 #include "htt.h"
+#include "testmode.h"
 
 unsigned int ath10k_debug_mask;
 static bool uart_print;
@@ -257,21 +258,42 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
 	return 0;
 }
 
-static int ath10k_download_fw(struct ath10k *ar)
+static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
 {
-	u32 address;
+	u32 address, data_len;
+	const char *mode_name;
+	const void *data;
 	int ret;
 
 	address = ar->hw_params.patch_load_addr;
 
-	ret = ath10k_bmi_fast_download(ar, address, ar->firmware_data,
-				       ar->firmware_len);
+	switch (mode) {
+	case ATH10K_FIRMWARE_MODE_NORMAL:
+		data = ar->firmware_data;
+		data_len = ar->firmware_len;
+		mode_name = "normal";
+		break;
+	case ATH10K_FIRMWARE_MODE_UTF:
+		data = ar->testmode.utf->data;
+		data_len = ar->testmode.utf->size;
+		mode_name = "utf";
+		break;
+	default:
+		ath10k_err(ar, "unknown firmware mode: %d\n", mode);
+		return -EINVAL;
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_BOOT,
+		   "boot uploading firmware image %p len %d mode %s\n",
+		   data, data_len, mode_name);
+
+	ret = ath10k_bmi_fast_download(ar, address, data, data_len);
 	if (ret) {
-		ath10k_err(ar, "could not write fw (%d)\n", ret);
-		goto exit;
+		ath10k_err(ar, "failed to download %s firmware: %d\n",
+			   mode_name, ret);
+		return ret;
 	}
 
-exit:
 	return ret;
 }
 
@@ -567,7 +589,8 @@ success:
 	return 0;
 }
 
-static int ath10k_init_download_firmware(struct ath10k *ar)
+static int ath10k_init_download_firmware(struct ath10k *ar,
+					 enum ath10k_firmware_mode mode)
 {
 	int ret;
 
@@ -583,7 +606,7 @@ static int ath10k_init_download_firmware(struct ath10k *ar)
 		return ret;
 	}
 
-	ret = ath10k_download_fw(ar);
+	ret = ath10k_download_fw(ar, mode);
 	if (ret) {
 		ath10k_err(ar, "failed to download firmware: %d\n", ret);
 		return ret;
@@ -685,12 +708,15 @@ static void ath10k_core_restart(struct work_struct *work)
 	case ATH10K_STATE_WEDGED:
 		ath10k_warn(ar, "device is wedged, will not restart\n");
 		break;
+	case ATH10K_STATE_UTF:
+		ath10k_warn(ar, "firmware restart in UTF mode not supported\n");
+		break;
 	}
 
 	mutex_unlock(&ar->conf_mutex);
 }
 
-int ath10k_core_start(struct ath10k *ar)
+int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
 {
 	int status;
 
@@ -703,7 +729,7 @@ int ath10k_core_start(struct ath10k *ar)
 		goto err;
 	}
 
-	status = ath10k_init_download_firmware(ar);
+	status = ath10k_init_download_firmware(ar, mode);
 	if (status)
 		goto err;
 
@@ -760,10 +786,12 @@ int ath10k_core_start(struct ath10k *ar)
 		goto err_hif_stop;
 	}
 
-	status = ath10k_htt_connect(&ar->htt);
-	if (status) {
-		ath10k_err(ar, "failed to connect htt (%d)\n", status);
-		goto err_hif_stop;
+	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+		status = ath10k_htt_connect(&ar->htt);
+		if (status) {
+			ath10k_err(ar, "failed to connect htt (%d)\n", status);
+			goto err_hif_stop;
+		}
 	}
 
 	status = ath10k_wmi_connect(ar);
@@ -778,11 +806,13 @@ int ath10k_core_start(struct ath10k *ar)
 		goto err_hif_stop;
 	}
 
-	status = ath10k_wmi_wait_for_service_ready(ar);
-	if (status <= 0) {
-		ath10k_warn(ar, "wmi service ready event not received");
-		status = -ETIMEDOUT;
-		goto err_hif_stop;
+	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+		status = ath10k_wmi_wait_for_service_ready(ar);
+		if (status <= 0) {
+			ath10k_warn(ar, "wmi service ready event not received");
+			status = -ETIMEDOUT;
+			goto err_hif_stop;
+		}
 	}
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
@@ -802,10 +832,13 @@ int ath10k_core_start(struct ath10k *ar)
 		goto err_hif_stop;
 	}
 
-	status = ath10k_htt_setup(&ar->htt);
-	if (status) {
-		ath10k_err(ar, "failed to setup htt: %d\n", status);
-		goto err_hif_stop;
+	/* we don't care about HTT in UTF mode */
+	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+		status = ath10k_htt_setup(&ar->htt);
+		if (status) {
+			ath10k_err(ar, "failed to setup htt: %d\n", status);
+			goto err_hif_stop;
+		}
 	}
 
 	status = ath10k_debug_start(ar);
@@ -861,7 +894,8 @@ void ath10k_core_stop(struct ath10k *ar)
 	lockdep_assert_held(&ar->conf_mutex);
 
 	/* try to suspend target */
-	if (ar->state != ATH10K_STATE_RESTARTING)
+	if (ar->state != ATH10K_STATE_RESTARTING &&
+	    ar->state != ATH10K_STATE_UTF)
 		ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
 
 	ath10k_debug_stop(ar);
@@ -914,7 +948,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 
 	mutex_lock(&ar->conf_mutex);
 
-	ret = ath10k_core_start(ar);
+	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
 	if (ret) {
 		ath10k_err(ar, "could not init core (%d)\n", ret);
 		ath10k_core_free_firmware_files(ar);
@@ -1041,6 +1075,8 @@ void ath10k_core_unregister(struct ath10k *ar)
 	 * unhappy about callback failures. */
 	ath10k_mac_unregister(ar);
 
+	ath10k_testmode_destroy(ar);
+
 	ath10k_core_free_firmware_files(ar);
 
 	ath10k_debug_unregister(ar);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index a2695e33f29a..fe531ea6926c 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -330,6 +330,17 @@ enum ath10k_state {
 	 * prevents completion timeouts and makes the driver more responsive to
 	 * userspace commands. This is also prevents recursive recovery. */
 	ATH10K_STATE_WEDGED,
+
+	/* factory tests */
+	ATH10K_STATE_UTF,
+};
+
+enum ath10k_firmware_mode {
+	/* the default mode, standard 802.11 functionality */
+	ATH10K_FIRMWARE_MODE_NORMAL,
+
+	/* factory tests etc */
+	ATH10K_FIRMWARE_MODE_UTF,
 };
 
 enum ath10k_fw_features {
@@ -543,6 +554,15 @@ struct ath10k {
 		struct ath10k_spec_scan config;
 	} spectral;
 
+	struct {
+		/* protected by conf_mutex */
+		const struct firmware *utf;
+		DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
+
+		/* protected by data_lock */
+		bool utf_monitor;
+	} testmode;
+
 	/* must be last */
 	u8 drv_priv[0] __aligned(sizeof(void *));
 };
@@ -551,7 +571,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 				  const struct ath10k_hif_ops *hif_ops);
 void ath10k_core_destroy(struct ath10k *ar);
 
-int ath10k_core_start(struct ath10k *ar);
+int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode);
 int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
 void ath10k_core_stop(struct ath10k *ar);
 int ath10k_core_register(struct ath10k *ar, u32 chip_id);
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 97109221ffb3..f948a4d8ee59 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -134,11 +134,12 @@ void ath10k_print_driver_info(struct ath10k *ar)
 		    ar->fw_api,
 		    ar->htt.target_version_major,
 		    ar->htt.target_version_minor);
-	ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d\n",
+	ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
 		    config_enabled(CONFIG_ATH10K_DEBUG),
 		    config_enabled(CONFIG_ATH10K_DEBUGFS),
 		    config_enabled(CONFIG_ATH10K_TRACING),
-		    config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
+		    config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
+		    config_enabled(CONFIG_NL80211_TESTMODE));
 }
 EXPORT_SYMBOL(ath10k_print_driver_info);
 
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 71c80842eea7..b3774f7f492c 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -34,6 +34,7 @@ enum ath10k_debug_mask {
 	ATH10K_DBG_DATA		= 0x00000200,
 	ATH10K_DBG_BMI		= 0x00000400,
 	ATH10K_DBG_REGULATORY	= 0x00000800,
+	ATH10K_DBG_TESTMODE	= 0x00001000,
 	ATH10K_DBG_ANY		= 0xffffffff,
 };
 
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 13568b01de9f..3cf5702c1e7e 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -36,6 +36,8 @@
 #define ATH10K_FW_API2_FILE		"firmware-2.bin"
 #define ATH10K_FW_API3_FILE		"firmware-3.bin"
 
+#define ATH10K_FW_UTF_FILE		"utf.bin"
+
 /* includes also the null byte */
 #define ATH10K_FIRMWARE_MAGIC               "QCA-ATH10K"
 
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index f80eeed16cb6..5b35fff8127f 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -26,6 +26,7 @@
 #include "wmi.h"
 #include "htt.h"
 #include "txrx.h"
+#include "testmode.h"
 
 /**********/
 /* Crypto */
@@ -2480,6 +2481,9 @@ static int ath10k_start(struct ieee80211_hw *hw)
 		WARN_ON(1);
 		ret = -EINVAL;
 		goto err;
+	case ATH10K_STATE_UTF:
+		ret = -EBUSY;
+		goto err;
 	}
 
 	ret = ath10k_hif_power_up(ar);
@@ -2488,7 +2492,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
 		goto err_off;
 	}
 
-	ret = ath10k_core_start(ar);
+	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
 	if (ret) {
 		ath10k_err(ar, "Could not init core: %d\n", ret);
 		goto err_power_down;
@@ -4456,6 +4460,9 @@ static const struct ieee80211_ops ath10k_ops = {
 	.sta_rc_update			= ath10k_sta_rc_update,
 	.get_tsf			= ath10k_get_tsf,
 	.ampdu_action			= ath10k_ampdu_action,
+
+	CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
+
 #ifdef CONFIG_PM
 	.suspend			= ath10k_suspend,
 	.resume				= ath10k_resume,
diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c
new file mode 100644
index 000000000000..9d77d72042ff
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2014 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 "testmode.h"
+
+#include <net/netlink.h>
+#include <linux/firmware.h>
+
+#include "debug.h"
+#include "wmi.h"
+#include "hif.h"
+#include "hw.h"
+
+#include "testmode_i.h"
+
+static const struct nla_policy ath10k_tm_policy[ATH10K_TM_ATTR_MAX + 1] = {
+	[ATH10K_TM_ATTR_CMD]		= { .type = NLA_U32 },
+	[ATH10K_TM_ATTR_DATA]		= { .type = NLA_BINARY,
+					    .len = ATH10K_TM_DATA_MAX_LEN },
+	[ATH10K_TM_ATTR_WMI_CMDID]	= { .type = NLA_U32 },
+	[ATH10K_TM_ATTR_VERSION_MAJOR]	= { .type = NLA_U32 },
+	[ATH10K_TM_ATTR_VERSION_MINOR]	= { .type = NLA_U32 },
+};
+
+/* Returns true if callee consumes the skb and the skb should be discarded.
+ * Returns false if skb is not used. Does not sleep.
+ */
+bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
+{
+	struct sk_buff *nl_skb;
+	bool consumed;
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+		   "testmode event wmi cmd_id %d skb %p skb->len %d\n",
+		   cmd_id, skb, skb->len);
+
+	ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
+
+	spin_lock_bh(&ar->data_lock);
+
+	if (!ar->testmode.utf_monitor) {
+		consumed = false;
+		goto out;
+	}
+
+	/* Only testmode.c should be handling events from utf firmware,
+	 * otherwise all sort of problems will arise as mac80211 operations
+	 * are not initialised.
+	 */
+	consumed = true;
+
+	nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
+						   2 * sizeof(u32) + skb->len,
+						   GFP_ATOMIC);
+	if (!nl_skb) {
+		ath10k_warn(ar,
+			    "failed to allocate skb for testmode wmi event\n");
+		goto out;
+	}
+
+	ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_CMD, ATH10K_TM_CMD_WMI);
+	if (ret) {
+		ath10k_warn(ar,
+			    "failed to to put testmode wmi event cmd attribute: %d\n",
+			    ret);
+		kfree_skb(nl_skb);
+		goto out;
+	}
+
+	ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_WMI_CMDID, cmd_id);
+	if (ret) {
+		ath10k_warn(ar,
+			    "failed to to put testmode wmi even cmd_id: %d\n",
+			    ret);
+		kfree_skb(nl_skb);
+		goto out;
+	}
+
+	ret = nla_put(nl_skb, ATH10K_TM_ATTR_DATA, skb->len, skb->data);
+	if (ret) {
+		ath10k_warn(ar,
+			    "failed to copy skb to testmode wmi event: %d\n",
+			    ret);
+		kfree_skb(nl_skb);
+		goto out;
+	}
+
+	cfg80211_testmode_event(nl_skb, GFP_ATOMIC);
+
+out:
+	spin_unlock_bh(&ar->data_lock);
+
+	return consumed;
+}
+
+static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
+{
+	struct sk_buff *skb;
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+		   "testmode cmd get version_major %d version_minor %d\n",
+		   ATH10K_TESTMODE_VERSION_MAJOR,
+		   ATH10K_TESTMODE_VERSION_MINOR);
+
+	skb = cfg80211_testmode_alloc_reply_skb(ar->hw->wiphy,
+						nla_total_size(sizeof(u32)));
+	if (!skb)
+		return -ENOMEM;
+
+	ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MAJOR,
+			  ATH10K_TESTMODE_VERSION_MAJOR);
+	if (ret) {
+		kfree_skb(skb);
+		return ret;
+	}
+
+	ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MINOR,
+			  ATH10K_TESTMODE_VERSION_MINOR);
+	if (ret) {
+		kfree_skb(skb);
+		return ret;
+	}
+
+	return cfg80211_testmode_reply(skb);
+}
+
+static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
+{
+	char filename[100];
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state == ATH10K_STATE_UTF) {
+		ret = -EALREADY;
+		goto err;
+	}
+
+	/* start utf only when the driver is not in use  */
+	if (ar->state != ATH10K_STATE_OFF) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	if (WARN_ON(ar->testmode.utf != NULL)) {
+		/* utf image is already downloaded, it shouldn't be */
+		ret = -EEXIST;
+		goto err;
+	}
+
+	snprintf(filename, sizeof(filename), "%s/%s",
+		 ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
+
+	/* load utf firmware image */
+	ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
+	if (ret) {
+		ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
+			    filename, ret);
+		goto err;
+	}
+
+	spin_lock_bh(&ar->data_lock);
+
+	ar->testmode.utf_monitor = true;
+
+	spin_unlock_bh(&ar->data_lock);
+
+	BUILD_BUG_ON(sizeof(ar->fw_features) !=
+		     sizeof(ar->testmode.orig_fw_features));
+
+	memcpy(ar->testmode.orig_fw_features, ar->fw_features,
+	       sizeof(ar->fw_features));
+
+	/* utf.bin firmware image does not advertise firmware features. Do
+	 * an ugly hack where we force the firmware features so that wmi.c
+	 * will use the correct WMI interface.
+	 */
+	memset(ar->fw_features, 0, sizeof(ar->fw_features));
+	__set_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features);
+
+	ret = ath10k_hif_power_up(ar);
+	if (ret) {
+		ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret);
+		ar->state = ATH10K_STATE_OFF;
+		goto err_fw_features;
+	}
+
+	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF);
+	if (ret) {
+		ath10k_err(ar, "failed to start core (testmode): %d\n", ret);
+		ar->state = ATH10K_STATE_OFF;
+		goto err_power_down;
+	}
+
+	ar->state = ATH10K_STATE_UTF;
+
+	ath10k_info(ar, "UTF firmware started\n");
+
+	mutex_unlock(&ar->conf_mutex);
+
+	return 0;
+
+err_power_down:
+	ath10k_hif_power_down(ar);
+
+err_fw_features:
+	/* return the original firmware features */
+	memcpy(ar->fw_features, ar->testmode.orig_fw_features,
+	       sizeof(ar->fw_features));
+
+	release_firmware(ar->testmode.utf);
+	ar->testmode.utf = NULL;
+
+err:
+	mutex_unlock(&ar->conf_mutex);
+
+	return ret;
+}
+
+static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
+{
+	lockdep_assert_held(&ar->conf_mutex);
+
+	ath10k_core_stop(ar);
+	ath10k_hif_power_down(ar);
+
+	spin_lock_bh(&ar->data_lock);
+
+	ar->testmode.utf_monitor = false;
+
+	spin_unlock_bh(&ar->data_lock);
+
+	/* return the original firmware features */
+	memcpy(ar->fw_features, ar->testmode.orig_fw_features,
+	       sizeof(ar->fw_features));
+
+	release_firmware(ar->testmode.utf);
+	ar->testmode.utf = NULL;
+}
+
+static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
+{
+	int ret;
+
+	ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf stop\n");
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_UTF) {
+		ret = -ENETDOWN;
+		goto out;
+	}
+
+	__ath10k_tm_cmd_utf_stop(ar);
+
+	ar->state = ATH10K_STATE_OFF;
+	ret = 0;
+
+	ath10k_info(ar, "UTF firmware stopped\n");
+
+out:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
+}
+
+static int ath10k_tm_cmd_wmi(struct ath10k *ar, struct nlattr *tb[])
+{
+	struct sk_buff *skb;
+	int ret, buf_len;
+	u32 cmd_id;
+	void *buf;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_UTF) {
+		ret = -ENETDOWN;
+		goto out;
+	}
+
+	if (!tb[ATH10K_TM_ATTR_DATA]) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (!tb[ATH10K_TM_ATTR_WMI_CMDID]) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	buf = nla_data(tb[ATH10K_TM_ATTR_DATA]);
+	buf_len = nla_len(tb[ATH10K_TM_ATTR_DATA]);
+	cmd_id = nla_get_u32(tb[ATH10K_TM_ATTR_WMI_CMDID]);
+
+	ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+		   "testmode cmd wmi cmd_id %d buf %p buf_len %d\n",
+		   cmd_id, buf, buf_len);
+
+	ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", buf, buf_len);
+
+	skb = ath10k_wmi_alloc_skb(ar, buf_len);
+	if (!skb) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(skb->data, buf, buf_len);
+
+	ret = ath10k_wmi_cmd_send(ar, skb, cmd_id);
+	if (ret) {
+		ath10k_warn(ar, "failed to transmit wmi command (testmode): %d\n",
+			    ret);
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
+}
+
+int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		  void *data, int len)
+{
+	struct ath10k *ar = hw->priv;
+	struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1];
+	int ret;
+
+	ret = nla_parse(tb, ATH10K_TM_ATTR_MAX, data, len,
+			ath10k_tm_policy);
+	if (ret)
+		return ret;
+
+	if (!tb[ATH10K_TM_ATTR_CMD])
+		return -EINVAL;
+
+	switch (nla_get_u32(tb[ATH10K_TM_ATTR_CMD])) {
+	case ATH10K_TM_CMD_GET_VERSION:
+		return ath10k_tm_cmd_get_version(ar, tb);
+	case ATH10K_TM_CMD_UTF_START:
+		return ath10k_tm_cmd_utf_start(ar, tb);
+	case ATH10K_TM_CMD_UTF_STOP:
+		return ath10k_tm_cmd_utf_stop(ar, tb);
+	case ATH10K_TM_CMD_WMI:
+		return ath10k_tm_cmd_wmi(ar, tb);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+void ath10k_testmode_destroy(struct ath10k *ar)
+{
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_UTF) {
+		/* utf firmware is not running, nothing to do */
+		goto out;
+	}
+
+	__ath10k_tm_cmd_utf_stop(ar);
+
+out:
+	mutex_unlock(&ar->conf_mutex);
+}
diff --git a/drivers/net/wireless/ath/ath10k/testmode.h b/drivers/net/wireless/ath/ath10k/testmode.h
new file mode 100644
index 000000000000..9cdd150815db
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/testmode.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 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 "core.h"
+
+#ifdef CONFIG_NL80211_TESTMODE
+
+void ath10k_testmode_destroy(struct ath10k *ar);
+
+bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb);
+int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		  void *data, int len);
+
+#else
+
+static inline void ath10k_testmode_destroy(struct ath10k *ar)
+{
+}
+
+static inline bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id,
+				       struct sk_buff *skb)
+{
+	return false;
+}
+
+static inline int ath10k_tm_cmd(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				void *data, int len)
+{
+	return 0;
+}
+
+#endif
diff --git a/drivers/net/wireless/ath/ath10k/testmode_i.h b/drivers/net/wireless/ath/ath10k/testmode_i.h
new file mode 100644
index 000000000000..ba81bf66ce85
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/testmode_i.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+/* "API" level of the ath10k testmode interface. Bump it after every
+ * incompatible interface change.
+ */
+#define ATH10K_TESTMODE_VERSION_MAJOR 1
+
+/* Bump this after every _compatible_ interface change, for example
+ * addition of a new command or an attribute.
+ */
+#define ATH10K_TESTMODE_VERSION_MINOR 0
+
+#define ATH10K_TM_DATA_MAX_LEN		5000
+
+enum ath10k_tm_attr {
+	__ATH10K_TM_ATTR_INVALID	= 0,
+	ATH10K_TM_ATTR_CMD		= 1,
+	ATH10K_TM_ATTR_DATA		= 2,
+	ATH10K_TM_ATTR_WMI_CMDID	= 3,
+	ATH10K_TM_ATTR_VERSION_MAJOR	= 4,
+	ATH10K_TM_ATTR_VERSION_MINOR	= 5,
+
+	/* keep last */
+	__ATH10K_TM_ATTR_AFTER_LAST,
+	ATH10K_TM_ATTR_MAX		= __ATH10K_TM_ATTR_AFTER_LAST - 1,
+};
+
+/* All ath10k testmode interface commands specified in
+ * ATH10K_TM_ATTR_CMD
+ */
+enum ath10k_tm_cmd {
+	/* Returns the supported ath10k testmode interface version in
+	 * ATH10K_TM_ATTR_VERSION. Always guaranteed to work. User space
+	 * uses this to verify it's using the correct version of the
+	 * testmode interface
+	 */
+	ATH10K_TM_CMD_GET_VERSION = 0,
+
+	/* Boots the UTF firmware, the netdev interface must be down at the
+	 * time.
+	 */
+	ATH10K_TM_CMD_UTF_START = 1,
+
+	/* Shuts down the UTF firmware and puts the driver back into OFF
+	 * state.
+	 */
+	ATH10K_TM_CMD_UTF_STOP = 2,
+
+	/* The command used to transmit a WMI command to the firmware and
+	 * the event to receive WMI events from the firmware. Without
+	 * struct wmi_cmd_hdr header, only the WMI payload. Command id is
+	 * provided with ATH10K_TM_ATTR_WMI_CMDID and payload in
+	 * ATH10K_TM_ATTR_DATA.
+	 */
+	ATH10K_TM_CMD_WMI = 3,
+};
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 67af370012f9..3e2213409074 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -23,6 +23,7 @@
 #include "debug.h"
 #include "wmi.h"
 #include "mac.h"
+#include "testmode.h"
 
 /* MAIN WMI cmd track */
 static struct wmi_cmd_map wmi_cmd_map = {
@@ -2479,6 +2480,7 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_cmd_hdr *cmd_hdr;
 	enum wmi_10x_event_id id;
+	bool consumed;
 
 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@@ -2488,6 +2490,18 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
 
 	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
 
+	consumed = ath10k_tm_event_wmi(ar, id, skb);
+
+	/* Ready event must be handled normally also in UTF mode so that we
+	 * know the UTF firmware has booted, others we are just bypass WMI
+	 * events to testmode.
+	 */
+	if (consumed && id != WMI_10X_READY_EVENTID) {
+		ath10k_dbg(ar, ATH10K_DBG_WMI,
+			   "wmi testmode consumed 0x%x\n", id);
+		goto out;
+	}
+
 	switch (id) {
 	case WMI_10X_MGMT_RX_EVENTID:
 		ath10k_wmi_event_mgmt_rx(ar, skb);
@@ -2574,11 +2588,15 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
 	case WMI_10X_READY_EVENTID:
 		ath10k_wmi_ready_event_rx(ar, skb);
 		break;
+	case WMI_10X_PDEV_UTF_EVENTID:
+		/* ignore utf events */
+		break;
 	default:
 		ath10k_warn(ar, "Unknown eventid: %d\n", id);
 		break;
 	}
 
+out:
 	dev_kfree_skb(skb);
 }
 



From kvalo at qca.qualcomm.com  Wed Sep 10 08:26:52 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 18:26:52 +0300
Subject: Firmware crash w/ 10.2 diagnosis?
In-Reply-To: <CABnBrYV6MSw1LgcgbL4O4sgR0K_P-9jCMEhOvMDmPt8yw2UeXQ@mail.gmail.com>
 (Denton Gentry's message of "Tue, 9 Sep 2014 13:05:21 -0700")
References: <CABnBrYV4Lh7EF9xaEK6zkPk0HhU=iP283WhH+wA9=i7XfHroGg@mail.gmail.com>
 <CA+BoTQ=tDMX4TKwmGcML4n-r-LPV3aici=X4Ms4rACoBhq2cKA@mail.gmail.com>
 <CABnBrYVb+BN4BFxrj82dj0KypxEy6GGYXtOitVW7twtzTeCArA@mail.gmail.com>
 <87tx4h8096.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQnC0Px3gi6nK1MTjFMTr2cY0dTntCi+KBcvnEd31ELVZA@mail.gmail.com>
 <CABnBrYV6MSw1LgcgbL4O4sgR0K_P-9jCMEhOvMDmPt8yw2UeXQ@mail.gmail.com>
Message-ID: <8761gv7ayr.fsf@kamboji.qca.qualcomm.com>

Denton Gentry <denton.gentry at gmail.com> writes:

> I'm using backports, and the kernel version is 3.2.
> hostapd says it is indeed using the cooked monitor:
>
>     monitor mode needed: 1 (poll_cmd=1 data_tx_status=0)
>
> I'll look at updating the kernel, if not to 3.16 then at least to
> something recent enough to stop using the monitor interface from
> hostapd.

Good. But if you use bridging the monitor vdev is created anyway. So
most likely switching to nl80211 management frame interface is not going
to workaround the firmware bug.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Sep 10 08:53:39 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 18:53:39 +0300
Subject: [PATCH] ath10k: Support firmware crash-by-assert.
In-Reply-To: <1409238957-30625-1-git-send-email-greearb@candelatech.com>
 (greearb@candelatech.com's message of "Thu, 28 Aug 2014 08:15:57
 -0700")
References: <1409238957-30625-1-git-send-email-greearb@candelatech.com>
Message-ID: <87wq9b5v5o.fsf@kamboji.qca.qualcomm.com>

greearb at candelatech.com writes:

> From: Ben Greear <greearb at candelatech.com>
>
> 10.1 firmware does not have an official way to
> cause assert on purpose, but it can be done with
> carefully crafted WMI command.  This is a different
> kind of crash from the 'hard' crash, which is
> a bad memory dereference.
>
> Different crashes decode in different manners, so
> this will help the crash-report testing as well as
> offer better ways to test firmware failure and
> recovery.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>

[...]

> --- a/drivers/net/wireless/ath/ath10k/wmi.c
> +++ b/drivers/net/wireless/ath/ath10k/wmi.c
> @@ -3725,6 +3725,26 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
>  				   ar->wmi.cmd->vdev_install_key_cmdid);
>  }
>  
> +int ath10k_wmi_vdev_assert(struct ath10k *ar, u32 crashme)
> +{
> +	struct wmi_vdev_install_key_cmd *cmd;
> +	struct sk_buff *skb;
> +
> +	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
> +	memset(cmd, 0, sizeof(*cmd));
> +	cmd->vdev_id = __cpu_to_le32(crashme);
> +
> +	ath10k_info(ar,
> +		    "simulating firmware ASSERT with bad install_key vdev-id: 0x%x\n",
> +		    cmd->vdev_id);

cmd->vdev_id is in little endian here.

> +	return ath10k_wmi_cmd_send(ar, skb,
> +				   ar->wmi.cmd->vdev_install_key_cmdid);
> +}

As this is not a real WMI command, I would actually prefer to have this
in debug.c. With my patch "ath10k: make ath10k_wmi_cmd_send() public"
that's possible now.

I can do the changes and will send v2 shortly. Just need to test it
first.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Sep 10 08:59:28 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 18:59:28 +0300
Subject: [PATCH v2] ath10k: support firmware crash-by-assert
Message-ID: <20140910155928.30418.45160.stgit@potku.adurom.net>

From: Ben Greear <greearb at candelatech.com>

10.1 firmware does not have an official way to
cause assert on purpose, but it can be done with
carefully crafted WMI command.  This is a different
kind of crash from the 'hard' crash, which is
a bad memory dereference.

Different crashes decode in different manners, so
this will help the crash-report testing as well as
offer better ways to test firmware failure and
recovery.

kvalo: move the wmi command creation to debug.c, modify
the info print

Signed-off-by: Ben Greear <greearb at candelatech.com>
Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/debug.c |   28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index f948a4d8ee59..c5d01058c2a3 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -565,6 +565,26 @@ static const struct file_operations fops_fw_stats = {
 	.llseek = default_llseek,
 };
 
+/* This is a clean assert crash in firmware. */
+static int ath10k_debug_fw_assert(struct ath10k *ar)
+{
+	struct wmi_vdev_install_key_cmd *cmd;
+	struct sk_buff *skb;
+
+	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
+	memset(cmd, 0, sizeof(*cmd));
+
+	/* big enough number so that firmware asserts */
+	cmd->vdev_id = __cpu_to_le32(0x7ffe);
+
+	return ath10k_wmi_cmd_send(ar, skb,
+				   ar->wmi.cmd->vdev_install_key_cmdid);
+}
+
 static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
 					     char __user *user_buf,
 					     size_t count, loff_t *ppos)
@@ -574,7 +594,10 @@ static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
 			   " WMI_FORCE_FW_HANG_ASSERT to firmware if FW"
 			   " supports that command.\n `hard` - this will send"
 			   " to firmware command with illegal parameters"
-			   " causing firmware crash.\n";
+			   " causing firmware crash.\n"
+			   "`assert` - this will send special illegal parameter"
+			   " to firmware to cause assert failure"
+			   " and crash.\n";
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
 }
@@ -623,6 +646,9 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
 		 */
 		ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
 					ar->wmi.vdev_param->rts_threshold, 0);
+	} else if (!strcmp(buf, "assert")) {
+		ath10k_info(ar, "simulating firmware assert crash\n");
+		ret = ath10k_debug_fw_assert(ar);
 	} else {
 		ret = -EINVAL;
 		goto exit;



From kvalo at qca.qualcomm.com  Wed Sep 10 09:14:37 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 10 Sep 2014 19:14:37 +0300
Subject: [PATCH v3] ath10k: fix debugfs_create_dir() checking
In-Reply-To: <1409827005-3777-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 4 Sep 2014 12:36:45 +0200")
References: <1409827005-3777-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87sijz5u6q.fsf@kamboji.qca.qualcomm.com>

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

> The function may return an -ENODEV if debugfs is
> disabled in kernel. This should originally be
> guarded by ath10k's Kconfig but it still makes
> sense to check for the non-NULL errno return
> value.
>

[...]

> Reported-by: Matteo Croce <matteo at openwrt.org>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
> ---
>
> Notes:
>     v2:
>      * fix commit subject (sorry for the noise!)
>     
>     v3:
>      * remove Kconfig patch (I accidentally amended something I shouldn't have,
>        sorry for the noise again! I guess I need a break..)
>
> @Kalle:
>
>  - this patch prevents kernel oops but ath10k will
>    fail to load
>
>  - Matteo's patch prevents kernel oops and ath10k
>    will load fine
>
> Since mine is just an extra precaution feel free
> to drop all but the first paragraph of my commit
> message if you want to.

Thanks, I just left the first paragraph like you recommended. Also I had
a conflict with this patch, please double check my resolution in
ath-next-test:

https://github.com/kvalo/ath/commit/bee6d655eefe488b76998c9c0018a4e6b0828de6

-- 
Kalle Valo


From greearb at candelatech.com  Wed Sep 10 09:34:24 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 10 Sep 2014 09:34:24 -0700
Subject: [PATCH v2] ath10k: support firmware crash-by-assert
In-Reply-To: <20140910155928.30418.45160.stgit@potku.adurom.net>
References: <20140910155928.30418.45160.stgit@potku.adurom.net>
Message-ID: <54107D90.7080907@candelatech.com>

On 09/10/2014 08:59 AM, Kalle Valo wrote:
> From: Ben Greear <greearb at candelatech.com>
>
> 10.1 firmware does not have an official way to
> cause assert on purpose, but it can be done with
> carefully crafted WMI command.  This is a different
> kind of crash from the 'hard' crash, which is
> a bad memory dereference.
>
> Different crashes decode in different manners, so
> this will help the crash-report testing as well as
> offer better ways to test firmware failure and
> recovery.
>
> kvalo: move the wmi command creation to debug.c, modify
> the info print

This looks fine to me.  I have not tested this version.

Thanks,
Ben

>
> Signed-off-by: Ben Greear <greearb at candelatech.com>
> Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
> ---
>   drivers/net/wireless/ath/ath10k/debug.c |   28 +++++++++++++++++++++++++++-
>   1 file changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
> index f948a4d8ee59..c5d01058c2a3 100644
> --- a/drivers/net/wireless/ath/ath10k/debug.c
> +++ b/drivers/net/wireless/ath/ath10k/debug.c
> @@ -565,6 +565,26 @@ static const struct file_operations fops_fw_stats = {
>   	.llseek = default_llseek,
>   };
>
> +/* This is a clean assert crash in firmware. */
> +static int ath10k_debug_fw_assert(struct ath10k *ar)
> +{
> +	struct wmi_vdev_install_key_cmd *cmd;
> +	struct sk_buff *skb;
> +
> +	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
> +	memset(cmd, 0, sizeof(*cmd));
> +
> +	/* big enough number so that firmware asserts */
> +	cmd->vdev_id = __cpu_to_le32(0x7ffe);
> +
> +	return ath10k_wmi_cmd_send(ar, skb,
> +				   ar->wmi.cmd->vdev_install_key_cmdid);
> +}
> +
>   static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
>   					     char __user *user_buf,
>   					     size_t count, loff_t *ppos)
> @@ -574,7 +594,10 @@ static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
>   			   " WMI_FORCE_FW_HANG_ASSERT to firmware if FW"
>   			   " supports that command.\n `hard` - this will send"
>   			   " to firmware command with illegal parameters"
> -			   " causing firmware crash.\n";
> +			   " causing firmware crash.\n"
> +			   "`assert` - this will send special illegal parameter"
> +			   " to firmware to cause assert failure"
> +			   " and crash.\n";
>
>   	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
>   }
> @@ -623,6 +646,9 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
>   		 */
>   		ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
>   					ar->wmi.vdev_param->rts_threshold, 0);
> +	} else if (!strcmp(buf, "assert")) {
> +		ath10k_info(ar, "simulating firmware assert crash\n");
> +		ret = ath10k_debug_fw_assert(ar);
>   	} else {
>   		ret = -EINVAL;
>   		goto exit;
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


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



From michal.kazior at tieto.com  Wed Sep 10 23:04:36 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 11 Sep 2014 08:04:36 +0200
Subject: [PATCH v3] ath10k: fix debugfs_create_dir() checking
In-Reply-To: <87sijz5u6q.fsf@kamboji.qca.qualcomm.com>
References: <1409827005-3777-1-git-send-email-michal.kazior@tieto.com>
 <87sijz5u6q.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQnc9Vvedo5bwzvoRbEAiu=xcTbagEmxUDJ=9+Uva_UbWg@mail.gmail.com>

On 10 September 2014 18:14, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
[...]
>> Since mine is just an extra precaution feel free
>> to drop all but the first paragraph of my commit
>> message if you want to.
>
> Thanks, I just left the first paragraph like you recommended. Also I had
> a conflict with this patch, please double check my resolution in
> ath-next-test:
>
> https://github.com/kvalo/ath/commit/bee6d655eefe488b76998c9c0018a4e6b0828de6

Looks good, thanks!


Micha?


From ohlee at mwnl.snu.ac.kr  Thu Sep 11 00:37:07 2014
From: ohlee at mwnl.snu.ac.kr (Okhwan Lee)
Date: Thu, 11 Sep 2014 16:37:07 +0900
Subject: Change the number of active antennas (RF-chains)
Message-ID: <CANzpp-k2QdD6C9VJF7hPR2sKOQwhXxxA4qsJcihjKVrwgtXQng@mail.gmail.com>

Hi,

I have been trying to configure the number of active antennas (not
spatial stream) by using ath10k/QCA9880.

When I use ath9k, we can easily change the number of active antenna by
using REG_WRITE(ah, AR_PHY_RX_CHAINMASK, ah->rxchainmask) function
used in ar9003_hw_set_chain_masks.

However, in ath10k, we failed to handle the values (e.g, rx/tx chain
mask of QCA9880) by using ath10k_wmi_pdev_set_param(ar,
ar->wmi.pdev_param->rx_chain_mask, rx_ant) funcion in used in
__ath10k_set_antenna.

I use debugfs module to configure the parameters and you can find our
code (for both ath9k and ath10k) at the end of this e-mail.
aWe measured  the power consumption of NIC to confirm whether the
codes can change the number of active RF-chains or not.
As you might know, the power consumption is highly depends on the
number of active RF-chains.
In ath9k, the power consumption decreases as the number of active
rf-chains (rx_chainmask, antennas) is decrease.
However, in ath10, we failed to configure the number of active
RF-chains, and the power consumption does not change at all.

If you have any idea on this issue, please let me know.

Thank you.

Okhwan

/********************ath10k/debug.c (this is not work)*********************/

static ssize_t ath10k_read_rx_chainmask(struct file *file,
                                        char __user *user_buf,
                                             size_t count, loff_t *ppos)
{
//      printk(KERN_DEBUG "%s",__FUNCTION__);
        ath10k_dbg(ATH10K_DBG_MAC, "%s -> ",__FUNCTION__);
        struct ath10k *ar = file->private_data;
        char buf[32];
        unsigned int len;

        len = sprintf(buf, "0x%08x\n", ar->cfg_rx_chainmask);
        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}

static ssize_t ath10k_write_rx_chainmask(struct file *file, const char
__user *user_buf,
                             size_t count, loff_t *ppos)
{
        ath10k_dbg(ATH10K_DBG_MAC, "%s -> ",__FUNCTION__);
        struct ath10k *ar = file->private_data;
        unsigned long mask;
        int ret;

        ret = kstrtoul_from_user(user_buf, count, 0, &mask);
        ath10k_dbg(ATH10K_DBG_MAC, "%s -> mask: 0x%x\n",__FUNCTION__,
(unsigned int)mask);
        if (mask > 0x7){
                ath10k_dbg(ATH10K_DBG_MAC, "%s -> mask: %lu should be
< 7\n",__FUNCTION__, mask);
                return -E2BIG;
        }

        if ((ar->state != ATH10K_STATE_ON) &&
            (ar->state != ATH10K_STATE_RESTARTED)){
                ath10k_dbg(ATH10K_DBG_MAC, "%s -> failed pass state
check stat: %d\n",__FUNCTION__, ar->state);
                ret = 1;
                goto out;
        }

        ath10k_dbg(ATH10K_DBG_MAC, "%s -> start lock\n",__FUNCTION__);
        mutex_lock(&ar->conf_mutex);
        ath10k_dbg(ATH10K_DBG_MAC, "%s -> locked\n",__FUNCTION__);

        ar->cfg_rx_chainmask = mask;

        ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->rx_chain_mask,
                                        (u32)mask);
        if (ret) {
                ath10k_warn("failed to set rx-chainmask: %d, req 0x%x\n",
                            ret, (unsigned int)mask);
                goto out;
        }
        ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_chain_mask,
                                        (u32)mask);



        ret = count;
out:
        mutex_unlock(&ar->conf_mutex);

        return ret;
}

static const struct file_operations fops_rx_chainmask = {
        .read = ath10k_read_rx_chainmask,
        .write = ath10k_write_rx_chainmask,
        .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
};

/*****************************************/


/********************ath9k/debug.c (this is work)*********************/


static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf,
           size_t count, loff_t *ppos)
{
  printk(KERN_DEBUG ?%s?,__FUNCTION__);
  struct ath_softc *sc = file->private_data;
  struct ath_hw *ah = sc->sc_ah;
  char buf[32];
  unsigned int len;


  len = sprintf(buf, ?0x%08x\n?, ah->rxchainmask);
  return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}


static ssize_t write_file_rx_chainmask(struct file *file, const char
__user *user_buf,
           size_t count, loff_t *ppos)
{
  printk(KERN_DEBUG ?%s?,__FUNCTION__);
  struct ath_softc *sc = file->private_data;
  struct ath_hw *ah = sc->sc_ah;
  unsigned long mask;
  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 (strict_strtoul(buf, 0, &mask))
    return -EINVAL;


  ah->rxchainmask = mask;
  ah->caps.rx_chainmask = mask;
  ah->eep_ops->fill_eeprom(ah);
  REG_WRITE(ah, AR_PHY_RX_CHAINMASK, ah->rxchainmask);
  REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, ah->rxchainmask);


  return count;
}


/*****************************************/

Sincerely yours,

Okhwan Lee , Ph.D. student
Multimedia & Wireless Networking Lab. (MWNL),
School of Electrical Engineering,
Seoul National University (SNU)

Tel: +82-2-880-1755
Cell: +82-10-4632-1980
URL: http://mwnl.snu.ac.kr/~ohlee


From michal.kazior at tieto.com  Thu Sep 11 02:47:34 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 11 Sep 2014 11:47:34 +0200
Subject: [PATCH v4 2/2] ath10k: add testmode
In-Reply-To: <20140910152329.12610.41409.stgit@potku.adurom.net>
References: <20140910152136.12610.18499.stgit@potku.adurom.net>
 <20140910152329.12610.41409.stgit@potku.adurom.net>
Message-ID: <CA+BoTQkBiKPzHBfTA2xpmgbUbutSj5Z6w6gP7EO6aotacM5_cA@mail.gmail.com>

On 10 September 2014 17:23, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
[...]

Just a small nitpick:

> +static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
> +{
> +       int ret;
> +
> +       ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf stop\n");
> +
> +       mutex_lock(&ar->conf_mutex);
> +
> +       if (ar->state != ATH10K_STATE_UTF) {
> +               ret = -ENETDOWN;
> +               goto out;
> +       }
> +
> +       __ath10k_tm_cmd_utf_stop(ar);
> +
> +       ar->state = ATH10K_STATE_OFF; // <-- this

I would move it to __ath10k_tm_cmd_utf_stop() itself so that the state
is reset in ath10k_testmode_destroy() as well.


Micha?


From michal.kazior at tieto.com  Thu Sep 11 03:35:52 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 11 Sep 2014 12:35:52 +0200
Subject: [RFC] ath10k: use raw tx
In-Reply-To: <5400F497.7070904@candelatech.com>
References: <1408693965-29858-1-git-send-email-michal.kazior@tieto.com>
 <5400F497.7070904@candelatech.com>
Message-ID: <CA+BoTQnhqxtHcX46-U+TjQBMDm27jM11xCJ956UFM_gjMvvs+A@mail.gmail.com>

On 29 August 2014 23:45, Ben Greear <greearb at candelatech.com> wrote:
> On 08/22/2014 12:52 AM, Michal Kazior wrote:
>> This is just a reference for anyone interested in
>> getting injection working with ath10k.
>
> Did you try this with encryption?  I can reproduce the crash
> in open mode on my CT firmware, but I couldn't even get
> DHCP to complete with wpa2 enabled.

Hi,

Late reply, sorry.

I've just did a quick test on 10.2 (both AP and STA) with WPA2.
Apparently the raw tx mode requires IV to be set up on host and packet
length (reported in HTT Tx command header) must be re-adjusted
differently, otherwise frames are broken (incorrect FCS, too long,
somewhat encrypted except LLC/SNAP). The best I could get were
FCS-correct undecryptable frames on air. Perhaps someone will figure
that out..

Another way around this would be to perform software crypto for tx
entirely on host.


Micha?


From kvalo at qca.qualcomm.com  Thu Sep 11 03:39:41 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 13:39:41 +0300
Subject: [PATCH v4 2/2] ath10k: add testmode
In-Reply-To: <CA+BoTQkBiKPzHBfTA2xpmgbUbutSj5Z6w6gP7EO6aotacM5_cA@mail.gmail.com>
 (Michal Kazior's message of "Thu, 11 Sep 2014 11:47:34 +0200")
References: <20140910152136.12610.18499.stgit@potku.adurom.net>
 <20140910152329.12610.41409.stgit@potku.adurom.net>
 <CA+BoTQkBiKPzHBfTA2xpmgbUbutSj5Z6w6gP7EO6aotacM5_cA@mail.gmail.com>
Message-ID: <87ppf230gi.fsf@kamboji.qca.qualcomm.com>

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

> On 10 September 2014 17:23, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> [...]
>
> Just a small nitpick:
>
>> +static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
>> +{
>> +       int ret;
>> +
>> +       ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf stop\n");
>> +
>> +       mutex_lock(&ar->conf_mutex);
>> +
>> +       if (ar->state != ATH10K_STATE_UTF) {
>> +               ret = -ENETDOWN;
>> +               goto out;
>> +       }
>> +
>> +       __ath10k_tm_cmd_utf_stop(ar);
>> +
>> +       ar->state = ATH10K_STATE_OFF; // <-- this
>
> I would move it to __ath10k_tm_cmd_utf_stop() itself so that the state
> is reset in ath10k_testmode_destroy() as well.

Ok. It doesn't make any difference on the functionality, but I'll change
it anyway. I folded this patch to the commit:

diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c
index 9d77d72042ff..483db9cb8c96 100644
--- a/drivers/net/wireless/ath/ath10k/testmode.c
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
@@ -253,6 +253,8 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
 
        release_firmware(ar->testmode.utf);
        ar->testmode.utf = NULL;
+
+       ar->state = ATH10K_STATE_OFF;
 }
 
 static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
@@ -270,7 +272,6 @@ static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
 
        __ath10k_tm_cmd_utf_stop(ar);
 
-       ar->state = ATH10K_STATE_OFF;
        ret = 0;
 
        ath10k_info(ar, "UTF firmware stopped\n");

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Thu Sep 11 03:47:58 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 13:47:58 +0300
Subject: [RFC] ath10k: use raw tx
In-Reply-To: <CA+BoTQnhqxtHcX46-U+TjQBMDm27jM11xCJ956UFM_gjMvvs+A@mail.gmail.com>
 (Michal Kazior's message of "Thu, 11 Sep 2014 12:35:52 +0200")
References: <1408693965-29858-1-git-send-email-michal.kazior@tieto.com>
 <5400F497.7070904@candelatech.com>
 <CA+BoTQnhqxtHcX46-U+TjQBMDm27jM11xCJ956UFM_gjMvvs+A@mail.gmail.com>
Message-ID: <87ha0e302p.fsf@kamboji.qca.qualcomm.com>

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

> On 29 August 2014 23:45, Ben Greear <greearb at candelatech.com> wrote:
>> On 08/22/2014 12:52 AM, Michal Kazior wrote:
>>> This is just a reference for anyone interested in
>>> getting injection working with ath10k.
>>
>> Did you try this with encryption?  I can reproduce the crash
>> in open mode on my CT firmware, but I couldn't even get
>> DHCP to complete with wpa2 enabled.
>
> Hi,
>
> Late reply, sorry.
>
> I've just did a quick test on 10.2 (both AP and STA) with WPA2.
> Apparently the raw tx mode requires IV to be set up on host and packet
> length (reported in HTT Tx command header) must be re-adjusted
> differently, otherwise frames are broken (incorrect FCS, too long,
> somewhat encrypted except LLC/SNAP). The best I could get were
> FCS-correct undecryptable frames on air. Perhaps someone will figure
> that out..
>
> Another way around this would be to perform software crypto for tx
> entirely on host.

BTW, it would be nice to get software crypto support to ath10k, for
example with a nohwcrypt module parameter like ath9k has.

-- 
Kalle Valo


From greearb at candelatech.com  Thu Sep 11 07:17:39 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 11 Sep 2014 07:17:39 -0700
Subject: [RFC] ath10k: use raw tx
In-Reply-To: <87ha0e302p.fsf@kamboji.qca.qualcomm.com>
References: <1408693965-29858-1-git-send-email-michal.kazior@tieto.com>	<5400F497.7070904@candelatech.com>	<CA+BoTQnhqxtHcX46-U+TjQBMDm27jM11xCJ956UFM_gjMvvs+A@mail.gmail.com>
 <87ha0e302p.fsf@kamboji.qca.qualcomm.com>
Message-ID: <5411AF03.9010008@candelatech.com>

On 09/11/2014 03:47 AM, Kalle Valo wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
>
>> On 29 August 2014 23:45, Ben Greear <greearb at candelatech.com> wrote:
>>> On 08/22/2014 12:52 AM, Michal Kazior wrote:
>>>> This is just a reference for anyone interested in
>>>> getting injection working with ath10k.
>>>
>>> Did you try this with encryption?  I can reproduce the crash
>>> in open mode on my CT firmware, but I couldn't even get
>>> DHCP to complete with wpa2 enabled.
>>
>> Hi,
>>
>> Late reply, sorry.
>>
>> I've just did a quick test on 10.2 (both AP and STA) with WPA2.
>> Apparently the raw tx mode requires IV to be set up on host and packet
>> length (reported in HTT Tx command header) must be re-adjusted
>> differently, otherwise frames are broken (incorrect FCS, too long,
>> somewhat encrypted except LLC/SNAP). The best I could get were
>> FCS-correct undecryptable frames on air. Perhaps someone will figure
>> that out..
>>
>> Another way around this would be to perform software crypto for tx
>> entirely on host.
>
> BTW, it would be nice to get software crypto support to ath10k, for
> example with a nohwcrypt module parameter like ath9k has.

You have to hack the firmware (and patch driver) to make this work.  I have patches to make
rx-sw-crypt work with my CT firmware.  Been releasing this only for non-commercial
use, but I'd be willing to make it supported without restriction and instead
limit number of stations to < 16 when sw-crypt was enabled.  This leaves my
commercial offering worth paying for for the few people that might compete against
our testing products.

I had all sorts of trouble, similar to what you describe trying to get raw tx
to work, and eventually gave up entirely.  My method of rx-sw-crypt uses normal tx
(with hardware offload), but decrypts on the host.

Thanks,
Ben


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



From greearb at candelatech.com  Thu Sep 11 07:19:22 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 11 Sep 2014 07:19:22 -0700
Subject: [RFC] ath10k: use raw tx
In-Reply-To: <CA+BoTQnhqxtHcX46-U+TjQBMDm27jM11xCJ956UFM_gjMvvs+A@mail.gmail.com>
References: <1408693965-29858-1-git-send-email-michal.kazior@tieto.com>	<5400F497.7070904@candelatech.com>
 <CA+BoTQnhqxtHcX46-U+TjQBMDm27jM11xCJ956UFM_gjMvvs+A@mail.gmail.com>
Message-ID: <5411AF6A.7010702@candelatech.com>

On 09/11/2014 03:35 AM, Michal Kazior wrote:
> On 29 August 2014 23:45, Ben Greear <greearb at candelatech.com> wrote:
>> On 08/22/2014 12:52 AM, Michal Kazior wrote:
>>> This is just a reference for anyone interested in
>>> getting injection working with ath10k.
>>
>> Did you try this with encryption?  I can reproduce the crash
>> in open mode on my CT firmware, but I couldn't even get
>> DHCP to complete with wpa2 enabled.
>
> Hi,
>
> Late reply, sorry.
>
> I've just did a quick test on 10.2 (both AP and STA) with WPA2.
> Apparently the raw tx mode requires IV to be set up on host and packet
> length (reported in HTT Tx command header) must be re-adjusted
> differently, otherwise frames are broken (incorrect FCS, too long,
> somewhat encrypted except LLC/SNAP). The best I could get were
> FCS-correct undecryptable frames on air. Perhaps someone will figure
> that out..
>
> Another way around this would be to perform software crypto for tx
> entirely on host.

That did not fix the problem for me.  The firmware/hardware could not be
convinced (by me, at least) to leave the encrypted packet alone and insisted on
doing at least partial re-crypt, or something like that.

Thanks,
Ben

>
>
> Micha?
>


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



From greearb at candelatech.com  Thu Sep 11 07:21:27 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 11 Sep 2014 07:21:27 -0700
Subject: Change the number of active antennas (RF-chains)
In-Reply-To: <CANzpp-k2QdD6C9VJF7hPR2sKOQwhXxxA4qsJcihjKVrwgtXQng@mail.gmail.com>
References: <CANzpp-k2QdD6C9VJF7hPR2sKOQwhXxxA4qsJcihjKVrwgtXQng@mail.gmail.com>
Message-ID: <5411AFE7.8060008@candelatech.com>

On 09/11/2014 12:37 AM, Okhwan Lee wrote:
> Hi,
>
> I have been trying to configure the number of active antennas (not
> spatial stream) by using ath10k/QCA9880.
>
> When I use ath9k, we can easily change the number of active antenna by
> using REG_WRITE(ah, AR_PHY_RX_CHAINMASK, ah->rxchainmask) function
> used in ar9003_hw_set_chain_masks.
>
> However, in ath10k, we failed to handle the values (e.g, rx/tx chain
> mask of QCA9880) by using ath10k_wmi_pdev_set_param(ar,
> ar->wmi.pdev_param->rx_chain_mask, rx_ant) funcion in used in
> __ath10k_set_antenna.

Newer kernels should have this support, and it seemed to work in my
testing.  I did not test power consumption.

What kernel version are you using?

Thanks,
Ben

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



From kvalo at qca.qualcomm.com  Thu Sep 11 13:31:32 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 23:31:32 +0300
Subject: [RFC PATCH 0/3] ath10k: export calibration data to user space
Message-ID: <20140911202926.12514.79908.stgit@potku.adurom.net>

Hi,

here's a small patchset exporting firmware calibration data to user space. This
makes it easier to debug various calibration data related problems. The first
patch is more or less a hack, not sure how to do that properly.

Please comment.

---

Kalle Valo (3):
      ath10k: ignore diagnose pipes in ath10k_pci_ce_recv_data()/_send_done()
      ath10k: add diag_read() to hif ops
      ath10k: add cal_data debugfs file


 drivers/net/wireless/ath/ath10k/debug.c |   81 +++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hif.h   |   10 ++++
 drivers/net/wireless/ath/ath10k/hw.h    |    2 +
 drivers/net/wireless/ath/ath10k/pci.c   |   14 +++++
 4 files changed, 107 insertions(+)



From kvalo at qca.qualcomm.com  Thu Sep 11 13:31:41 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 23:31:41 +0300
Subject: [RFC PATCH 1/3] ath10k: ignore diagnose pipes in
 ath10k_pci_ce_recv_data()/_send_done()
In-Reply-To: <20140911202926.12514.79908.stgit@potku.adurom.net>
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
Message-ID: <20140911203141.12514.23469.stgit@potku.adurom.net>

As ath10k_pci_diag_read_mem() uses polling to receive data from CE, the CE callbacks
have to ignore the pipe used for diagnose reads. Otherwise ath10k crashes due
to NULL dereference and polling reads timeout.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/pci.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index baeb98e78b1f..154451ab3e3c 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -819,6 +819,9 @@ static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state)
 	unsigned int nbytes;
 	unsigned int transfer_id;
 
+	if (ce_state->id == 7)
+		return;
+
 	while (ath10k_ce_completed_send_next(ce_state, &transfer_context,
 					     &ce_data, &nbytes,
 					     &transfer_id) == 0) {
@@ -844,6 +847,9 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
 	unsigned int transfer_id;
 	unsigned int flags;
 
+	if (ce_state->id == 7)
+		return;
+
 	while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
 					     &ce_data, &nbytes, &transfer_id,
 					     &flags) == 0) {



From kvalo at qca.qualcomm.com  Thu Sep 11 13:31:47 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 23:31:47 +0300
Subject: [RFC PATCH 2/3] ath10k: add diag_read() to hif ops
In-Reply-To: <20140911202926.12514.79908.stgit@potku.adurom.net>
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
Message-ID: <20140911203147.12514.84857.stgit@potku.adurom.net>

diag_read() is used for reading from firmware memory via the diagnose window.
First user will be cal_data debugfs file.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/hif.h |   10 ++++++++++
 drivers/net/wireless/ath/ath10k/pci.c |    8 ++++++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 2ac7beacddca..0a8877d33f1f 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -43,6 +43,10 @@ struct ath10k_hif_ops {
 	int (*tx_sg)(struct ath10k *ar, u8 pipe_id,
 		     struct ath10k_hif_sg_item *items, int n_items);
 
+	/* read firmware memory through the diagnose interface */
+	int (*diag_read)(struct ath10k *ar, u32 address, void *buf,
+			 size_t buf_len);
+
 	/*
 	 * API to handle HIF-specific BMI message exchanges, this API is
 	 * synchronous and only allowed to be called from a context that
@@ -99,6 +103,12 @@ static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
 	return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items);
 }
 
+static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
+				       size_t buf_len)
+{
+	return ar->hif.ops->diag_read(ar, address, buf, buf_len);
+}
+
 static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
 					      void *request, u32 request_len,
 					      void *response, u32 *response_len)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 154451ab3e3c..d3c51079034e 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -941,6 +941,13 @@ err:
 	return err;
 }
 
+static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
+				    size_t buf_len)
+{
+	/* FIXME: locking */
+	return ath10k_pci_diag_read_mem(ar, address, buf, buf_len);
+}
+
 static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
 {
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -1926,6 +1933,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
 
 static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
 	.tx_sg			= ath10k_pci_hif_tx_sg,
+	.diag_read		= ath10k_pci_hif_diag_read,
 	.exchange_bmi_msg	= ath10k_pci_hif_exchange_bmi_msg,
 	.start			= ath10k_pci_hif_start,
 	.stop			= ath10k_pci_hif_stop,



From kvalo at qca.qualcomm.com  Thu Sep 11 13:31:52 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 23:31:52 +0300
Subject: [RFC PATCH 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <20140911202926.12514.79908.stgit@potku.adurom.net>
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
Message-ID: <20140911203152.12514.95332.stgit@potku.adurom.net>

Provide calibration data used by the firmware to user space via a debugfs file.
This makes it easier to debug calibration related problems.

Example:

sudo cp /sys/kernel/debug/ieee80211/phy0/ath10k/cal_data 1.cal

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/debug.c |   81 +++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hw.h    |    2 +
 2 files changed, 83 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index f948a4d8ee59..6500fd44f527 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -23,6 +23,7 @@
 
 #include "core.h"
 #include "debug.h"
+#include "hif.h"
 
 /* ms */
 #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
@@ -1014,6 +1015,83 @@ static const struct file_operations fops_fw_dbglog = {
 	.llseek = default_llseek,
 };
 
+static int ath10k_cal_data_open(struct inode *inode, struct file *file)
+{
+	struct ath10k *ar = inode->i_private;
+	void *buf;
+	u32 hi_addr;
+	__le32 addr;
+	int ret;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_ON &&
+	    ar->state != ATH10K_STATE_UTF) {
+		ret = -ENETDOWN;
+		goto err;
+	}
+
+	buf = vmalloc(QCA988X_CAL_DATA_LEN);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
+
+	ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
+	if (ret) {
+		ath10k_warn("failed to read hi_board_data address: %d\n", ret);
+		goto err_vfree;
+	}
+
+	ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
+				   QCA988X_CAL_DATA_LEN);
+	if (ret) {
+		ath10k_warn("failed to read calibration data: %d\n", ret);
+		goto err_vfree;
+	}
+
+	file->private_data = buf;
+
+	mutex_unlock(&ar->conf_mutex);
+
+	return 0;
+
+err_vfree:
+	vfree(buf);
+
+err:
+	mutex_unlock(&ar->conf_mutex);
+
+	return ret;
+}
+
+static ssize_t ath10k_cal_data_read(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	void *buf = file->private_data;
+
+	return simple_read_from_buffer(user_buf, count, ppos,
+				       buf, QCA988X_CAL_DATA_LEN);
+}
+
+static int ath10k_cal_data_release(struct inode *inode,
+				   struct file *file)
+{
+	vfree(file->private_data);
+
+	return 0;
+}
+
+static const struct file_operations fops_cal_data = {
+	.open = ath10k_cal_data_open,
+	.read = ath10k_cal_data_read,
+	.release = ath10k_cal_data_release,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 int ath10k_debug_start(struct ath10k *ar)
 {
 	int ret;
@@ -1183,6 +1261,9 @@ int ath10k_debug_register(struct ath10k *ar)
 	debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_fw_dbglog);
 
+	debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
+			    ar, &fops_cal_data);
+
 	if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
 		debugfs_create_file("dfs_simulate_radar", S_IWUSR,
 				    ar->debug.debugfs_phy, ar,
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 3cf5702c1e7e..006a9cbc60b2 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -43,6 +43,8 @@
 
 #define REG_DUMP_COUNT_QCA988X 60
 
+#define QCA988X_CAL_DATA_LEN		2116
+
 struct ath10k_fw_ie {
 	__le32 id;
 	__le32 len;



From kvalo at qca.qualcomm.com  Thu Sep 11 13:40:26 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 23:40:26 +0300
Subject: [PATCH v2] ath10k: support firmware crash-by-assert
In-Reply-To: <54107D90.7080907@candelatech.com> (Ben Greear's message of "Wed, 
 10 Sep 2014 09:34:24 -0700")
References: <20140910155928.30418.45160.stgit@potku.adurom.net>
 <54107D90.7080907@candelatech.com>
Message-ID: <874mwd3n7p.fsf@kamboji.qca.qualcomm.com>

Ben Greear <greearb at candelatech.com> writes:

> On 09/10/2014 08:59 AM, Kalle Valo wrote:
>> From: Ben Greear <greearb at candelatech.com>
>>
>> 10.1 firmware does not have an official way to
>> cause assert on purpose, but it can be done with
>> carefully crafted WMI command.  This is a different
>> kind of crash from the 'hard' crash, which is
>> a bad memory dereference.
>>
>> Different crashes decode in different manners, so
>> this will help the crash-report testing as well as
>> offer better ways to test firmware failure and
>> recovery.
>>
>> kvalo: move the wmi command creation to debug.c, modify
>> the info print
>
> This looks fine to me.  I have not tested this version.

I did test it and seems to work as it should.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Thu Sep 11 13:43:13 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 23:43:13 +0300
Subject: [PATCH v4 0/2] ath10k: testmode support
In-Reply-To: <20140910152136.12610.18499.stgit@potku.adurom.net> (Kalle Valo's
 message of "Wed, 10 Sep 2014 18:23:16 +0300")
References: <20140910152136.12610.18499.stgit@potku.adurom.net>
Message-ID: <87zje528im.fsf@kamboji.qca.qualcomm.com>

Kalle Valo <kvalo at qca.qualcomm.com> writes:

> latest version of my testmode patches. Getting closer, more or less cosmetic
> changes this time :)
>

[...]

>
> Kalle Valo (2):
>       ath10k: make ath10k_wmi_cmd_send() public
>       ath10k: add testmode

Applied, with an addition of the small change in patch 2 suggested by
Michal.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Thu Sep 11 13:44:00 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 23:44:00 +0300
Subject: [PATCH v2] ath10k: support firmware crash-by-assert
In-Reply-To: <20140910155928.30418.45160.stgit@potku.adurom.net> (Kalle Valo's
 message of "Wed, 10 Sep 2014 18:59:28 +0300")
References: <20140910155928.30418.45160.stgit@potku.adurom.net>
Message-ID: <87vbot28hb.fsf@kamboji.qca.qualcomm.com>

Kalle Valo <kvalo at qca.qualcomm.com> writes:

> From: Ben Greear <greearb at candelatech.com>
>
> 10.1 firmware does not have an official way to
> cause assert on purpose, but it can be done with
> carefully crafted WMI command.  This is a different
> kind of crash from the 'hard' crash, which is
> a bad memory dereference.
>
> Different crashes decode in different manners, so
> this will help the crash-report testing as well as
> offer better ways to test firmware failure and
> recovery.
>
> kvalo: move the wmi command creation to debug.c, modify
> the info print
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>
> Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>

Thanks Ben, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Thu Sep 11 13:45:29 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 23:45:29 +0300
Subject: [PATCH v3] ath10k: fix debugfs_create_dir() checking
In-Reply-To: <1409827005-3777-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 4 Sep 2014 12:36:45 +0200")
References: <1409827005-3777-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87r3zh28eu.fsf@kamboji.qca.qualcomm.com>

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

> The function may return an -ENODEV if debugfs is
> disabled in kernel. This should originally be
> guarded by ath10k's Kconfig but it still makes
> sense to check for the non-NULL errno return
> value.
>

[...]

> Reported-by: Matteo Croce <matteo at openwrt.org>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Thu Sep 11 13:53:42 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 11 Sep 2014 23:53:42 +0300
Subject: [RFC PATCH 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <20140911203152.12514.95332.stgit@potku.adurom.net> (Kalle Valo's
 message of "Thu, 11 Sep 2014 23:31:52 +0300")
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
 <20140911203152.12514.95332.stgit@potku.adurom.net>
Message-ID: <87mwa52815.fsf@kamboji.qca.qualcomm.com>

Kalle Valo <kvalo at qca.qualcomm.com> writes:

> Provide calibration data used by the firmware to user space via a debugfs file.
> This makes it easier to debug calibration related problems.
>
> Example:
>
> sudo cp /sys/kernel/debug/ieee80211/phy0/ath10k/cal_data 1.cal
>
> Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>

[...]

> +	ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
> +	if (ret) {
> +		ath10k_warn("failed to read hi_board_data address: %d\n", ret);

This and rest of the fuction is missing 'ar' parameter. Obviously it's
too late for me :)

-- 
Kalle Valo


From greearb at candelatech.com  Thu Sep 11 15:45:35 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 11 Sep 2014 15:45:35 -0700
Subject: [RFC PATCH 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <20140911203152.12514.95332.stgit@potku.adurom.net>
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
 <20140911203152.12514.95332.stgit@potku.adurom.net>
Message-ID: <5412260F.80607@candelatech.com>

On 09/11/2014 01:31 PM, Kalle Valo wrote:
> Provide calibration data used by the firmware to user space via a debugfs file.
> This makes it easier to debug calibration related problems.
>
> Example:
>
> sudo cp /sys/kernel/debug/ieee80211/phy0/ath10k/cal_data 1.cal

Is this data that could be made human readable, or does it need to
be parsed by some private tool?

Thanks,
Ben

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



From ohlee at mwnl.snu.ac.kr  Thu Sep 11 20:48:07 2014
From: ohlee at mwnl.snu.ac.kr (Okhwan Lee)
Date: Fri, 12 Sep 2014 12:48:07 +0900
Subject: Change the number of active antennas (RF-chains)
In-Reply-To: <5411AFE7.8060008@candelatech.com>
References: <CANzpp-k2QdD6C9VJF7hPR2sKOQwhXxxA4qsJcihjKVrwgtXQng@mail.gmail.com>
 <5411AFE7.8060008@candelatech.com>
Message-ID: <AFAC18488DA64ACD88984878834DF25A@mwnl.snu.ac.kr>

Hi,  

Thank you for your answer.  
I use 3.16.1 kernel version,  3.16.1 backport version and 10.1.467.2-1 firmware version.  
I am curious to know your testing.  

This is my test bash-script.

########### test.sh ###########

#!/usr/bin/sudo /bin/bash
rmmod ath10k_pci ath10k_core ath mac80211 cfg80211
modprobe ath10k_pci  
ifconfig wlan0 2>/dev/null 1>/dev/null
while [ $? -ne 0 ]  
do
ifconfig wlan0 2>/dev/null 1>/dev/null
done
echo 0x12 > /sys/module/ath10k_core/parameters/debug_mask
iw dev wlan0 interface add mon0 type monitor
iw mon0 set freq 5180 80 5210
ifconfig mon0 up



######################

then ? type the following command in shell prompt  

echo 0x1 > /sys/kernel/debug/ieee80211/phy*/ath10k/rx_chainmask
echo 0x7 > /sys/kernel/debug/ieee80211/phy*/ath10k/rx_chainmask

.
.
.

I also test it by using hostapd.

Thank you.  

--
Okhwan Lee,
Multimedia & Wireless Networking Lab. (MWNL),
Seoul National University (SNU).

Tel: +82-2-880-1755
Cell: +82-10-4632-1980
URL: http://mwnl.snu.ac.kr/~ohlee


On 2014? 9? 11? Thursday at ?? 11:21, Ben Greear wrote:

> On 09/11/2014 12:37 AM, Okhwan Lee wrote:
> > Hi,
> >  
> > I have been trying to configure the number of active antennas (not
> > spatial stream) by using ath10k/QCA9880.
> >  
> > When I use ath9k, we can easily change the number of active antenna by
> > using REG_WRITE(ah, AR_PHY_RX_CHAINMASK, ah->rxchainmask) function
> > used in ar9003_hw_set_chain_masks.
> >  
> > However, in ath10k, we failed to handle the values (e.g, rx/tx chain
> > mask of QCA9880) by using ath10k_wmi_pdev_set_param(ar,
> > ar->wmi.pdev_param->rx_chain_mask, rx_ant) funcion in used in
> > __ath10k_set_antenna.
>  
>  
>  
> Newer kernels should have this support, and it seemed to work in my
> testing. I did not test power consumption.
>  
> What kernel version are you using?
>  
> Thanks,
> Ben
>  
> --  
> Ben Greear <greearb at candelatech.com (mailto:greearb at candelatech.com)>
> Candela Technologies Inc http://www.candelatech.com




From michal.kazior at tieto.com  Fri Sep 12 00:53:08 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Fri, 12 Sep 2014 09:53:08 +0200
Subject: [RFC PATCH 1/3] ath10k: ignore diagnose pipes in
 ath10k_pci_ce_recv_data()/_send_done()
In-Reply-To: <20140911203141.12514.23469.stgit@potku.adurom.net>
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
 <20140911203141.12514.23469.stgit@potku.adurom.net>
Message-ID: <CA+BoTQ=9kUFXpTKwE1i8TjEPFeszih+U9FDpWRdaYguf7Xa-Gw@mail.gmail.com>

On 11 September 2014 22:31, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> As ath10k_pci_diag_read_mem() uses polling to receive data from CE, the CE callbacks
> have to ignore the pipe used for diagnose reads. Otherwise ath10k crashes due
> to NULL dereference and polling reads timeout.
>
> Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
> ---
>  drivers/net/wireless/ath/ath10k/pci.c |    6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
> index baeb98e78b1f..154451ab3e3c 100644
> --- a/drivers/net/wireless/ath/ath10k/pci.c
> +++ b/drivers/net/wireless/ath/ath10k/pci.c
> @@ -819,6 +819,9 @@ static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state)
>         unsigned int nbytes;
>         unsigned int transfer_id;
>
> +       if (ce_state->id == 7)
> +               return;

I think you can check it in a saner way: (ce_state == ar_pci->ce_diag).

Another approach is to prevent this from happening in the first place
by never unmasking the diagnostic window copy engine pipe in
ath10k_ce_enable_interrupts() and preventing
ath10k_ce_per_engine_service() from being called in
ath10k_pci_hif_send_complete_check() for the diagnostic ce pipe.


Micha?


From kvalo at qca.qualcomm.com  Fri Sep 12 01:01:12 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 12 Sep 2014 11:01:12 +0300
Subject: [RFC PATCH 1/3] ath10k: ignore diagnose pipes in
 ath10k_pci_ce_recv_data()/_send_done()
In-Reply-To: <CA+BoTQ=9kUFXpTKwE1i8TjEPFeszih+U9FDpWRdaYguf7Xa-Gw@mail.gmail.com>
 (Michal Kazior's message of "Fri, 12 Sep 2014 09:53:08 +0200")
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
 <20140911203141.12514.23469.stgit@potku.adurom.net>
 <CA+BoTQ=9kUFXpTKwE1i8TjEPFeszih+U9FDpWRdaYguf7Xa-Gw@mail.gmail.com>
Message-ID: <8761gt1d4n.fsf@kamboji.qca.qualcomm.com>

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

> On 11 September 2014 22:31, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> As ath10k_pci_diag_read_mem() uses polling to receive data from CE, the CE callbacks
>> have to ignore the pipe used for diagnose reads. Otherwise ath10k crashes due
>> to NULL dereference and polling reads timeout.
>>
>> Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
>> ---
>>  drivers/net/wireless/ath/ath10k/pci.c |    6 ++++++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
>> index baeb98e78b1f..154451ab3e3c 100644
>> --- a/drivers/net/wireless/ath/ath10k/pci.c
>> +++ b/drivers/net/wireless/ath/ath10k/pci.c
>> @@ -819,6 +819,9 @@ static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state)
>>         unsigned int nbytes;
>>         unsigned int transfer_id;
>>
>> +       if (ce_state->id == 7)
>> +               return;
>
> I think you can check it in a saner way: (ce_state == ar_pci->ce_diag).
>
> Another approach is to prevent this from happening in the first place
> by never unmasking the diagnostic window copy engine pipe in
> ath10k_ce_enable_interrupts() and preventing
> ath10k_ce_per_engine_service() from being called in
> ath10k_pci_hif_send_complete_check() for the diagnostic ce pipe.

I like the latter approach and I'll try to implement that first. Thanks!

-- 
Kalle Valo


From michal.kazior at tieto.com  Fri Sep 12 02:57:46 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Fri, 12 Sep 2014 11:57:46 +0200
Subject: [RFC PATCH 2/3] ath10k: add diag_read() to hif ops
In-Reply-To: <20140911203147.12514.84857.stgit@potku.adurom.net>
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
 <20140911203147.12514.84857.stgit@potku.adurom.net>
Message-ID: <CA+BoTQ=oj9SkaeWBbX2jsD2UHUknhb6f_-ZUBbVSmuWUXFvm-g@mail.gmail.com>

On 11 September 2014 22:31, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> diag_read() is used for reading from firmware memory via the diagnose window.
> First user will be cal_data debugfs file.
[...]
> diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
> index 154451ab3e3c..d3c51079034e 100644
> --- a/drivers/net/wireless/ath/ath10k/pci.c
> +++ b/drivers/net/wireless/ath/ath10k/pci.c
> @@ -941,6 +941,13 @@ err:
>         return err;
>  }
>
> +static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
> +                                   size_t buf_len)
> +{
> +       /* FIXME: locking */
> +       return ath10k_pci_diag_read_mem(ar, address, buf, buf_len);

Hmm.. This can potentially collide with firmware crash as it uses CE
diag window as well.

I'm thinking entire bodies of diag_read_mem()/diag_writemem() should
be protected by ar_pci->ce_lock. It shouldn't be hard. As for
diag_read_mem():

 * s/ath10k_ce_rx_post_buf/__ath10k_ce_rx_post_buf/
 * s/ath10k_ce_send/ath10k_ce_send_nolock/
 * s/ath10k_ce_completed_send_next/ath10k_ce_completed_send_next_nolock/
 * s/ath10k_ce_completed_recv_next/ath10k_ce_completed_recv_next_nolock/

Note: Most _nolock stuff is static in ce.c so it needs to be changed
to be accessible in pci.c.


Micha?


From kvalo at qca.qualcomm.com  Fri Sep 12 03:03:48 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 12 Sep 2014 13:03:48 +0300
Subject: [RFC PATCH 2/3] ath10k: add diag_read() to hif ops
In-Reply-To: <CA+BoTQ=oj9SkaeWBbX2jsD2UHUknhb6f_-ZUBbVSmuWUXFvm-g@mail.gmail.com>
 (Michal Kazior's message of "Fri, 12 Sep 2014 11:57:46 +0200")
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
 <20140911203147.12514.84857.stgit@potku.adurom.net>
 <CA+BoTQ=oj9SkaeWBbX2jsD2UHUknhb6f_-ZUBbVSmuWUXFvm-g@mail.gmail.com>
Message-ID: <878ulpyx2z.fsf@kamboji.qca.qualcomm.com>

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

> On 11 September 2014 22:31, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> diag_read() is used for reading from firmware memory via the diagnose window.
>> First user will be cal_data debugfs file.
> [...]
>> diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
>> index 154451ab3e3c..d3c51079034e 100644
>> --- a/drivers/net/wireless/ath/ath10k/pci.c
>> +++ b/drivers/net/wireless/ath/ath10k/pci.c
>> @@ -941,6 +941,13 @@ err:
>>         return err;
>>  }
>>
>> +static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
>> +                                   size_t buf_len)
>> +{
>> +       /* FIXME: locking */
>> +       return ath10k_pci_diag_read_mem(ar, address, buf, buf_len);
>
> Hmm.. This can potentially collide with firmware crash as it uses CE
> diag window as well.

Yeah, I was worried something like that could happen.

> I'm thinking entire bodies of diag_read_mem()/diag_writemem() should
> be protected by ar_pci->ce_lock. It shouldn't be hard. As for
> diag_read_mem():
>
>  * s/ath10k_ce_rx_post_buf/__ath10k_ce_rx_post_buf/
>  * s/ath10k_ce_send/ath10k_ce_send_nolock/
>  * s/ath10k_ce_completed_send_next/ath10k_ce_completed_send_next_nolock/
>  * s/ath10k_ce_completed_recv_next/ath10k_ce_completed_recv_next_nolock/
>
> Note: Most _nolock stuff is static in ce.c so it needs to be changed
> to be accessible in pci.c.

Sounds like a good idea, I'll take a closer look and see how it works
out. On the downside this means that there will be one more function
call in hot path (I assume the compiler is able to inline the _nolock
static functions).

-- 
Kalle Valo


From michal.kazior at tieto.com  Fri Sep 12 03:11:06 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Fri, 12 Sep 2014 12:11:06 +0200
Subject: [RFC PATCH 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <20140911203152.12514.95332.stgit@potku.adurom.net>
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
 <20140911203152.12514.95332.stgit@potku.adurom.net>
Message-ID: <CA+BoTQkPVN2ivGx0LRkXX2TSVpJLgqjBr9nPhtdntYhWdTpabQ@mail.gmail.com>

On 11 September 2014 22:31, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Provide calibration data used by the firmware to user space via a debugfs file.
> This makes it easier to debug calibration related problems.
>
> Example:
>
> sudo cp /sys/kernel/debug/ieee80211/phy0/ath10k/cal_data 1.cal

How about having a generic r/w access to target memory via debugfs?
Userspace would deal with the extraction of the cal data. Or do you
want to make it easier for the user to provide the cal data without
any extra tools (and that sending entire unprocessed target memory
dump may introduce some privacy concerns)?


Micha?


From yeohchunyeow at gmail.com  Fri Sep 12 03:41:25 2014
From: yeohchunyeow at gmail.com (Yeoh Chun-Yeow)
Date: Fri, 12 Sep 2014 18:41:25 +0800
Subject: [RFC] ath10k: use raw tx
In-Reply-To: <5411AF6A.7010702@candelatech.com>
References: <1408693965-29858-1-git-send-email-michal.kazior@tieto.com>
 <5400F497.7070904@candelatech.com>
 <CA+BoTQnhqxtHcX46-U+TjQBMDm27jM11xCJ956UFM_gjMvvs+A@mail.gmail.com>
 <5411AF6A.7010702@candelatech.com>
Message-ID: <CAEFj985XJgeyX7iXaXpYGvFMFUsPndajVVGAYFqzp0P_4zp8Lw@mail.gmail.com>

Hi, all

Did anyone try the raw tx on adhoc mode? I have tested this patch with
firmware 999.999.0.636.

The unicast frame is not transmitted using raw tx, only broadcast.

After adjust the cmd_tx.len as follow, I have managed to make the
adhoc STA to ping each others.

skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len -
sizeof(struct ieee80211_hdr_3addr) + sizeof(struct ethhdr));

Can someone comment on this?

----
Chun-Yeow


On Thu, Sep 11, 2014 at 10:19 PM, Ben Greear <greearb at candelatech.com> wrote:
> On 09/11/2014 03:35 AM, Michal Kazior wrote:
>>
>> On 29 August 2014 23:45, Ben Greear <greearb at candelatech.com> wrote:
>>>
>>> On 08/22/2014 12:52 AM, Michal Kazior wrote:
>>>>
>>>> This is just a reference for anyone interested in
>>>> getting injection working with ath10k.
>>>
>>>
>>> Did you try this with encryption?  I can reproduce the crash
>>> in open mode on my CT firmware, but I couldn't even get
>>> DHCP to complete with wpa2 enabled.
>>
>>
>> Hi,
>>
>> Late reply, sorry.
>>
>> I've just did a quick test on 10.2 (both AP and STA) with WPA2.
>> Apparently the raw tx mode requires IV to be set up on host and packet
>> length (reported in HTT Tx command header) must be re-adjusted
>> differently, otherwise frames are broken (incorrect FCS, too long,
>> somewhat encrypted except LLC/SNAP). The best I could get were
>> FCS-correct undecryptable frames on air. Perhaps someone will figure
>> that out..
>>
>> Another way around this would be to perform software crypto for tx
>> entirely on host.
>
>
> That did not fix the problem for me.  The firmware/hardware could not be
> convinced (by me, at least) to leave the encrypted packet alone and insisted
> on
> doing at least partial re-crypt, or something like that.
>
> Thanks,
> Ben
>
>>
>>
>> Micha?
>>
>
>
> --
> 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 kvalo at qca.qualcomm.com  Fri Sep 12 03:50:30 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 12 Sep 2014 13:50:30 +0300
Subject: [RFC PATCH 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <CA+BoTQkPVN2ivGx0LRkXX2TSVpJLgqjBr9nPhtdntYhWdTpabQ@mail.gmail.com>
 (Michal Kazior's message of "Fri, 12 Sep 2014 12:11:06 +0200")
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
 <20140911203152.12514.95332.stgit@potku.adurom.net>
 <CA+BoTQkPVN2ivGx0LRkXX2TSVpJLgqjBr9nPhtdntYhWdTpabQ@mail.gmail.com>
Message-ID: <874mwdyux5.fsf@kamboji.qca.qualcomm.com>

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

> On 11 September 2014 22:31, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> Provide calibration data used by the firmware to user space via a debugfs file.
>> This makes it easier to debug calibration related problems.
>>
>> Example:
>>
>> sudo cp /sys/kernel/debug/ieee80211/phy0/ath10k/cal_data 1.cal
>
> How about having a generic r/w access to target memory via debugfs?
> Userspace would deal with the extraction of the cal data. 

Yeah, Yanbo is working on that kind of generic interface.

> Or do you want to make it easier for the user to provide the cal data
> without any extra tools (and that sending entire unprocessed target
> memory dump may introduce some privacy concerns)?

This (to make it easier) is exactly my motivation here. In some of the
problems, especially once we add support to get calibration data from
host instead of just OTP, it's important to get easily access to the
calibration data. User only needs to do a simple cp operation and send
the file to us for further investigation.

Of course we could use the generic target memory interface for this, but
it's just more complicated for an unexperienced user and that's why I
think we should have this interface. But to be honest I'm not 100% sure
yet so other comments are more than welcome.

-- 
Kalle Valo


From michal.kazior at tieto.com  Fri Sep 12 04:05:45 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Fri, 12 Sep 2014 13:05:45 +0200
Subject: [RFC] ath10k: use raw tx
In-Reply-To: <CAEFj985XJgeyX7iXaXpYGvFMFUsPndajVVGAYFqzp0P_4zp8Lw@mail.gmail.com>
References: <1408693965-29858-1-git-send-email-michal.kazior@tieto.com>
 <5400F497.7070904@candelatech.com>
 <CA+BoTQnhqxtHcX46-U+TjQBMDm27jM11xCJ956UFM_gjMvvs+A@mail.gmail.com>
 <5411AF6A.7010702@candelatech.com>
 <CAEFj985XJgeyX7iXaXpYGvFMFUsPndajVVGAYFqzp0P_4zp8Lw@mail.gmail.com>
Message-ID: <CA+BoTQkr0gB_uYvRk3Za035vAcT1BhqVccVD2gR1iJXGmMpABA@mail.gmail.com>

On 12 September 2014 12:41, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
> Hi, all
>
> Did anyone try the raw tx on adhoc mode? I have tested this patch with
> firmware 999.999.0.636.
>
> The unicast frame is not transmitted using raw tx, only broadcast.

I did not test 636 with IBSS.


> After adjust the cmd_tx.len as follow, I have managed to make the
> adhoc STA to ping each others.
>
> skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len -
> sizeof(struct ieee80211_hdr_3addr) + sizeof(struct ethhdr));
>
> Can someone comment on this?

Interesting!

Can you confirm what kind of a header your unicast frames actually
have? Do you perhaps run 4addr mode? Or maybe Data/QoS Data (2 byte
difference at least) calculation is the problem.


Micha?


From kvalo at qca.qualcomm.com  Fri Sep 12 04:25:01 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 12 Sep 2014 14:25:01 +0300
Subject: [RFC PATCH 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <5412260F.80607@candelatech.com> (Ben Greear's message of "Thu,
 11 Sep 2014 15:45:35 -0700")
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
 <20140911203152.12514.95332.stgit@potku.adurom.net>
 <5412260F.80607@candelatech.com>
Message-ID: <87sijxxer6.fsf@kamboji.qca.qualcomm.com>

Ben Greear <greearb at candelatech.com> writes:

> On 09/11/2014 01:31 PM, Kalle Valo wrote:
>> Provide calibration data used by the firmware to user space via a debugfs file.
>> This makes it easier to debug calibration related problems.
>>
>> Example:
>>
>> sudo cp /sys/kernel/debug/ieee80211/phy0/ath10k/cal_data 1.cal
>
> Is this data that could be made human readable, or does it need to
> be parsed by some private tool?

A private tool is needed for this.

-- 
Kalle Valo


From greearb at candelatech.com  Fri Sep 12 09:17:55 2014
From: greearb at candelatech.com (Ben Greear)
Date: Fri, 12 Sep 2014 09:17:55 -0700
Subject: [RFC PATCH 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <874mwdyux5.fsf@kamboji.qca.qualcomm.com>
References: <20140911202926.12514.79908.stgit@potku.adurom.net>
 <20140911203152.12514.95332.stgit@potku.adurom.net>
 <CA+BoTQkPVN2ivGx0LRkXX2TSVpJLgqjBr9nPhtdntYhWdTpabQ@mail.gmail.com>
 <874mwdyux5.fsf@kamboji.qca.qualcomm.com>
Message-ID: <54131CB3.3070104@candelatech.com>

On 09/12/2014 03:50 AM, Kalle Valo wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
> 
>> On 11 September 2014 22:31, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>>> Provide calibration data used by the firmware to user space via a debugfs file.
>>> This makes it easier to debug calibration related problems.
>>>
>>> Example:
>>>
>>> sudo cp /sys/kernel/debug/ieee80211/phy0/ath10k/cal_data 1.cal
>>
>> How about having a generic r/w access to target memory via debugfs?
>> Userspace would deal with the extraction of the cal data. 
> 
> Yeah, Yanbo is working on that kind of generic interface.
> 
>> Or do you want to make it easier for the user to provide the cal data
>> without any extra tools (and that sending entire unprocessed target
>> memory dump may introduce some privacy concerns)?
> 
> This (to make it easier) is exactly my motivation here. In some of the
> problems, especially once we add support to get calibration data from
> host instead of just OTP, it's important to get easily access to the
> calibration data. User only needs to do a simple cp operation and send
> the file to us for further investigation.
> 
> Of course we could use the generic target memory interface for this, but
> it's just more complicated for an unexperienced user and that's why I
> think we should have this interface. But to be honest I'm not 100% sure
> yet so other comments are more than welcome.

Different firmware may place this at different locations, so I definitely
like a well-defined interface to grab the requested data instead of having to
try to grab it out of a full ram dump.

Thanks,
Ben


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



From greearb at candelatech.com  Fri Sep 12 09:23:41 2014
From: greearb at candelatech.com (Ben Greear)
Date: Fri, 12 Sep 2014 09:23:41 -0700
Subject: Change the number of active antennas (RF-chains)
In-Reply-To: <AFAC18488DA64ACD88984878834DF25A@mwnl.snu.ac.kr>
References: <CANzpp-k2QdD6C9VJF7hPR2sKOQwhXxxA4qsJcihjKVrwgtXQng@mail.gmail.com>
 <5411AFE7.8060008@candelatech.com>
 <AFAC18488DA64ACD88984878834DF25A@mwnl.snu.ac.kr>
Message-ID: <54131E0D.3010903@candelatech.com>

On 09/11/2014 08:48 PM, Okhwan Lee wrote:
> Hi,  
> 
> Thank you for your answer.  
> I use 3.16.1 kernel version,  3.16.1 backport version and 10.1.467.2-1 firmware version.  
> I am curious to know your testing.  
> 
> This is my test bash-script.
> 
> ########### test.sh ###########
> 
> #!/usr/bin/sudo /bin/bash
> rmmod ath10k_pci ath10k_core ath mac80211 cfg80211
> modprobe ath10k_pci  
> ifconfig wlan0 2>/dev/null 1>/dev/null
> while [ $? -ne 0 ]  
> do
> ifconfig wlan0 2>/dev/null 1>/dev/null
> done

What are the commands above supposed to be doing?

> echo 0x12 > /sys/module/ath10k_core/parameters/debug_mask
> iw dev wlan0 interface add mon0 type monitor
> iw mon0 set freq 5180 80 5210
> ifconfig mon0 up
> 
> 
> 
> ######################
> 
> then ? type the following command in shell prompt  
> 
> echo 0x1 > /sys/kernel/debug/ieee80211/phy*/ath10k/rx_chainmask
> echo 0x7 > /sys/kernel/debug/ieee80211/phy*/ath10k/rx_chainmask

You should be able to configure this using 'iw'

And, you probably need to configure the chainmask before
creating or starting the wlan and other vifs.

Thanks,
Ben

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



From yeohchunyeow at gmail.com  Fri Sep 12 18:07:37 2014
From: yeohchunyeow at gmail.com (Yeoh Chun-Yeow)
Date: Sat, 13 Sep 2014 09:07:37 +0800
Subject: [RFC] ath10k: use raw tx
In-Reply-To: <CA+BoTQkr0gB_uYvRk3Za035vAcT1BhqVccVD2gR1iJXGmMpABA@mail.gmail.com>
References: <1408693965-29858-1-git-send-email-michal.kazior@tieto.com>
 <5400F497.7070904@candelatech.com>
 <CA+BoTQnhqxtHcX46-U+TjQBMDm27jM11xCJ956UFM_gjMvvs+A@mail.gmail.com>
 <5411AF6A.7010702@candelatech.com>
 <CAEFj985XJgeyX7iXaXpYGvFMFUsPndajVVGAYFqzp0P_4zp8Lw@mail.gmail.com>
 <CA+BoTQkr0gB_uYvRk3Za035vAcT1BhqVccVD2gR1iJXGmMpABA@mail.gmail.com>
Message-ID: <CAEFj987FUy7UrTXz-nSCcpMQ+vYwEXTMnd3BzpJ7HEEbC5Ti8A@mail.gmail.com>

On Fri, Sep 12, 2014 at 7:05 PM, Michal Kazior <michal.kazior at tieto.com> wrote:
> On 12 September 2014 12:41, Yeoh Chun-Yeow <yeohchunyeow at gmail.com> wrote:
>
> Interesting!
>
> Can you confirm what kind of a header your unicast frames actually
> have? Do you perhaps run 4addr mode? Or maybe Data/QoS Data (2 byte
> difference at least) calculation is the problem.
>

It's a QoS Data frame. Yes (2 byte different). Probably the firmware
raw tx mode only cater for non-QoS frame?

Question, 4addr mode is allowed in adhoc mode by the firmware? No, right?

----
Chun-Yeow


From kvalo at qca.qualcomm.com  Sun Sep 14 02:49:55 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:49:55 +0300
Subject: [PATCH 00/10] ath10k: checkpatch fixes from v3.17
Message-ID: <20140914094728.9063.32593.stgit@x230>

Hi,

some fixes to recently added checkpatch warnings. Please review.

Kalle

---

Kalle Valo (10):
      ath10k: fix parenthesis alignment warning in ath10k_htt_rx_alloc()
      ath10k: fix checkpatch warnings about parenthesis alignment
      ath10k: fix use of multiple blank lines
      ath10k: fix missing a blank line after declarations
      ath10k: fix space after a cast style errors
      ath10k: don't use return on void functions
      ath10k: else is not generally useful after a break or return
      ath10k: miscellaneous checkpatch fixes
      ath10k: reformat help text in ath10k_read_simulate_fw_crash()
      ath10k: use ether_addr_copy()


 drivers/net/wireless/ath/ath10k/bmi.h       |    1 
 drivers/net/wireless/ath/ath10k/ce.c        |    2 -
 drivers/net/wireless/ath/ath10k/ce.h        |   13 ++---
 drivers/net/wireless/ath/ath10k/debug.c     |   33 ++++++--------
 drivers/net/wireless/ath/ath10k/hif.h       |    1 
 drivers/net/wireless/ath/ath10k/htc.c       |   10 +---
 drivers/net/wireless/ath/ath10k/htc.h       |    1 
 drivers/net/wireless/ath/ath10k/htt.c       |    2 -
 drivers/net/wireless/ath/ath10k/htt.h       |    3 -
 drivers/net/wireless/ath/ath10k/htt_rx.c    |   52 +++++++++++----------
 drivers/net/wireless/ath/ath10k/htt_tx.c    |    2 -
 drivers/net/wireless/ath/ath10k/mac.c       |   45 ++++++++----------
 drivers/net/wireless/ath/ath10k/pci.c       |   37 ++++++++-------
 drivers/net/wireless/ath/ath10k/rx_desc.h   |    1 
 drivers/net/wireless/ath/ath10k/targaddrs.h |    1 
 drivers/net/wireless/ath/ath10k/txrx.c      |    2 -
 drivers/net/wireless/ath/ath10k/wmi.c       |   66 ++++++++++++++-------------
 drivers/net/wireless/ath/ath10k/wmi.h       |   17 ++-----
 18 files changed, 132 insertions(+), 157 deletions(-)


From kvalo at qca.qualcomm.com  Sun Sep 14 02:50:00 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:50:00 +0300
Subject: [PATCH 01/10] ath10k: fix parenthesis alignment warning in
 ath10k_htt_rx_alloc()
In-Reply-To: <20140914094728.9063.32593.stgit@x230>
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <20140914095000.9063.95112.stgit@x230>

Fixes checkpatch warning:

ath10k/htt_rx.c:519: CHECK: Alignment should match open parenthesis

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 57e1fe77602b..7313bd16a4b3 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -488,6 +488,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
 	struct ath10k *ar = htt->ar;
 	dma_addr_t paddr;
 	void *vaddr;
+	size_t size;
 	struct timer_list *timer = &htt->rx_ring.refill_retry_timer;
 
 	htt->rx_ring.size = ath10k_htt_rx_ring_size(htt);
@@ -515,9 +516,9 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
 	if (!htt->rx_ring.netbufs_ring)
 		goto err_netbuf;
 
-	vaddr = dma_alloc_coherent(htt->ar->dev,
-		   (htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring)),
-		   &paddr, GFP_DMA);
+	size = htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring);
+
+	vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_DMA);
 	if (!vaddr)
 		goto err_dma_ring;
 



From kvalo at qca.qualcomm.com  Sun Sep 14 02:50:06 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:50:06 +0300
Subject: [PATCH 02/10] ath10k: fix checkpatch warnings about parenthesis
 alignment
In-Reply-To: <20140914094728.9063.32593.stgit@x230>
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <20140914095006.9063.41102.stgit@x230>

CHECK: Alignment should match open parenthesis

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/ce.h     |   10 +++++-----
 drivers/net/wireless/ath/ath10k/debug.c  |   15 ++++++++-------
 drivers/net/wireless/ath/ath10k/htc.c    |    2 +-
 drivers/net/wireless/ath/ath10k/htt.c    |    2 +-
 drivers/net/wireless/ath/ath10k/htt_rx.c |   12 ++++++------
 drivers/net/wireless/ath/ath10k/mac.c    |   13 +++++++------
 drivers/net/wireless/ath/ath10k/pci.c    |   14 +++++++-------
 drivers/net/wireless/ath/ath10k/wmi.c    |   30 ++++++++++++++++--------------
 drivers/net/wireless/ath/ath10k/wmi.h    |    8 ++++----
 9 files changed, 55 insertions(+), 51 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index 82d1f23546b9..ad4fa7eb945f 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -189,10 +189,10 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
  * Pops 1 completed send buffer from Source ring.
  */
 int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
-			   void **per_transfer_contextp,
-			   u32 *bufferp,
-			   unsigned int *nbytesp,
-			   unsigned int *transfer_idp);
+				  void **per_transfer_contextp,
+				  u32 *bufferp,
+				  unsigned int *nbytesp,
+				  unsigned int *transfer_idp);
 
 /*==================CE Engine Initialization=======================*/
 
@@ -202,7 +202,7 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
 			void (*recv_cb)(struct ath10k_ce_pipe *));
 void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
 int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
-			  const struct ce_attr *attr);
+			 const struct ce_attr *attr);
 void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id);
 
 /*==================CE Engine Shutdown=======================*/
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index c1921143a870..2bfd00b29204 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -645,7 +645,8 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
 		 * firmware variants in order to force a firmware crash.
 		 */
 		ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
-					ar->wmi.vdev_param->rts_threshold, 0);
+						ar->wmi.vdev_param->rts_threshold,
+						0);
 	} else if (!strcmp(buf, "assert")) {
 		ath10k_info(ar, "simulating firmware assert crash\n");
 		ret = ath10k_debug_fw_assert(ar);
@@ -867,8 +868,8 @@ static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
 }
 
 static ssize_t ath10k_read_htt_stats_mask(struct file *file,
-					    char __user *user_buf,
-					    size_t count, loff_t *ppos)
+					  char __user *user_buf,
+					  size_t count, loff_t *ppos)
 {
 	struct ath10k *ar = file->private_data;
 	char buf[32];
@@ -880,8 +881,8 @@ static ssize_t ath10k_read_htt_stats_mask(struct file *file,
 }
 
 static ssize_t ath10k_write_htt_stats_mask(struct file *file,
-					     const char __user *user_buf,
-					     size_t count, loff_t *ppos)
+					   const char __user *user_buf,
+					   size_t count, loff_t *ppos)
 {
 	struct ath10k *ar = file->private_data;
 	unsigned long mask;
@@ -986,8 +987,8 @@ static const struct file_operations fops_htt_max_amsdu_ampdu = {
 };
 
 static ssize_t ath10k_read_fw_dbglog(struct file *file,
-					    char __user *user_buf,
-					    size_t count, loff_t *ppos)
+				     char __user *user_buf,
+				     size_t count, loff_t *ppos)
 {
 	struct ath10k *ar = file->private_data;
 	unsigned int len;
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index fd9a251f0659..b7ee24b19f59 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -569,7 +569,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 			ath10k_hif_send_complete_check(htc->ar, i, 1);
 
 		status = wait_for_completion_timeout(&htc->ctl_resp,
-					ATH10K_HTC_WAIT_TIMEOUT_HZ);
+						     ATH10K_HTC_WAIT_TIMEOUT_HZ);
 
 		if (status == 0)
 			status = -ETIMEDOUT;
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 87daae11f116..56cb4aceb383 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -101,7 +101,7 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
 		return status;
 
 	status = wait_for_completion_timeout(&htt->target_version_received,
-						HTT_TARGET_VERSION_TIMEOUT_HZ);
+					     HTT_TARGET_VERSION_TIMEOUT_HZ);
 	if (status <= 0) {
 		ath10k_warn(ar, "htt version request timed out\n");
 		return -ETIMEDOUT;
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 7313bd16a4b3..a720de3d20c4 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -626,7 +626,7 @@ static struct ieee80211_hdr *ath10k_htt_rx_skb_get_hdr(struct sk_buff *skb)
 
 	rxd = (void *)skb->data - sizeof(*rxd);
 	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
-			RX_MSDU_START_INFO1_DECAP_FORMAT);
+		 RX_MSDU_START_INFO1_DECAP_FORMAT);
 
 	if (fmt == RX_MSDU_DECAP_RAW)
 		return (void *)skb->data;
@@ -915,7 +915,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 
 	rxd = (void *)skb->data - sizeof(*rxd);
 	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
-			RX_MPDU_START_INFO0_ENCRYPT_TYPE);
+		     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
 
 	hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
 	hdr_len = ieee80211_hdrlen(hdr->frame_control);
@@ -1030,9 +1030,9 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
 
 	rxd = (void *)skb->data - sizeof(*rxd);
 	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
-			RX_MSDU_START_INFO1_DECAP_FORMAT);
+		 RX_MSDU_START_INFO1_DECAP_FORMAT);
 	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
-			RX_MPDU_START_INFO0_ENCRYPT_TYPE);
+		     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
 	hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
 	hdr_len = ieee80211_hdrlen(hdr->frame_control);
 
@@ -1333,7 +1333,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
 }
 
 static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
-				struct htt_rx_fragment_indication *frag)
+				       struct htt_rx_fragment_indication *frag)
 {
 	struct ath10k *ar = htt->ar;
 	struct sk_buff *msdu_head, *msdu_tail;
@@ -1379,7 +1379,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
 	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);
+		 RX_MSDU_START_INFO1_DECAP_FORMAT);
 
 	if (fmt != RX_MSDU_DECAP_RAW) {
 		ath10k_warn(ar, "we dont support non-raw fragmented rx yet\n");
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 5b35fff8127f..bd852078a413 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -896,7 +896,7 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
 }
 
 static void ath10k_control_beaconing(struct ath10k_vif *arvif,
-				struct ieee80211_bss_conf *info)
+				     struct ieee80211_bss_conf *info)
 {
 	struct ath10k *ar = arvif->ar;
 	int ret = 0;
@@ -1106,9 +1106,9 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
 		ies = rcu_dereference(bss->ies);
 
 		wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
-				WLAN_OUI_TYPE_MICROSOFT_WPA,
-				ies->data,
-				ies->len);
+						WLAN_OUI_TYPE_MICROSOFT_WPA,
+						ies->data,
+						ies->len);
 		rcu_read_unlock();
 		cfg80211_put_bss(ar->hw->wiphy, bss);
 	}
@@ -1291,7 +1291,8 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar,
 		   sta->listen_interval - mac80211 patch required.
 		   Currently use 10 seconds */
 		ret = ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, sta->addr,
-					WMI_AP_PS_PEER_PARAM_AGEOUT_TIME, 10);
+						 WMI_AP_PS_PEER_PARAM_AGEOUT_TIME,
+						 10);
 		if (ret) {
 			ath10k_warn(ar, "failed to set ap ps peer param ageout time for vdev %i: %d\n",
 				    arvif->vdev_id, ret);
@@ -3568,7 +3569,7 @@ exit:
 }
 
 static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
-				 u16 ac, bool enable)
+				u16 ac, bool enable)
 {
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	u32 value = 0;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index baeb98e78b1f..52f273b92fa3 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -527,7 +527,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 						     address);
 
 		ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0,
-				 0);
+				     0);
 		if (ret)
 			goto done;
 
@@ -1106,7 +1106,7 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar,
 }
 
 static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar,
-						u8 *ul_pipe, u8 *dl_pipe)
+					    u8 *ul_pipe, u8 *dl_pipe)
 {
 	int ul_is_polled, dl_is_polled;
 
@@ -1476,8 +1476,8 @@ static int ath10k_pci_init_config(struct ath10k *ar)
 	}
 
 	ret = ath10k_pci_diag_write_mem(ar, pipe_cfg_targ_addr,
-				 target_ce_config_wlan,
-				 sizeof(target_ce_config_wlan));
+					target_ce_config_wlan,
+					sizeof(target_ce_config_wlan));
 
 	if (ret != 0) {
 		ath10k_err(ar, "Failed to write pipe cfg: %d\n", ret);
@@ -1500,8 +1500,8 @@ static int ath10k_pci_init_config(struct ath10k *ar)
 	}
 
 	ret = ath10k_pci_diag_write_mem(ar, svc_to_pipe_map,
-				 target_service_to_ce_map_wlan,
-				 sizeof(target_service_to_ce_map_wlan));
+					target_service_to_ce_map_wlan,
+					sizeof(target_service_to_ce_map_wlan));
 	if (ret != 0) {
 		ath10k_err(ar, "Failed to write svc/pipe map: %d\n", ret);
 		return ret;
@@ -2160,7 +2160,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
 	if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) {
 		ar_pci->num_msi_intrs = MSI_NUM_REQUEST;
 		ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs,
-							 ar_pci->num_msi_intrs);
+					   ar_pci->num_msi_intrs);
 		if (ret > 0)
 			return 0;
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 3e2213409074..3b5749d8b081 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1859,9 +1859,10 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar,
 	}
 }
 
-static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
-				struct wmi_single_phyerr_rx_event *event,
-				u64 tsf)
+static void
+ath10k_wmi_event_spectral_scan(struct ath10k *ar,
+			       struct wmi_single_phyerr_rx_event *event,
+			       u64 tsf)
 {
 	int buf_len, tlv_len, res, i = 0;
 	struct phyerr_tlv *tlv;
@@ -1989,7 +1990,7 @@ static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
 }
 
 static void ath10k_wmi_event_profile_match(struct ath10k *ar,
-				    struct sk_buff *skb)
+					   struct sk_buff *skb)
 {
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PROFILE_MATCH\n");
 }
@@ -2040,13 +2041,13 @@ static void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar,
 }
 
 static void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar,
-					     struct sk_buff *skb)
+						    struct sk_buff *skb)
 {
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_RTT_MEASUREMENT_REPORT_EVENTID\n");
 }
 
 static void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar,
-					     struct sk_buff *skb)
+						    struct sk_buff *skb)
 {
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TSF_MEASUREMENT_REPORT_EVENTID\n");
 }
@@ -2082,7 +2083,7 @@ static void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar,
 }
 
 static void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar,
-					 struct sk_buff *skb)
+						struct sk_buff *skb)
 {
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_GTK_OFFLOAD_STATUS_EVENTID\n");
 }
@@ -2106,7 +2107,7 @@ static void ath10k_wmi_event_addba_complete(struct ath10k *ar,
 }
 
 static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
-						struct sk_buff *skb)
+						       struct sk_buff *skb)
 {
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n");
 }
@@ -2130,7 +2131,7 @@ static void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar,
 }
 
 static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
-				      u32 num_units, u32 unit_len)
+				     u32 num_units, u32 unit_len)
 {
 	dma_addr_t paddr;
 	u32 pool_size;
@@ -3520,9 +3521,10 @@ int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id)
 	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid);
 }
 
-static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
-				const struct wmi_vdev_start_request_arg *arg,
-				u32 cmd_id)
+static int
+ath10k_wmi_vdev_start_restart(struct ath10k *ar,
+			      const struct wmi_vdev_start_request_arg *arg,
+			      u32 cmd_id)
 {
 	struct wmi_vdev_start_request_cmd *cmd;
 	struct sk_buff *skb;
@@ -3603,7 +3605,7 @@ int ath10k_wmi_vdev_start(struct ath10k *ar,
 }
 
 int ath10k_wmi_vdev_restart(struct ath10k *ar,
-		     const struct wmi_vdev_start_request_arg *arg)
+			    const struct wmi_vdev_start_request_arg *arg)
 {
 	u32 cmd_id = ar->wmi.cmd->vdev_restart_request_cmdid;
 
@@ -4172,7 +4174,7 @@ static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
 }
 
 int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
-			const struct wmi_pdev_set_wmm_params_arg *arg)
+				   const struct wmi_pdev_set_wmm_params_arg *arg)
 {
 	struct wmi_pdev_set_wmm_params *cmd;
 	struct sk_buff *skb;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index f8c1afbdb442..1cc594e18a07 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -4776,11 +4776,11 @@ int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
 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]);
+			   const u8 peer_addr[ETH_ALEN]);
 int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
-		    const u8 peer_addr[ETH_ALEN]);
+			   const u8 peer_addr[ETH_ALEN]);
 int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
-		   const u8 peer_addr[ETH_ALEN], u32 tid_bitmap);
+			  const u8 peer_addr[ETH_ALEN], u32 tid_bitmap);
 int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
 			      const u8 *peer_addr,
 			      enum wmi_peer_param param_id, u32 param_value);
@@ -4797,7 +4797,7 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar,
 			      const struct wmi_scan_chan_list_arg *arg);
 int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif);
 int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
-			const struct wmi_pdev_set_wmm_params_arg *arg);
+				   const struct wmi_pdev_set_wmm_params_arg *arg);
 int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id);
 int ath10k_wmi_force_fw_hang(struct ath10k *ar,
 			     enum wmi_force_fw_hang_type type, u32 delay_ms);



From kvalo at qca.qualcomm.com  Sun Sep 14 02:50:11 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:50:11 +0300
Subject: [PATCH 03/10] ath10k: fix use of multiple blank lines
In-Reply-To: <20140914094728.9063.32593.stgit@x230>
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <20140914095011.9063.98994.stgit@x230>

Fixes checkpatch warnings:

CHECK: Please don't use multiple blank lines

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/bmi.h       |    1 -
 drivers/net/wireless/ath/ath10k/ce.c        |    2 --
 drivers/net/wireless/ath/ath10k/ce.h        |    3 ---
 drivers/net/wireless/ath/ath10k/hif.h       |    1 -
 drivers/net/wireless/ath/ath10k/htc.h       |    1 -
 drivers/net/wireless/ath/ath10k/htt.h       |    2 --
 drivers/net/wireless/ath/ath10k/htt_rx.c    |    1 -
 drivers/net/wireless/ath/ath10k/htt_tx.c    |    1 -
 drivers/net/wireless/ath/ath10k/mac.c       |    4 ----
 drivers/net/wireless/ath/ath10k/rx_desc.h   |    1 -
 drivers/net/wireless/ath/ath10k/targaddrs.h |    1 -
 drivers/net/wireless/ath/ath10k/wmi.c       |    2 --
 drivers/net/wireless/ath/ath10k/wmi.h       |    9 ---------
 13 files changed, 29 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index 111ab701465c..31a990635490 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -177,7 +177,6 @@ struct bmi_target_info {
 	u32 type;
 };
 
-
 /* in msec */
 #define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ)
 
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 71eef233bd01..101cadb6e4ba 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -260,7 +260,6 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
 	ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask);
 }
 
-
 /*
  * Guts of ath10k_ce_send, used by both ath10k_ce_send and
  * ath10k_ce_sendlist_send.
@@ -385,7 +384,6 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe)
 	return delta;
 }
 
-
 int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe)
 {
 	struct ath10k *ar = pipe->ar;
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index ad4fa7eb945f..329b7340fa72 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -20,7 +20,6 @@
 
 #include "hif.h"
 
-
 /* Maximum number of Copy Engine's supported */
 #define CE_COUNT_MAX 8
 #define CE_HTT_H2T_MSG_SRC_NENTRIES 4096
@@ -37,7 +36,6 @@
 
 struct ath10k_ce_pipe;
 
-
 #define CE_DESC_FLAGS_GATHER         (1 << 0)
 #define CE_DESC_FLAGS_BYTE_SWAP      (1 << 1)
 #define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC
@@ -383,7 +381,6 @@ struct ce_attr {
 #define DST_WATERMARK_HIGH_RESET		0
 #define DST_WATERMARK_ADDRESS			0x0050
 
-
 static inline u32 ath10k_ce_base_address(unsigned int ce_id)
 {
 	return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 2ac7beacddca..62323fea27e1 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -91,7 +91,6 @@ struct ath10k_hif_ops {
 	int (*resume)(struct ath10k *ar);
 };
 
-
 static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
 				   struct ath10k_hif_sg_item *items,
 				   int n_items)
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index bf532f671189..527179c0edce 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -214,7 +214,6 @@ struct ath10k_htc_frame {
 	struct ath10k_htc_record trailer[0];
 } __packed __aligned(4);
 
-
 /*******************/
 /* Host-side stuff */
 /*******************/
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 6c93f3885ee5..e20472672efe 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -265,7 +265,6 @@ enum htt_mgmt_tx_status {
 
 /*=== target -> host messages ===============================================*/
 
-
 enum htt_t2h_msg_type {
 	HTT_T2H_MSG_TYPE_VERSION_CONF		= 0x0,
 	HTT_T2H_MSG_TYPE_RX_IND			= 0x1,
@@ -1148,7 +1147,6 @@ struct htt_resp {
 	};
 } __packed;
 
-
 /*** host side structures follow ***/
 
 struct htt_tx_done {
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index a720de3d20c4..1e69db52e465 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -42,7 +42,6 @@
 /* when under memory pressure rx ring refill may fail and needs a retry */
 #define HTT_RX_RING_REFILL_RETRY_MS 50
 
-
 static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
 static void ath10k_htt_txrx_compl_task(unsigned long ptr);
 
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index eaa73aa99c20..1ab64631ba1b 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -377,7 +377,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
 	int msdu_id = -1;
 	int res;
 
-
 	res = ath10k_htt_tx_inc_pending(htt);
 	if (res)
 		goto err;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index bd852078a413..75b30adfd367 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -225,7 +225,6 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
 	return first_errno;
 }
 
-
 /*********************/
 /* General utilities */
 /*********************/
@@ -1262,7 +1261,6 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar,
 			uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
 				 WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
 
-
 		if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)
 			max_sp = sta->max_sp;
 
@@ -1316,7 +1314,6 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
 	arg->peer_flags |= WMI_PEER_VHT;
 	arg->peer_vht_caps = vht_cap->cap;
 
-
 	ampdu_factor = (vht_cap->cap &
 			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
 		       IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
@@ -4715,7 +4712,6 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
 	return ht_cap;
 }
 
-
 static void ath10k_get_arvif_iter(void *data, u8 *mac,
 				  struct ieee80211_vif *vif)
 {
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h
index 1c584c4b019c..e1ffdd57a18c 100644
--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
@@ -839,7 +839,6 @@ struct rx_ppdu_start {
  *		Reserved: HW should fill with 0, FW should ignore.
 */
 
-
 #define RX_PPDU_END_FLAGS_PHY_ERR             (1 << 0)
 #define RX_PPDU_END_FLAGS_RX_LOCATION         (1 << 1)
 #define RX_PPDU_END_FLAGS_TXBF_H_INFO         (1 << 2)
diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h
index be7ba1e78afe..9d0ae30f9ff1 100644
--- a/drivers/net/wireless/ath/ath10k/targaddrs.h
+++ b/drivers/net/wireless/ath/ath10k/targaddrs.h
@@ -284,7 +284,6 @@ Fw Mode/SubMode Mask
 #define HI_OPTION_ALL_FW_SUBMODE_MASK  0xFF00
 #define HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8
 
-
 /* hi_option_flag2 options */
 #define HI_OPTION_OFFLOAD_AMSDU     0x01
 #define HI_OPTION_DFS_SUPPORT       0x02 /* Enable DFS support */
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 3b5749d8b081..ed438edb9763 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1511,7 +1511,6 @@ static u32 ath10k_p2p_calc_noa_ie_len(struct wmi_p2p_noa_info *noa)
 	u8 opp_ps_info = noa->ctwindow_oppps;
 	bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT);
 
-
 	if (!noa_descriptors && !opps_enabled)
 		return len;
 
@@ -1568,7 +1567,6 @@ cleanup:
 	kfree(old_data);
 }
 
-
 static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_host_swba_event *ev;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 1cc594e18a07..86f5ebccfe79 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -1269,7 +1269,6 @@ enum wmi_channel_change_cause {
 				WMI_HT_CAP_RX_STBC       | \
 				WMI_HT_CAP_LDPC)
 
-
 /*
  * WMI_VHT_CAP_* these maps to ieee 802.11ac vht capability information
  * field. The fields not defined here are not supported, or reserved.
@@ -1471,7 +1470,6 @@ struct wmi_service_ready_event_10x {
 	struct wlan_host_mem_req mem_reqs[1];
 } __packed;
 
-
 #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ)
 #define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ)
 
@@ -2125,7 +2123,6 @@ struct wmi_start_scan_cmd_10x {
 	 */
 } __packed;
 
-
 struct wmi_ssid_arg {
 	int len;
 	const u8 *ssid;
@@ -2186,7 +2183,6 @@ struct wmi_start_scan_arg {
 /* WMI_SCAN_CLASS_MASK must be the same value as IEEE80211_SCAN_CLASS_MASK */
 #define WMI_SCAN_CLASS_MASK 0xFF000000
 
-
 enum wmi_stop_scan_type {
 	WMI_SCAN_STOP_ONE	= 0x00000000, /* stop by scan_id */
 	WMI_SCAN_STOP_VDEV_ALL	= 0x01000000, /* stop by vdev_id */
@@ -2371,7 +2367,6 @@ struct wmi_single_phyerr_rx_hdr {
 	__le32 nf_list_1;
 	__le32 nf_list_2;
 
-
 	/* Length of the frame */
 	__le32 buf_len;
 } __packed;
@@ -2473,7 +2468,6 @@ struct phyerr_fft_report {
 #define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_MASK	0x000000FF
 #define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_LSB	0
 
-
 struct phyerr_tlv {
 	__le16 len;
 	u8 tag;
@@ -2504,7 +2498,6 @@ struct wmi_echo_cmd {
 	__le32 value;
 } __packed;
 
-
 struct wmi_pdev_set_regdomain_cmd {
 	__le32 reg_domain;
 	__le32 reg_domain_2G;
@@ -2553,7 +2546,6 @@ struct wmi_pdev_set_quiet_cmd {
 	__le32 enabled;
 } __packed;
 
-
 /*
  * 802.11g protection mode.
  */
@@ -4291,7 +4283,6 @@ struct wmi_tbtt_offset_event {
 	__le32 tbttoffset_list[WMI_MAX_AP_VDEV];
 } __packed;
 
-
 struct wmi_peer_create_cmd {
 	__le32 vdev_id;
 	struct wmi_mac_addr peer_macaddr;



From kvalo at qca.qualcomm.com  Sun Sep 14 02:50:17 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:50:17 +0300
Subject: [PATCH 04/10] ath10k: fix missing a blank line after declarations
In-Reply-To: <20140914094728.9063.32593.stgit@x230>
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <20140914095017.9063.87892.stgit@x230>

Fixes checkpatch warnings:

WARNING: Missing a blank line after declarations

Please note that some of the cases I fixed by moving the variable declarations
to the beginning of the function, which is the preferred style in ath10k.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c |   10 +++++++---
 drivers/net/wireless/ath/ath10k/mac.c    |    6 ++----
 drivers/net/wireless/ath/ath10k/wmi.c    |    8 ++++++--
 3 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 1e69db52e465..26196ed947bc 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -222,6 +222,7 @@ static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt)
 static void ath10k_htt_rx_ring_refill_retry(unsigned long arg)
 {
 	struct ath10k_htt *htt = (struct ath10k_htt *)arg;
+
 	ath10k_htt_rx_msdu_buff_replenish(htt);
 }
 
@@ -313,7 +314,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
 {
 	struct ath10k *ar = htt->ar;
 	int msdu_len, msdu_chaining = 0;
-	struct sk_buff *msdu;
+	struct sk_buff *msdu, *next;
 	struct htt_rx_desc *rx_desc;
 
 	lockdep_assert_held(&htt->rx_ring.lock);
@@ -450,7 +451,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
 			msdu->next = NULL;
 			break;
 		} else {
-			struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt);
+			next = ath10k_htt_rx_netbuf_pop(htt);
 			msdu->next = next;
 			msdu = next;
 		}
@@ -479,6 +480,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
 static void ath10k_htt_rx_replenish_task(unsigned long ptr)
 {
 	struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
+
 	ath10k_htt_rx_msdu_buff_replenish(htt);
 }
 
@@ -636,8 +638,10 @@ static struct ieee80211_hdr *ath10k_htt_rx_skb_get_hdr(struct sk_buff *skb)
 /* This function only applies for first msdu in an msdu chain */
 static bool ath10k_htt_rx_hdr_is_amsdu(struct ieee80211_hdr *hdr)
 {
+	u8 *qc;
+
 	if (ieee80211_is_data_qos(hdr->frame_control)) {
-		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		qc = ieee80211_get_qos_ctl(hdr);
 		if (qc[0] & 0x80)
 			return true;
 	}
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 75b30adfd367..c1cf6ff319e8 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1157,6 +1157,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
 {
 	const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
 	int i, n;
+	u32 stbc;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
@@ -1193,7 +1194,6 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
 	}
 
 	if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
-		u32 stbc;
 		stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC;
 		stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
 		stbc = stbc << WMI_RC_RX_STBC_FLAG_S;
@@ -3011,7 +3011,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
 	int ret = 0;
-	u32 vdev_param, pdev_param;
+	u32 vdev_param, pdev_param, slottime, preamble;
 
 	mutex_lock(&ar->conf_mutex);
 
@@ -3132,7 +3132,6 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
 	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT) {
-		u32 slottime;
 		if (info->use_short_slot)
 			slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */
 
@@ -3151,7 +3150,6 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
 	}
 
 	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		u32 preamble;
 		if (info->use_short_preamble)
 			preamble = WMI_VDEV_PREAMBLE_SHORT;
 		else
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index ed438edb9763..6b9f38b8b827 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -612,6 +612,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
 int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
 {
 	int ret;
+
 	ret = wait_for_completion_timeout(&ar->wmi.service_ready,
 					  WMI_SERVICE_READY_TIMEOUT_HZ);
 	return ret;
@@ -620,6 +621,7 @@ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
 int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar)
 {
 	int ret;
+
 	ret = wait_for_completion_timeout(&ar->wmi.unified_ready,
 					  WMI_UNIFIED_READY_TIMEOUT_HZ);
 	return ret;
@@ -1384,6 +1386,8 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
 	struct ieee80211_tim_ie *tim;
 	u8 *ies, *ie;
 	u8 ie_len, pvm_len;
+	__le32 t;
+	u32 v;
 
 	/* if next SWBA has no tim_changed the tim_bitmap is garbage.
 	 * we must copy the bitmap upon change and reuse it later */
@@ -1394,8 +1398,8 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
 			     sizeof(bcn_info->tim_info.tim_bitmap));
 
 		for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) {
-			__le32 t = bcn_info->tim_info.tim_bitmap[i / 4];
-			u32 v = __le32_to_cpu(t);
+			t = bcn_info->tim_info.tim_bitmap[i / 4];
+			v = __le32_to_cpu(t);
 			arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF;
 		}
 



From kvalo at qca.qualcomm.com  Sun Sep 14 02:50:23 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:50:23 +0300
Subject: [PATCH 05/10] ath10k: fix space after a cast style errors
In-Reply-To: <20140914094728.9063.32593.stgit@x230>
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <20140914095023.9063.66403.stgit@x230>

Fixes checkpatch warnings:

CHECK: No space is necessary after a cast

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/pci.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 52f273b92fa3..08e88a3758c1 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -340,8 +340,8 @@ static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar)
 
 	/* IMPORTANT: this extra read transaction is required to
 	 * flush the posted write buffer. */
-	(void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-				 PCIE_INTR_ENABLE_ADDRESS);
+	(void)ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+				PCIE_INTR_ENABLE_ADDRESS);
 }
 
 static void ath10k_pci_enable_legacy_irq(struct ath10k *ar)
@@ -352,8 +352,8 @@ static void ath10k_pci_enable_legacy_irq(struct ath10k *ar)
 
 	/* IMPORTANT: this extra read transaction is required to
 	 * flush the posted write buffer. */
-	(void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-				 PCIE_INTR_ENABLE_ADDRESS);
+	(void)ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+				PCIE_INTR_ENABLE_ADDRESS);
 }
 
 static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar)
@@ -547,7 +547,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 			goto done;
 		}
 
-		if (buf != (u32) address) {
+		if (buf != (u32)address) {
 			ret = -EIO;
 			goto done;
 		}
@@ -695,7 +695,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 		 * Request CE to send caller-supplied data that
 		 * was copied to bounce buffer to Target(!) address.
 		 */
-		ret = ath10k_ce_send(ce_diag, NULL, (u32) ce_data,
+		ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data,
 				     nbytes, 0, 0);
 		if (ret != 0)
 			goto done;
@@ -1624,7 +1624,7 @@ static int ath10k_pci_ce_init(struct ath10k *ar)
 			continue;
 		}
 
-		pipe_info->buf_sz = (size_t) (attr->src_sz_max);
+		pipe_info->buf_sz = (size_t)(attr->src_sz_max);
 	}
 
 	return 0;



From kvalo at qca.qualcomm.com  Sun Sep 14 02:50:28 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:50:28 +0300
Subject: [PATCH 06/10] ath10k: don't use return on void functions
In-Reply-To: <20140914094728.9063.32593.stgit@x230>
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <20140914095028.9063.64532.stgit@x230>

Fixes a checkpatch warning:

WARNING: void function return statements are not generally useful

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/htt_tx.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 1ab64631ba1b..bd87a35201d8 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -154,7 +154,6 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
 	kfree(htt->pending_tx);
 	kfree(htt->used_msdu_ids);
 	dma_pool_destroy(htt->tx_pool);
-	return;
 }
 
 void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)



From kvalo at qca.qualcomm.com  Sun Sep 14 02:50:33 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:50:33 +0300
Subject: [PATCH 07/10] ath10k: else is not generally useful after a break or
 return
In-Reply-To: <20140914094728.9063.32593.stgit@x230>
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <20140914095033.9063.17325.stgit@x230>

Fixes checkpatch warnings:

WARNING: else is not generally useful after a break or return

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/debug.c  |    4 ++--
 drivers/net/wireless/ath/ath10k/htt_rx.c |   12 ++++++------
 drivers/net/wireless/ath/ath10k/mac.c    |   12 ++++++------
 drivers/net/wireless/ath/ath10k/pci.c    |    7 ++++---
 4 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 2bfd00b29204..ff914b4ac0e6 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1180,8 +1180,8 @@ int ath10k_debug_register(struct ath10k *ar)
 	if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
 		if (IS_ERR(ar->debug.debugfs_phy))
 			return PTR_ERR(ar->debug.debugfs_phy);
-		else
-			return -ENOMEM;
+
+		return -ENOMEM;
 	}
 
 	INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 26196ed947bc..18117b9a1e9a 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -450,11 +450,11 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
 		if (last_msdu) {
 			msdu->next = NULL;
 			break;
-		} else {
-			next = ath10k_htt_rx_netbuf_pop(htt);
-			msdu->next = next;
-			msdu = next;
 		}
+
+		next = ath10k_htt_rx_netbuf_pop(htt);
+		msdu->next = next;
+		msdu = next;
 	}
 	*tail_msdu = msdu;
 
@@ -631,8 +631,8 @@ static struct ieee80211_hdr *ath10k_htt_rx_skb_get_hdr(struct sk_buff *skb)
 
 	if (fmt == RX_MSDU_DECAP_RAW)
 		return (void *)skb->data;
-	else
-		return (void *)skb->data - RX_HTT_HDR_STATUS_LEN;
+
+	return (void *)skb->data - RX_HTT_HDR_STATUS_LEN;
 }
 
 /* This function only applies for first msdu in an msdu chain */
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index c1cf6ff319e8..28e6db1d3846 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -698,8 +698,8 @@ static int ath10k_monitor_recalc(struct ath10k *ar)
 
 	if (should_start)
 		return ath10k_monitor_start(ar);
-	else
-		return ath10k_monitor_stop(ar);
+
+	return ath10k_monitor_stop(ar);
 }
 
 static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
@@ -4065,8 +4065,8 @@ ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask,
 			continue;
 		else if (mask->control[band].ht_mcs[i] == 0x00)
 			break;
-		else
-			return false;
+
+		return false;
 	}
 
 	ht_nss = i;
@@ -4077,8 +4077,8 @@ ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask,
 			continue;
 		else if (mask->control[band].vht_mcs[i] == 0x0000)
 			break;
-		else
-			return false;
+
+		return false;
 	}
 
 	vht_nss = i;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 08e88a3758c1..abd0a681d56c 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -362,10 +362,11 @@ static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar)
 
 	if (ar_pci->num_msi_intrs > 1)
 		return "msi-x";
-	else if (ar_pci->num_msi_intrs == 1)
+
+	if (ar_pci->num_msi_intrs == 1)
 		return "msi";
-	else
-		return "legacy";
+
+	return "legacy";
 }
 
 static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe)



From kvalo at qca.qualcomm.com  Sun Sep 14 02:50:44 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:50:44 +0300
Subject: [PATCH 09/10] ath10k: reformat help text in
 ath10k_read_simulate_fw_crash()
In-Reply-To: <20140914094728.9063.32593.stgit@x230>
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <20140914095044.9063.32376.stgit@x230>

Makes it more readable and fixes checkpatch warnings:

drivers/net/wireless/ath/ath10k/debug.c:593: WARNING: quoted string split across lines
drivers/net/wireless/ath/ath10k/debug.c:594: WARNING: quoted string split across lines
drivers/net/wireless/ath/ath10k/debug.c:595: WARNING: quoted string split across lines
drivers/net/wireless/ath/ath10k/debug.c:596: WARNING: quoted string split across lines
drivers/net/wireless/ath/ath10k/debug.c:597: WARNING: quoted string split across lines
drivers/net/wireless/ath/ath10k/debug.c:599: WARNING: quoted string split across lines
drivers/net/wireless/ath/ath10k/debug.c:600: WARNING: quoted string split across lines

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/debug.c |   14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index ff914b4ac0e6..3756feba3223 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -589,15 +589,11 @@ static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
 					     char __user *user_buf,
 					     size_t count, loff_t *ppos)
 {
-	const char buf[] = "To simulate firmware crash write one of the"
-			   " keywords to this file:\n `soft` - this will send"
-			   " WMI_FORCE_FW_HANG_ASSERT to firmware if FW"
-			   " supports that command.\n `hard` - this will send"
-			   " to firmware command with illegal parameters"
-			   " causing firmware crash.\n"
-			   "`assert` - this will send special illegal parameter"
-			   " to firmware to cause assert failure"
-			   " and crash.\n";
+	const char buf[] =
+		"To simulate firmware crash write one of the keywords to this file:\n"
+		"`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
+		"`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
+		"`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n";
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
 }



From kvalo at qca.qualcomm.com  Sun Sep 14 02:50:39 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:50:39 +0300
Subject: [PATCH 08/10] ath10k: miscellaneous checkpatch fixes
In-Reply-To: <20140914094728.9063.32593.stgit@x230>
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <20140914095038.9063.72668.stgit@x230>

Fixes checkpatch warnings:

ath10k/htc.c:49: WARNING: Possible unnecessary 'out of memory' message
ath10k/htc.c:810: WARNING: Possible unnecessary 'out of memory' message
ath10k/htt.h:1034: CHECK: Please use a blank line after function/struct/union/enum declarations
ath10k/htt_rx.c:135: CHECK: Unnecessary parentheses around htt->rx_ring.alloc_idx.vaddr
ath10k/htt_rx.c:173: CHECK: Unnecessary parentheses around htt->rx_ring.alloc_idx.vaddr
ath10k/pci.c:633: WARNING: macros should not use a trailing semicolon
ath10k/wmi.c:3594: WARNING: quoted string split across lines

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/htc.c    |    8 ++------
 drivers/net/wireless/ath/ath10k/htt.h    |    1 +
 drivers/net/wireless/ath/ath10k/htt_rx.c |    4 ++--
 drivers/net/wireless/ath/ath10k/pci.c    |    2 +-
 drivers/net/wireless/ath/ath10k/wmi.c    |    4 ++--
 5 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index b7ee24b19f59..676bd4ed969b 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -45,10 +45,8 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
 	struct ath10k_skb_cb *skb_cb;
 
 	skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE);
-	if (!skb) {
-		ath10k_warn(ar, "Unable to allocate ctrl skb\n");
+	if (!skb)
 		return NULL;
-	}
 
 	skb_reserve(skb, 20); /* FIXME: why 20 bytes? */
 	WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
@@ -806,10 +804,8 @@ struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size)
 	struct sk_buff *skb;
 
 	skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr));
-	if (!skb) {
-		ath10k_warn(ar, "could not allocate HTC tx skb\n");
+	if (!skb)
 		return NULL;
-	}
 
 	skb_reserve(skb, sizeof(struct ath10k_htc_hdr));
 
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index e20472672efe..3b44217a6c19 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1031,6 +1031,7 @@ static inline struct htt_stats_conf_item *htt_stats_conf_next_item(
 {
 	return (void *)item + sizeof(*item) + roundup(item->length, 4);
 }
+
 /*
  * host -> target FRAG DESCRIPTOR/MSDU_EXT DESC bank
  *
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 18117b9a1e9a..92b56e43d2d8 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -132,7 +132,7 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num)
 	dma_addr_t paddr;
 	int ret = 0, idx;
 
-	idx = __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr));
+	idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr);
 	while (num > 0) {
 		skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN);
 		if (!skb) {
@@ -170,7 +170,7 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num)
 	}
 
 fail:
-	*(htt->rx_ring.alloc_idx.vaddr) = __cpu_to_le32(idx);
+	*htt->rx_ring.alloc_idx.vaddr = __cpu_to_le32(idx);
 	return ret;
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index abd0a681d56c..59e0ea83be50 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -631,7 +631,7 @@ static int __ath10k_pci_diag_read_hi(struct ath10k *ar, void *dest,
 }
 
 #define ath10k_pci_diag_read_hi(ar, dest, src, len)		\
-	__ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len);
+	__ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len)
 
 static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 				     const void *data, int nbytes)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 6b9f38b8b827..c71376218ee5 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -3590,8 +3590,8 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar,
 	cmd->chan.antenna_max = arg->channel.max_antenna_gain;
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
-		   "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, "
-		   "ch_flags: 0x%0X, max_power: %d\n", cmdname, arg->vdev_id,
+		   "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n",
+		   cmdname, arg->vdev_id,
 		   flags, arg->channel.freq, arg->channel.mode,
 		   cmd->chan.flags, arg->channel.max_power);
 



From kvalo at qca.qualcomm.com  Sun Sep 14 02:50:49 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sun, 14 Sep 2014 12:50:49 +0300
Subject: [PATCH 10/10] ath10k: use ether_addr_copy()
In-Reply-To: <20140914094728.9063.32593.stgit@x230>
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <20140914095049.9063.17016.stgit@x230>

As suggeested by checkpatch:

WARNING: Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)

In wmi.c I had to change due to sparse warnings copying of struct wmi_mac_addr
from form &cmd->peer_macaddr.addr to cmd->peer_macaddr.addr. In
ath10k_wmi_set_ap_ps_param() I also added the missing ".addr" to the copy
command.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c |    8 ++++----
 drivers/net/wireless/ath/ath10k/mac.c    |   10 +++++-----
 drivers/net/wireless/ath/ath10k/txrx.c   |    2 +-
 drivers/net/wireless/ath/ath10k/wmi.c    |   22 +++++++++++-----------
 4 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 92b56e43d2d8..60d40a04508b 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -954,8 +954,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 			/* pull decapped header and copy SA & DA */
 			hdr = (struct ieee80211_hdr *)skb->data;
 			hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
-			memcpy(da, ieee80211_get_DA(hdr), ETH_ALEN);
-			memcpy(sa, ieee80211_get_SA(hdr), ETH_ALEN);
+			ether_addr_copy(da, ieee80211_get_DA(hdr));
+			ether_addr_copy(sa, ieee80211_get_SA(hdr));
 			skb_pull(skb, hdr_len);
 
 			/* push original 802.11 header */
@@ -972,8 +972,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
 			/* 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);
+			ether_addr_copy(ieee80211_get_DA(hdr), da);
+			ether_addr_copy(ieee80211_get_SA(hdr), sa);
 			break;
 		case RX_MSDU_DECAP_ETHERNET2_DIX:
 			/* strip ethernet header and insert decapped 802.11
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 28e6db1d3846..c708c100e361 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -199,7 +199,7 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
 		list_for_each_entry(peer, &ar->peers, list) {
 			for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
 				if (peer->keys[i] == key) {
-					memcpy(addr, peer->addr, ETH_ALEN);
+					ether_addr_copy(addr, peer->addr);
 					peer->keys[i] = NULL;
 					break;
 				}
@@ -930,7 +930,7 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
 		return;
 
 	arvif->aid = 0;
-	memcpy(arvif->bssid, info->bssid, ETH_ALEN);
+	ether_addr_copy(arvif->bssid, info->bssid);
 
 	ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
 				 arvif->bssid);
@@ -1050,7 +1050,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
 {
 	lockdep_assert_held(&ar->conf_mutex);
 
-	memcpy(arg->addr, sta->addr, ETH_ALEN);
+	ether_addr_copy(arg->addr, sta->addr);
 	arg->vdev_id = arvif->vdev_id;
 	arg->peer_aid = sta->aid;
 	arg->peer_flags |= WMI_PEER_AUTH;
@@ -1524,7 +1524,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
 		   arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
 
 	arvif->aid = bss_conf->aid;
-	memcpy(arvif->bssid, bss_conf->bssid, ETH_ALEN);
+	ether_addr_copy(arvif->bssid, bss_conf->bssid);
 
 	ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
 	if (ret) {
@@ -3090,7 +3090,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
 				 * this is never erased as we it for crypto key
 				 * clearing; this is FW requirement
 				 */
-				memcpy(arvif->bssid, info->bssid, ETH_ALEN);
+				ether_addr_copy(arvif->bssid, info->bssid);
 
 				ath10k_dbg(ar, ATH10K_DBG_MAC,
 					   "mac vdev %d start %pM\n",
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 2eeec8a63d5c..a0cbc21d0d4b 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -178,7 +178,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
 			goto exit;
 
 		peer->vdev_id = ev->vdev_id;
-		memcpy(peer->addr, ev->addr, ETH_ALEN);
+		ether_addr_copy(peer->addr, ev->addr);
 		list_add(&peer->list, &ar->peers);
 		wake_up(&ar->peer_mapping_wq);
 	}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index c71376218ee5..2c42bd504b79 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -794,7 +794,7 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
 	cmd->hdr.tx_power = 0;
 	cmd->hdr.buf_len = __cpu_to_le32(buf_len);
 
-	memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN);
+	ether_addr_copy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr));
 	memcpy(cmd->buf, skb->data, skb->len);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n",
@@ -2350,7 +2350,7 @@ static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb)
 	if (WARN_ON(skb->len < sizeof(*ev)))
 		return -EINVAL;
 
-	memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN);
+	ether_addr_copy(ar->mac_addr, ev->mac_addr.addr);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d skb->len %i ev-sz %zu\n",
@@ -3496,7 +3496,7 @@ int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id,
 	cmd->vdev_id      = __cpu_to_le32(vdev_id);
 	cmd->vdev_type    = __cpu_to_le32(type);
 	cmd->vdev_subtype = __cpu_to_le32(subtype);
-	memcpy(cmd->vdev_macaddr.addr, macaddr, ETH_ALEN);
+	ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "WMI vdev create: id %d type %d subtype %d macaddr %pM\n",
@@ -3643,7 +3643,7 @@ int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
 	cmd = (struct wmi_vdev_up_cmd *)skb->data;
 	cmd->vdev_id       = __cpu_to_le32(vdev_id);
 	cmd->vdev_assoc_id = __cpu_to_le32(aid);
-	memcpy(&cmd->vdev_bssid.addr, bssid, ETH_ALEN);
+	ether_addr_copy(cmd->vdev_bssid.addr, bssid);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n",
@@ -3724,7 +3724,7 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
 	cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
 
 	if (arg->macaddr)
-		memcpy(cmd->peer_macaddr.addr, arg->macaddr, ETH_ALEN);
+		ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
 	if (arg->key_data)
 		memcpy(cmd->key_data, arg->key_data, arg->key_len);
 
@@ -3803,7 +3803,7 @@ int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
 
 	cmd = (struct wmi_peer_create_cmd *)skb->data;
 	cmd->vdev_id = __cpu_to_le32(vdev_id);
-	memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
+	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi peer create vdev_id %d peer_addr %pM\n",
@@ -3823,7 +3823,7 @@ int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
 
 	cmd = (struct wmi_peer_delete_cmd *)skb->data;
 	cmd->vdev_id = __cpu_to_le32(vdev_id);
-	memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
+	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi peer delete vdev_id %d peer_addr %pM\n",
@@ -3844,7 +3844,7 @@ int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
 	cmd = (struct wmi_peer_flush_tids_cmd *)skb->data;
 	cmd->vdev_id         = __cpu_to_le32(vdev_id);
 	cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
-	memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
+	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n",
@@ -3867,7 +3867,7 @@ int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
 	cmd->vdev_id     = __cpu_to_le32(vdev_id);
 	cmd->param_id    = __cpu_to_le32(param_id);
 	cmd->param_value = __cpu_to_le32(param_value);
-	memcpy(&cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
+	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi vdev %d peer 0x%pM set param %d value %d\n",
@@ -3938,7 +3938,7 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
 	cmd->vdev_id = __cpu_to_le32(vdev_id);
 	cmd->param_id = __cpu_to_le32(param_id);
 	cmd->param_value = __cpu_to_le32(value);
-	memcpy(&cmd->peer_macaddr, mac, ETH_ALEN);
+	ether_addr_copy(cmd->peer_macaddr.addr, mac);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n",
@@ -4022,7 +4022,7 @@ ath10k_wmi_peer_assoc_fill(struct ath10k *ar, void *buf,
 	cmd->peer_vht_caps      = __cpu_to_le32(arg->peer_vht_caps);
 	cmd->peer_phymode       = __cpu_to_le32(arg->peer_phymode);
 
-	memcpy(cmd->peer_macaddr.addr, arg->addr, ETH_ALEN);
+	ether_addr_copy(cmd->peer_macaddr.addr, arg->addr);
 
 	cmd->peer_legacy_rates.num_rates =
 		__cpu_to_le32(arg->peer_legacy_rates.num_rates);



From greearb at candelatech.com  Mon Sep 15 09:27:45 2014
From: greearb at candelatech.com (Ben Greear)
Date: Mon, 15 Sep 2014 09:27:45 -0700
Subject: Spamming logs on firmware crash.
Message-ID: <54171381.2040900@candelatech.com>

Looks like my firmware died horribly and cannot recover.  That happens,
and I'm not sure what to do about it, but maybe we can at least not spam
the logs endlessly with this sort of thing?

I'd actually like some way to indicate to user-space that a reboot
is required (since warm/cold start have failed to recover the firmware).

May be a udev event?  I could also do an ethtool stat that could
be polled....

[253648.757661] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.757663] systemd-journald[353]: /dev/kmsg buffer overrun, some messages lost.
[253648.757664] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.757668] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.757673] ath10086] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758091] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758095] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758099] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758103] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758108] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758112] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758116] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758119] systemd-journald[353]: /dev/kmsg buffer overrun, some messages lost.
[253648.758120] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758124] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758128] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758131] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758134] systemd-journald[353]: /dev/kmsg buffer overrun, some messages lost.
[253648.758136] ath10k_pci 0000:04:00.0: boot target indicator ffffffff
[253648.758140] ath10k_pci 0000:04:00.0: boot target indicator ffffffff


Kernel is Linux ath10k-2220 3.17.0-rc2-wl-ath+, has some of my patches,
and was using my CT firmware.

Thanks,
Ben

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



From greearb at candelatech.com  Tue Sep 16 11:42:52 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 16 Sep 2014 11:42:52 -0700
Subject: Hard lockup during vif restart tests.
Message-ID: <541884AC.3020402@candelatech.com>

This is on a 3.14.14+ hacked kernel, with CT firmware.

Test case is to restart stations (and the AP
on the other side) every 10-30 seconds.
After a bit, the station machine locked up hard.

I have no idea how to trouble-shoot this better, so this is
just FYI.

wlan1: deauthenticated from 04:f0:21:03:38:99 (Reason: 7)
ath10k: mac vdev 0 peer delete 04:f0:21:03:38:99 (sta gone)
ath10k: mac vdev 0 stop (disassociated
ath10k: mac vdev 0 down
ath10k: mac vdev 0 cts_prot 0
ath10k: mac vdev 0 slot_time 1
ath10k: mac vdev 0 preamble 1n
ath10k: mac config channel 5180 mhz flags 0x120
ath10k: mac radar config update: chan 5180MHz radar 0 chan radar 0 chan state USABLE
ath10k: mac config channel to 5180MHz (cf1 5180MHz cf2 0MHz width 20 (noht))
ath10k: mac vdev 0 delete (remove interface)
ath10k: boot suspend complete
ath10k: boot hif stop
ath10k: boot warm reset
ath10k: boot host cpu intr cause: 0x00007800
ath10k: boot target cpu intr cause: 0x02001000
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x02000000
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: 0x02000000
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x02000000
ath10k: boot target reset state: 0x00000800
ath10k: boot warm reset complete
ath10k: stop, state OFF
ath10k: boot hif power up
ath10k: boot warm reset
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x02000000
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x02000000
ath10k: boot target reset state: 0x00000800
ath10k: boot warm reset complete
ath10k: boot init ce src ring id 0 entries 16 base_addr ffff8800d206a000
ath10k: boot ce dest ring id 1 entries 512 base_addr ffff8800d5420000
ath10k: boot ce dest ring id 2 entries 32 base_addr ffff8800d2069000
ath10k: boot init ce src ring id 3 entries 32 base_addr ffff8800d2068000
ath10k: boot init ce src ring id 4 entries 4096 base_addr ffff8800d5570000
ath10k: boot init ce src ring id 7 entries 2 base_addr ffff8800d2067000
ath10k: boot ce dest ring id 7 entries 2 base_addr ffff8800d2066000
ath10k_pci 0000:04:00.0: irq 52 for MSI/MSI-X
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 0
ath10k: boot target indicator 0
ath10k: boot target indicator 0
ath10k: failed to receive initialized event from target: 00000000
ath10k: failed to wait for target to init: -110
ath10k: boot warm reset
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x02000000
ath10k: boot host cpu intr cause: 0x00000000
ath10k: boot target cpu intr cause: 0x02000000
ath10k: boot target reset state: 0x00000800
ath10k: boot warm reset complete
ath10k: failed to power up target using warm reset: -110
ath10k: trying cold reset
ath10k: boot cold reset
ath10k: boot cold reset complete
[hang, even sysrq will not work]


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



From michal.kazior at tieto.com  Tue Sep 16 23:34:44 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 17 Sep 2014 08:34:44 +0200
Subject: Hard lockup during vif restart tests.
In-Reply-To: <541884AC.3020402@candelatech.com>
References: <541884AC.3020402@candelatech.com>
Message-ID: <CA+BoTQkeSSp5K=Ov-Sce9tcKz5ARL1im615PckPgNK-X8O-c1Q@mail.gmail.com>

On 16 September 2014 20:42, Ben Greear <greearb at candelatech.com> wrote:
> This is on a 3.14.14+ hacked kernel, with CT firmware.
>
> Test case is to restart stations (and the AP
> on the other side) every 10-30 seconds.
> After a bit, the station machine locked up hard.
>
> I have no idea how to trouble-shoot this better, so this is
> just FYI.
>
[...]
> ath10k: boot warm reset complete
> ath10k: failed to power up target using warm reset: -110
> ath10k: trying cold reset
> ath10k: boot cold reset
> ath10k: boot cold reset complete
> [hang, even sysrq will not work]

There's a known problem with cold reset being capable of locking up
entire system (depends on the pci-e controller, e.g. AP135 splats a
Data Bus Error instead).

Actually warm reset can do the same in some corner cases: try running
Rx traffic and just start the recovery sequence (without actually
crashing the fw). My x86 locks up very easily with this.

I strongly suggest you use reset_mode=1 when you load ath10k_pci so
cold reset isn't used. This may result in ath10k being unable to bring
up the device in some rare cases (e.g. after an IOMMU fault if your
system supports it) but I believe it's far better than having the
whole system lock up.

My suspicion is tx/rx rings, dma transfer engines, internal irqs
aren't stopped properly. I have a prototype patch for the warm reset
problem but it's incomplete and I'm not sure if I can share it yet.


Micha?


From greearb at candelatech.com  Wed Sep 17 08:52:18 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 17 Sep 2014 08:52:18 -0700
Subject: Hard lockup during vif restart tests.
In-Reply-To: <CA+BoTQkeSSp5K=Ov-Sce9tcKz5ARL1im615PckPgNK-X8O-c1Q@mail.gmail.com>
References: <541884AC.3020402@candelatech.com>
 <CA+BoTQkeSSp5K=Ov-Sce9tcKz5ARL1im615PckPgNK-X8O-c1Q@mail.gmail.com>
Message-ID: <5419AE32.6010805@candelatech.com>

On 09/16/2014 11:34 PM, Michal Kazior wrote:
> On 16 September 2014 20:42, Ben Greear <greearb at candelatech.com> wrote:
>> This is on a 3.14.14+ hacked kernel, with CT firmware.
>>
>> Test case is to restart stations (and the AP
>> on the other side) every 10-30 seconds.
>> After a bit, the station machine locked up hard.
>>
>> I have no idea how to trouble-shoot this better, so this is
>> just FYI.
>>
> [...]
>> ath10k: boot warm reset complete
>> ath10k: failed to power up target using warm reset: -110
>> ath10k: trying cold reset
>> ath10k: boot cold reset
>> ath10k: boot cold reset complete
>> [hang, even sysrq will not work]
> 
> There's a known problem with cold reset being capable of locking up
> entire system (depends on the pci-e controller, e.g. AP135 splats a
> Data Bus Error instead).
> 
> Actually warm reset can do the same in some corner cases: try running
> Rx traffic and just start the recovery sequence (without actually
> crashing the fw). My x86 locks up very easily with this.
> 
> I strongly suggest you use reset_mode=1 when you load ath10k_pci so
> cold reset isn't used. This may result in ath10k being unable to bring
> up the device in some rare cases (e.g. after an IOMMU fault if your
> system supports it) but I believe it's far better than having the
> whole system lock up.
> 
> My suspicion is tx/rx rings, dma transfer engines, internal irqs
> aren't stopped properly. I have a prototype patch for the warm reset
> problem but it's incomplete and I'm not sure if I can share it yet.

I will try the warm-reset-only flag, and I do hope you have success
with the warm/cold reset fixes.

But, I still wonder if we could just reset less often and maybe
make it a bit harder to hit these problems?

Why do we reset the firmware/NIC when we admin down/up the
vif (when a single vif is active)?  Couldn't we just keep
the firmware active in this state and not risk lockup due
to reset?

Thanks,
Ben


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



From michal.kazior at tieto.com  Wed Sep 17 23:23:17 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 08:23:17 +0200
Subject: Hard lockup during vif restart tests.
In-Reply-To: <5419AE32.6010805@candelatech.com>
References: <541884AC.3020402@candelatech.com>
 <CA+BoTQkeSSp5K=Ov-Sce9tcKz5ARL1im615PckPgNK-X8O-c1Q@mail.gmail.com>
 <5419AE32.6010805@candelatech.com>
Message-ID: <CA+BoTQkcP=Yc8kA2=OotrWbaAf09aMOmiPQp5W2j1vxsu3x4Kg@mail.gmail.com>

On 17 September 2014 17:52, Ben Greear <greearb at candelatech.com> wrote:
> On 09/16/2014 11:34 PM, Michal Kazior wrote:
>> On 16 September 2014 20:42, Ben Greear <greearb at candelatech.com> wrote:
>>> This is on a 3.14.14+ hacked kernel, with CT firmware.
>>>
>>> Test case is to restart stations (and the AP
>>> on the other side) every 10-30 seconds.
>>> After a bit, the station machine locked up hard.
>>>
>>> I have no idea how to trouble-shoot this better, so this is
>>> just FYI.
>>>
>> [...]
>>> ath10k: boot warm reset complete
>>> ath10k: failed to power up target using warm reset: -110
>>> ath10k: trying cold reset
>>> ath10k: boot cold reset
>>> ath10k: boot cold reset complete
>>> [hang, even sysrq will not work]
>>
>> There's a known problem with cold reset being capable of locking up
>> entire system (depends on the pci-e controller, e.g. AP135 splats a
>> Data Bus Error instead).
>>
>> Actually warm reset can do the same in some corner cases: try running
>> Rx traffic and just start the recovery sequence (without actually
>> crashing the fw). My x86 locks up very easily with this.
>>
>> I strongly suggest you use reset_mode=1 when you load ath10k_pci so
>> cold reset isn't used. This may result in ath10k being unable to bring
>> up the device in some rare cases (e.g. after an IOMMU fault if your
>> system supports it) but I believe it's far better than having the
>> whole system lock up.
>>
>> My suspicion is tx/rx rings, dma transfer engines, internal irqs
>> aren't stopped properly. I have a prototype patch for the warm reset
>> problem but it's incomplete and I'm not sure if I can share it yet.
>
> I will try the warm-reset-only flag, and I do hope you have success
> with the warm/cold reset fixes.

It sort of works as it is now but it's ugly.


> But, I still wonder if we could just reset less often and maybe
> make it a bit harder to hit these problems?
>
> Why do we reset the firmware/NIC when we admin down/up the
> vif (when a single vif is active)?  Couldn't we just keep
> the firmware active in this state and not risk lockup due
> to reset?

If you put down last interface mac80211 calls drv_stop(). There isn't
any real need to keep the device up and running after that other than
trying to workaround the reset issue. But then you need to deal with
firmware quirks. I recall it could report Rx indications after all
vdevs had been removed (and this is now also observable with 10.2
during probing/bootup). It's just simpler to reboot firmware on
drv_stop/start().


Micha?


From michal.kazior at tieto.com  Wed Sep 17 23:55:58 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 08:55:58 +0200
Subject: [PATCH] ath10k: workaround fw beaconing bug
Message-ID: <1411023358-5703-1-git-send-email-michal.kazior@tieto.com>

Some firmware revisions don't wait for beacon tx
completion before sending another SWBA event. This
could lead to hardware using old (freed) beacon
data in some cases, e.g. tx credit starvation
combined with missed TBTT. This is very very rare.

On non-IOMMU-enabled hosts this could be a
possible security issue because hw could beacon
some random data on the air.  On IOMMU-enabled
hosts DMAR faults would occur in most cases and
target device would crash.

Since there are no beacon tx completions (implicit
nor explicit) propagated to host the only
workaround for this is to allocate a DMA-coherent
buffer for a lifetime of a vif and use it for all
beacon tx commands. Worst case for this approach
is some beacons may become corrupted, e.g. garbled
IEs or out-of-date TIM bitmap.

Keep the original beacon-related code as-is in
case future firmware revisions solve this problem
so that the old path can be easily re-enabled with
a fw_feature flag.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h |   2 +
 drivers/net/wireless/ath/ath10k/mac.c  | 106 ++++++++++++++++++++++++---------
 drivers/net/wireless/ath/ath10k/mac.h  |   1 +
 drivers/net/wireless/ath/ath10k/wmi.c  |  36 ++++++-----
 4 files changed, 102 insertions(+), 43 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index fe531ea..d1ea936 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -234,6 +234,8 @@ struct ath10k_vif {
 	struct sk_buff *beacon;
 	/* protected by data_lock */
 	bool beacon_sent;
+	void *beacon_buf;
+	dma_addr_t beacon_paddr;
 
 	struct ath10k *ar;
 	struct ieee80211_vif *vif;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 5b35fff..aa6e659 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -480,6 +480,40 @@ static void ath10k_peer_cleanup_all(struct ath10k *ar)
 /* Interface management */
 /************************/
 
+void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif)
+{
+	struct ath10k *ar = arvif->ar;
+
+	lockdep_assert_held(&ar->data_lock);
+
+	if (!arvif->beacon)
+		return;
+
+	if (!arvif->beacon_buf)
+		dma_unmap_single(ar->dev, ATH10K_SKB_CB(arvif->beacon)->paddr,
+				 arvif->beacon->len, DMA_TO_DEVICE);
+
+	dev_kfree_skb_any(arvif->beacon);
+
+	arvif->beacon = NULL;
+	arvif->beacon_sent = false;
+}
+
+static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif)
+{
+	struct ath10k *ar = arvif->ar;
+
+	lockdep_assert_held(&ar->data_lock);
+
+	ath10k_mac_vif_beacon_free(arvif);
+
+	if (arvif->beacon_buf) {
+		dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
+				  arvif->beacon_buf, arvif->beacon_paddr);
+		arvif->beacon_buf = NULL;
+	}
+}
+
 static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
 {
 	int ret;
@@ -910,15 +944,7 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
 		arvif->is_up = false;
 
 		spin_lock_bh(&arvif->ar->data_lock);
-		if (arvif->beacon) {
-			dma_unmap_single(arvif->ar->dev,
-					 ATH10K_SKB_CB(arvif->beacon)->paddr,
-					 arvif->beacon->len, DMA_TO_DEVICE);
-			dev_kfree_skb_any(arvif->beacon);
-
-			arvif->beacon = NULL;
-			arvif->beacon_sent = false;
-		}
+		ath10k_mac_vif_beacon_free(arvif);
 		spin_unlock_bh(&arvif->ar->data_lock);
 
 		return;
@@ -2378,16 +2404,8 @@ void ath10k_halt(struct ath10k *ar)
 	ath10k_hif_power_down(ar);
 
 	spin_lock_bh(&ar->data_lock);
-	list_for_each_entry(arvif, &ar->arvifs, list) {
-		if (!arvif->beacon)
-			continue;
-
-		dma_unmap_single(arvif->ar->dev,
-				 ATH10K_SKB_CB(arvif->beacon)->paddr,
-				 arvif->beacon->len, DMA_TO_DEVICE);
-		dev_kfree_skb_any(arvif->beacon);
-		arvif->beacon = NULL;
-	}
+	list_for_each_entry(arvif, &ar->arvifs, list)
+		ath10k_mac_vif_beacon_cleanup(arvif);
 	spin_unlock_bh(&ar->data_lock);
 }
 
@@ -2806,8 +2824,39 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 		break;
 	}
 
-	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d\n",
-		   arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype);
+	/* Some firmware revisions don't wait for beacon tx completion before
+	 * sending another SWBA event. This could lead to hardware using old
+	 * (freed) beacon data in some cases, e.g. tx credit starvation
+	 * combined with missed TBTT. This is very very rare.
+	 *
+	 * On non-IOMMU-enabled hosts this could be a possible security issue
+	 * because hw could beacon some random data on the air.  On
+	 * IOMMU-enabled hosts DMAR faults would occur in most cases and target
+	 * device would crash.
+	 *
+	 * Since there are no beacon tx completions (implicit nor explicit)
+	 * propagated to host the only workaround for this is to allocate a
+	 * DMA-coherent buffer for a lifetime of a vif and use it for all
+	 * beacon tx commands. Worst case for this approach is some beacons may
+	 * become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap.
+	 */
+	if (vif->type == NL80211_IFTYPE_ADHOC ||
+	    vif->type == NL80211_IFTYPE_AP) {
+		arvif->beacon_buf = dma_zalloc_coherent(ar->dev,
+							IEEE80211_MAX_FRAME_LEN,
+							&arvif->beacon_paddr,
+							GFP_KERNEL);
+		if (!arvif->beacon_buf) {
+			ret = -ENOMEM;
+			ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
+				    ret);
+			goto err;
+		}
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n",
+		   arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
+		   arvif->beacon_buf ? "single-buf" : "per-skb");
 
 	ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type,
 				     arvif->vdev_subtype, vif->addr);
@@ -2914,6 +2963,12 @@ err_vdev_delete:
 	list_del(&arvif->list);
 
 err:
+	if (arvif->beacon_buf) {
+		dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
+				  arvif->beacon_buf, arvif->beacon_paddr);
+		arvif->beacon_buf = NULL;
+	}
+
 	mutex_unlock(&ar->conf_mutex);
 
 	return ret;
@@ -2931,14 +2986,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 	cancel_work_sync(&arvif->wep_key_work);
 
 	spin_lock_bh(&ar->data_lock);
-	if (arvif->beacon) {
-		dma_unmap_single(arvif->ar->dev,
-				 ATH10K_SKB_CB(arvif->beacon)->paddr,
-				 arvif->beacon->len, DMA_TO_DEVICE);
-		dev_kfree_skb_any(arvif->beacon);
-		arvif->beacon = NULL;
-	}
-
+	ath10k_mac_vif_beacon_cleanup(arvif);
 	spin_unlock_bh(&ar->data_lock);
 
 	ret = ath10k_spectral_vif_stop(arvif);
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index 6c80eea..965c511 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -39,6 +39,7 @@ void ath10k_offchan_tx_work(struct work_struct *work);
 void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar);
 void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work);
 void ath10k_halt(struct ath10k *ar);
+void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif);
 
 static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
 {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 3e22134..ce073c1 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1577,6 +1577,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
 	struct wmi_bcn_info *bcn_info;
 	struct ath10k_vif *arvif;
 	struct sk_buff *bcn;
+	dma_addr_t paddr;
 	int ret, vdev_id = 0;
 
 	ev = (struct wmi_host_swba_event *)skb->data;
@@ -1645,22 +1646,29 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
 				ath10k_warn(ar, "SWBA overrun on vdev %d\n",
 					    arvif->vdev_id);
 
-			dma_unmap_single(arvif->ar->dev,
-					 ATH10K_SKB_CB(arvif->beacon)->paddr,
-					 arvif->beacon->len, DMA_TO_DEVICE);
-			dev_kfree_skb_any(arvif->beacon);
-			arvif->beacon = NULL;
+			ath10k_mac_vif_beacon_free(arvif);
 		}
 
-		ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev,
-							   bcn->data, bcn->len,
-							   DMA_TO_DEVICE);
-		ret = dma_mapping_error(arvif->ar->dev,
-					ATH10K_SKB_CB(bcn)->paddr);
-		if (ret) {
-			ath10k_warn(ar, "failed to map beacon: %d\n", ret);
-			dev_kfree_skb_any(bcn);
-			goto skip;
+		if (!arvif->beacon_buf) {
+			paddr = dma_map_single(arvif->ar->dev, bcn->data,
+					       bcn->len, DMA_TO_DEVICE);
+			ret = dma_mapping_error(arvif->ar->dev, paddr);
+			if (ret) {
+				ath10k_warn(ar, "failed to map beacon: %d\n",
+					    ret);
+				dev_kfree_skb_any(bcn);
+				goto skip;
+			}
+
+			ATH10K_SKB_CB(bcn)->paddr = paddr;
+		} else {
+			if (bcn->len > IEEE80211_MAX_FRAME_LEN) {
+				ath10k_warn(ar, "trimming beacon %d -> %d bytes!\n",
+					    bcn->len, IEEE80211_MAX_FRAME_LEN);
+				skb_trim(bcn, IEEE80211_MAX_FRAME_LEN);
+			}
+			memcpy(arvif->beacon_buf, bcn->data, bcn->len);
+			ATH10K_SKB_CB(bcn)->paddr = arvif->beacon_paddr;
 		}
 
 		arvif->beacon = bcn;
-- 
1.8.5.3



From kvalo at qca.qualcomm.com  Thu Sep 18 00:31:55 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 18 Sep 2014 10:31:55 +0300
Subject: Hard lockup during vif restart tests.
In-Reply-To: <CA+BoTQkcP=Yc8kA2=OotrWbaAf09aMOmiPQp5W2j1vxsu3x4Kg@mail.gmail.com>
 (Michal Kazior's message of "Thu, 18 Sep 2014 08:23:17 +0200")
References: <541884AC.3020402@candelatech.com>
 <CA+BoTQkeSSp5K=Ov-Sce9tcKz5ARL1im615PckPgNK-X8O-c1Q@mail.gmail.com>
 <5419AE32.6010805@candelatech.com>
 <CA+BoTQkcP=Yc8kA2=OotrWbaAf09aMOmiPQp5W2j1vxsu3x4Kg@mail.gmail.com>
Message-ID: <87vbols7tg.fsf@kamboji.qca.qualcomm.com>

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

>> Why do we reset the firmware/NIC when we admin down/up the
>> vif (when a single vif is active)?  Couldn't we just keep
>> the firmware active in this state and not risk lockup due
>> to reset?
>
> If you put down last interface mac80211 calls drv_stop(). There isn't
> any real need to keep the device up and running after that other than
> trying to workaround the reset issue. But then you need to deal with
> firmware quirks. I recall it could report Rx indications after all
> vdevs had been removed (and this is now also observable with 10.2
> during probing/bootup). It's just simpler to reboot firmware on
> drv_stop/start().

And there's the reliability issue. Being able to reset the firmware with
interface down/up sequency is pretty useful and AFAIK almost all
upstream drivers do that. And let's not forget power consumption either.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Thu Sep 18 00:50:54 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Thu, 18 Sep 2014 10:50:54 +0300
Subject: [PATCH 00/10] ath10k: checkpatch fixes from v3.17
In-Reply-To: <20140914094728.9063.32593.stgit@x230> (Kalle Valo's message of
 "Sun, 14 Sep 2014 12:49:55 +0300")
References: <20140914094728.9063.32593.stgit@x230>
Message-ID: <87r3z9s6xt.fsf@kamboji.qca.qualcomm.com>

Kalle Valo <kvalo at qca.qualcomm.com> writes:

> Hi,
>
> some fixes to recently added checkpatch warnings. Please review.
>
> Kalle
>
> ---
>
> Kalle Valo (10):
>       ath10k: fix parenthesis alignment warning in ath10k_htt_rx_alloc()
>       ath10k: fix checkpatch warnings about parenthesis alignment
>       ath10k: fix use of multiple blank lines
>       ath10k: fix missing a blank line after declarations
>       ath10k: fix space after a cast style errors
>       ath10k: don't use return on void functions
>       ath10k: else is not generally useful after a break or return
>       ath10k: miscellaneous checkpatch fixes
>       ath10k: reformat help text in ath10k_read_simulate_fw_crash()
>       ath10k: use ether_addr_copy()

All ten applied.

-- 
Kalle Valo


From michal.kazior at tieto.com  Thu Sep 18 06:21:18 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:21:18 +0200
Subject: [PATCH 0/9] ath10k: mostly cleanups
Message-ID: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>

Hi,

Here's a bunch of clean up patches for WMI and a
single fix. I'm including the fix in this patchset
because one of the clean up patches depends on it.


Michal Kazior (9):
  ath10k: fix tx/rx chainmask init
  ath10k: remove unused pdev_set_channel command
  ath10k: deduplicate wmi_channel code
  ath10k: deduplicate host mem chunk code
  ath10k: relocate wmi attach/deatch functions
  ath10k: deduplicate wmi service ready logic
  ath10k: clean up phyerr code
  ath10k: unify wmi event function names
  ath10k: re-work scan start command building

 drivers/net/wireless/ath/ath10k/core.h     |   4 +-
 drivers/net/wireless/ath/ath10k/debug.c    |   2 +-
 drivers/net/wireless/ath/ath10k/debug.h    |   4 +-
 drivers/net/wireless/ath/ath10k/mac.c      |  10 +-
 drivers/net/wireless/ath/ath10k/spectral.c |  34 +-
 drivers/net/wireless/ath/ath10k/spectral.h |   8 +-
 drivers/net/wireless/ath/ath10k/wmi.c      | 823 +++++++++++++----------------
 drivers/net/wireless/ath/ath10k/wmi.h      | 244 ++-------
 8 files changed, 445 insertions(+), 684 deletions(-)

-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:21:19 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:21:19 +0200
Subject: [PATCH 1/9] ath10k: fix tx/rx chainmask init
In-Reply-To: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046487-19544-2-git-send-email-michal.kazior@tieto.com>

Firmware reports the number of RF chains so use
that for initialization of supp_{tx,rx}_chainmask
instead of using a macro for 3x3 chips.

This should make tx/rx chainmask reports correct
for chips other than 3x3.

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

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 4670930..c738827 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4800,15 +4800,6 @@ int ath10k_mac_register(struct ath10k *ar)
 		BIT(NL80211_IFTYPE_STATION) |
 		BIT(NL80211_IFTYPE_AP);
 
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-		/* TODO:  Have to deal with 2x2 chips if/when the come out. */
-		ar->supp_tx_chainmask = TARGET_10X_TX_CHAIN_MASK;
-		ar->supp_rx_chainmask = TARGET_10X_RX_CHAIN_MASK;
-	} else {
-		ar->supp_tx_chainmask = TARGET_TX_CHAIN_MASK;
-		ar->supp_rx_chainmask = TARGET_RX_CHAIN_MASK;
-	}
-
 	ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
 	ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 2c42bd5..772cca5 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2198,6 +2198,9 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
 		ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
 	}
 
+	ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
+	ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
+
 	ar->ath_common.regulatory.current_rd =
 		__le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
 
@@ -2268,6 +2271,9 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
 		ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
 	}
 
+	ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
+	ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
+
 	ar->ath_common.regulatory.current_rd =
 		__le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
 
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:21:20 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:21:20 +0200
Subject: [PATCH 2/9] ath10k: remove unused pdev_set_channel command
In-Reply-To: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046487-19544-3-git-send-email-michal.kazior@tieto.com>

This command is not used anymore and most firmware
revisions do not seem to handle it well. Channel
switching is done via vdev restarting.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/wmi.c | 36 -----------------------------------
 drivers/net/wireless/ath/ath10k/wmi.h |  7 -------
 2 files changed, 43 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 772cca5..89e63d5 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2871,42 +2871,6 @@ int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
 							 ctl2g, ctl5g);
 }
 
-int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
-				const struct wmi_channel_arg *arg)
-{
-	struct wmi_set_channel_cmd *cmd;
-	struct sk_buff *skb;
-	u32 ch_flags = 0;
-
-	if (arg->passive)
-		return -EINVAL;
-
-	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-	if (!skb)
-		return -ENOMEM;
-
-	if (arg->chan_radar)
-		ch_flags |= WMI_CHAN_FLAG_DFS;
-
-	cmd = (struct wmi_set_channel_cmd *)skb->data;
-	cmd->chan.mhz               = __cpu_to_le32(arg->freq);
-	cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq);
-	cmd->chan.mode              = arg->mode;
-	cmd->chan.flags		   |= __cpu_to_le32(ch_flags);
-	cmd->chan.min_power         = arg->min_power;
-	cmd->chan.max_power         = arg->max_power;
-	cmd->chan.reg_power         = arg->max_reg_power;
-	cmd->chan.reg_classid       = arg->reg_class_id;
-	cmd->chan.antenna_max       = arg->max_antenna_gain;
-
-	ath10k_dbg(ar, ATH10K_DBG_WMI,
-		   "wmi set channel mode %d freq %d\n",
-		   arg->mode, arg->freq);
-
-	return ath10k_wmi_cmd_send(ar, skb,
-				   ar->wmi.cmd->pdev_set_channel_cmdid);
-}
-
 int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
 {
 	struct wmi_pdev_suspend_cmd *cmd;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 86f5ebc..b8098d2 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2908,11 +2908,6 @@ enum wmi_tp_scale {
 	WMI_TP_SCALE_SIZE   = 5,	/* max num of enum     */
 };
 
-struct wmi_set_channel_cmd {
-	/* channel (only frequency and mode info are used) */
-	struct wmi_channel chan;
-} __packed;
-
 struct wmi_pdev_chanlist_update_event {
 	/* number of channels */
 	__le32 num_chan;
@@ -4732,8 +4727,6 @@ int ath10k_wmi_connect(struct ath10k *ar);
 struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
 int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
 
-int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
-				const struct wmi_channel_arg *);
 int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
 int ath10k_wmi_pdev_resume_target(struct ath10k *ar);
 int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:21:23 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:21:23 +0200
Subject: [PATCH 5/9] ath10k: relocate wmi attach/deatch functions
In-Reply-To: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046487-19544-6-git-send-email-michal.kazior@tieto.com>

Init functions should be placed at the end of
files in most cases to avoid forward declarations
for static functions.

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

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index f99cdef..029a127 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2772,45 +2772,6 @@ static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
 	}
 }
 
-/* WMI Initialization functions */
-int ath10k_wmi_attach(struct ath10k *ar)
-{
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-		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 {
-		ar->wmi.cmd = &wmi_cmd_map;
-		ar->wmi.vdev_param = &wmi_vdev_param_map;
-		ar->wmi.pdev_param = &wmi_pdev_param_map;
-	}
-
-	init_completion(&ar->wmi.service_ready);
-	init_completion(&ar->wmi.unified_ready);
-	init_waitqueue_head(&ar->wmi.tx_credits_wq);
-
-	return 0;
-}
-
-void ath10k_wmi_detach(struct ath10k *ar)
-{
-	int i;
-
-	/* free the host memory chunks requested by firmware */
-	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
-		dma_free_coherent(ar->dev,
-				  ar->wmi.mem_chunks[i].len,
-				  ar->wmi.mem_chunks[i].vaddr,
-				  ar->wmi.mem_chunks[i].paddr);
-	}
-
-	ar->wmi.num_mem_chunks = 0;
-}
-
 int ath10k_wmi_connect(struct ath10k *ar)
 {
 	int status;
@@ -4179,3 +4140,41 @@ int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable)
 
 	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid);
 }
+
+int ath10k_wmi_attach(struct ath10k *ar)
+{
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+		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 {
+		ar->wmi.cmd = &wmi_cmd_map;
+		ar->wmi.vdev_param = &wmi_vdev_param_map;
+		ar->wmi.pdev_param = &wmi_pdev_param_map;
+	}
+
+	init_completion(&ar->wmi.service_ready);
+	init_completion(&ar->wmi.unified_ready);
+	init_waitqueue_head(&ar->wmi.tx_credits_wq);
+
+	return 0;
+}
+
+void ath10k_wmi_detach(struct ath10k *ar)
+{
+	int i;
+
+	/* free the host memory chunks requested by firmware */
+	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+		dma_free_coherent(ar->dev,
+				  ar->wmi.mem_chunks[i].len,
+				  ar->wmi.mem_chunks[i].vaddr,
+				  ar->wmi.mem_chunks[i].paddr);
+	}
+
+	ar->wmi.num_mem_chunks = 0;
+}
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:21:21 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:21:21 +0200
Subject: [PATCH 3/9] ath10k: deduplicate wmi_channel code
In-Reply-To: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046487-19544-4-git-send-email-michal.kazior@tieto.com>

The structure is being set up in 2 places.
Deduplicate the code by creating a helper.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c |  1 +
 drivers/net/wireless/ath/ath10k/wmi.c | 77 ++++++++++++++++-------------------
 2 files changed, 37 insertions(+), 41 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index c738827..f0d11e2 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1729,6 +1729,7 @@ static int ath10k_update_channel_list(struct ath10k *ar)
 			ch->passive = passive;
 
 			ch->freq = channel->center_freq;
+			ch->band_center_freq1 = channel->center_freq;
 			ch->min_power = 0;
 			ch->max_power = channel->max_power * 2;
 			ch->max_reg_power = channel->max_reg_power * 2;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 89e63d5..78fc5aaf 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -609,6 +609,40 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
 	.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
 };
 
+static void
+ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
+			   const struct wmi_channel_arg *arg)
+{
+	u32 flags = 0;
+
+	memset(ch, 0, sizeof(*ch));
+
+	if (arg->passive)
+		flags |= WMI_CHAN_FLAG_PASSIVE;
+	if (arg->allow_ibss)
+		flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED;
+	if (arg->allow_ht)
+		flags |= WMI_CHAN_FLAG_ALLOW_HT;
+	if (arg->allow_vht)
+		flags |= WMI_CHAN_FLAG_ALLOW_VHT;
+	if (arg->ht40plus)
+		flags |= WMI_CHAN_FLAG_HT40_PLUS;
+	if (arg->chan_radar)
+		flags |= WMI_CHAN_FLAG_DFS;
+
+	ch->mhz = __cpu_to_le32(arg->freq);
+	ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1);
+	ch->band_center_freq2 = 0;
+	ch->min_power = arg->min_power;
+	ch->max_power = arg->max_power;
+	ch->reg_power = arg->max_reg_power;
+	ch->antenna_max = arg->max_antenna_gain;
+
+	/* mode & flags share storage */
+	ch->mode = arg->mode;
+	ch->flags |= __cpu_to_le32(flags);
+}
+
 int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
 {
 	int ret;
@@ -3502,7 +3536,6 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar,
 	struct sk_buff *skb;
 	const char *cmdname;
 	u32 flags = 0;
-	u32 ch_flags = 0;
 
 	if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid &&
 	    cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid)
@@ -3529,8 +3562,6 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar,
 		flags |= WMI_VDEV_START_HIDDEN_SSID;
 	if (arg->pmf_enabled)
 		flags |= WMI_VDEV_START_PMF_ENABLED;
-	if (arg->channel.chan_radar)
-		ch_flags |= WMI_CHAN_FLAG_DFS;
 
 	cmd = (struct wmi_vdev_start_request_cmd *)skb->data;
 	cmd->vdev_id         = __cpu_to_le32(arg->vdev_id);
@@ -3546,18 +3577,7 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar,
 		memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
 	}
 
-	cmd->chan.mhz = __cpu_to_le32(arg->channel.freq);
-
-	cmd->chan.band_center_freq1 =
-		__cpu_to_le32(arg->channel.band_center_freq1);
-
-	cmd->chan.mode = arg->channel.mode;
-	cmd->chan.flags |= __cpu_to_le32(ch_flags);
-	cmd->chan.min_power = arg->channel.min_power;
-	cmd->chan.max_power = arg->channel.max_power;
-	cmd->chan.reg_power = arg->channel.max_reg_power;
-	cmd->chan.reg_classid = arg->channel.reg_class_id;
-	cmd->chan.antenna_max = arg->channel.max_antenna_gain;
+	ath10k_wmi_put_wmi_channel(&cmd->chan, &arg->channel);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n",
@@ -3938,35 +3958,10 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar,
 	cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
 
 	for (i = 0; i < arg->n_channels; i++) {
-		u32 flags = 0;
-
 		ch = &arg->channels[i];
 		ci = &cmd->chan_info[i];
 
-		if (ch->passive)
-			flags |= WMI_CHAN_FLAG_PASSIVE;
-		if (ch->allow_ibss)
-			flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED;
-		if (ch->allow_ht)
-			flags |= WMI_CHAN_FLAG_ALLOW_HT;
-		if (ch->allow_vht)
-			flags |= WMI_CHAN_FLAG_ALLOW_VHT;
-		if (ch->ht40plus)
-			flags |= WMI_CHAN_FLAG_HT40_PLUS;
-		if (ch->chan_radar)
-			flags |= WMI_CHAN_FLAG_DFS;
-
-		ci->mhz               = __cpu_to_le32(ch->freq);
-		ci->band_center_freq1 = __cpu_to_le32(ch->freq);
-		ci->band_center_freq2 = 0;
-		ci->min_power         = ch->min_power;
-		ci->max_power         = ch->max_power;
-		ci->reg_power         = ch->max_reg_power;
-		ci->antenna_max       = ch->max_antenna_gain;
-
-		/* mode & flags share storage */
-		ci->mode              = ch->mode;
-		ci->flags            |= __cpu_to_le32(flags);
+		ath10k_wmi_put_wmi_channel(ci, ch);
 	}
 
 	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid);
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:21:22 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:21:22 +0200
Subject: [PATCH 4/9] ath10k: deduplicate host mem chunk code
In-Reply-To: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046487-19544-5-git-send-email-michal.kazior@tieto.com>

Simplify the code by deduplicating structure
definitions and code.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/wmi.c | 103 +++++++++-------------------------
 drivers/net/wireless/ath/ath10k/wmi.h |  30 +++-------
 2 files changed, 34 insertions(+), 99 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 78fc5aaf..f99cdef 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2955,13 +2955,34 @@ int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value)
 	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid);
 }
 
+static void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar,
+					   struct wmi_host_mem_chunks *chunks)
+{
+	struct host_memory_chunk *chunk;
+	int i;
+
+	chunks->count = __cpu_to_le32(ar->wmi.num_mem_chunks);
+
+	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+		chunk = &chunks->items[i];
+		chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
+		chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
+		chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
+
+		ath10k_dbg(ar, 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);
+	}
+}
+
 static int ath10k_wmi_main_cmd_init(struct ath10k *ar)
 {
 	struct wmi_init_cmd *cmd;
 	struct sk_buff *buf;
 	struct wmi_resource_config config = {};
 	u32 len, val;
-	int i;
 
 	config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS);
 	config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS);
@@ -3023,32 +3044,8 @@ static int ath10k_wmi_main_cmd_init(struct ath10k *ar)
 
 	cmd = (struct wmi_init_cmd *)buf->data;
 
-	if (ar->wmi.num_mem_chunks == 0) {
-		cmd->num_host_mem_chunks = 0;
-		goto out;
-	}
-
-	ath10k_dbg(ar, 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(ar, 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, &config, sizeof(config));
+	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init\n");
 	return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
@@ -3060,7 +3057,6 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar)
 	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);
@@ -3114,32 +3110,8 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar)
 
 	cmd = (struct wmi_init_cmd_10x *)buf->data;
 
-	if (ar->wmi.num_mem_chunks == 0) {
-		cmd->num_host_mem_chunks = 0;
-		goto out;
-	}
-
-	ath10k_dbg(ar, 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(ar, 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, &config, sizeof(config));
+	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10x\n");
 	return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
@@ -3151,7 +3123,6 @@ static int ath10k_wmi_10_2_cmd_init(struct ath10k *ar)
 	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);
@@ -3205,32 +3176,8 @@ static int ath10k_wmi_10_2_cmd_init(struct ath10k *ar)
 
 	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(ar, 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(ar, 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_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.2\n");
 	return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index b8098d2..fc8bc9d 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -1883,38 +1883,26 @@ struct host_memory_chunk {
 	__le32 size;
 } __packed;
 
+struct wmi_host_mem_chunks {
+	__le32 count;
+	/* some fw revisions require at least 1 chunk regardless of count */
+	struct host_memory_chunk items[1];
+} __packed;
+
 struct wmi_init_cmd {
 	struct wmi_resource_config 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];
+	struct wmi_host_mem_chunks mem_chunks;
 } __packed;
 
 /* _10x stucture is from 10.X FW API */
 struct wmi_init_cmd_10x {
 	struct wmi_resource_config_10x 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];
+	struct wmi_host_mem_chunks mem_chunks;
 } __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];
+	struct wmi_host_mem_chunks mem_chunks;
 } __packed;
 
 struct wmi_chan_list_entry {
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:21:24 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:21:24 +0200
Subject: [PATCH 6/9] ath10k: deduplicate wmi service ready logic
In-Reply-To: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046487-19544-7-git-send-email-michal.kazior@tieto.com>

The logic responsible for processing the event is
no different across different firmware binaries.
The difference that needs to be dealt with is the
ABI of data structures.

The intermediate structure uses __le32 to avoid
extra memory allocations to byteswap
variable-length substructures (i.e. host mem
chunks).

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h  |   4 +-
 drivers/net/wireless/ath/ath10k/debug.c |   2 +-
 drivers/net/wireless/ath/ath10k/debug.h |   4 +-
 drivers/net/wireless/ath/ath10k/wmi.c   | 237 ++++++++++++++++----------------
 drivers/net/wireless/ath/ath10k/wmi.h   |  24 +++-
 5 files changed, 142 insertions(+), 129 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index fe531ea..a4ef3c6 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -96,8 +96,6 @@ struct ath10k_bmi {
 	bool done_sent;
 };
 
-#define ATH10K_MAX_MEM_REQS 16
-
 struct ath10k_mem_chunk {
 	void *vaddr;
 	dma_addr_t paddr;
@@ -115,7 +113,7 @@ struct ath10k_wmi {
 	struct wmi_pdev_param_map *pdev_param;
 
 	u32 num_mem_chunks;
-	struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS];
+	struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
 };
 
 struct ath10k_peer_stat {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 3756feb..101c6f9 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -182,7 +182,7 @@ EXPORT_SYMBOL(ath10k_warn);
 #ifdef CONFIG_ATH10K_DEBUGFS
 
 void ath10k_debug_read_service_map(struct ath10k *ar,
-				   void *service_map,
+				   const void *service_map,
 				   size_t map_size)
 {
 	memcpy(ar->debug.wmi_service_bitmap, service_map, map_size);
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index b3774f7..d6276fe 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -53,7 +53,7 @@ void ath10k_debug_destroy(struct ath10k *ar);
 int ath10k_debug_register(struct ath10k *ar);
 void ath10k_debug_unregister(struct ath10k *ar);
 void ath10k_debug_read_service_map(struct ath10k *ar,
-				   void *service_map,
+				   const void *service_map,
 				   size_t map_size);
 void ath10k_debug_read_target_stats(struct ath10k *ar,
 				    struct wmi_stats_event *ev);
@@ -93,7 +93,7 @@ static inline void ath10k_debug_unregister(struct ath10k *ar)
 }
 
 static inline void ath10k_debug_read_service_map(struct ath10k *ar,
-						 void *service_map,
+						 const void *service_map,
 						 size_t map_size)
 {
 }
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 029a127..eab6b70 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2197,30 +2197,113 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
 	return 0;
 }
 
+static int ath10k_wmi_pull_svc_rdy_ev(struct sk_buff *skb,
+				      struct wmi_svc_rdy_ev_arg *arg)
+{
+	struct wmi_service_ready_event *ev;
+	size_t i, n;
+
+	if (skb->len < sizeof(*ev))
+		return -EPROTO;
+
+	ev = (void *)skb->data;
+	skb_pull(skb, sizeof(*ev));
+	arg->min_tx_power = ev->hw_min_tx_power;
+	arg->max_tx_power = ev->hw_max_tx_power;
+	arg->ht_cap = ev->ht_cap_info;
+	arg->vht_cap = ev->vht_cap_info;
+	arg->sw_ver0 = ev->sw_version;
+	arg->sw_ver1 = ev->sw_version_1;
+	arg->phy_capab = ev->phy_capability;
+	arg->num_rf_chains = ev->num_rf_chains;
+	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
+	arg->num_mem_reqs = ev->num_mem_reqs;
+	arg->service_map = ev->wmi_service_bitmap;
+
+	n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
+		  ARRAY_SIZE(arg->mem_reqs));
+	for (i = 0; i < n; i++)
+		arg->mem_reqs[i] = &ev->mem_reqs[i];
+
+	if (skb->len <
+	    __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
+		return -EPROTO;
+
+	return 0;
+}
+
+static int ath10k_wmi_10x_pull_svc_rdy_ev(struct sk_buff *skb,
+					  struct wmi_svc_rdy_ev_arg *arg)
+{
+	struct wmi_10x_service_ready_event *ev;
+	int i, n;
+
+	if (skb->len < sizeof(*ev))
+		return -EPROTO;
+
+	ev = (void *)skb->data;
+	skb_pull(skb, sizeof(*ev));
+	arg->min_tx_power = ev->hw_min_tx_power;
+	arg->max_tx_power = ev->hw_max_tx_power;
+	arg->ht_cap = ev->ht_cap_info;
+	arg->vht_cap = ev->vht_cap_info;
+	arg->sw_ver0 = ev->sw_version;
+	arg->phy_capab = ev->phy_capability;
+	arg->num_rf_chains = ev->num_rf_chains;
+	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
+	arg->num_mem_reqs = ev->num_mem_reqs;
+	arg->service_map = ev->wmi_service_bitmap;
+
+	n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
+		  ARRAY_SIZE(arg->mem_reqs));
+	for (i = 0; i < n; i++)
+		arg->mem_reqs[i] = &ev->mem_reqs[i];
+
+	if (skb->len <
+	    __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
+		return -EPROTO;
+
+	return 0;
+}
+
 static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
 					      struct sk_buff *skb)
 {
-	struct wmi_service_ready_event *ev = (void *)skb->data;
+	struct wmi_svc_rdy_ev_arg arg = {};
+	u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
 	DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
+	int ret;
 
-	if (skb->len < sizeof(*ev)) {
-		ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
-			    skb->len, sizeof(*ev));
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+		ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg);
+		wmi_10x_svc_map(arg.service_map, svc_bmap);
+	} else {
+		ret = ath10k_wmi_pull_svc_rdy_ev(skb, &arg);
+		wmi_main_svc_map(arg.service_map, svc_bmap);
+	}
+
+	if (ret) {
+		ath10k_warn(ar, "failed to parse service ready: %d\n", ret);
 		return;
 	}
 
-	ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power);
-	ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power);
-	ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info);
-	ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info);
+	ar->hw_min_tx_power = __le32_to_cpu(arg.min_tx_power);
+	ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power);
+	ar->ht_cap_info = __le32_to_cpu(arg.ht_cap);
+	ar->vht_cap_info = __le32_to_cpu(arg.vht_cap);
 	ar->fw_version_major =
-		(__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24;
-	ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff);
+		(__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24;
+	ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff);
 	ar->fw_version_release =
-		(__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16;
-	ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff);
-	ar->phy_capability = __le32_to_cpu(ev->phy_capability);
-	ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
+		(__le32_to_cpu(arg.sw_ver1) & 0xffff0000) >> 16;
+	ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff);
+	ar->phy_capability = __le32_to_cpu(arg.phy_capab);
+	ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
+	ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd);
+
+	ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
+	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
+			arg.service_map, sizeof(arg.service_map));
 
 	/* only manually set fw features when not using FW IE format */
 	if (ar->fw_api == 1 && ar->fw_version_build > 636)
@@ -2235,14 +2318,6 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
 	ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
 	ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
 
-	ar->ath_common.regulatory.current_rd =
-		__le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
-
-	wmi_main_svc_map(ev->wmi_service_bitmap, svc_bmap);
-	ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
-	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "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,
 			 sizeof(ar->hw->wiphy->fw_version),
@@ -2253,96 +2328,18 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
 			 ar->fw_version_build);
 	}
 
-	/* FIXME: it probably should be better to support this */
-	if (__le32_to_cpu(ev->num_mem_reqs) > 0) {
-		ath10k_warn(ar, "target requested %d memory chunks; ignoring\n",
-			    __le32_to_cpu(ev->num_mem_reqs));
-	}
-
-	ath10k_dbg(ar, ATH10K_DBG_WMI,
-		   "wmi event service ready sw_ver 0x%08x sw_ver1 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
-		   __le32_to_cpu(ev->sw_version),
-		   __le32_to_cpu(ev->sw_version_1),
-		   __le32_to_cpu(ev->abi_version),
-		   __le32_to_cpu(ev->phy_capability),
-		   __le32_to_cpu(ev->ht_cap_info),
-		   __le32_to_cpu(ev->vht_cap_info),
-		   __le32_to_cpu(ev->vht_supp_mcs),
-		   __le32_to_cpu(ev->sys_cap_info),
-		   __le32_to_cpu(ev->num_mem_reqs),
-		   __le32_to_cpu(ev->num_rf_chains));
-
-	complete(&ar->wmi.service_ready);
-}
-
-static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
-						  struct sk_buff *skb)
-{
-	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_MAX) = {};
-
-	if (skb->len < sizeof(*ev)) {
-		ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
-			    skb->len, sizeof(*ev));
-		return;
-	}
-
-	ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power);
-	ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power);
-	ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info);
-	ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info);
-	ar->fw_version_major =
-		(__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24;
-	ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff);
-	ar->phy_capability = __le32_to_cpu(ev->phy_capability);
-	ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
-
-	if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
-		ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
-			    ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
-		ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
-	}
-
-	ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
-	ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
-
-	ar->ath_common.regulatory.current_rd =
-		__le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
-
-	wmi_10x_svc_map(ev->wmi_service_bitmap, svc_bmap);
-	ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
-	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "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,
-			 sizeof(ar->hw->wiphy->fw_version),
-			 "%u.%u",
-			 ar->fw_version_major,
-			 ar->fw_version_minor);
-	}
-
-	num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs);
-
-	if (num_mem_reqs > ATH10K_MAX_MEM_REQS) {
+	num_mem_reqs = __le32_to_cpu(arg.num_mem_reqs);
+	if (num_mem_reqs > WMI_MAX_MEM_REQS) {
 		ath10k_warn(ar, "requested memory chunks number (%d) exceeds the limit\n",
 			    num_mem_reqs);
 		return;
 	}
 
-	if (!num_mem_reqs)
-		goto exit;
-
-	ath10k_dbg(ar, ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n",
-		   num_mem_reqs);
-
 	for (i = 0; i < num_mem_reqs; ++i) {
-		req_id = __le32_to_cpu(ev->mem_reqs[i].req_id);
-		num_units = __le32_to_cpu(ev->mem_reqs[i].num_units);
-		unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size);
-		num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info);
+		req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id);
+		num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units);
+		unit_size = __le32_to_cpu(arg.mem_reqs[i]->unit_size);
+		num_unit_info = __le32_to_cpu(arg.mem_reqs[i]->num_unit_info);
 
 		if (num_unit_info & NUM_UNITS_IS_NUM_PEERS)
 			/* number of units to allocate is number of
@@ -2356,7 +2353,7 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
 		ath10k_dbg(ar, ATH10K_DBG_WMI,
 			   "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n",
 			   req_id,
-			   __le32_to_cpu(ev->mem_reqs[i].num_units),
+			   __le32_to_cpu(arg.mem_reqs[i]->num_units),
 			   num_unit_info,
 			   unit_size,
 			   num_units);
@@ -2367,18 +2364,18 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
 			return;
 	}
 
-exit:
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
-		   "wmi event service ready sw_ver 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
-		   __le32_to_cpu(ev->sw_version),
-		   __le32_to_cpu(ev->abi_version),
-		   __le32_to_cpu(ev->phy_capability),
-		   __le32_to_cpu(ev->ht_cap_info),
-		   __le32_to_cpu(ev->vht_cap_info),
-		   __le32_to_cpu(ev->vht_supp_mcs),
-		   __le32_to_cpu(ev->sys_cap_info),
-		   __le32_to_cpu(ev->num_mem_reqs),
-		   __le32_to_cpu(ev->num_rf_chains));
+		   "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
+		   __le32_to_cpu(arg.min_tx_power),
+		   __le32_to_cpu(arg.max_tx_power),
+		   __le32_to_cpu(arg.ht_cap),
+		   __le32_to_cpu(arg.vht_cap),
+		   __le32_to_cpu(arg.sw_ver0),
+		   __le32_to_cpu(arg.sw_ver1),
+		   __le32_to_cpu(arg.phy_capab),
+		   __le32_to_cpu(arg.num_rf_chains),
+		   __le32_to_cpu(arg.eeprom_rd),
+		   __le32_to_cpu(arg.num_mem_reqs));
 
 	complete(&ar->wmi.service_ready);
 }
@@ -2626,7 +2623,7 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
 		ath10k_wmi_event_vdev_resume_req(ar, skb);
 		break;
 	case WMI_10X_SERVICE_READY_EVENTID:
-		ath10k_wmi_10x_service_ready_event_rx(ar, skb);
+		ath10k_wmi_service_ready_event_rx(ar, skb);
 		break;
 	case WMI_10X_READY_EVENTID:
 		ath10k_wmi_ready_event_rx(ar, skb);
@@ -2737,7 +2734,7 @@ static void ath10k_wmi_10_2_process_rx(struct ath10k *ar, struct sk_buff *skb)
 		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);
+		ath10k_wmi_service_ready_event_rx(ar, skb);
 		break;
 	case WMI_10_2_READY_EVENTID:
 		ath10k_wmi_ready_event_rx(ar, skb);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index fc8bc9d..ebdf154 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -1394,6 +1394,7 @@ struct wlan_host_mem_req {
  * wmi_service_ready_event,e.g., 11ac pass some of the
  * device capability to the host.
  */
+
 struct wmi_service_ready_event {
 	__le32 sw_version;
 	__le32 sw_version_1;
@@ -1428,11 +1429,11 @@ struct wmi_service_ready_event {
 	 * where FW can access this memory directly (or) by DMA.
 	 */
 	__le32 num_mem_reqs;
-	struct wlan_host_mem_req mem_reqs[1];
+	struct wlan_host_mem_req mem_reqs[0];
 } __packed;
 
 /* This is the definition from 10.X firmware branch */
-struct wmi_service_ready_event_10x {
+struct wmi_10x_service_ready_event {
 	__le32 sw_version;
 	__le32 abi_version;
 
@@ -1467,7 +1468,7 @@ struct wmi_service_ready_event_10x {
 	 */
 	__le32 num_mem_reqs;
 
-	struct wlan_host_mem_req mem_reqs[1];
+	struct wlan_host_mem_req mem_reqs[0];
 } __packed;
 
 #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ)
@@ -4702,6 +4703,23 @@ struct wmi_dbglog_cfg_cmd {
 /* By default disable power save for IBSS */
 #define ATH10K_DEFAULT_ATIM 0
 
+#define WMI_MAX_MEM_REQS 16
+
+struct wmi_svc_rdy_ev_arg {
+	__le32 min_tx_power;
+	__le32 max_tx_power;
+	__le32 ht_cap;
+	__le32 vht_cap;
+	__le32 sw_ver0;
+	__le32 sw_ver1;
+	__le32 phy_capab;
+	__le32 num_rf_chains;
+	__le32 eeprom_rd;
+	__le32 num_mem_reqs;
+	const __le32 *service_map;
+	const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
+};
+
 struct ath10k;
 struct ath10k_vif;
 
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:21:26 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:21:26 +0200
Subject: [PATCH 8/9] ath10k: unify wmi event function names
In-Reply-To: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046487-19544-9-git-send-email-michal.kazior@tieto.com>

Make all wmi event functions match the same naming
style, i.e. ath10k_wmi_event_<name>.

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

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 592e3af..6819255 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2266,8 +2266,8 @@ static int ath10k_wmi_10x_pull_svc_rdy_ev(struct sk_buff *skb,
 	return 0;
 }
 
-static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
-					      struct sk_buff *skb)
+static void ath10k_wmi_event_service_ready(struct ath10k *ar,
+					   struct sk_buff *skb)
 {
 	struct wmi_svc_rdy_ev_arg arg = {};
 	u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
@@ -2380,7 +2380,7 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
 	complete(&ar->wmi.service_ready);
 }
 
-static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb)
+static int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data;
 
@@ -2503,10 +2503,10 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
 		ath10k_wmi_event_vdev_install_key_complete(ar, skb);
 		break;
 	case WMI_SERVICE_READY_EVENTID:
-		ath10k_wmi_service_ready_event_rx(ar, skb);
+		ath10k_wmi_event_service_ready(ar, skb);
 		break;
 	case WMI_READY_EVENTID:
-		ath10k_wmi_ready_event_rx(ar, skb);
+		ath10k_wmi_event_ready(ar, skb);
 		break;
 	default:
 		ath10k_warn(ar, "Unknown eventid: %d\n", id);
@@ -2623,10 +2623,10 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
 		ath10k_wmi_event_vdev_resume_req(ar, skb);
 		break;
 	case WMI_10X_SERVICE_READY_EVENTID:
-		ath10k_wmi_service_ready_event_rx(ar, skb);
+		ath10k_wmi_event_service_ready(ar, skb);
 		break;
 	case WMI_10X_READY_EVENTID:
-		ath10k_wmi_ready_event_rx(ar, skb);
+		ath10k_wmi_event_ready(ar, skb);
 		break;
 	case WMI_10X_PDEV_UTF_EVENTID:
 		/* ignore utf events */
@@ -2734,10 +2734,10 @@ static void ath10k_wmi_10_2_process_rx(struct ath10k *ar, struct sk_buff *skb)
 		ath10k_wmi_event_vdev_resume_req(ar, skb);
 		break;
 	case WMI_10_2_SERVICE_READY_EVENTID:
-		ath10k_wmi_service_ready_event_rx(ar, skb);
+		ath10k_wmi_event_service_ready(ar, skb);
 		break;
 	case WMI_10_2_READY_EVENTID:
-		ath10k_wmi_ready_event_rx(ar, skb);
+		ath10k_wmi_event_ready(ar, skb);
 		break;
 	case WMI_10_2_RTT_KEEPALIVE_EVENTID:
 	case WMI_10_2_GPIO_INPUT_EVENTID:
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:21:25 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:21:25 +0200
Subject: [PATCH 7/9] ath10k: clean up phyerr code
In-Reply-To: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046487-19544-8-git-send-email-michal.kazior@tieto.com>

Make the phyerr structures more compact and easier
to understand. Also add constness.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/spectral.c | 34 ++++-------
 drivers/net/wireless/ath/ath10k/spectral.h |  8 +--
 drivers/net/wireless/ath/ath10k/wmi.c      | 90 +++++++++++++++---------------
 drivers/net/wireless/ath/ath10k/wmi.h      | 83 +++------------------------
 4 files changed, 66 insertions(+), 149 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
index 3e1454b..63ce61f 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.c
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -56,14 +56,14 @@ static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
 }
 
 int ath10k_spectral_process_fft(struct ath10k *ar,
-				struct wmi_single_phyerr_rx_event *event,
-				struct phyerr_fft_report *fftr,
+				const struct wmi_phyerr *phyerr,
+				const 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;
+	u32 reg0, reg1;
 	u8 chain_idx, *bins;
 	int dc_pos;
 
@@ -82,7 +82,7 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
 	/* 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) {
+	switch (phyerr->chan_width_mhz) {
 	case 20:
 		fft_sample->chan_width_mhz = 22;
 		break;
@@ -101,7 +101,7 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
 		fft_sample->chan_width_mhz = 88;
 		break;
 	default:
-		fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
+		fft_sample->chan_width_mhz = phyerr->chan_width_mhz;
 	}
 
 	fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
@@ -110,36 +110,22 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
 	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;
+	fft_sample->rssi = phyerr->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);
+	freq1 = __le16_to_cpu(phyerr->freq1);
+	freq2 = __le16_to_cpu(phyerr->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->noise = __cpu_to_be16(
+			__le16_to_cpu(phyerr->nf_chains[chain_idx]));
 
 	bins = (u8 *)fftr;
 	bins += sizeof(*fftr);
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
index ddc57c5..042f5b3 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.h
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -47,8 +47,8 @@ enum ath10k_spectral_mode {
 #ifdef CONFIG_ATH10K_DEBUGFS
 
 int ath10k_spectral_process_fft(struct ath10k *ar,
-				struct wmi_single_phyerr_rx_event *event,
-				struct phyerr_fft_report *fftr,
+				const struct wmi_phyerr *phyerr,
+				const 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);
@@ -59,8 +59,8 @@ void ath10k_spectral_destroy(struct ath10k *ar);
 
 static inline int
 ath10k_spectral_process_fft(struct ath10k *ar,
-			    struct wmi_single_phyerr_rx_event *event,
-			    struct phyerr_fft_report *fftr,
+			    const struct wmi_phyerr *phyerr,
+			    const struct phyerr_fft_report *fftr,
 			    size_t bin_len, u64 tsf)
 {
 	return 0;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index eab6b70..592e3af 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1715,8 +1715,8 @@ static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar,
 }
 
 static void ath10k_dfs_radar_report(struct ath10k *ar,
-				    struct wmi_single_phyerr_rx_event *event,
-				    struct phyerr_radar_report *rr,
+				    const struct wmi_phyerr *phyerr,
+				    const struct phyerr_radar_report *rr,
 				    u64 tsf)
 {
 	u32 reg0, reg1, tsf32l;
@@ -1749,12 +1749,12 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
 		return;
 
 	/* report event to DFS pattern detector */
-	tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp);
+	tsf32l = __le32_to_cpu(phyerr->tsf_timestamp);
 	tsf64 = tsf & (~0xFFFFFFFFULL);
 	tsf64 |= tsf32l;
 
 	width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR);
-	rssi = event->hdr.rssi_combined;
+	rssi = phyerr->rssi_combined;
 
 	/* hardware store this as 8 bit signed value,
 	 * set to zero if negative number
@@ -1793,8 +1793,8 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
 }
 
 static int ath10k_dfs_fft_report(struct ath10k *ar,
-				 struct wmi_single_phyerr_rx_event *event,
-				 struct phyerr_fft_report *fftr,
+				 const struct wmi_phyerr *phyerr,
+				 const struct phyerr_fft_report *fftr,
 				 u64 tsf)
 {
 	u32 reg0, reg1;
@@ -1802,7 +1802,7 @@ static int ath10k_dfs_fft_report(struct ath10k *ar,
 
 	reg0 = __le32_to_cpu(fftr->reg0);
 	reg1 = __le32_to_cpu(fftr->reg1);
-	rssi = event->hdr.rssi_combined;
+	rssi = phyerr->rssi_combined;
 
 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
 		   "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n",
@@ -1831,20 +1831,20 @@ static int ath10k_dfs_fft_report(struct ath10k *ar,
 }
 
 static void ath10k_wmi_event_dfs(struct ath10k *ar,
-				 struct wmi_single_phyerr_rx_event *event,
+				 const struct wmi_phyerr *phyerr,
 				 u64 tsf)
 {
 	int buf_len, tlv_len, res, i = 0;
-	struct phyerr_tlv *tlv;
-	struct phyerr_radar_report *rr;
-	struct phyerr_fft_report *fftr;
-	u8 *tlv_buf;
+	const struct phyerr_tlv *tlv;
+	const struct phyerr_radar_report *rr;
+	const struct phyerr_fft_report *fftr;
+	const u8 *tlv_buf;
 
-	buf_len = __le32_to_cpu(event->hdr.buf_len);
+	buf_len = __le32_to_cpu(phyerr->buf_len);
 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
 		   "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n",
-		   event->hdr.phy_err_code, event->hdr.rssi_combined,
-		   __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len);
+		   phyerr->phy_err_code, phyerr->rssi_combined,
+		   __le32_to_cpu(phyerr->tsf_timestamp), tsf, buf_len);
 
 	/* Skip event if DFS disabled */
 	if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED))
@@ -1859,9 +1859,9 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar,
 			return;
 		}
 
-		tlv = (struct phyerr_tlv *)&event->bufp[i];
+		tlv = (struct phyerr_tlv *)&phyerr->buf[i];
 		tlv_len = __le16_to_cpu(tlv->len);
-		tlv_buf = &event->bufp[i + sizeof(*tlv)];
+		tlv_buf = &phyerr->buf[i + sizeof(*tlv)];
 		ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
 			   "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n",
 			   tlv_len, tlv->tag, tlv->sig);
@@ -1875,7 +1875,7 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar,
 			}
 
 			rr = (struct phyerr_radar_report *)tlv_buf;
-			ath10k_dfs_radar_report(ar, event, rr, tsf);
+			ath10k_dfs_radar_report(ar, phyerr, rr, tsf);
 			break;
 		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
 			if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) {
@@ -1885,7 +1885,7 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar,
 			}
 
 			fftr = (struct phyerr_fft_report *)tlv_buf;
-			res = ath10k_dfs_fft_report(ar, event, fftr, tsf);
+			res = ath10k_dfs_fft_report(ar, phyerr, fftr, tsf);
 			if (res)
 				return;
 			break;
@@ -1897,16 +1897,16 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar,
 
 static void
 ath10k_wmi_event_spectral_scan(struct ath10k *ar,
-			       struct wmi_single_phyerr_rx_event *event,
+			       const struct wmi_phyerr *phyerr,
 			       u64 tsf)
 {
 	int buf_len, tlv_len, res, i = 0;
 	struct phyerr_tlv *tlv;
-	u8 *tlv_buf;
-	struct phyerr_fft_report *fftr;
+	const void *tlv_buf;
+	const struct phyerr_fft_report *fftr;
 	size_t fftr_len;
 
-	buf_len = __le32_to_cpu(event->hdr.buf_len);
+	buf_len = __le32_to_cpu(phyerr->buf_len);
 
 	while (i < buf_len) {
 		if (i + sizeof(*tlv) > buf_len) {
@@ -1915,9 +1915,9 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar,
 			return;
 		}
 
-		tlv = (struct phyerr_tlv *)&event->bufp[i];
+		tlv = (struct phyerr_tlv *)&phyerr->buf[i];
 		tlv_len = __le16_to_cpu(tlv->len);
-		tlv_buf = &event->bufp[i + sizeof(*tlv)];
+		tlv_buf = &phyerr->buf[i + sizeof(*tlv)];
 
 		if (i + sizeof(*tlv) + tlv_len > buf_len) {
 			ath10k_warn(ar, "failed to parse phyerr tlv payload at byte %d\n",
@@ -1934,8 +1934,8 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar,
 			}
 
 			fftr_len = tlv_len - sizeof(*fftr);
-			fftr = (struct phyerr_fft_report *)tlv_buf;
-			res = ath10k_spectral_process_fft(ar, event,
+			fftr = tlv_buf;
+			res = ath10k_spectral_process_fft(ar, phyerr,
 							  fftr, fftr_len,
 							  tsf);
 			if (res < 0) {
@@ -1952,8 +1952,8 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar,
 
 static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
 {
-	struct wmi_comb_phyerr_rx_event *comb_event;
-	struct wmi_single_phyerr_rx_event *event;
+	const struct wmi_phyerr_event *ev;
+	const struct wmi_phyerr *phyerr;
 	u32 count, i, buf_len, phy_err_code;
 	u64 tsf;
 	int left_len = skb->len;
@@ -1961,38 +1961,38 @@ static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
 	ATH10K_DFS_STAT_INC(ar, phy_errors);
 
 	/* Check if combined event available */
-	if (left_len < sizeof(*comb_event)) {
+	if (left_len < sizeof(*ev)) {
 		ath10k_warn(ar, "wmi phyerr combined event wrong len\n");
 		return;
 	}
 
-	left_len -= sizeof(*comb_event);
+	left_len -= sizeof(*ev);
 
 	/* Check number of included events */
-	comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data;
-	count = __le32_to_cpu(comb_event->hdr.num_phyerr_events);
+	ev = (const struct wmi_phyerr_event *)skb->data;
+	count = __le32_to_cpu(ev->num_phyerrs);
 
-	tsf = __le32_to_cpu(comb_event->hdr.tsf_u32);
+	tsf = __le32_to_cpu(ev->tsf_u32);
 	tsf <<= 32;
-	tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32);
+	tsf |= __le32_to_cpu(ev->tsf_l32);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI,
 		   "wmi event phyerr count %d tsf64 0x%llX\n",
 		   count, tsf);
 
-	event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp;
+	phyerr = ev->phyerrs;
 	for (i = 0; i < count; i++) {
 		/* Check if we can read event header */
-		if (left_len < sizeof(*event)) {
+		if (left_len < sizeof(*phyerr)) {
 			ath10k_warn(ar, "single event (%d) wrong head len\n",
 				    i);
 			return;
 		}
 
-		left_len -= sizeof(*event);
+		left_len -= sizeof(*phyerr);
 
-		buf_len = __le32_to_cpu(event->hdr.buf_len);
-		phy_err_code = event->hdr.phy_err_code;
+		buf_len = __le32_to_cpu(phyerr->buf_len);
+		phy_err_code = phyerr->phy_err_code;
 
 		if (left_len < buf_len) {
 			ath10k_warn(ar, "single event (%d) wrong buf len\n", i);
@@ -2003,20 +2003,20 @@ static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
 
 		switch (phy_err_code) {
 		case PHY_ERROR_RADAR:
-			ath10k_wmi_event_dfs(ar, event, tsf);
+			ath10k_wmi_event_dfs(ar, phyerr, tsf);
 			break;
 		case PHY_ERROR_SPECTRAL_SCAN:
-			ath10k_wmi_event_spectral_scan(ar, event, tsf);
+			ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
 			break;
 		case PHY_ERROR_FALSE_RADAR_EXT:
-			ath10k_wmi_event_dfs(ar, event, tsf);
-			ath10k_wmi_event_spectral_scan(ar, event, tsf);
+			ath10k_wmi_event_dfs(ar, phyerr, tsf);
+			ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
 			break;
 		default:
 			break;
 		}
 
-		event += sizeof(*event) + buf_len;
+		phyerr = (void *)phyerr + sizeof(*phyerr) + buf_len;
 	}
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index ebdf154..a041567 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2295,94 +2295,25 @@ struct wmi_mgmt_rx_event_v2 {
 #define PHY_ERROR_FALSE_RADAR_EXT		0x24
 #define PHY_ERROR_RADAR				0x05
 
-struct wmi_single_phyerr_rx_hdr {
-	/* TSF timestamp */
+struct wmi_phyerr {
 	__le32 tsf_timestamp;
-
-	/*
-	 * Current freq1, freq2
-	 *
-	 * [7:0]:    freq1[lo]
-	 * [15:8] :   freq1[hi]
-	 * [23:16]:   freq2[lo]
-	 * [31:24]:   freq2[hi]
-	 */
 	__le16 freq1;
 	__le16 freq2;
-
-	/*
-	 * Combined RSSI over all chains and channel width for this PHY error
-	 *
-	 * [7:0]: RSSI combined
-	 * [15:8]: Channel width (MHz)
-	 * [23:16]: PHY error code
-	 * [24:16]: reserved (future use)
-	 */
 	u8 rssi_combined;
 	u8 chan_width_mhz;
 	u8 phy_err_code;
 	u8 rsvd0;
-
-	/*
-	 * RSSI on chain 0 through 3
-	 *
-	 * This is formatted the same as the PPDU_START RX descriptor
-	 * field:
-	 *
-	 * [7:0]:   pri20
-	 * [15:8]:  sec20
-	 * [23:16]: sec40
-	 * [31:24]: sec80
-	 */
-
-	__le32 rssi_chain0;
-	__le32 rssi_chain1;
-	__le32 rssi_chain2;
-	__le32 rssi_chain3;
-
-	/*
-	 * Last calibrated NF value for chain 0 through 3
-	 *
-	 * nf_list_1:
-	 *
-	 * + [15:0] - chain 0
-	 * + [31:16] - chain 1
-	 *
-	 * nf_list_2:
-	 *
-	 * + [15:0] - chain 2
-	 * + [31:16] - chain 3
-	 */
-	__le32 nf_list_1;
-	__le32 nf_list_2;
-
-	/* Length of the frame */
+	__le32 rssi_chains[4];
+	__le16 nf_chains[4];
 	__le32 buf_len;
+	u8 buf[0];
 } __packed;
 
-struct wmi_single_phyerr_rx_event {
-	/* Phy error event header */
-	struct wmi_single_phyerr_rx_hdr hdr;
-	/* frame buffer */
-	u8 bufp[0];
-} __packed;
-
-struct wmi_comb_phyerr_rx_hdr {
-	/* Phy error phy error count */
-	__le32 num_phyerr_events;
+struct wmi_phyerr_event {
+	__le32 num_phyerrs;
 	__le32 tsf_l32;
 	__le32 tsf_u32;
-} __packed;
-
-struct wmi_comb_phyerr_rx_event {
-	/* Phy error phy error count */
-	struct wmi_comb_phyerr_rx_hdr hdr;
-	/*
-	 * frame buffer - contains multiple payloads in the order:
-	 *                    header - payload, header - payload...
-	 *  (The header is of type: wmi_single_phyerr_rx_hdr)
-	 */
-	u8 bufp[0];
+	struct wmi_phyerr phyerrs[0];
 } __packed;
 
 #define PHYERR_TLV_SIG				0xBB
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:21:27 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:21:27 +0200
Subject: [PATCH 9/9] ath10k: re-work scan start command building
In-Reply-To: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046487-19544-10-git-send-email-michal.kazior@tieto.com>

This gets rid of the ugly scan structure building
and uses a saner way to do it.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/wmi.c | 191 ++++++++++++++++++----------------
 drivers/net/wireless/ath/ath10k/wmi.h | 100 +++---------------
 2 files changed, 119 insertions(+), 172 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 6819255..5537523 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -3157,52 +3157,50 @@ int ath10k_wmi_cmd_init(struct ath10k *ar)
 	return ret;
 }
 
-static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar,
-					  const struct wmi_start_scan_arg *arg)
+static int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg)
 {
-	int len;
+	if (arg->ie_len && !arg->ie)
+		return -EINVAL;
+	if (arg->n_channels && !arg->channels)
+		return -EINVAL;
+	if (arg->n_ssids && !arg->ssids)
+		return -EINVAL;
+	if (arg->n_bssids && !arg->bssids)
+		return -EINVAL;
 
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-		len = sizeof(struct wmi_start_scan_cmd_10x);
-	else
-		len = sizeof(struct wmi_start_scan_cmd);
+	if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
+		return -EINVAL;
+	if (arg->n_channels > ARRAY_SIZE(arg->channels))
+		return -EINVAL;
+	if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
+		return -EINVAL;
+	if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
+		return -EINVAL;
 
-	if (arg->ie_len) {
-		if (!arg->ie)
-			return -EINVAL;
-		if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
-			return -EINVAL;
+	return 0;
+}
 
+static size_t
+ath10k_wmi_start_scan_tlvs_len(const struct wmi_start_scan_arg *arg)
+{
+	int len = 0;
+
+	if (arg->ie_len) {
 		len += sizeof(struct wmi_ie_data);
 		len += roundup(arg->ie_len, 4);
 	}
 
 	if (arg->n_channels) {
-		if (!arg->channels)
-			return -EINVAL;
-		if (arg->n_channels > ARRAY_SIZE(arg->channels))
-			return -EINVAL;
-
 		len += sizeof(struct wmi_chan_list);
 		len += sizeof(__le32) * arg->n_channels;
 	}
 
 	if (arg->n_ssids) {
-		if (!arg->ssids)
-			return -EINVAL;
-		if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
-			return -EINVAL;
-
 		len += sizeof(struct wmi_ssid_list);
 		len += sizeof(struct wmi_ssid) * arg->n_ssids;
 	}
 
 	if (arg->n_bssids) {
-		if (!arg->bssids)
-			return -EINVAL;
-		if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
-			return -EINVAL;
-
 		len += sizeof(struct wmi_bssid_list);
 		len += sizeof(struct wmi_mac_addr) * arg->n_bssids;
 	}
@@ -3210,28 +3208,12 @@ static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar,
 	return len;
 }
 
-int ath10k_wmi_start_scan(struct ath10k *ar,
-			  const struct wmi_start_scan_arg *arg)
+static void
+ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn,
+				 const struct wmi_start_scan_arg *arg)
 {
-	struct wmi_start_scan_cmd *cmd;
-	struct sk_buff *skb;
-	struct wmi_ie_data *ie;
-	struct wmi_chan_list *channels;
-	struct wmi_ssid_list *ssids;
-	struct wmi_bssid_list *bssids;
 	u32 scan_id;
 	u32 scan_req_id;
-	int off;
-	int len = 0;
-	int i;
-
-	len = ath10k_wmi_start_scan_calc_len(ar, arg);
-	if (len < 0)
-		return len; /* len contains error code here */
-
-	skb = ath10k_wmi_alloc_skb(ar, len);
-	if (!skb)
-		return -ENOMEM;
 
 	scan_id  = WMI_HOST_SCAN_REQ_ID_PREFIX;
 	scan_id |= arg->scan_id;
@@ -3239,35 +3221,36 @@ int ath10k_wmi_start_scan(struct ath10k *ar,
 	scan_req_id  = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
 	scan_req_id |= arg->scan_req_id;
 
-	cmd = (struct wmi_start_scan_cmd *)skb->data;
-	cmd->scan_id            = __cpu_to_le32(scan_id);
-	cmd->scan_req_id        = __cpu_to_le32(scan_req_id);
-	cmd->vdev_id            = __cpu_to_le32(arg->vdev_id);
-	cmd->scan_priority      = __cpu_to_le32(arg->scan_priority);
-	cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events);
-	cmd->dwell_time_active  = __cpu_to_le32(arg->dwell_time_active);
-	cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive);
-	cmd->min_rest_time      = __cpu_to_le32(arg->min_rest_time);
-	cmd->max_rest_time      = __cpu_to_le32(arg->max_rest_time);
-	cmd->repeat_probe_time  = __cpu_to_le32(arg->repeat_probe_time);
-	cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time);
-	cmd->idle_time          = __cpu_to_le32(arg->idle_time);
-	cmd->max_scan_time      = __cpu_to_le32(arg->max_scan_time);
-	cmd->probe_delay        = __cpu_to_le32(arg->probe_delay);
-	cmd->scan_ctrl_flags    = __cpu_to_le32(arg->scan_ctrl_flags);
-
-	/* TLV list starts after fields included in the struct */
-	/* There's just one filed that differes the two start_scan
-	 * structures - burst_duration, which we are not using btw,
-	   no point to make the split here, just shift the buffer to fit with
-	   given FW */
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-		off = sizeof(struct wmi_start_scan_cmd_10x);
-	else
-		off = sizeof(struct wmi_start_scan_cmd);
+	cmn->scan_id            = __cpu_to_le32(scan_id);
+	cmn->scan_req_id        = __cpu_to_le32(scan_req_id);
+	cmn->vdev_id            = __cpu_to_le32(arg->vdev_id);
+	cmn->scan_priority      = __cpu_to_le32(arg->scan_priority);
+	cmn->notify_scan_events = __cpu_to_le32(arg->notify_scan_events);
+	cmn->dwell_time_active  = __cpu_to_le32(arg->dwell_time_active);
+	cmn->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive);
+	cmn->min_rest_time      = __cpu_to_le32(arg->min_rest_time);
+	cmn->max_rest_time      = __cpu_to_le32(arg->max_rest_time);
+	cmn->repeat_probe_time  = __cpu_to_le32(arg->repeat_probe_time);
+	cmn->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time);
+	cmn->idle_time          = __cpu_to_le32(arg->idle_time);
+	cmn->max_scan_time      = __cpu_to_le32(arg->max_scan_time);
+	cmn->probe_delay        = __cpu_to_le32(arg->probe_delay);
+	cmn->scan_ctrl_flags    = __cpu_to_le32(arg->scan_ctrl_flags);
+}
+
+static void
+ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs,
+			       const struct wmi_start_scan_arg *arg)
+{
+	struct wmi_ie_data *ie;
+	struct wmi_chan_list *channels;
+	struct wmi_ssid_list *ssids;
+	struct wmi_bssid_list *bssids;
+	void *ptr = tlvs->tlvs;
+	int i;
 
 	if (arg->n_channels) {
-		channels = (void *)skb->data + off;
+		channels = ptr;
 		channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG);
 		channels->num_chan = __cpu_to_le32(arg->n_channels);
 
@@ -3275,12 +3258,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar,
 			channels->channel_list[i].freq =
 				__cpu_to_le16(arg->channels[i]);
 
-		off += sizeof(*channels);
-		off += sizeof(__le32) * arg->n_channels;
+		ptr += sizeof(*channels);
+		ptr += sizeof(__le32) * arg->n_channels;
 	}
 
 	if (arg->n_ssids) {
-		ssids = (void *)skb->data + off;
+		ssids = ptr;
 		ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG);
 		ssids->num_ssids = __cpu_to_le32(arg->n_ssids);
 
@@ -3292,12 +3275,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar,
 			       arg->ssids[i].len);
 		}
 
-		off += sizeof(*ssids);
-		off += sizeof(struct wmi_ssid) * arg->n_ssids;
+		ptr += sizeof(*ssids);
+		ptr += sizeof(struct wmi_ssid) * arg->n_ssids;
 	}
 
 	if (arg->n_bssids) {
-		bssids = (void *)skb->data + off;
+		bssids = ptr;
 		bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG);
 		bssids->num_bssid = __cpu_to_le32(arg->n_bssids);
 
@@ -3306,23 +3289,57 @@ int ath10k_wmi_start_scan(struct ath10k *ar,
 			       arg->bssids[i].bssid,
 			       ETH_ALEN);
 
-		off += sizeof(*bssids);
-		off += sizeof(struct wmi_mac_addr) * arg->n_bssids;
+		ptr += sizeof(*bssids);
+		ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids;
 	}
 
 	if (arg->ie_len) {
-		ie = (void *)skb->data + off;
+		ie = ptr;
 		ie->tag = __cpu_to_le32(WMI_IE_TAG);
 		ie->ie_len = __cpu_to_le32(arg->ie_len);
 		memcpy(ie->ie_data, arg->ie, arg->ie_len);
 
-		off += sizeof(*ie);
-		off += roundup(arg->ie_len, 4);
+		ptr += sizeof(*ie);
+		ptr += roundup(arg->ie_len, 4);
 	}
+}
 
-	if (off != skb->len) {
-		dev_kfree_skb(skb);
-		return -EINVAL;
+int ath10k_wmi_start_scan(struct ath10k *ar,
+			  const struct wmi_start_scan_arg *arg)
+{
+	struct sk_buff *skb;
+	size_t len;
+	int ret;
+
+	ret = ath10k_wmi_start_scan_verify(arg);
+	if (ret)
+		return ret;
+
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+		len = sizeof(struct wmi_start_scan_cmd) +
+		      ath10k_wmi_start_scan_tlvs_len(arg);
+	else
+		len = sizeof(struct wmi_10x_start_scan_cmd) +
+		      ath10k_wmi_start_scan_tlvs_len(arg);
+
+	skb = ath10k_wmi_alloc_skb(ar, len);
+	if (!skb)
+		return -ENOMEM;
+
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+		struct wmi_10x_start_scan_cmd *cmd;
+
+		cmd = (struct wmi_10x_start_scan_cmd *)skb->data;
+		ath10k_wmi_put_start_scan_common(&cmd->common, arg);
+		ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
+	} else {
+		struct wmi_start_scan_cmd *cmd;
+
+		cmd = (struct wmi_start_scan_cmd *)skb->data;
+		cmd->burst_duration_ms = __cpu_to_le32(0);
+
+		ath10k_wmi_put_start_scan_common(&cmd->common, arg);
+		ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
 	}
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n");
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index a041567..d896bd3 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -1963,7 +1963,7 @@ enum wmi_scan_priority {
 	WMI_SCAN_PRIORITY_COUNT   /* number of priorities supported */
 };
 
-struct wmi_start_scan_cmd {
+struct wmi_start_scan_common {
 	/* Scan ID */
 	__le32 scan_id;
 	/* Scan requestor ID */
@@ -2021,95 +2021,25 @@ struct wmi_start_scan_cmd {
 	__le32 probe_delay;
 	/* Scan control flags */
 	__le32 scan_ctrl_flags;
-
-	/* Burst duration time in msecs */
-	__le32 burst_duration;
-	/*
-	 * TLV (tag length value )  paramerters follow the scan_cmd structure.
-	 * TLV can contain channel list, bssid list, ssid list and
-	 * ie. the TLV tags are defined above;
-	 */
 } __packed;
 
-/* This is the definition from 10.X firmware branch */
-struct wmi_start_scan_cmd_10x {
-	/* Scan ID */
-	__le32 scan_id;
-
-	/* Scan requestor ID */
-	__le32 scan_req_id;
-
-	/* VDEV id(interface) that is requesting scan */
-	__le32 vdev_id;
-
-	/* Scan Priority, input to scan scheduler */
-	__le32 scan_priority;
-
-	/* Scan events subscription */
-	__le32 notify_scan_events;
-
-	/* dwell time in msec on active channels */
-	__le32 dwell_time_active;
-
-	/* dwell time in msec on passive channels */
-	__le32 dwell_time_passive;
-
-	/*
-	 * min time in msec on the BSS channel,only valid if atleast one
-	 * VDEV is active
-	 */
-	__le32 min_rest_time;
-
-	/*
-	 * max rest time in msec on the BSS channel,only valid if at least
-	 * one VDEV is active
-	 */
-	/*
-	 * the scanner will rest on the bss channel at least min_rest_time
-	 * after min_rest_time the scanner will start checking for tx/rx
-	 * activity on all VDEVs. if there is no activity the scanner will
-	 * switch to off channel. if there is activity the scanner will let
-	 * the radio on the bss channel until max_rest_time expires.at
-	 * max_rest_time scanner will switch to off channel irrespective of
-	 * activity. activity is determined by the idle_time parameter.
-	 */
-	__le32 max_rest_time;
-
-	/*
-	 * time before sending next set of probe requests.
-	 * The scanner keeps repeating probe requests transmission with
-	 * period specified by repeat_probe_time.
-	 * The number of probe requests specified depends on the ssid_list
-	 * and bssid_list
-	 */
-	__le32 repeat_probe_time;
-
-	/* time in msec between 2 consequetive probe requests with in a set. */
-	__le32 probe_spacing_time;
-
-	/*
-	 * data inactivity time in msec on bss channel that will be used by
-	 * scanner for measuring the inactivity.
-	 */
-	__le32 idle_time;
-
-	/* maximum time in msec allowed for scan  */
-	__le32 max_scan_time;
-
-	/*
-	 * delay in msec before sending first probe request after switching
-	 * to a channel
+struct wmi_start_scan_tlvs {
+	/* TLV parameters. These includes channel list, ssid list, bssid list,
+	 * extra ies.
 	 */
-	__le32 probe_delay;
+	u8 tlvs[0];
+} __packed;
 
-	/* Scan control flags */
-	__le32 scan_ctrl_flags;
+struct wmi_start_scan_cmd {
+	struct wmi_start_scan_common common;
+	__le32 burst_duration_ms;
+	struct wmi_start_scan_tlvs tlvs;
+} __packed;
 
-	/*
-	 * TLV (tag length value )  paramerters follow the scan_cmd structure.
-	 * TLV can contain channel list, bssid list, ssid list and
-	 * ie. the TLV tags are defined above;
-	 */
+/* This is the definition from 10.X firmware branch */
+struct wmi_10x_start_scan_cmd {
+	struct wmi_start_scan_common common;
+	struct wmi_start_scan_tlvs tlvs;
 } __packed;
 
 struct wmi_ssid_arg {
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:25:19 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:25:19 +0200
Subject: [PATCH 1/3] ath10k: print wmi version info
In-Reply-To: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>
References: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046721-20510-2-git-send-email-michal.kazior@tieto.com>

HTT version is already printed so print WMI
version as well for consistency.

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

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 3756feb..f1e5916 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -126,14 +126,18 @@ EXPORT_SYMBOL(ath10k_info);
 
 void ath10k_print_driver_info(struct ath10k *ar)
 {
-	ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
+	ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d\n",
 		    ar->hw_params.name,
 		    ar->target_version,
 		    ar->chip_id,
 		    ar->hw->wiphy->fw_version,
 		    ar->fw_api,
 		    ar->htt.target_version_major,
-		    ar->htt.target_version_minor);
+		    ar->htt.target_version_minor,
+		    ar->fw_version_major,
+		    ar->fw_version_minor,
+		    ar->fw_version_release,
+		    ar->fw_version_build);
 	ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
 		    config_enabled(CONFIG_ATH10K_DEBUG),
 		    config_enabled(CONFIG_ATH10K_DEBUGFS),
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:25:18 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:25:18 +0200
Subject: [PATCH 0/3] ath10k: debug improvements
Message-ID: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>

Hi,

This adds extra prints and information for
debugging purposes.


Michal Kazior (3):
  ath10k: print wmi version info
  ath10k: dump hex bytes with dev string prefix
  ath10k: add debug dump for pci rx

 drivers/net/wireless/ath/ath10k/debug.c | 29 ++++++++++++++++++++++++++---
 drivers/net/wireless/ath/ath10k/pci.c   |  6 ++++++
 2 files changed, 32 insertions(+), 3 deletions(-)

-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:25:20 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:25:20 +0200
Subject: [PATCH 2/3] ath10k: dump hex bytes with dev string prefix
In-Reply-To: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>
References: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046721-20510-3-git-send-email-michal.kazior@tieto.com>

This makes it easier to debug hex dumps on systems
with more than a single ath10k device.

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

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index f1e5916..9f8dddc 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1264,11 +1264,30 @@ void ath10k_dbg_dump(struct ath10k *ar,
 		     const char *msg, const char *prefix,
 		     const void *buf, size_t len)
 {
+	char linebuf[256];
+	unsigned int linebuflen;
+	const void *ptr;
+
 	if (ath10k_debug_mask & mask) {
 		if (msg)
 			ath10k_dbg(ar, mask, "%s\n", msg);
 
-		print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
+		for (ptr = buf; (ptr - buf) < len; ptr += 16) {
+			linebuflen = 0;
+			if (prefix)
+				linebuflen += scnprintf(linebuf + linebuflen,
+							sizeof(linebuf) -
+							linebuflen,
+							"%s", prefix);
+			linebuflen += scnprintf(linebuf + linebuflen,
+						sizeof(linebuf) - linebuflen,
+						"%08x: ",
+						(unsigned int)(ptr - buf));
+			hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
+					   linebuf + linebuflen,
+					   sizeof(linebuf) - linebuflen, true);
+			dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
+		}
 	}
 
 	/* tracing code doesn't like null strings :/ */
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 18 06:25:21 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 18 Sep 2014 15:25:21 +0200
Subject: [PATCH 3/3] ath10k: add debug dump for pci rx
In-Reply-To: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>
References: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411046721-20510-4-git-send-email-michal.kazior@tieto.com>

This makes it easier to debug the device-target
communication at a very low level.

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

diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 59e0ea8..8319d83 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -861,6 +861,12 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
 		}
 
 		skb_put(skb, nbytes);
+
+		ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n",
+			   ce_state->id, skb->len);
+		ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ",
+				skb->data, skb->len);
+
 		cb->rx_completion(ar, skb, pipe_info->pipe_num);
 	}
 
-- 
1.8.5.3



From greearb at candelatech.com  Thu Sep 18 09:06:41 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 18 Sep 2014 09:06:41 -0700
Subject: Hard lockup during vif restart tests.
In-Reply-To: <87vbols7tg.fsf@kamboji.qca.qualcomm.com>
References: <541884AC.3020402@candelatech.com>
 <CA+BoTQkeSSp5K=Ov-Sce9tcKz5ARL1im615PckPgNK-X8O-c1Q@mail.gmail.com>
 <5419AE32.6010805@candelatech.com>
 <CA+BoTQkcP=Yc8kA2=OotrWbaAf09aMOmiPQp5W2j1vxsu3x4Kg@mail.gmail.com>
 <87vbols7tg.fsf@kamboji.qca.qualcomm.com>
Message-ID: <541B0311.3060508@candelatech.com>

On 09/18/2014 12:31 AM, Kalle Valo wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
> 
>>> Why do we reset the firmware/NIC when we admin down/up the
>>> vif (when a single vif is active)?  Couldn't we just keep
>>> the firmware active in this state and not risk lockup due
>>> to reset?
>>
>> If you put down last interface mac80211 calls drv_stop(). There isn't
>> any real need to keep the device up and running after that other than
>> trying to workaround the reset issue. But then you need to deal with
>> firmware quirks. I recall it could report Rx indications after all
>> vdevs had been removed (and this is now also observable with 10.2
>> during probing/bootup). It's just simpler to reboot firmware on
>> drv_stop/start().
> 
> And there's the reliability issue. Being able to reset the firmware with
> interface down/up sequency is pretty useful and AFAIK almost all
> upstream drivers do that. And let's not forget power consumption either.

The fact that restarting firmware can hang the machine or require
reboot to recover is so serious that I think a work-around is
worth looking into.

Thanks,
Ben

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



From greearb at candelatech.com  Thu Sep 18 09:11:49 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 18 Sep 2014 09:11:49 -0700
Subject: [PATCH 1/9] ath10k: fix tx/rx chainmask init
In-Reply-To: <1411046487-19544-2-git-send-email-michal.kazior@tieto.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
 <1411046487-19544-2-git-send-email-michal.kazior@tieto.com>
Message-ID: <541B0445.7040707@candelatech.com>

On 09/18/2014 06:21 AM, Michal Kazior wrote:
> Firmware reports the number of RF chains so use
> that for initialization of supp_{tx,rx}_chainmask
> instead of using a macro for 3x3 chips.
> 
> This should make tx/rx chainmask reports correct
> for chips other than 3x3.

> diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
> index 2c42bd5..772cca5 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi.c
> +++ b/drivers/net/wireless/ath/ath10k/wmi.c
> @@ -2198,6 +2198,9 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
>  		ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
>  	}
>  
> +	ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
> +	ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;

Are there are no chips that support a different number
of tx and rx chains?


Thanks,
Ben


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



From michal.kazior at tieto.com  Thu Sep 18 22:59:09 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Fri, 19 Sep 2014 07:59:09 +0200
Subject: [PATCH 1/9] ath10k: fix tx/rx chainmask init
In-Reply-To: <541B0445.7040707@candelatech.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
 <1411046487-19544-2-git-send-email-michal.kazior@tieto.com>
 <541B0445.7040707@candelatech.com>
Message-ID: <CA+BoTQnanQmHn_y_5hFZSaEVvCzbY42U+3Z=PVnWTRun-6Jx4g@mail.gmail.com>

On 18 September 2014 18:11, Ben Greear <greearb at candelatech.com> wrote:
> On 09/18/2014 06:21 AM, Michal Kazior wrote:
>> Firmware reports the number of RF chains so use
>> that for initialization of supp_{tx,rx}_chainmask
>> instead of using a macro for 3x3 chips.
>>
>> This should make tx/rx chainmask reports correct
>> for chips other than 3x3.
>
>> diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
>> index 2c42bd5..772cca5 100644
>> --- a/drivers/net/wireless/ath/ath10k/wmi.c
>> +++ b/drivers/net/wireless/ath/ath10k/wmi.c
>> @@ -2198,6 +2198,9 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
>>               ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
>>       }
>>
>> +     ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
>> +     ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
>
> Are there are no chips that support a different number
> of tx and rx chains?

I don't think current firmware interface is capable of advertising
that to the host so I'm guessing there are none yet.


Micha?


From kvalo at qca.qualcomm.com  Fri Sep 19 01:37:10 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 19 Sep 2014 11:37:10 +0300
Subject: [PATCH 6/9] ath10k: deduplicate wmi service ready logic
In-Reply-To: <1411046487-19544-7-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 18 Sep 2014 15:21:24 +0200")
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
 <1411046487-19544-7-git-send-email-michal.kazior@tieto.com>
Message-ID: <87a95wngzt.fsf@kamboji.qca.qualcomm.com>

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

> The logic responsible for processing the event is
> no different across different firmware binaries.
> The difference that needs to be dealt with is the
> ABI of data structures.
>
> The intermediate structure uses __le32 to avoid
> extra memory allocations to byteswap
> variable-length substructures (i.e. host mem
> chunks).
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

[...]

> +	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
> +		ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg);
> +		wmi_10x_svc_map(arg.service_map, svc_bmap);
> +	} else {
> +		ret = ath10k_wmi_pull_svc_rdy_ev(skb, &arg);
> +		wmi_main_svc_map(arg.service_map, svc_bmap);
> +	}

For consistency shouldn't the latter be
ath10k_wmi_main_pull_svc_rdy_ev()?

> --- a/drivers/net/wireless/ath/ath10k/wmi.h
> +++ b/drivers/net/wireless/ath/ath10k/wmi.h
> @@ -1394,6 +1394,7 @@ struct wlan_host_mem_req {
>   * wmi_service_ready_event,e.g., 11ac pass some of the
>   * device capability to the host.
>   */
> +
>  struct wmi_service_ready_event {
>  	__le32 sw_version;
>  	__le32 sw_version_1;

Isn't this unneeded change?

-- 
Kalle Valo


From michal.kazior at tieto.com  Fri Sep 19 01:43:25 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Fri, 19 Sep 2014 10:43:25 +0200
Subject: [PATCH 6/9] ath10k: deduplicate wmi service ready logic
In-Reply-To: <87a95wngzt.fsf@kamboji.qca.qualcomm.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
 <1411046487-19544-7-git-send-email-michal.kazior@tieto.com>
 <87a95wngzt.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQmsVqvGgu_fUqKGqhEKXV7E_w0KdcH_GFoPhAvyjtVdDA@mail.gmail.com>

On 19 September 2014 10:37, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
>
>> The logic responsible for processing the event is
>> no different across different firmware binaries.
>> The difference that needs to be dealt with is the
>> ABI of data structures.
>>
>> The intermediate structure uses __le32 to avoid
>> extra memory allocations to byteswap
>> variable-length substructures (i.e. host mem
>> chunks).
>>
>> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
>
> [...]
>
>> +     if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
>> +             ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg);
>> +             wmi_10x_svc_map(arg.service_map, svc_bmap);
>> +     } else {
>> +             ret = ath10k_wmi_pull_svc_rdy_ev(skb, &arg);
>> +             wmi_main_svc_map(arg.service_map, svc_bmap);
>> +     }
>
> For consistency shouldn't the latter be
> ath10k_wmi_main_pull_svc_rdy_ev()?

Good point. Makes sense. I'll add the _main to the function name.


>> --- a/drivers/net/wireless/ath/ath10k/wmi.h
>> +++ b/drivers/net/wireless/ath/ath10k/wmi.h
>> @@ -1394,6 +1394,7 @@ struct wlan_host_mem_req {
>>   * wmi_service_ready_event,e.g., 11ac pass some of the
>>   * device capability to the host.
>>   */
>> +
>>  struct wmi_service_ready_event {
>>       __le32 sw_version;
>>       __le32 sw_version_1;
>
> Isn't this unneeded change?

Good catch. I'll fix that.


Micha?


From greearb at candelatech.com  Fri Sep 19 11:04:49 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Fri, 19 Sep 2014 11:04:49 -0700
Subject: [PATCH 2/3] ath10k:  support CT firmware flag.
In-Reply-To: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
References: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411149890-12618-2-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Add placeholder so CT firmware can more easily co-exist with upstream
kernel.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/core.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 20c5e40..3f14858 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -361,6 +361,9 @@ enum ath10k_fw_features {
 	 */
 	ATH10K_FW_FEATURE_WMI_10_2 = 4,
 
+	/* Firmware from Candela Technologies, enables more VIFs, etc */
+	ATH10K_FW_FEATURE_WMI_10X_CT = 5,
+
 	/* keep last */
 	ATH10K_FW_FEATURE_COUNT,
 };
-- 
1.7.11.7



From greearb at candelatech.com  Fri Sep 19 11:04:48 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Fri, 19 Sep 2014 11:04:48 -0700
Subject: [PATCH 1/3] ath10k:  use 64-bit vdev map.
Message-ID: <1411149890-12618-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

This can allow more than 32 stations to be supported
without over-running the bitmap.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/core.c |  4 ++--
 drivers/net/wireless/ath/ath10k/core.h |  2 +-
 drivers/net/wireless/ath/ath10k/mac.c  | 21 ++++++++++++---------
 3 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index cee18c8..37e3166 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -846,9 +846,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
 		goto err_hif_stop;
 
 	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-		ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1;
+		ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
 	else
-		ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
+		ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;
 
 	INIT_LIST_HEAD(&ar->arvifs);
 
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index fe531ea..20c5e40 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -482,7 +482,7 @@ struct ath10k {
 	/* current operating channel definition */
 	struct cfg80211_chan_def chandef;
 
-	int free_vdev_map;
+	unsigned long long free_vdev_map;
 	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 4670930..e1ddac4 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -590,9 +590,9 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar)
 		return -ENOMEM;
 	}
 
-	bit = ffs(ar->free_vdev_map);
+	bit = __ffs64(ar->free_vdev_map);
 
-	ar->monitor_vdev_id = bit - 1;
+	ar->monitor_vdev_id = bit;
 
 	ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id,
 				     WMI_VDEV_TYPE_MONITOR,
@@ -603,7 +603,7 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar)
 		return ret;
 	}
 
-	ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id);
+	ar->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
 	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n",
 		   ar->monitor_vdev_id);
 
@@ -623,7 +623,7 @@ static int ath10k_monitor_vdev_delete(struct ath10k *ar)
 		return ret;
 	}
 
-	ar->free_vdev_map |= 1 << ar->monitor_vdev_id;
+	ar->free_vdev_map |= 1LL << ar->monitor_vdev_id;
 
 	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n",
 		   ar->monitor_vdev_id);
@@ -2772,9 +2772,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 		ret = -EBUSY;
 		goto err;
 	}
-	bit = ffs(ar->free_vdev_map);
+	bit = __ffs64(ar->free_vdev_map);
 
-	arvif->vdev_id = bit - 1;
+	ath10k_warn(ar, "Creating vdev id: %i  map: %llu\n",
+		    bit, ar->free_vdev_map);
+
+	arvif->vdev_id = bit;
 	arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
 
 	if (ar->p2p)
@@ -2815,7 +2818,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 		goto err;
 	}
 
-	ar->free_vdev_map &= ~(1 << arvif->vdev_id);
+	ar->free_vdev_map &= ~(1LL << arvif->vdev_id);
 	list_add(&arvif->list, &ar->arvifs);
 
 	vdev_param = ar->wmi.vdev_param->def_keyid;
@@ -2908,7 +2911,7 @@ err_peer_delete:
 
 err_vdev_delete:
 	ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
-	ar->free_vdev_map |= 1 << arvif->vdev_id;
+	ar->free_vdev_map |= 1LL << arvif->vdev_id;
 	list_del(&arvif->list);
 
 err:
@@ -2944,7 +2947,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 		ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n",
 			    arvif->vdev_id, ret);
 
-	ar->free_vdev_map |= 1 << arvif->vdev_id;
+	ar->free_vdev_map |= 1LL << arvif->vdev_id;
 	list_del(&arvif->list);
 
 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
-- 
1.7.11.7



From greearb at candelatech.com  Fri Sep 19 11:04:50 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Fri, 19 Sep 2014 11:04:50 -0700
Subject: [PATCH 3/3] ath10k: support 32+ stations.
In-Reply-To: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
References: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411149890-12618-3-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Support up to 32 stations when using CT firmware.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/core.c |  4 +++-
 drivers/net/wireless/ath/ath10k/hw.h   |  6 +++++
 drivers/net/wireless/ath/ath10k/mac.c  | 42 ++++++++++++++++++++++++++++++++--
 drivers/net/wireless/ath/ath10k/wmi.c  | 25 ++++++++++++++++----
 4 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 37e3166..507f31a 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -845,7 +845,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
 	if (status)
 		goto err_hif_stop;
 
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
+		ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS_CT) - 1;
+	else if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
 		ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
 	else
 		ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 3cf5702..9583555 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -122,6 +122,12 @@ enum ath10k_mcast2ucast_mode {
 #define TARGET_10X_AST_SKID_LIMIT		16
 #define TARGET_10X_NUM_PEERS			(128 + (TARGET_10X_NUM_VDEVS))
 #define TARGET_10X_NUM_PEERS_MAX		128
+
+/* Over-rides for Candela Technologies firmware */
+#define TARGET_10X_NUM_VDEVS_CT			32
+#define TARGET_10X_NUM_PEERS_CT			(32 + (TARGET_10X_NUM_VDEVS_CT))
+#define TARGET_10X_AST_SKID_LIMIT_CT		(TARGET_10X_NUM_PEERS_CT * TARGET_10X_NUM_PEER_AST)
+
 #define TARGET_10X_NUM_OFFLOAD_PEERS		0
 #define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS	0
 #define TARGET_10X_NUM_PEER_KEYS		2
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index e1ddac4..b517f71 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3497,7 +3497,9 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
 		/*
 		 * New station addition.
 		 */
-		if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+		if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
+			max_num_peers = TARGET_10X_NUM_PEERS_CT - 1;
+		else if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
 			max_num_peers = TARGET_10X_NUM_PEERS_MAX - 1;
 		else
 			max_num_peers = TARGET_NUM_PEERS;
@@ -4601,6 +4603,22 @@ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = {
 	},
 };
 
+static const struct ieee80211_iface_limit ath10k_10x_ct_if_limits[] = {
+	{
+	.max	= TARGET_10X_NUM_VDEVS_CT,
+	.types	= BIT(NL80211_IFTYPE_STATION)
+		| BIT(NL80211_IFTYPE_P2P_CLIENT)
+	},
+	{
+	.max	= 3,
+	.types	= BIT(NL80211_IFTYPE_P2P_GO)
+	},
+	{
+	.max	= 7,
+	.types	= BIT(NL80211_IFTYPE_AP)
+	},
+};
+
 static const struct ieee80211_iface_combination ath10k_if_comb[] = {
 	{
 		.limits = ath10k_if_limits,
@@ -4627,6 +4645,22 @@ static const struct ieee80211_iface_combination ath10k_10x_if_comb[] = {
 	},
 };
 
+static const struct ieee80211_iface_combination ath10k_10x_ct_if_comb[] = {
+	{
+		.limits = ath10k_10x_ct_if_limits,
+		.n_limits = ARRAY_SIZE(ath10k_10x_ct_if_limits),
+		.max_interfaces = TARGET_10X_NUM_VDEVS_CT,
+		.num_different_channels = 1,
+		.beacon_int_infra_match = true,
+#ifdef CONFIG_ATH10K_DFS_CERTIFIED
+		.radar_detect_widths =	BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+					BIT(NL80211_CHAN_WIDTH_20) |
+					BIT(NL80211_CHAN_WIDTH_40) |
+					BIT(NL80211_CHAN_WIDTH_80),
+#endif
+	},
+};
+
 static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
 {
 	struct ieee80211_sta_vht_cap vht_cap = {0};
@@ -4863,7 +4897,11 @@ int ath10k_mac_register(struct ath10k *ar)
 	 */
 	ar->hw->queues = 4;
 
-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features)) {
+		ar->hw->wiphy->iface_combinations = ath10k_10x_ct_if_comb;
+		ar->hw->wiphy->n_iface_combinations =
+			ARRAY_SIZE(ath10k_10x_ct_if_comb);
+	} else if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
 		ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
 		ar->hw->wiphy->n_iface_combinations =
 			ARRAY_SIZE(ath10k_10x_if_comb);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 2c42bd5..76abdd7 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2245,6 +2245,13 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
 	int ret;
 	struct wmi_service_ready_event_10x *ev = (void *)skb->data;
 	DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
+	int my_num_peers = TARGET_10X_NUM_PEERS;
+	int my_num_vdevs = TARGET_10X_NUM_VDEVS;
+
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features)) {
+		my_num_peers = TARGET_10X_NUM_PEERS_CT;
+		my_num_vdevs = TARGET_10X_NUM_VDEVS_CT;
+	}
 
 	if (skb->len < sizeof(*ev)) {
 		ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
@@ -2309,9 +2316,9 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
 			 * peers, 1 extra for self peer on target */
 			/* this needs to be tied, host and target
 			 * can get out of sync */
-			num_units = TARGET_10X_NUM_PEERS + 1;
+			num_units = my_num_peers + 1;
 		else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS)
-			num_units = TARGET_10X_NUM_VDEVS + 1;
+			num_units = my_num_vdevs + 1;
 
 		ath10k_dbg(ar, ATH10K_DBG_WMI,
 			   "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n",
@@ -3057,12 +3064,20 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar)
 	struct wmi_resource_config_10x config = {};
 	u32 len, val;
 	int i;
+	u32 skid_limit;
 
-	config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
-	config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features)) {
+		config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS_CT);
+		config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS_CT);
+		skid_limit = TARGET_10X_AST_SKID_LIMIT_CT;
+	} else {
+		config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
+		config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
+		skid_limit = TARGET_10X_AST_SKID_LIMIT;
+	}
+	config.ast_skid_limit = __cpu_to_le32(skid_limit);
 	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);
-- 
1.7.11.7



From greearb at candelatech.com  Fri Sep 19 11:17:38 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Fri, 19 Sep 2014 11:17:38 -0700
Subject: [PATCH 1/2] ath10k: add helper method to grab debug stats.
Message-ID: <1411150659-10998-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

It can be nice to update the firmware's stats while
debugging other bits of the driver, so add helper method
to do this.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/debug.c | 26 +++++++++++++++++---------
 drivers/net/wireless/ath/ath10k/debug.h |  3 +++
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 3756feb..e223ba9 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -371,6 +371,21 @@ void ath10k_debug_read_target_stats(struct ath10k *ar,
 	complete(&ar->debug.event_stats_compl);
 }
 
+int ath10k_refresh_peer_stats(struct ath10k *ar)
+{
+	int ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
+	if (ret) {
+		ath10k_warn(ar, "could not request stats (%d)\n", ret);
+		return ret;
+	}
+
+	ret = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
+	if (ret <= 0)
+		return ret;
+
+	return 0;
+}
+
 static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
 				    size_t count, loff_t *ppos)
 {
@@ -379,7 +394,6 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
 	char *buf = NULL;
 	unsigned int len = 0, buf_len = 8000;
 	ssize_t ret_cnt = 0;
-	long left;
 	int i;
 	int ret;
 
@@ -394,14 +408,8 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
 	if (!buf)
 		goto exit;
 
-	ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
-	if (ret) {
-		ath10k_warn(ar, "could not request stats (%d)\n", ret);
-		goto exit;
-	}
-
-	left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
-	if (left <= 0)
+	ret = ath10k_refresh_peer_stats(ar);
+	if (ret)
 		goto exit;
 
 	spin_lock_bh(&ar->data_lock);
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index b3774f7..91b217e 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -142,4 +142,7 @@ static inline void ath10k_dbg_dump(struct ath10k *ar,
 {
 }
 #endif /* CONFIG_ATH10K_DEBUG */
+
+int ath10k_refresh_peer_stats(struct ath10k *ar);
+
 #endif /* _DEBUG_H_ */
-- 
1.7.11.7



From greearb at candelatech.com  Fri Sep 19 11:17:39 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Fri, 19 Sep 2014 11:17:39 -0700
Subject: [PATCH 2/2] ath10k: support ethtool stats.
In-Reply-To: <1411150659-10998-1-git-send-email-greearb@candelatech.com>
References: <1411150659-10998-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411150659-10998-2-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Add support for reading firmware stats through the ethtool
API.  This may be easier for applications to manipulate
compared to parsing a text based debugfs file.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/core.h  |   4 +
 drivers/net/wireless/ath/ath10k/debug.c | 143 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/debug.h |   9 ++
 drivers/net/wireless/ath/ath10k/mac.c   |   5 ++
 drivers/net/wireless/ath/ath10k/pci.c   |   4 +
 5 files changed, 165 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 3f14858..3c8d904 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -544,6 +544,10 @@ struct ath10k {
 
 	struct dfs_pattern_detector *dfs_detector;
 
+	u32 fw_crash_counter;
+	u32 fw_warm_reset_counter;
+	u32 fw_cold_reset_counter;
+
 #ifdef CONFIG_ATH10K_DEBUGFS
 	struct ath10k_debug debug;
 #endif
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index e223ba9..e3cda06 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1037,6 +1037,149 @@ exit:
 	return ret;
 }
 
+#ifdef CONFIG_ATH10K_DEBUGFS
+/* TODO:  Would be nice to always support ethtool stats, would need to
+ * move the stats storage out of ath10k_debug, or always have ath10k_debug
+ * struct available..
+ */
+
+/* This generally cooresponds to the debugfs fw_stats file */
+static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"tx_pkts_nic",
+	"tx_bytes_nic",
+	"rx_pkts_nic",
+	"rx_bytes_nic",
+	"d_noise_floor",
+	"d_cycle_count",
+	"d_phy_error",
+	"d_rts_bad",
+	"d_rts_good",
+	"d_tx_power", /* in .5 dbM I think */
+	"d_rx_crc_err", /* fcs_bad */
+	"d_no_beacon",
+	"d_tx_mpdus_queued",
+	"d_tx_msdu_queued",
+	"d_tx_msdu_dropped",
+	"d_local_enqued",
+	"d_local_freed",
+	"d_tx_ppdu_hw_queued",
+	"d_tx_ppdu_reaped",
+	"d_tx_fifo_underrun",
+	"d_tx_ppdu_abort",
+	"d_tx_mpdu_requed",
+	"d_tx_excessive_retries",
+	"d_tx_hw_rate",
+	"d_tx_dropped_sw_retries",
+	"d_tx_illegal_rate",
+	"d_tx_continuous_xretries",
+	"d_tx_timeout",
+	"d_tx_mpdu_txop_limit",
+	"d_pdev_resets",
+	"d_rx_mid_ppdu_route_change",
+	"d_rx_status",
+	"d_rx_extra_frags_ring0",
+	"d_rx_extra_frags_ring1",
+	"d_rx_extra_frags_ring2",
+	"d_rx_extra_frags_ring3",
+	"d_rx_msdu_htt",
+	"d_rx_mpdu_htt",
+	"d_rx_msdu_stack",
+	"d_rx_mpdu_stack",
+	"d_rx_phy_err",
+	"d_rx_phy_err_drops",
+	"d_rx_mpdu_errors", /* FCS, MIC, ENC */
+	"d_fw_crash_count",
+	"d_fw_warm_reset_count",
+	"d_fw_cold_reset_count",
+};
+#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
+
+void ath10k_get_et_strings(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif,
+			   u32 sset, u8 *data)
+{
+	if (sset == ETH_SS_STATS)
+		memcpy(data, *ath10k_gstrings_stats,
+		       sizeof(ath10k_gstrings_stats));
+}
+
+int ath10k_get_et_sset_count(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif, int sset)
+{
+	if (sset == ETH_SS_STATS)
+		return ATH10K_SSTATS_LEN;
+	return 0;
+}
+
+void ath10k_get_et_stats(struct ieee80211_hw *hw,
+			 struct ieee80211_vif *vif,
+			 struct ethtool_stats *stats, u64 *data)
+{
+	struct ath10k *ar = hw->priv;
+	int i = 0;
+	struct ath10k_target_stats *fw_stats;
+
+	fw_stats = &ar->debug.target_stats;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state == ATH10K_STATE_ON)
+		ath10k_refresh_peer_stats(ar);
+
+	data[i++] = fw_stats->hw_reaped; /* ppdu reaped */
+	data[i++] = 0; /* tx bytes */
+	data[i++] = fw_stats->htt_mpdus;
+	data[i++] = 0; /* rx bytes */
+	data[i++] = fw_stats->ch_noise_floor;
+	data[i++] = fw_stats->cycle_count;
+	data[i++] = fw_stats->phy_err_count;
+	data[i++] = fw_stats->rts_bad;
+	data[i++] = fw_stats->rts_good;
+	data[i++] = fw_stats->chan_tx_power;
+	data[i++] = fw_stats->fcs_bad;
+	data[i++] = fw_stats->no_beacons;
+	data[i++] = fw_stats->mpdu_enqued;
+	data[i++] = fw_stats->msdu_enqued;
+	data[i++] = fw_stats->wmm_drop;
+	data[i++] = fw_stats->local_enqued;
+	data[i++] = fw_stats->local_freed;
+	data[i++] = fw_stats->hw_queued;
+	data[i++] = fw_stats->hw_reaped;
+	data[i++] = fw_stats->underrun;
+	data[i++] = fw_stats->tx_abort;
+	data[i++] = fw_stats->mpdus_requed;
+	data[i++] = fw_stats->tx_ko;
+	data[i++] = fw_stats->data_rc;
+	data[i++] = fw_stats->sw_retry_failure;
+	data[i++] = fw_stats->illgl_rate_phy_err;
+	data[i++] = fw_stats->pdev_cont_xretry;
+	data[i++] = fw_stats->pdev_tx_timeout;
+	data[i++] = fw_stats->txop_ovf;
+	data[i++] = fw_stats->pdev_resets;
+	data[i++] = fw_stats->mid_ppdu_route_change;
+	data[i++] = fw_stats->status_rcvd;
+	data[i++] = fw_stats->r0_frags;
+	data[i++] = fw_stats->r1_frags;
+	data[i++] = fw_stats->r2_frags;
+	data[i++] = fw_stats->r3_frags;
+	data[i++] = fw_stats->htt_msdus;
+	data[i++] = fw_stats->htt_mpdus;
+	data[i++] = fw_stats->loc_msdus;
+	data[i++] = fw_stats->loc_mpdus;
+	data[i++] = fw_stats->phy_errs;
+	data[i++] = fw_stats->phy_err_drop;
+	data[i++] = fw_stats->mpdu_errs;
+	data[i++] = ar->fw_crash_counter;
+	data[i++] = ar->fw_warm_reset_counter;
+	data[i++] = ar->fw_cold_reset_counter;
+
+	mutex_unlock(&ar->conf_mutex);
+
+	WARN_ON(i != ATH10K_SSTATS_LEN);
+}
+
+#endif
+
 static const struct file_operations fops_fw_dbglog = {
 	.read = ath10k_read_fw_dbglog,
 	.write = ath10k_write_fw_dbglog,
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 91b217e..e44e6fc 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -64,6 +64,15 @@ void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
 
 #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
 
+void ath10k_get_et_strings(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif,
+			   u32 sset, u8 *data);
+int ath10k_get_et_sset_count(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif, int sset);
+void ath10k_get_et_stats(struct ieee80211_hw *hw,
+			 struct ieee80211_vif *vif,
+			 struct ethtool_stats *stats, u64 *data);
+
 #else
 static inline int ath10k_debug_start(struct ath10k *ar)
 {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b517f71..af24f6c 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4468,6 +4468,11 @@ static const struct ieee80211_ops ath10k_ops = {
 	.suspend			= ath10k_suspend,
 	.resume				= ath10k_resume,
 #endif
+#ifdef CONFIG_ATH10K_DEBUGFS
+	.get_et_sset_count  = ath10k_get_et_sset_count,
+	.get_et_stats       = ath10k_get_et_stats,
+	.get_et_strings     = ath10k_get_et_strings,
+#endif
 };
 
 #define RATETAB_ENT(_rate, _rateid, _flags) { \
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 59e0ea8..38f7386 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -986,6 +986,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
 
 	spin_lock_bh(&ar->data_lock);
 
+	ar->fw_crash_counter++;
+
 	crash_data = ath10k_debug_get_new_fw_crash_data(ar);
 
 	if (crash_data)
@@ -1671,6 +1673,7 @@ static int ath10k_pci_warm_reset(struct ath10k *ar)
 	u32 val;
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
+	ar->fw_warm_reset_counter++;
 
 	/* debug */
 	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
@@ -2286,6 +2289,7 @@ static int ath10k_pci_cold_reset(struct ath10k *ar)
 	u32 val;
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
+	ar->fw_cold_reset_counter++;
 
 	/* Put Target, including PCIe, into RESET. */
 	val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS);
-- 
1.7.11.7



From greearb at candelatech.com  Fri Sep 19 11:28:24 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Fri, 19 Sep 2014 11:28:24 -0700
Subject: [PATCH] ath10k: request firmware flush in ath10k_flush.
Message-ID: <1411151304-31544-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

CT firmware now supports flushing all tids for all
peers for all vdevs.  This appears to help the ath10k_flush
logic work faster and not cause timeouts.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

This requires the previously-sent patch that enables the
ATH10K_FW_FEATURE_WMI_10X_CT feature bit.  This patch provide
a nice improvement in stability and flush performance in my
testing scenarios.

 drivers/net/wireless/ath/ath10k/mac.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index af24f6c..6014856 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3830,6 +3830,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	struct ath10k *ar = hw->priv;
 	bool skip;
 	int ret;
+	u8 peer_addr[ETH_ALEN] = {0};
 
 	/* mac80211 doesn't care if we really xmit queued frames or not
 	 * we'll collect those frames either way if we stop/delete vdevs */
@@ -3841,6 +3842,12 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	if (ar->state == ATH10K_STATE_WEDGED)
 		goto skip;
 
+	/* If we are CT firmware, ask it to flush all tids on all peers on
+	 * all vdevs.  Normal firmware will just crash if you do this.
+	 */
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
+		ath10k_wmi_peer_flush(ar, 0xFFFFFFFF, peer_addr, 0xFFFFFFFF);
+
 	ret = wait_event_timeout(ar->htt.empty_tx_wq, ({
 			bool empty;
 
-- 
1.7.11.7



From kvalo at qca.qualcomm.com  Mon Sep 22 02:46:35 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 22 Sep 2014 12:46:35 +0300
Subject: [PATCH 6/9] ath10k: deduplicate wmi service ready logic
In-Reply-To: <CA+BoTQmsVqvGgu_fUqKGqhEKXV7E_w0KdcH_GFoPhAvyjtVdDA@mail.gmail.com>
 (Michal Kazior's message of "Fri, 19 Sep 2014 10:43:25 +0200")
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
 <1411046487-19544-7-git-send-email-michal.kazior@tieto.com>
 <87a95wngzt.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQmsVqvGgu_fUqKGqhEKXV7E_w0KdcH_GFoPhAvyjtVdDA@mail.gmail.com>
Message-ID: <87oau8m1hg.fsf@kamboji.qca.qualcomm.com>

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

> On 19 September 2014 10:37, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> Michal Kazior <michal.kazior at tieto.com> writes:
>>
>>> +     if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
>>> +             ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg);
>>> +             wmi_10x_svc_map(arg.service_map, svc_bmap);
>>> +     } else {
>>> +             ret = ath10k_wmi_pull_svc_rdy_ev(skb, &arg);
>>> +             wmi_main_svc_map(arg.service_map, svc_bmap);
>>> +     }
>>
>> For consistency shouldn't the latter be
>> ath10k_wmi_main_pull_svc_rdy_ev()?
>
> Good point. Makes sense. I'll add the _main to the function name.
>
>
>>> --- a/drivers/net/wireless/ath/ath10k/wmi.h
>>> +++ b/drivers/net/wireless/ath/ath10k/wmi.h
>>> @@ -1394,6 +1394,7 @@ struct wlan_host_mem_req {
>>>   * wmi_service_ready_event,e.g., 11ac pass some of the
>>>   * device capability to the host.
>>>   */
>>> +
>>>  struct wmi_service_ready_event {
>>>       __le32 sw_version;
>>>       __le32 sw_version_1;
>>
>> Isn't this unneeded change?
>
> Good catch. I'll fix that.

Like discussed in IRC, you don't need to resent the whole patchset just
because of this. I have now folded the patch below onto your patch in
ath-next-test, please review:

https://github.com/kvalo/ath/commit/1d13ab4a3bdfd342ed8fbead859de398b379435c

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 37a520150358..a7c11b292bf4 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2205,8 +2205,8 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
 	return 0;
 }
 
-static int ath10k_wmi_pull_svc_rdy_ev(struct sk_buff *skb,
-				      struct wmi_svc_rdy_ev_arg *arg)
+static int ath10k_wmi_main_pull_svc_rdy_ev(struct sk_buff *skb,
+					   struct wmi_svc_rdy_ev_arg *arg)
 {
 	struct wmi_service_ready_event *ev;
 	size_t i, n;
@@ -2286,7 +2286,7 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
 		ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg);
 		wmi_10x_svc_map(arg.service_map, svc_bmap);
 	} else {
-		ret = ath10k_wmi_pull_svc_rdy_ev(skb, &arg);
+		ret = ath10k_wmi_main_pull_svc_rdy_ev(skb, &arg);
 		wmi_main_svc_map(arg.service_map, svc_bmap);
 	}
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index ebdf15454f27..ca31cdbac557 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -1394,7 +1394,6 @@ struct wlan_host_mem_req {
  * wmi_service_ready_event,e.g., 11ac pass some of the
  * device capability to the host.
  */
-
 struct wmi_service_ready_event {
 	__le32 sw_version;
 	__le32 sw_version_1;


-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 22 03:05:35 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 22 Sep 2014 13:05:35 +0300
Subject: [PATCH 1/3] ath10k: print wmi version info
In-Reply-To: <1411046721-20510-2-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 18 Sep 2014 15:25:19 +0200")
References: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>
 <1411046721-20510-2-git-send-email-michal.kazior@tieto.com>
Message-ID: <87fvfkm0ls.fsf@kamboji.qca.qualcomm.com>

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

> HTT version is already printed so print WMI
> version as well for consistency.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
> ---
>  drivers/net/wireless/ath/ath10k/debug.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
> index 3756feb..f1e5916 100644
> --- a/drivers/net/wireless/ath/ath10k/debug.c
> +++ b/drivers/net/wireless/ath/ath10k/debug.c
> @@ -126,14 +126,18 @@ EXPORT_SYMBOL(ath10k_info);
>  
>  void ath10k_print_driver_info(struct ath10k *ar)
>  {
> -	ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
> +	ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d\n",

Heh, I have been thinking about to add something similar.

But if in the future we add the u32 FW IE for WMI version I would like
to print that as well. I guess we could do that with "%d/%d.%d.%d.%d",
the %d being the u32. The idea here being that both version numbers are
good to know.

But of course for now the above is good, just thinking aloud here.

-- 
Kalle Valo


From michal.kazior at tieto.com  Mon Sep 22 03:33:39 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 22 Sep 2014 12:33:39 +0200
Subject: [PATCH 6/9] ath10k: deduplicate wmi service ready logic
In-Reply-To: <87oau8m1hg.fsf@kamboji.qca.qualcomm.com>
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
 <1411046487-19544-7-git-send-email-michal.kazior@tieto.com>
 <87a95wngzt.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQmsVqvGgu_fUqKGqhEKXV7E_w0KdcH_GFoPhAvyjtVdDA@mail.gmail.com>
 <87oau8m1hg.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQmNx2BaJB5b0irmZUi14xAhBeAtVZAcQU_K=M6QnZXHHQ@mail.gmail.com>

On 22 September 2014 11:46, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
[...]
> Like discussed in IRC, you don't need to resent the whole patchset just
> because of this. I have now folded the patch below onto your patch in
> ath-next-test, please review:
>
> https://github.com/kvalo/ath/commit/1d13ab4a3bdfd342ed8fbead859de398b379435c

Looks good. Thanks!


Micha?


From kvalo at qca.qualcomm.com  Mon Sep 22 03:52:05 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 22 Sep 2014 13:52:05 +0300
Subject: [PATCH 2/3] ath10k: dump hex bytes with dev string prefix
In-Reply-To: <1411046721-20510-3-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 18 Sep 2014 15:25:20 +0200")
References: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>
 <1411046721-20510-3-git-send-email-michal.kazior@tieto.com>
Message-ID: <877g0wlyga.fsf@kamboji.qca.qualcomm.com>

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

> This makes it easier to debug hex dumps on systems
> with more than a single ath10k device.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

[...]

> -		print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
> +		for (ptr = buf; (ptr - buf) < len; ptr += 16) {
> +			linebuflen = 0;
> +			if (prefix)
> +				linebuflen += scnprintf(linebuf + linebuflen,
> +							sizeof(linebuf) -
> +							linebuflen,
> +							"%s", prefix);
> +			linebuflen += scnprintf(linebuf + linebuflen,
> +						sizeof(linebuf) - linebuflen,
> +						"%08x: ",
> +						(unsigned int)(ptr - buf));
> +			hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
> +					   linebuf + linebuflen,
> +					   sizeof(linebuf) - linebuflen, true);
> +			dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
> +		}

Would it be possible to simplify this to one scnprintf()? Something
like:

linebuflen += scnprintf(linebuf + linebuflen,
			sizeof(linebuf) - linebuflen,
			"%s%08x: ",
                        prefix ? prefix : "",
			(unsigned int)(ptr - buf));

-- 
Kalle Valo


From michal.kazior at tieto.com  Mon Sep 22 05:03:48 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 22 Sep 2014 14:03:48 +0200
Subject: [PATCH 2/3] ath10k: dump hex bytes with dev string prefix
In-Reply-To: <877g0wlyga.fsf@kamboji.qca.qualcomm.com>
References: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>
 <1411046721-20510-3-git-send-email-michal.kazior@tieto.com>
 <877g0wlyga.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQm1_X992b_fMokcpuuqooQFThHpQoAEe4cjzOu7P3CV1A@mail.gmail.com>

On 22 September 2014 12:52, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
>
>> This makes it easier to debug hex dumps on systems
>> with more than a single ath10k device.
>>
>> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
>
> [...]
>
>> -             print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
>> +             for (ptr = buf; (ptr - buf) < len; ptr += 16) {
>> +                     linebuflen = 0;
>> +                     if (prefix)
>> +                             linebuflen += scnprintf(linebuf + linebuflen,
>> +                                                     sizeof(linebuf) -
>> +                                                     linebuflen,
>> +                                                     "%s", prefix);
>> +                     linebuflen += scnprintf(linebuf + linebuflen,
>> +                                             sizeof(linebuf) - linebuflen,
>> +                                             "%08x: ",
>> +                                             (unsigned int)(ptr - buf));
>> +                     hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
>> +                                        linebuf + linebuflen,
>> +                                        sizeof(linebuf) - linebuflen, true);
>> +                     dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
>> +             }
>
> Would it be possible to simplify this to one scnprintf()? Something
> like:
>
> linebuflen += scnprintf(linebuf + linebuflen,
>                         sizeof(linebuf) - linebuflen,
>                         "%s%08x: ",
>                         prefix ? prefix : "",
>                         (unsigned int)(ptr - buf));

It should be fine. You want me to re-send it?


Micha?


From kvalo at qca.qualcomm.com  Mon Sep 22 05:07:35 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 22 Sep 2014 15:07:35 +0300
Subject: [PATCH 2/3] ath10k: dump hex bytes with dev string prefix
In-Reply-To: <CA+BoTQm1_X992b_fMokcpuuqooQFThHpQoAEe4cjzOu7P3CV1A@mail.gmail.com>
 (Michal Kazior's message of "Mon, 22 Sep 2014 14:03:48 +0200")
References: <1411046721-20510-1-git-send-email-michal.kazior@tieto.com>
 <1411046721-20510-3-git-send-email-michal.kazior@tieto.com>
 <877g0wlyga.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQm1_X992b_fMokcpuuqooQFThHpQoAEe4cjzOu7P3CV1A@mail.gmail.com>
Message-ID: <8738bjn9iw.fsf@kamboji.qca.qualcomm.com>

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

> On 22 September 2014 12:52, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> Michal Kazior <michal.kazior at tieto.com> writes:
>>
>>> -             print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
>>> +             for (ptr = buf; (ptr - buf) < len; ptr += 16) {
>>> +                     linebuflen = 0;
>>> +                     if (prefix)
>>> +                             linebuflen += scnprintf(linebuf + linebuflen,
>>> +                                                     sizeof(linebuf) -
>>> +                                                     linebuflen,
>>> +                                                     "%s", prefix);
>>> +                     linebuflen += scnprintf(linebuf + linebuflen,
>>> +                                             sizeof(linebuf) - linebuflen,
>>> +                                             "%08x: ",
>>> +                                             (unsigned int)(ptr - buf));
>>> +                     hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
>>> +                                        linebuf + linebuflen,
>>> +                                        sizeof(linebuf) - linebuflen, true);
>>> +                     dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
>>> +             }
>>
>> Would it be possible to simplify this to one scnprintf()? Something
>> like:
>>
>> linebuflen += scnprintf(linebuf + linebuflen,
>>                         sizeof(linebuf) - linebuflen,
>>                         "%s%08x: ",
>>                         prefix ? prefix : "",
>>                         (unsigned int)(ptr - buf));
>
> It should be fine. You want me to re-send it?

Yes, that would be good. I don't feel comfortable editing patches with
logic changes like this.

-- 
Kalle Valo


From joe at perches.com  Mon Sep 22 10:35:34 2014
From: joe at perches.com (Joe Perches)
Date: Mon, 22 Sep 2014 10:35:34 -0700
Subject: [PATCH] ath: change logging functions to return void
Message-ID: <1411407334.2952.46.camel@joe-AO725>

The return values are not used by callers of these functions
so change the functions to return void.

Other miscellanea:

o add __printf verification to wil6210 logging functions
  No format/argument mismatches found

Signed-off-by: Joe Perches <joe at perches.com>
---
This change is associated to a desire to eventually
change printk to return void.

 drivers/net/wireless/ath/ath10k/debug.c    | 18 +++++-------------
 drivers/net/wireless/ath/ath10k/debug.h    |  6 +++---
 drivers/net/wireless/ath/ath6kl/common.h   |  2 +-
 drivers/net/wireless/ath/ath6kl/debug.c    | 28 ++++++++--------------------
 drivers/net/wireless/ath/ath6kl/debug.h    | 13 ++++++-------
 drivers/net/wireless/ath/wil6210/debug.c   | 14 ++++----------
 drivers/net/wireless/ath/wil6210/wil6210.h |  7 +++++--
 7 files changed, 32 insertions(+), 56 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index f3f0a80..29eb2aa 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -106,21 +106,18 @@ struct ath10k_dump_file_data {
 	u8 data[0];
 } __packed;
 
-int ath10k_info(struct ath10k *ar, const char *fmt, ...)
+void ath10k_info(struct ath10k *ar, const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
-	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	ret = dev_info(ar->dev, "%pV", &vaf);
+	dev_info(ar->dev, "%pV", &vaf);
 	trace_ath10k_log_info(&vaf);
 	va_end(args);
-
-	return ret;
 }
 EXPORT_SYMBOL(ath10k_info);
 
@@ -142,25 +139,22 @@ void ath10k_print_driver_info(struct ath10k *ar)
 }
 EXPORT_SYMBOL(ath10k_print_driver_info);
 
-int ath10k_err(struct ath10k *ar, const char *fmt, ...)
+void ath10k_err(struct ath10k *ar, const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
-	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	ret = dev_err(ar->dev, "%pV", &vaf);
+	dev_err(ar->dev, "%pV", &vaf);
 	trace_ath10k_log_err(&vaf);
 	va_end(args);
-
-	return ret;
 }
 EXPORT_SYMBOL(ath10k_err);
 
-int ath10k_warn(struct ath10k *ar, const char *fmt, ...)
+void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
@@ -173,8 +167,6 @@ int ath10k_warn(struct ath10k *ar, const char *fmt, ...)
 	trace_ath10k_log_warn(&vaf);
 
 	va_end(args);
-
-	return 0;
 }
 EXPORT_SYMBOL(ath10k_warn);
 
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 5674653..a4d35e4 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -39,9 +39,9 @@ enum ath10k_debug_mask {
 
 extern unsigned int ath10k_debug_mask;
 
-__printf(2, 3) int ath10k_info(struct ath10k *ar, const char *fmt, ...);
-__printf(2, 3) int ath10k_err(struct ath10k *ar, const char *fmt, ...);
-__printf(2, 3) int ath10k_warn(struct ath10k *ar, const char *fmt, ...);
+__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
+__printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...);
+__printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...);
 void ath10k_print_driver_info(struct ath10k *ar);
 
 #ifdef CONFIG_ATH10K_DEBUGFS
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h
index 05debf7..4f82e86 100644
--- a/drivers/net/wireless/ath/ath6kl/common.h
+++ b/drivers/net/wireless/ath/ath6kl/common.h
@@ -22,7 +22,7 @@
 
 #define ATH6KL_MAX_IE			256
 
-__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...);
+__printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...);
 
 /*
  * Reflects the version of binary interface exposed by ATH6KL target
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index 55c4064..81ba48d 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -37,76 +37,64 @@ struct ath6kl_fwlog_slot {
 
 #define ATH6KL_FWLOG_VALID_MASK 0x1ffff
 
-int ath6kl_printk(const char *level, const char *fmt, ...)
+void ath6kl_printk(const char *level, const char *fmt, ...)
 {
 	struct va_format vaf;
 	va_list args;
-	int rtn;
 
 	va_start(args, fmt);
 
 	vaf.fmt = fmt;
 	vaf.va = &args;
 
-	rtn = printk("%sath6kl: %pV", level, &vaf);
+	printk("%sath6kl: %pV", level, &vaf);
 
 	va_end(args);
-
-	return rtn;
 }
 EXPORT_SYMBOL(ath6kl_printk);
 
-int ath6kl_info(const char *fmt, ...)
+void ath6kl_info(const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
-	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	ret = ath6kl_printk(KERN_INFO, "%pV", &vaf);
+	ath6kl_printk(KERN_INFO, "%pV", &vaf);
 	trace_ath6kl_log_info(&vaf);
 	va_end(args);
-
-	return ret;
 }
 EXPORT_SYMBOL(ath6kl_info);
 
-int ath6kl_err(const char *fmt, ...)
+void ath6kl_err(const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
-	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	ret = ath6kl_printk(KERN_ERR, "%pV", &vaf);
+	ath6kl_printk(KERN_ERR, "%pV", &vaf);
 	trace_ath6kl_log_err(&vaf);
 	va_end(args);
-
-	return ret;
 }
 EXPORT_SYMBOL(ath6kl_err);
 
-int ath6kl_warn(const char *fmt, ...)
+void ath6kl_warn(const char *fmt, ...)
 {
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
-	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf);
+	ath6kl_printk(KERN_WARNING, "%pV", &vaf);
 	trace_ath6kl_log_warn(&vaf);
 	va_end(args);
-
-	return ret;
 }
 EXPORT_SYMBOL(ath6kl_warn);
 
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index e194c10d..19106ed 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -50,10 +50,10 @@ enum ATH6K_DEBUG_MASK {
 };
 
 extern unsigned int debug_mask;
-__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...);
-__printf(1, 2) int ath6kl_info(const char *fmt, ...);
-__printf(1, 2) int ath6kl_err(const char *fmt, ...);
-__printf(1, 2) int ath6kl_warn(const char *fmt, ...);
+__printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...);
+__printf(1, 2) void ath6kl_info(const char *fmt, ...);
+__printf(1, 2) void ath6kl_err(const char *fmt, ...);
+__printf(1, 2) void ath6kl_warn(const char *fmt, ...);
 
 enum ath6kl_war {
 	ATH6KL_WAR_INVALID_RATE,
@@ -81,10 +81,9 @@ int ath6kl_debug_init_fs(struct ath6kl *ar);
 void ath6kl_debug_cleanup(struct ath6kl *ar);
 
 #else
-static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
-			     const char *fmt, ...)
+static inline void ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
+			      const char *fmt, ...)
 {
-	return 0;
 }
 
 static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
diff --git a/drivers/net/wireless/ath/wil6210/debug.c b/drivers/net/wireless/ath/wil6210/debug.c
index 9eeabf4..7a925ac 100644
--- a/drivers/net/wireless/ath/wil6210/debug.c
+++ b/drivers/net/wireless/ath/wil6210/debug.c
@@ -17,40 +17,34 @@
 #include "wil6210.h"
 #include "trace.h"
 
-int wil_err(struct wil6210_priv *wil, const char *fmt, ...)
+void wil_err(struct wil6210_priv *wil, const char *fmt, ...)
 {
 	struct net_device *ndev = wil_to_ndev(wil);
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
-	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	ret = netdev_err(ndev, "%pV", &vaf);
+	netdev_err(ndev, "%pV", &vaf);
 	trace_wil6210_log_err(&vaf);
 	va_end(args);
-
-	return ret;
 }
 
-int wil_info(struct wil6210_priv *wil, const char *fmt, ...)
+void wil_info(struct wil6210_priv *wil, const char *fmt, ...)
 {
 	struct net_device *ndev = wil_to_ndev(wil);
 	struct va_format vaf = {
 		.fmt = fmt,
 	};
 	va_list args;
-	int ret;
 
 	va_start(args, fmt);
 	vaf.va = &args;
-	ret = netdev_info(ndev, "%pV", &vaf);
+	netdev_info(ndev, "%pV", &vaf);
 	trace_wil6210_log_info(&vaf);
 	va_end(args);
-
-	return ret;
 }
 
 int wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...)
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 133eeb8..d13fa53 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -451,9 +451,12 @@ struct wil6210_priv {
 #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr))
 #define wil_to_pcie_dev(i) (&i->pdev->dev)
 
+__printf(2, 3)
 int wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...);
-int wil_err(struct wil6210_priv *wil, const char *fmt, ...);
-int wil_info(struct wil6210_priv *wil, const char *fmt, ...);
+__printf(2, 3)
+void wil_err(struct wil6210_priv *wil, const char *fmt, ...);
+__printf(2, 3)
+void wil_info(struct wil6210_priv *wil, const char *fmt, ...);
 #define wil_dbg(wil, fmt, arg...) do { \
 	netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \
 	wil_dbg_trace(wil, fmt, ##arg); \




From greearb at candelatech.com  Mon Sep 22 10:42:56 2014
From: greearb at candelatech.com (Ben Greear)
Date: Mon, 22 Sep 2014 10:42:56 -0700
Subject: Using host's rate-ctrl in ath10k?
Message-ID: <54205FA0.5000802@candelatech.com>

Has anyone looked into what it would take to use standard host OS's
rate control (minstrel_ht) with ath10k?

I suspect the ath10k rate control logic in the firmware is
a bit dodgy, and it would be nice to use something with wider
testing such as minstrel_ht...

Thanks,
Ben

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



From kathy.giori at gmail.com  Mon Sep 22 12:26:28 2014
From: kathy.giori at gmail.com (Kathy Giori)
Date: Mon, 22 Sep 2014 12:26:28 -0700
Subject: Dusseldorf: LPC special session on ath10k
Message-ID: <CAMowtuPU=nnz9wGeJsKJEN1XFK3=6m3ddmW22fuPownr2ZLPGA@mail.gmail.com>

Hey there ath10k enthusiasts,

The afternoon prior to the Linux wireless summit that John Linville
and Johannes Berg are hosting:
http://www.linuxplumbersconf.org/2014/ocw/events/LPC2014/tracks/339

we've reserved a conference room to focus on ath10k topics of
interest. If you have specific items you'd like to see addressed,
please let me (or Kalle Valo) know in advance.

The mini ath10k summit will be held in the "VIP-SH" sponsor meeting
room that is located on the 2nd floor of the CCD. Apparently there
will be signage onsite to guide you to the room. We have the room
reserved from 1-5pm Wednesday, October 15. And we might want to carry
on the conversations into the evening over dinner or whatever -- so
let me know if you are interested in that part as well. Hoping to see
you there!

kathy


From dave.taht at gmail.com  Mon Sep 22 12:41:12 2014
From: dave.taht at gmail.com (Dave Taht)
Date: Mon, 22 Sep 2014 12:41:12 -0700
Subject: Dusseldorf: LPC special session on ath10k
In-Reply-To: <CAMowtuPU=nnz9wGeJsKJEN1XFK3=6m3ddmW22fuPownr2ZLPGA@mail.gmail.com>
References: <CAMowtuPU=nnz9wGeJsKJEN1XFK3=6m3ddmW22fuPownr2ZLPGA@mail.gmail.com>
Message-ID: <CAA93jw5Aw_edkMPBEUxR3FZ_GFQ8hQ1C+rsK7dURb+n3Kjm1-g@mail.gmail.com>

On Mon, Sep 22, 2014 at 12:26 PM, Kathy Giori <kathy.giori at gmail.com> wrote:
> Hey there ath10k enthusiasts,
>
> The afternoon prior to the Linux wireless summit that John Linville
> and Johannes Berg are hosting:
> http://www.linuxplumbersconf.org/2014/ocw/events/LPC2014/tracks/339
>
> we've reserved a conference room to focus on ath10k topics of
> interest. If you have specific items you'd like to see addressed,
> please let me (or Kalle Valo) know in advance.
>
> The mini ath10k summit will be held in the "VIP-SH" sponsor meeting
> room that is located on the 2nd floor of the CCD. Apparently there
> will be signage onsite to guide you to the room. We have the room
> reserved from 1-5pm Wednesday, October 15. And we might want to carry
> on the conversations into the evening over dinner or whatever -- so
> let me know if you are interested in that part as well. Hoping to see
> you there!

I won't be there, but I hope progress is made. Last week I had a chance
to give a short talk at the ieee plenary, and a longer presentation in front of
the ieee 802.11 wng meeting in athens, greece, about some of the problems
we are seeing in the 802.11* world, and some possible solutions.

I don't know if that preso is available outside the ieee reflector, the
slides are at:

http://snapon.lab.bufferbloat.net/~d/ieee802.11-sept-17-2014/11-14-1265-00-0wng-More-on-Bufferbloat.pdf

Of most relevance are slides 23-34.

I was pleased to see various "latency" requirements get added to the 802.11ax
documents and testing plans the next day.


-- 
Dave T?ht

https://www.bufferbloat.net/projects/make-wifi-fast


From greearb at candelatech.com  Mon Sep 22 13:54:05 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Mon, 22 Sep 2014 13:54:05 -0700
Subject: [PATCH 2/2] ath10k: apply chainmask settings to vdev on creation.
In-Reply-To: <1411419245-25799-1-git-send-email-greearb@candelatech.com>
References: <1411419245-25799-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411419245-25799-2-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

It appears it takes more than just setting the
hardware's chainmask to make things work well.  Without
this patch, a vdev would only use 1x1 rates when chainmask
was set to 0x3.

Setting the 'nss' (number of spatial streams) on the vdev
helps the firmware's rate-control algorithm work properly.

Tested on CT firmware, but probably this works (and
is required) on normal firmware.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 4dc5a40..855c71c 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2767,6 +2767,17 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
 	return ret;
 }
 
+static u32 get_nss_from_chainmask(u16 chain_mask)
+{
+	if ((chain_mask & 0x15) == 0x15)
+		return 4;
+	else if ((chain_mask & 0x7) == 0x7)
+		return 3;
+	else if ((chain_mask & 0x3) == 0x3)
+		return 2;
+	return 1;
+}
+
 /*
  * TODO:
  * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
@@ -2868,6 +2879,19 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 		goto err_vdev_delete;
 	}
 
+	if (ar->cfg_tx_chainmask) {
+		u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
+		vdev_param = ar->wmi.vdev_param->nss;
+		ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+						nss);
+		if (ret) {
+			ath10k_warn(ar, "failed to set vdev %i chainmask 0x%x, nss %i: %d\n",
+				    arvif->vdev_id, ar->cfg_tx_chainmask, nss,
+				    ret);
+			goto err_vdev_delete;
+		}
+	}
+
 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
 		ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr);
 		if (ret) {
-- 
1.7.11.7



From greearb at candelatech.com  Mon Sep 22 13:54:04 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Mon, 22 Sep 2014 13:54:04 -0700
Subject: [PATCH 1/2] ath10k:  make firmware text debug messages more verbose.
Message-ID: <1411419245-25799-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

There are not many of these messages producted by the
firmware, but they are generally fairly useful, so print
them at info level.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/wmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index cd60940..6be62ac 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2050,7 +2050,7 @@ static void ath10k_wmi_event_debug_print(struct ath10k *ar,
 	/* the last byte is always reserved for the null character */
 	buf[i] = '\0';
 
-	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug print '%s'\n", buf);
+	ath10k_info(ar, "wmi event debug print '%s'\n", buf);
 }
 
 static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb)
-- 
1.7.11.7



From greearb at candelatech.com  Mon Sep 22 16:00:20 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Mon, 22 Sep 2014 16:00:20 -0700
Subject: [PATCH] ath10k:  use configured nss instead of max nss.
Message-ID: <1411426820-4047-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

When re-associating a station, the nss was set back to
maximum value even if user had configured small number
of tx chains.  So, pay attention to user's config in
this case as well.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 855c71c..c5d31cc 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4086,6 +4086,10 @@ ath10k_default_bitrate_mask(struct ath10k *ar,
 	u32 legacy = 0x00ff;
 	u8 ht = 0xff, i;
 	u16 vht = 0x3ff;
+	u16 nrf = ar->num_rf_chains;
+
+	if (ar->cfg_tx_chainmask)
+		nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
 
 	switch (band) {
 	case IEEE80211_BAND_2GHZ:
@@ -4101,11 +4105,11 @@ ath10k_default_bitrate_mask(struct ath10k *ar,
 	if (mask->control[band].legacy != legacy)
 		return false;
 
-	for (i = 0; i < ar->num_rf_chains; i++)
+	for (i = 0; i < nrf; i++)
 		if (mask->control[band].ht_mcs[i] != ht)
 			return false;
 
-	for (i = 0; i < ar->num_rf_chains; i++)
+	for (i = 0; i < nrf; i++)
 		if (mask->control[band].vht_mcs[i] != vht)
 			return false;
 
@@ -4356,6 +4360,9 @@ static int ath10k_set_bitrate_mask(struct ieee80211_hw *hw,
 	u8 fixed_nss = ar->num_rf_chains;
 	u8 force_sgi;
 
+	if (ar->cfg_tx_chainmask)
+		fixed_nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
+
 	force_sgi = mask->control[band].gi;
 	if (force_sgi == NL80211_TXRATE_FORCE_LGI)
 		return -EINVAL;
-- 
1.7.11.7



From greearb at candelatech.com  Mon Sep 22 17:20:42 2014
From: greearb at candelatech.com (Ben Greear)
Date: Mon, 22 Sep 2014 17:20:42 -0700
Subject: Rate ctrl problem with 2x2 station.
Message-ID: <5420BCDA.5010701@candelatech.com>

While testing the previously posted patches that fix up the
transmit rate for 3x3 NICs configured for 2x2 chainmask, I
noticed that an ath10k configured as 3x3 AP will use only
1x1 rates when transmitting to a 2x2 station.

>From debugging so far, it appears the root cause is that
the method ath10k_peer_assoc_h_ht in mac.c is passed an
sta with rx_nss set to 3, when in fact the station *should*
be showing up as 2x2.

Possibly station system is still messed up some how...

Thanks,
Ben

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



From kvalo at qca.qualcomm.com  Mon Sep 22 21:20:53 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 07:20:53 +0300
Subject: [PATCH] ath: change logging functions to return void
In-Reply-To: <1411407334.2952.46.camel@joe-AO725> (Joe Perches's message of
 "Mon, 22 Sep 2014 10:35:34 -0700")
References: <1411407334.2952.46.camel@joe-AO725>
Message-ID: <874mvzj7bu.fsf@kamboji.qca.qualcomm.com>

Joe Perches <joe at perches.com> writes:

> The return values are not used by callers of these functions
> so change the functions to return void.
>
> Other miscellanea:
>
> o add __printf verification to wil6210 logging functions
>   No format/argument mismatches found
>
> Signed-off-by: Joe Perches <joe at perches.com>
> ---
> This change is associated to a desire to eventually
> change printk to return void.
>
>  drivers/net/wireless/ath/ath10k/debug.c    | 18 +++++-------------
>  drivers/net/wireless/ath/ath10k/debug.h    |  6 +++---
>  drivers/net/wireless/ath/ath6kl/common.h   |  2 +-
>  drivers/net/wireless/ath/ath6kl/debug.c    | 28 ++++++++--------------------
>  drivers/net/wireless/ath/ath6kl/debug.h    | 13 ++++++-------

For ath6kl and ath10k:

Acked-by: Kalle Valo <kvalo at qca.qualcomm.com>

>  drivers/net/wireless/ath/wil6210/debug.c   | 14 ++++----------
>  drivers/net/wireless/ath/wil6210/wil6210.h |  7 +++++--
>  7 files changed, 32 insertions(+), 56 deletions(-)

John, as this patch also contains a wil6210 change how do you want to
handle this?

-- 
Kalle Valo


From michal.kazior at tieto.com  Tue Sep 23 00:17:35 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 09:17:35 +0200
Subject: Using host's rate-ctrl in ath10k?
In-Reply-To: <54205FA0.5000802@candelatech.com>
References: <54205FA0.5000802@candelatech.com>
Message-ID: <CA+BoTQ=wwCbfFqdQqgYfu9RTLiuot-bNh3mNN0c3R=1R_FUTzQ@mail.gmail.com>

On 22 September 2014 19:42, Ben Greear <greearb at candelatech.com> wrote:
> Has anyone looked into what it would take to use standard host OS's
> rate control (minstrel_ht) with ath10k?
>
> I suspect the ath10k rate control logic in the firmware is
> a bit dodgy, and it would be nice to use something with wider
> testing such as minstrel_ht...

Correct me if I'm wrong but that would require tx completions to
include tx retry information and a way to setup tx retries.

I recall there's a WMI command to control tx retries in 10.1 but I
think the WMI service bitmap doesn't indicate it as enabled (at least
in official firmware binaries) so I guess it's just a no-op now.
There's also HTT pktlog which is able to deliver tx descriptors to the
host but these aren't public.


Micha?


From michal.kazior at tieto.com  Tue Sep 23 01:22:51 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 10:22:51 +0200
Subject: [PATCH v2 0/3] ath10k: debug improvements
Message-ID: <1411460574-5424-1-git-send-email-michal.kazior@tieto.com>

Hi,

This adds extra prints and information for
debugging purposes.


v2:
 * merge scnprintfs

Michal Kazior (3):
  ath10k: print wmi version info
  ath10k: dump hex bytes with dev string prefix
  ath10k: add debug dump for pci rx

 drivers/net/wireless/ath/ath10k/debug.c | 25 ++++++++++++++++++++++---
 drivers/net/wireless/ath/ath10k/pci.c   |  6 ++++++
 2 files changed, 28 insertions(+), 3 deletions(-)

-- 
1.8.5.3



From michal.kazior at tieto.com  Tue Sep 23 01:22:52 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 10:22:52 +0200
Subject: [PATCH v2 1/3] ath10k: print wmi version info
In-Reply-To: <1411460574-5424-1-git-send-email-michal.kazior@tieto.com>
References: <1411460574-5424-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411460574-5424-2-git-send-email-michal.kazior@tieto.com>

HTT version is already printed so print WMI
version as well for consistency.

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

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 3756feb..f1e5916 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -126,14 +126,18 @@ EXPORT_SYMBOL(ath10k_info);
 
 void ath10k_print_driver_info(struct ath10k *ar)
 {
-	ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
+	ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d\n",
 		    ar->hw_params.name,
 		    ar->target_version,
 		    ar->chip_id,
 		    ar->hw->wiphy->fw_version,
 		    ar->fw_api,
 		    ar->htt.target_version_major,
-		    ar->htt.target_version_minor);
+		    ar->htt.target_version_minor,
+		    ar->fw_version_major,
+		    ar->fw_version_minor,
+		    ar->fw_version_release,
+		    ar->fw_version_build);
 	ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
 		    config_enabled(CONFIG_ATH10K_DEBUG),
 		    config_enabled(CONFIG_ATH10K_DEBUGFS),
-- 
1.8.5.3



From michal.kazior at tieto.com  Tue Sep 23 01:22:53 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 10:22:53 +0200
Subject: [PATCH v2 2/3] ath10k: dump hex bytes with dev string prefix
In-Reply-To: <1411460574-5424-1-git-send-email-michal.kazior@tieto.com>
References: <1411460574-5424-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411460574-5424-3-git-send-email-michal.kazior@tieto.com>

This makes it easier to debug hex dumps on systems
with more than a single ath10k device.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---

Notes:
    v2:
     * merge 2 scnprintfs into 1 [Kalle]

 drivers/net/wireless/ath/ath10k/debug.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index f1e5916..1110f0f 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1264,11 +1264,26 @@ void ath10k_dbg_dump(struct ath10k *ar,
 		     const char *msg, const char *prefix,
 		     const void *buf, size_t len)
 {
+	char linebuf[256];
+	unsigned int linebuflen;
+	const void *ptr;
+
 	if (ath10k_debug_mask & mask) {
 		if (msg)
 			ath10k_dbg(ar, mask, "%s\n", msg);
 
-		print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
+		for (ptr = buf; (ptr - buf) < len; ptr += 16) {
+			linebuflen = 0;
+			linebuflen += scnprintf(linebuf + linebuflen,
+						sizeof(linebuf) - linebuflen,
+						"%s%08x: ",
+						(prefix ? prefix : ""),
+						(unsigned int)(ptr - buf));
+			hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
+					   linebuf + linebuflen,
+					   sizeof(linebuf) - linebuflen, true);
+			dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
+		}
 	}
 
 	/* tracing code doesn't like null strings :/ */
-- 
1.8.5.3



From michal.kazior at tieto.com  Tue Sep 23 01:22:54 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 10:22:54 +0200
Subject: [PATCH v2 3/3] ath10k: add debug dump for pci rx
In-Reply-To: <1411460574-5424-1-git-send-email-michal.kazior@tieto.com>
References: <1411460574-5424-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411460574-5424-4-git-send-email-michal.kazior@tieto.com>

This makes it easier to debug the device-target
communication at a very low level.

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

diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 59e0ea8..8319d83 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -861,6 +861,12 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
 		}
 
 		skb_put(skb, nbytes);
+
+		ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n",
+			   ce_state->id, skb->len);
+		ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ",
+				skb->data, skb->len);
+
 		cb->rx_completion(ar, skb, pipe_info->pipe_num);
 	}
 
-- 
1.8.5.3



From michal.kazior at tieto.com  Tue Sep 23 01:43:54 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 10:43:54 +0200
Subject: Rate ctrl problem with 2x2 station.
In-Reply-To: <5420BCDA.5010701@candelatech.com>
References: <5420BCDA.5010701@candelatech.com>
Message-ID: <CA+BoTQ=21YJ=WC+T51J_15m1qtDKhWSVP0cYw-P6R-tEmLoLNQ@mail.gmail.com>

On 23 September 2014 02:20, Ben Greear <greearb at candelatech.com> wrote:
> While testing the previously posted patches that fix up the
> transmit rate for 3x3 NICs configured for 2x2 chainmask, I
> noticed that an ath10k configured as 3x3 AP will use only
> 1x1 rates when transmitting to a 2x2 station.
>
> From debugging so far, it appears the root cause is that
> the method ath10k_peer_assoc_h_ht in mac.c is passed an
> sta with rx_nss set to 3, when in fact the station *should*
> be showing up as 2x2.
>
> Possibly station system is still messed up some how...

Am I understanding correctly that the 2x2 station is just a 3x3 ath10k
device with "tx/rx_chainmask" being set to 0x3? If so then rx_nss
being 3 is okay because setting chainmasks does not affect advertised
capabilities and association sequences remain unaffected.

The problem might be  the hw rate control is unable to deal with the
strange chainmask setup. Did you try 10.2? I've been told it contains
some rate control improvements.


Micha?


From michal.kazior at tieto.com  Tue Sep 23 01:53:42 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 10:53:42 +0200
Subject: [PATCH 2/2] ath10k: apply chainmask settings to vdev on creation.
In-Reply-To: <1411419245-25799-2-git-send-email-greearb@candelatech.com>
References: <1411419245-25799-1-git-send-email-greearb@candelatech.com>
 <1411419245-25799-2-git-send-email-greearb@candelatech.com>
Message-ID: <CA+BoTQ=NtS3hOD+gVZ2whx+K2xsKrZUWBPUa=gfKxaNFcoTHEw@mail.gmail.com>

On 22 September 2014 22:54,  <greearb at candelatech.com> wrote:
> From: Ben Greear <greearb at candelatech.com>
>
> It appears it takes more than just setting the
> hardware's chainmask to make things work well.  Without
> this patch, a vdev would only use 1x1 rates when chainmask
> was set to 0x3.
>
> Setting the 'nss' (number of spatial streams) on the vdev
> helps the firmware's rate-control algorithm work properly.
>
> Tested on CT firmware, but probably this works (and
> is required) on normal firmware.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>
> ---
>  drivers/net/wireless/ath/ath10k/mac.c | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
> index 4dc5a40..855c71c 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -2767,6 +2767,17 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
>         return ret;
>  }
>
> +static u32 get_nss_from_chainmask(u16 chain_mask)
> +{
> +       if ((chain_mask & 0x15) == 0x15)
> +               return 4;
> +       else if ((chain_mask & 0x7) == 0x7)
> +               return 3;
> +       else if ((chain_mask & 0x3) == 0x3)
> +               return 2;
> +       return 1;
> +}

So a chainmask of `BIT(0) | BIT(2) = 0x5` is nss=1?

Why not just use `hweight16()` kernel macro? Or do we want to forbid
odd chainmasks (in which case additional checks need to be added as
well)?


> +
>  /*
>   * TODO:
>   * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
> @@ -2868,6 +2879,19 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
>                 goto err_vdev_delete;
>         }
>
> +       if (ar->cfg_tx_chainmask) {
> +               u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
> +               vdev_param = ar->wmi.vdev_param->nss;
> +               ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
> +                                               nss);
> +               if (ret) {
> +                       ath10k_warn(ar, "failed to set vdev %i chainmask 0x%x, nss %i: %d\n",
> +                                   arvif->vdev_id, ar->cfg_tx_chainmask, nss,
> +                                   ret);
> +                       goto err_vdev_delete;
> +               }
> +       }
> +

If this is required won't setting up peer nss (after association) be
necessary as well?

Shouldn't the vdev nss param be set in __ath10k_set_antenna() as well?
What about peer nss (assuming it's necessary to update it) in that
case?


Micha?


From michal.kazior at tieto.com  Tue Sep 23 01:59:40 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 10:59:40 +0200
Subject: [PATCH] ath10k: use configured nss instead of max nss.
In-Reply-To: <1411426820-4047-1-git-send-email-greearb@candelatech.com>
References: <1411426820-4047-1-git-send-email-greearb@candelatech.com>
Message-ID: <CA+BoTQn9sECMNZsxQpB4i3wHPxfVL+LXq9=2GBd-opH6+9TD=A@mail.gmail.com>

On 23 September 2014 01:00,  <greearb at candelatech.com> wrote:
> From: Ben Greear <greearb at candelatech.com>
>
> When re-associating a station, the nss was set back to
> maximum value even if user had configured small number
> of tx chains.  So, pay attention to user's config in
> this case as well.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>
> ---
>  drivers/net/wireless/ath/ath10k/mac.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
> index 855c71c..c5d31cc 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -4086,6 +4086,10 @@ ath10k_default_bitrate_mask(struct ath10k *ar,
>         u32 legacy = 0x00ff;
>         u8 ht = 0xff, i;
>         u16 vht = 0x3ff;
> +       u16 nrf = ar->num_rf_chains;
> +
> +       if (ar->cfg_tx_chainmask)
> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);

Oh, so you do update the peer nss value here.

I think it might be a good idea to convey the limitation of tx/rx
chainmask to the user: you can't change the tx/rx chainmask on the fly
easily (while connected/have associated stations). Or do you plan to
schedule peer reassoc in __ath10k_set_antenna() in a follow up
patch(es) later?


Micha?


From michal.kazior at tieto.com  Tue Sep 23 02:04:21 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 11:04:21 +0200
Subject: [PATCH 1/3] ath10k: use 64-bit vdev map.
In-Reply-To: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
References: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
Message-ID: <CA+BoTQmMuwz54ExCCBvScfUAzSHmGhGvDi-Xb268eAfsNyUxfQ@mail.gmail.com>

On 19 September 2014 20:04,  <greearb at candelatech.com> wrote:
> From: Ben Greear <greearb at candelatech.com>
>
> This can allow more than 32 stations to be supported
> without over-running the bitmap.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>
> ---
>  drivers/net/wireless/ath/ath10k/core.c |  4 ++--
>  drivers/net/wireless/ath/ath10k/core.h |  2 +-
>  drivers/net/wireless/ath/ath10k/mac.c  | 21 ++++++++++++---------
>  3 files changed, 15 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
> index cee18c8..37e3166 100644
[...]
> @@ -2772,9 +2772,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
>                 ret = -EBUSY;
>                 goto err;
>         }
> -       bit = ffs(ar->free_vdev_map);
> +       bit = __ffs64(ar->free_vdev_map);
>
> -       arvif->vdev_id = bit - 1;
> +       ath10k_warn(ar, "Creating vdev id: %i  map: %llu\n",
> +                   bit, ar->free_vdev_map);

Shouldn't this be a ath10k_dbg()? It probably makes sense to print the
map as hex instead of a decimal too. Prints should be lower case and
debug needs a prefix, i.e.

 "mac create vdev %i map %llx"


Micha?


From michal.kazior at tieto.com  Tue Sep 23 02:12:23 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 11:12:23 +0200
Subject: [PATCH 2/2] ath10k: support ethtool stats.
In-Reply-To: <1411150659-10998-2-git-send-email-greearb@candelatech.com>
References: <1411150659-10998-1-git-send-email-greearb@candelatech.com>
 <1411150659-10998-2-git-send-email-greearb@candelatech.com>
Message-ID: <CA+BoTQkxQK82rtQZXi1tyn5g=AsGQGDyKf1bF7jpuDPFq1Okbw@mail.gmail.com>

On 19 September 2014 20:17,  <greearb at candelatech.com> wrote:
> From: Ben Greear <greearb at candelatech.com>
>
> Add support for reading firmware stats through the ethtool
> API.  This may be easier for applications to manipulate
> compared to parsing a text based debugfs file.

You also seem to be adding fw crash and reset countes. It's probably
worth including this in the commit log.


> +#ifdef CONFIG_ATH10K_DEBUGFS
> +/* TODO:  Would be nice to always support ethtool stats, would need to
> + * move the stats storage out of ath10k_debug, or always have ath10k_debug
> + * struct available..
> + */

I was actually wondering about moving ath10k_target_stats out of debug
while doing some cleanups. Your patch can actually justify this kind
of move.


[...]
> +       data[i++] = fw_stats->hw_reaped; /* ppdu reaped */
> +       data[i++] = 0; /* tx bytes */
> +       data[i++] = fw_stats->htt_mpdus;
> +       data[i++] = 0; /* rx bytes */
> +       data[i++] = fw_stats->ch_noise_floor;
> +       data[i++] = fw_stats->cycle_count;
> +       data[i++] = fw_stats->phy_err_count;
> +       data[i++] = fw_stats->rts_bad;
> +       data[i++] = fw_stats->rts_good;
> +       data[i++] = fw_stats->chan_tx_power;
> +       data[i++] = fw_stats->fcs_bad;
> +       data[i++] = fw_stats->no_beacons;
> +       data[i++] = fw_stats->mpdu_enqued;
> +       data[i++] = fw_stats->msdu_enqued;
> +       data[i++] = fw_stats->wmm_drop;
> +       data[i++] = fw_stats->local_enqued;
> +       data[i++] = fw_stats->local_freed;
> +       data[i++] = fw_stats->hw_queued;
> +       data[i++] = fw_stats->hw_reaped;
> +       data[i++] = fw_stats->underrun;
> +       data[i++] = fw_stats->tx_abort;
> +       data[i++] = fw_stats->mpdus_requed;
> +       data[i++] = fw_stats->tx_ko;
> +       data[i++] = fw_stats->data_rc;
> +       data[i++] = fw_stats->sw_retry_failure;
> +       data[i++] = fw_stats->illgl_rate_phy_err;
> +       data[i++] = fw_stats->pdev_cont_xretry;
> +       data[i++] = fw_stats->pdev_tx_timeout;
> +       data[i++] = fw_stats->txop_ovf;
> +       data[i++] = fw_stats->pdev_resets;
> +       data[i++] = fw_stats->mid_ppdu_route_change;
> +       data[i++] = fw_stats->status_rcvd;
> +       data[i++] = fw_stats->r0_frags;
> +       data[i++] = fw_stats->r1_frags;
> +       data[i++] = fw_stats->r2_frags;
> +       data[i++] = fw_stats->r3_frags;
> +       data[i++] = fw_stats->htt_msdus;
> +       data[i++] = fw_stats->htt_mpdus;
> +       data[i++] = fw_stats->loc_msdus;
> +       data[i++] = fw_stats->loc_mpdus;
> +       data[i++] = fw_stats->phy_errs;
> +       data[i++] = fw_stats->phy_err_drop;
> +       data[i++] = fw_stats->mpdu_errs;
> +       data[i++] = ar->fw_crash_counter;
> +       data[i++] = ar->fw_warm_reset_counter;
> +       data[i++] = ar->fw_cold_reset_counter;

fw_stats should be protected by ar->data_lock. See
ath10k_read_fw_stats(). You could in theory report inconsistent stats.


> --- a/drivers/net/wireless/ath/ath10k/pci.c
> +++ b/drivers/net/wireless/ath/ath10k/pci.c
> @@ -986,6 +986,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
>
>         spin_lock_bh(&ar->data_lock);
>
> +       ar->fw_crash_counter++;
> +
>         crash_data = ath10k_debug_get_new_fw_crash_data(ar);
>
>         if (crash_data)
> @@ -1671,6 +1673,7 @@ static int ath10k_pci_warm_reset(struct ath10k *ar)
>         u32 val;
>
>         ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
> +       ar->fw_warm_reset_counter++;
>
>         /* debug */
>         val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
> @@ -2286,6 +2289,7 @@ static int ath10k_pci_cold_reset(struct ath10k *ar)
>         u32 val;
>
>         ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
> +       ar->fw_cold_reset_counter++;
>
>         /* Put Target, including PCIe, into RESET. */
>         val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS);

Unprotected? I guess it's not terribly wrong since this is the only
place it updates the values.


Micha?


From michal.kazior at tieto.com  Tue Sep 23 02:16:17 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 23 Sep 2014 11:16:17 +0200
Subject: [PATCH] ath10k: request firmware flush in ath10k_flush.
In-Reply-To: <1411151304-31544-1-git-send-email-greearb@candelatech.com>
References: <1411151304-31544-1-git-send-email-greearb@candelatech.com>
Message-ID: <CA+BoTQm1rZO+yBbYxihpgEvR1cGZWS4Pr0AP+KMODcG4jpd_jQ@mail.gmail.com>

On 19 September 2014 20:28,  <greearb at candelatech.com> wrote:
[...]
> +       /* If we are CT firmware, ask it to flush all tids on all peers on
> +        * all vdevs.  Normal firmware will just crash if you do this.
> +        */
> +       if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
> +               ath10k_wmi_peer_flush(ar, 0xFFFFFFFF, peer_addr, 0xFFFFFFFF);

I recall you've explained this some time ago, but can you refresh my
memory, please? Is this any different from iterating over all peers
and flushing each? Or does your firmware do so extra magic that is
impossible to do with normal firmware commands?


Micha?


From kvalo at qca.qualcomm.com  Tue Sep 23 02:26:58 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 12:26:58 +0300
Subject: Pull request: ath 20140923
Message-ID: <8738big00t.fsf@kamboji.qca.qualcomm.com>

Hi John,

a new pull request just with ath10k changes this time. Changelog below
and please let me know if there are any problems.

----------------------------------------------------------------------

The only new feature is testmode support from me. Ben added a new method
to crash the firmware with an assert for debug purposes. As usual, we
have lots of smaller fixes from Michal. Matteo fixed a Kconfig
dependency with debugfs. I fixed some warnings recently added to
checkpatch.

----------------------------------------------------------------------


The following changes since commit 6a5d088a923854569e20eac4f3f569926d5911ec:

  carl9170: tx: Replace rcu_assign_pointer() with RCU_INIT_POINTER() (2014-08-28 14:50:13 -0400)

are available in the git repository at:

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

for you to fetch changes up to b25f32cb02155d68c690255ba846796a1c248fd3:

  ath10k: use ether_addr_copy() (2014-09-18 10:47:03 +0300)

----------------------------------------------------------------
Ben Greear (1):
      ath10k: support firmware crash-by-assert

Kalle Valo (12):
      ath10k: make ath10k_wmi_cmd_send() public
      ath10k: add testmode
      ath10k: fix parenthesis alignment warning in ath10k_htt_rx_alloc()
      ath10k: fix checkpatch warnings about parenthesis alignment
      ath10k: fix use of multiple blank lines
      ath10k: fix missing a blank line after declarations
      ath10k: fix space after a cast style errors
      ath10k: don't use return on void functions
      ath10k: else is not generally useful after a break or return
      ath10k: miscellaneous checkpatch fixes
      ath10k: reformat help text in ath10k_read_simulate_fw_crash()
      ath10k: use ether_addr_copy()

Matteo Croce (1):
      ath10k: ATH10K_DEBUGFS depends on DEBUG_FS

Michal Kazior (11):
      ath10k: re-enable interrupts properly in hw recovery
      ath10k: fix num_legacy_stations tracking
      ath10k: kill tasklets after free_irq
      ath10k: fix monitor start/stop sequences
      ath10k: stop monitor vdev for sta assoc
      ath10k: remove diag_*_access functions
      ath10k: add device/driver strings to tracepoints
      ath10k: don't access tx_info while overwriting it
      ath10k: move fw_crash_dump allocation
      ath10k: use proper service bitmap size
      ath10k: fix debugfs_create_dir() checking

 drivers/net/wireless/ath/ath10k/Kconfig      |    2 +-
 drivers/net/wireless/ath/ath10k/Makefile     |    1 +
 drivers/net/wireless/ath/ath10k/bmi.h        |    1 -
 drivers/net/wireless/ath/ath10k/ce.c         |    2 -
 drivers/net/wireless/ath/ath10k/ce.h         |   13 +-
 drivers/net/wireless/ath/ath10k/core.c       |  106 +++++--
 drivers/net/wireless/ath/ath10k/core.h       |   25 +-
 drivers/net/wireless/ath/ath10k/debug.c      |  102 ++++---
 drivers/net/wireless/ath/ath10k/debug.h      |   12 +
 drivers/net/wireless/ath/ath10k/hif.h        |    1 -
 drivers/net/wireless/ath/ath10k/htc.c        |   10 +-
 drivers/net/wireless/ath/ath10k/htc.h        |    1 -
 drivers/net/wireless/ath/ath10k/htt.c        |    2 +-
 drivers/net/wireless/ath/ath10k/htt.h        |    3 +-
 drivers/net/wireless/ath/ath10k/htt_rx.c     |   54 ++--
 drivers/net/wireless/ath/ath10k/htt_tx.c     |    2 -
 drivers/net/wireless/ath/ath10k/hw.h         |    2 +
 drivers/net/wireless/ath/ath10k/mac.c        |  192 ++++++-------
 drivers/net/wireless/ath/ath10k/pci.c        |  183 ++++--------
 drivers/net/wireless/ath/ath10k/rx_desc.h    |    1 -
 drivers/net/wireless/ath/ath10k/targaddrs.h  |    1 -
 drivers/net/wireless/ath/ath10k/testmode.c   |  382 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/testmode.h   |   46 ++++
 drivers/net/wireless/ath/ath10k/testmode_i.h |   70 +++++
 drivers/net/wireless/ath/ath10k/trace.h      |  105 +++++--
 drivers/net/wireless/ath/ath10k/txrx.c       |    2 +-
 drivers/net/wireless/ath/ath10k/wmi.c        |  103 ++++---
 drivers/net/wireless/ath/ath10k/wmi.h        |   33 +--
 28 files changed, 1017 insertions(+), 440 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode.c
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode.h
 create mode 100644 drivers/net/wireless/ath/ath10k/testmode_i.h

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep 23 02:29:46 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 12:29:46 +0300
Subject: [PATCH] ath10k: workaround fw beaconing bug
In-Reply-To: <1411023358-5703-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 18 Sep 2014 08:55:58 +0200")
References: <1411023358-5703-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87y4taelbp.fsf@kamboji.qca.qualcomm.com>

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

> Some firmware revisions don't wait for beacon tx
> completion before sending another SWBA event. This
> could lead to hardware using old (freed) beacon
> data in some cases, e.g. tx credit starvation
> combined with missed TBTT. This is very very rare.
>
> On non-IOMMU-enabled hosts this could be a
> possible security issue because hw could beacon
> some random data on the air.  On IOMMU-enabled
> hosts DMAR faults would occur in most cases and
> target device would crash.
>
> Since there are no beacon tx completions (implicit
> nor explicit) propagated to host the only
> workaround for this is to allocate a DMA-coherent
> buffer for a lifetime of a vif and use it for all
> beacon tx commands. Worst case for this approach
> is some beacons may become corrupted, e.g. garbled
> IEs or out-of-date TIM bitmap.
>
> Keep the original beacon-related code as-is in
> case future firmware revisions solve this problem
> so that the old path can be easily re-enabled with
> a fw_feature flag.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep 23 02:33:04 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 12:33:04 +0300
Subject: [PATCH 0/9] ath10k: mostly cleanups
In-Reply-To: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 18 Sep 2014 15:21:18 +0200")
References: <1411046487-19544-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87tx3yel67.fsf@kamboji.qca.qualcomm.com>

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

> Here's a bunch of clean up patches for WMI and a
> single fix. I'm including the fix in this patchset
> because one of the clean up patches depends on it.
>
>
> Michal Kazior (9):
>   ath10k: fix tx/rx chainmask init
>   ath10k: remove unused pdev_set_channel command
>   ath10k: deduplicate wmi_channel code
>   ath10k: deduplicate host mem chunk code
>   ath10k: relocate wmi attach/deatch functions
>   ath10k: deduplicate wmi service ready logic
>   ath10k: clean up phyerr code
>   ath10k: unify wmi event function names
>   ath10k: re-work scan start command building

Thanks, all nine patches applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep 23 05:54:31 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 15:54:31 +0300
Subject: [PATCH 1/3] ath10k:  use 64-bit vdev map.
In-Reply-To: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
 (greearb@candelatech.com's message of "Fri, 19 Sep 2014 11:04:48
 -0700")
References: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
Message-ID: <878ulaebug.fsf@kamboji.qca.qualcomm.com>

greearb at candelatech.com writes:

> From: Ben Greear <greearb at candelatech.com>
>
> This can allow more than 32 stations to be supported
> without over-running the bitmap.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>

[...]

> -	ar->monitor_vdev_id = bit - 1;
> +	ar->monitor_vdev_id = bit;

[...]

> -	arvif->vdev_id = bit - 1;
> +	ath10k_warn(ar, "Creating vdev id: %i  map: %llu\n",
> +		    bit, ar->free_vdev_map);
> +
> +	arvif->vdev_id = bit;

Why remove the "- 1"? Are you sure that's not going to break any
assumptions somewhere?

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep 23 05:59:06 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 15:59:06 +0300
Subject: [PATCH 3/3] ath10k: support 32+ stations.
In-Reply-To: <1411149890-12618-3-git-send-email-greearb@candelatech.com>
 (greearb@candelatech.com's message of "Fri, 19 Sep 2014 11:04:50
 -0700")
References: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
 <1411149890-12618-3-git-send-email-greearb@candelatech.com>
Message-ID: <874mvyebmt.fsf@kamboji.qca.qualcomm.com>

greearb at candelatech.com writes:

> From: Ben Greear <greearb at candelatech.com>
>
> Support up to 32 stations when using CT firmware.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>

[...]

> -	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
> +	if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
> +		ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS_CT) - 1;
> +	else if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
>  		ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
>  	else
>  		ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;

[...]

> +/* Over-rides for Candela Technologies firmware */
> +#define TARGET_10X_NUM_VDEVS_CT			32
> +#define TARGET_10X_NUM_PEERS_CT			(32 + (TARGET_10X_NUM_VDEVS_CT))
> +#define TARGET_10X_AST_SKID_LIMIT_CT		(TARGET_10X_NUM_PEERS_CT * TARGET_10X_NUM_PEER_AST)

[...]

> +		if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
> +			max_num_peers = TARGET_10X_NUM_PEERS_CT - 1;

Like I said before, this hardcoding of values using feature bits is not
going to work in the long run. It's better that these values come
directly from FW IEs as integers, that gives us a lot more flexibility
between firmware versions.

That's why I'll drop patches 2 and 3.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep 23 06:13:28 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 16:13:28 +0300
Subject: [PATCH 1/2] ath10k: make firmware text debug messages more
 verbose.
In-Reply-To: <1411419245-25799-1-git-send-email-greearb@candelatech.com>
 (greearb@candelatech.com's message of "Mon, 22 Sep 2014 13:54:04
 -0700")
References: <1411419245-25799-1-git-send-email-greearb@candelatech.com>
Message-ID: <87zjdqcwef.fsf@kamboji.qca.qualcomm.com>

greearb at candelatech.com writes:

> From: Ben Greear <greearb at candelatech.com>
>
> There are not many of these messages producted by the
> firmware, but they are generally fairly useful, so print
> them at info level.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>
> ---
>  drivers/net/wireless/ath/ath10k/wmi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
> index cd60940..6be62ac 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi.c
> +++ b/drivers/net/wireless/ath/ath10k/wmi.c
> @@ -2050,7 +2050,7 @@ static void ath10k_wmi_event_debug_print(struct ath10k *ar,
>  	/* the last byte is always reserved for the null character */
>  	buf[i] = '\0';
>  
> -	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug print '%s'\n", buf);
> +	ath10k_info(ar, "wmi event debug print '%s'\n", buf);

This does not bring any extra value to normal users, it's only useful to
firmware engineers. That's why it needs to stay as a debug message.
Maybe we should add a new debug level just for these events, would that
help?

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Tue Sep 23 06:23:57 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 16:23:57 +0300
Subject: [PATCH 1/2] ath10k: save firmware stacks upon firmware crash
In-Reply-To: <1409934849-23078-1-git-send-email-greearb@candelatech.com>
 (greearb@candelatech.com's message of "Fri, 5 Sep 2014 09:34:08
 -0700")
References: <1409934849-23078-1-git-send-email-greearb@candelatech.com>
Message-ID: <87vboecvwy.fsf@kamboji.qca.qualcomm.com>

greearb at candelatech.com writes:

> 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>
> Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>

Like we talked on IRC, I think it's better to take a dump of the whole
DRAM and find all the info during postprocessing in user space. I just
consider it too much work to investigate firmware internals from ath10k
as the internals can change between firmware versions. In user space
that's a lot easier to manage.

Of course downside is the increased memory usage, but if that becomes a
problem there are ways to solve that. For example, adding a module
parameter with bitmask for individually enabling enum
ath10k_fw_crash_dump_type is first which comes to my mind.

I have patches ready for the DRAM thing, but I have some issues which I
found during testing. I'll post the patches soon as I have solved the
issues, but don't know how long that will take.

-- 
Kalle Valo


From qca_vkondrat at qca.qualcomm.com  Tue Sep 23 07:05:34 2014
From: qca_vkondrat at qca.qualcomm.com (Vladimir Kondratiev)
Date: Tue, 23 Sep 2014 17:05:34 +0300
Subject: [PATCH] ath: change logging functions to return void
In-Reply-To: <1411407334.2952.46.camel@joe-AO725>
References: <1411407334.2952.46.camel@joe-AO725>
Message-ID: <27145768.oo3Xk8YHvr@lx-wigig-72>

On Monday, September 22, 2014 10:35:34 AM Joe Perches wrote:
> Other miscellanea:
> 
> o add __printf verification to wil6210 logging functions
>   No format/argument mismatches found
> 
> Signed-off-by: Joe Perches <joe at perches.com>
> 

For wil6210:

Acked-by: Vladimir Kondratiev <qca_vkondrat at qca.qualcomm.com>




From greearb at candelatech.com  Tue Sep 23 07:19:54 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 23 Sep 2014 07:19:54 -0700
Subject: [PATCH] ath10k: request firmware flush in ath10k_flush.
In-Reply-To: <CA+BoTQm1rZO+yBbYxihpgEvR1cGZWS4Pr0AP+KMODcG4jpd_jQ@mail.gmail.com>
References: <1411151304-31544-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQm1rZO+yBbYxihpgEvR1cGZWS4Pr0AP+KMODcG4jpd_jQ@mail.gmail.com>
Message-ID: <5421818A.9040501@candelatech.com>



On 09/23/2014 02:16 AM, Michal Kazior wrote:
> On 19 September 2014 20:28,  <greearb at candelatech.com> wrote:
> [...]
>> +       /* If we are CT firmware, ask it to flush all tids on all peers on
>> +        * all vdevs.  Normal firmware will just crash if you do this.
>> +        */
>> +       if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
>> +               ath10k_wmi_peer_flush(ar, 0xFFFFFFFF, peer_addr, 0xFFFFFFFF);
>
> I recall you've explained this some time ago, but can you refresh my
> memory, please? Is this any different from iterating over all peers
> and flushing each? Or does your firmware do so extra magic that is
> impossible to do with normal firmware commands?

My firmware does that iteration internally.

You could probably do that in the driver, but it would be a lot
of messages (for all vdevs, all peers, all tids)...
I was not sure if there were limits to the number
of commands you should attempt during the flush...

Thanks,
Ben


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


From greearb at candelatech.com  Tue Sep 23 07:21:59 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 23 Sep 2014 07:21:59 -0700
Subject: [PATCH 1/3] ath10k:  use 64-bit vdev map.
In-Reply-To: <878ulaebug.fsf@kamboji.qca.qualcomm.com>
References: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
 <878ulaebug.fsf@kamboji.qca.qualcomm.com>
Message-ID: <54218207.6050907@candelatech.com>



On 09/23/2014 05:54 AM, Kalle Valo wrote:
> greearb at candelatech.com writes:
>
>> From: Ben Greear <greearb at candelatech.com>
>>
>> This can allow more than 32 stations to be supported
>> without over-running the bitmap.
>>
>> Signed-off-by: Ben Greear <greearb at candelatech.com>
>
> [...]
>
>> -	ar->monitor_vdev_id = bit - 1;
>> +	ar->monitor_vdev_id = bit;
>
> [...]
>
>> -	arvif->vdev_id = bit - 1;
>> +	ath10k_warn(ar, "Creating vdev id: %i  map: %llu\n",
>> +		    bit, ar->free_vdev_map);
>> +
>> +	arvif->vdev_id = bit;
>
> Why remove the "- 1"? Are you sure that's not going to break any
> assumptions somewhere?

I have been testing this patch in one form or another for almost a year
and have not noticed any problems with it.

The return value is subtly different when using the 64-bit version,
so you don't need the -1.

Thanks,
Ben

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


From kvalo at qca.qualcomm.com  Tue Sep 23 07:32:19 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 17:32:19 +0300
Subject: [PATCH v2 1/3] ath10k: don't enable interrupts for the diagnostic
 window
Message-ID: <20140923143219.23585.34114.stgit@potku.adurom.net>

The diagnostic window (CE7) uses polling and is not initiliased to retrieve
interrupts so disable interrupts altogether for CE7. Otherwise ath10k crashes
when using the diagnostic window while the firmware is running due to NULL
dereference and polling reads timeout.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/ce.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 101cadb6e4ba..03b3a2c441fe 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -817,7 +817,9 @@ void ath10k_ce_enable_interrupts(struct ath10k *ar)
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	int ce_id;
 
-	for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
+	/* Skip the last copy engine, CE7 the diagnostic window, as that
+	 * uses polling and isn't initialized for interrupts. */
+	for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++)
 		ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]);
 }
 



From kvalo at qca.qualcomm.com  Tue Sep 23 07:32:26 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 17:32:26 +0300
Subject: [PATCH v2 2/3] ath10k: add diag_read() to hif ops
In-Reply-To: <20140923143219.23585.34114.stgit@potku.adurom.net>
References: <20140923143219.23585.34114.stgit@potku.adurom.net>
Message-ID: <20140923143226.23585.50550.stgit@potku.adurom.net>

diag_read() is used for reading from firmware memory via the diagnose window.
First user will be cal_data debugfs file.

To serialise diagnostic window access and make it safe to use while firmware is
running take ce_lock both in ath10k_pci_diag_write_mem() and
ath10k_pci_diag_read_mem(). Because of that all the CE calls had to be changed
to _nolock variants.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/ce.c  |   22 +++++++-------
 drivers/net/wireless/ath/ath10k/ce.h  |   13 ++++++++
 drivers/net/wireless/ath/ath10k/hif.h |   10 ++++++
 drivers/net/wireless/ath/ath10k/pci.c |   51 +++++++++++++++++++++------------
 4 files changed, 67 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 03b3a2c441fe..2f895bead693 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -443,12 +443,12 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
  * Guts of ath10k_ce_completed_recv_next.
  * The caller takes responsibility for any necessary locking.
  */
-static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
-						void **per_transfer_contextp,
-						u32 *bufferp,
-						unsigned int *nbytesp,
-						unsigned int *transfer_idp,
-						unsigned int *flagsp)
+int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
+					 void **per_transfer_contextp,
+					 u32 *bufferp,
+					 unsigned int *nbytesp,
+					 unsigned int *transfer_idp,
+					 unsigned int *flagsp)
 {
 	struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
 	unsigned int nentries_mask = dest_ring->nentries_mask;
@@ -576,11 +576,11 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
  * Guts of ath10k_ce_completed_send_next.
  * The caller takes responsibility for any necessary locking.
  */
-static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
-						void **per_transfer_contextp,
-						u32 *bufferp,
-						unsigned int *nbytesp,
-						unsigned int *transfer_idp)
+int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
+					 void **per_transfer_contextp,
+					 u32 *bufferp,
+					 unsigned int *nbytesp,
+					 unsigned int *transfer_idp)
 {
 	struct ath10k_ce_ring *src_ring = ce_state->src_ring;
 	u32 ctrl_addr = ce_state->ctrl_addr;
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index 329b7340fa72..608262ab964e 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -192,6 +192,12 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
 				  unsigned int *nbytesp,
 				  unsigned int *transfer_idp);
 
+int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
+					 void **per_transfer_contextp,
+					 u32 *bufferp,
+					 unsigned int *nbytesp,
+					 unsigned int *transfer_idp);
+
 /*==================CE Engine Initialization=======================*/
 
 int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
@@ -213,6 +219,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
 			       void **per_transfer_contextp,
 			       u32 *bufferp);
 
+int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
+					 void **per_transfer_contextp,
+					 u32 *bufferp,
+					 unsigned int *nbytesp,
+					 unsigned int *transfer_idp,
+					 unsigned int *flagsp);
+
 /*
  * Support clean shutdown by allowing the caller to cancel
  * pending sends.  Target DMA must be stopped before using
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 62323fea27e1..30301f5b6051 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -43,6 +43,10 @@ struct ath10k_hif_ops {
 	int (*tx_sg)(struct ath10k *ar, u8 pipe_id,
 		     struct ath10k_hif_sg_item *items, int n_items);
 
+	/* read firmware memory through the diagnose interface */
+	int (*diag_read)(struct ath10k *ar, u32 address, void *buf,
+			 size_t buf_len);
+
 	/*
 	 * API to handle HIF-specific BMI message exchanges, this API is
 	 * synchronous and only allowed to be called from a context that
@@ -98,6 +102,12 @@ static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
 	return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items);
 }
 
+static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
+				       size_t buf_len)
+{
+	return ar->hif.ops->diag_read(ar, address, buf, buf_len);
+}
+
 static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
 					      void *request, u32 request_len,
 					      void *response, u32 *response_len)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 59e0ea83be50..0784b48b04ce 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -485,6 +485,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 	void *data_buf = NULL;
 	int i;
 
+	spin_lock_bh(&ar_pci->ce_lock);
+
 	ce_diag = ar_pci->ce_diag;
 
 	/*
@@ -511,7 +513,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 		nbytes = min_t(unsigned int, remaining_bytes,
 			       DIAG_TRANSFER_LIMIT);
 
-		ret = ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
+		ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
 		if (ret != 0)
 			goto done;
 
@@ -527,15 +529,15 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 		address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem,
 						     address);
 
-		ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0,
-				     0);
+		ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0,
+					    0);
 		if (ret)
 			goto done;
 
 		i = 0;
-		while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
-						     &completed_nbytes,
-						     &id) != 0) {
+		while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
+							    &completed_nbytes,
+							    &id) != 0) {
 			mdelay(1);
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
 				ret = -EBUSY;
@@ -554,9 +556,9 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 		}
 
 		i = 0;
-		while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
-						     &completed_nbytes,
-						     &id, &flags) != 0) {
+		while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
+							    &completed_nbytes,
+							    &id, &flags) != 0) {
 			mdelay(1);
 
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -591,6 +593,8 @@ done:
 		dma_free_coherent(ar->dev, orig_nbytes, data_buf,
 				  ce_data_base);
 
+	spin_unlock_bh(&ar_pci->ce_lock);
+
 	return ret;
 }
 
@@ -648,6 +652,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 	dma_addr_t ce_data_base = 0;
 	int i;
 
+	spin_lock_bh(&ar_pci->ce_lock);
+
 	ce_diag = ar_pci->ce_diag;
 
 	/*
@@ -688,7 +694,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 		nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT);
 
 		/* Set up to receive directly into Target(!) address */
-		ret = ath10k_ce_rx_post_buf(ce_diag, NULL, address);
+		ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address);
 		if (ret != 0)
 			goto done;
 
@@ -696,15 +702,15 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 		 * Request CE to send caller-supplied data that
 		 * was copied to bounce buffer to Target(!) address.
 		 */
-		ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data,
-				     nbytes, 0, 0);
+		ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data,
+					    nbytes, 0, 0);
 		if (ret != 0)
 			goto done;
 
 		i = 0;
-		while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
-						     &completed_nbytes,
-						     &id) != 0) {
+		while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
+							    &completed_nbytes,
+							    &id) != 0) {
 			mdelay(1);
 
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -724,9 +730,9 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 		}
 
 		i = 0;
-		while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
-						     &completed_nbytes,
-						     &id, &flags) != 0) {
+		while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
+							    &completed_nbytes,
+							    &id, &flags) != 0) {
 			mdelay(1);
 
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -760,6 +766,8 @@ done:
 		ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n",
 			    address, ret);
 
+	spin_unlock_bh(&ar_pci->ce_lock);
+
 	return ret;
 }
 
@@ -936,6 +944,12 @@ err:
 	return err;
 }
 
+static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
+				    size_t buf_len)
+{
+	return ath10k_pci_diag_read_mem(ar, address, buf, buf_len);
+}
+
 static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
 {
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -1921,6 +1935,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
 
 static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
 	.tx_sg			= ath10k_pci_hif_tx_sg,
+	.diag_read		= ath10k_pci_hif_diag_read,
 	.exchange_bmi_msg	= ath10k_pci_hif_exchange_bmi_msg,
 	.start			= ath10k_pci_hif_start,
 	.stop			= ath10k_pci_hif_stop,



From kvalo at qca.qualcomm.com  Tue Sep 23 07:32:34 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 17:32:34 +0300
Subject: [PATCH v2 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <20140923143219.23585.34114.stgit@potku.adurom.net>
References: <20140923143219.23585.34114.stgit@potku.adurom.net>
Message-ID: <20140923143234.23585.2139.stgit@potku.adurom.net>

Provide calibration data used by the firmware to user space via a debugfs file.
This makes it easier to debug calibration related problems.

Example:

sudo cp /sys/kernel/debug/ieee80211/phy0/ath10k/cal_data 1.cal

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/debug.c |   81 +++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hw.h    |    2 +
 2 files changed, 83 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 101c6f9cf2a8..426341480262 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -23,6 +23,7 @@
 
 #include "core.h"
 #include "debug.h"
+#include "hif.h"
 
 /* ms */
 #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
@@ -1037,6 +1038,83 @@ static const struct file_operations fops_fw_dbglog = {
 	.llseek = default_llseek,
 };
 
+static int ath10k_cal_data_open(struct inode *inode, struct file *file)
+{
+	struct ath10k *ar = inode->i_private;
+	void *buf;
+	u32 hi_addr;
+	__le32 addr;
+	int ret;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_ON &&
+	    ar->state != ATH10K_STATE_UTF) {
+		ret = -ENETDOWN;
+		goto err;
+	}
+
+	buf = vmalloc(QCA988X_CAL_DATA_LEN);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
+
+	ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
+	if (ret) {
+		ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
+		goto err_vfree;
+	}
+
+	ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
+				   QCA988X_CAL_DATA_LEN);
+	if (ret) {
+		ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
+		goto err_vfree;
+	}
+
+	file->private_data = buf;
+
+	mutex_unlock(&ar->conf_mutex);
+
+	return 0;
+
+err_vfree:
+	vfree(buf);
+
+err:
+	mutex_unlock(&ar->conf_mutex);
+
+	return ret;
+}
+
+static ssize_t ath10k_cal_data_read(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	void *buf = file->private_data;
+
+	return simple_read_from_buffer(user_buf, count, ppos,
+				       buf, QCA988X_CAL_DATA_LEN);
+}
+
+static int ath10k_cal_data_release(struct inode *inode,
+				   struct file *file)
+{
+	vfree(file->private_data);
+
+	return 0;
+}
+
+static const struct file_operations fops_cal_data = {
+	.open = ath10k_cal_data_open,
+	.read = ath10k_cal_data_read,
+	.release = ath10k_cal_data_release,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 int ath10k_debug_start(struct ath10k *ar)
 {
 	int ret;
@@ -1210,6 +1288,9 @@ int ath10k_debug_register(struct ath10k *ar)
 	debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_fw_dbglog);
 
+	debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
+			    ar, &fops_cal_data);
+
 	if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
 		debugfs_create_file("dfs_simulate_radar", S_IWUSR,
 				    ar->debug.debugfs_phy, ar,
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 3cf5702c1e7e..006a9cbc60b2 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -43,6 +43,8 @@
 
 #define REG_DUMP_COUNT_QCA988X 60
 
+#define QCA988X_CAL_DATA_LEN		2116
+
 struct ath10k_fw_ie {
 	__le32 id;
 	__le32 len;



From kvalo at qca.qualcomm.com  Tue Sep 23 07:38:27 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 17:38:27 +0300
Subject: [PATCH v2 1/3] ath10k: don't enable interrupts for the diagnostic
 window
In-Reply-To: <20140923143219.23585.34114.stgit@potku.adurom.net> (Kalle Valo's
 message of "Tue, 23 Sep 2014 17:32:19 +0300")
References: <20140923143219.23585.34114.stgit@potku.adurom.net>
Message-ID: <87d2amcsgs.fsf@kamboji.qca.qualcomm.com>

Hi,

I forgot add --edit-cover to stg. So here's the cover letter :)

ath10k: export calibration data to user space

here's a small patchset exporting firmware calibration data to user space. This
makes it easier to debug various calibration data related problems.

Please comment.

v2:

* never unmask the diagnostic window copy engine pipe in
  ath10k_ce_enable_interrupts()

* add locking for diag_read_mem()/diag_write_mem()

-- 
Kalle Valo


From greearb at candelatech.com  Tue Sep 23 07:58:34 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 23 Sep 2014 07:58:34 -0700
Subject: [PATCH 3/3] ath10k: support 32+ stations.
In-Reply-To: <874mvyebmt.fsf@kamboji.qca.qualcomm.com>
References: <1411149890-12618-1-git-send-email-greearb@candelatech.com>
 <1411149890-12618-3-git-send-email-greearb@candelatech.com>
 <874mvyebmt.fsf@kamboji.qca.qualcomm.com>
Message-ID: <54218A9A.7090305@candelatech.com>



On 09/23/2014 05:59 AM, Kalle Valo wrote:
> greearb at candelatech.com writes:
>
>> From: Ben Greear <greearb at candelatech.com>
>>
>> Support up to 32 stations when using CT firmware.
>>
>> Signed-off-by: Ben Greear <greearb at candelatech.com>
>
> [...]
>
>> -	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
>> +	if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
>> +		ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS_CT) - 1;
>> +	else if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
>>   		ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
>>   	else
>>   		ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;
>
> [...]
>
>> +/* Over-rides for Candela Technologies firmware */
>> +#define TARGET_10X_NUM_VDEVS_CT			32
>> +#define TARGET_10X_NUM_PEERS_CT			(32 + (TARGET_10X_NUM_VDEVS_CT))
>> +#define TARGET_10X_AST_SKID_LIMIT_CT		(TARGET_10X_NUM_PEERS_CT * TARGET_10X_NUM_PEER_AST)
>
> [...]
>
>> +		if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
>> +			max_num_peers = TARGET_10X_NUM_PEERS_CT - 1;
>
> Like I said before, this hardcoding of values using feature bits is not
> going to work in the long run. It's better that these values come
> directly from FW IEs as integers, that gives us a lot more flexibility
> between firmware versions.
>
> That's why I'll drop patches 2 and 3.

Please suggest the name and definition of the IE(s) that you want for
this feature so I don't have to guess.

I also have a pending patch that supports tx status when using CT
firmware.  How would you prefer this feature be communicated to
the driver?  IE flag?

Please also understand, it will be a bad idea to force the number of
stations based on IE, but we could note upper limits and let module
parameters tune the actual stations?

Note that my patch above, for instance, decreases number of peers, but
increases vdevs.  That works well for my purposes, but others may
want more peers and less vdevs.

Thanks,
Ben

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


From linville at tuxdriver.com  Tue Sep 23 07:46:27 2014
From: linville at tuxdriver.com (John W. Linville)
Date: Tue, 23 Sep 2014 10:46:27 -0400
Subject: [PATCH] ath: change logging functions to return void
In-Reply-To: <874mvzj7bu.fsf@kamboji.qca.qualcomm.com>
References: <1411407334.2952.46.camel@joe-AO725>
 <874mvzj7bu.fsf@kamboji.qca.qualcomm.com>
Message-ID: <20140923144627.GG23806@tuxdriver.com>

On Tue, Sep 23, 2014 at 07:20:53AM +0300, Kalle Valo wrote:
> Joe Perches <joe at perches.com> writes:
> 
> > The return values are not used by callers of these functions
> > so change the functions to return void.
> >
> > Other miscellanea:
> >
> > o add __printf verification to wil6210 logging functions
> >   No format/argument mismatches found
> >
> > Signed-off-by: Joe Perches <joe at perches.com>
> > ---
> > This change is associated to a desire to eventually
> > change printk to return void.
> >
> >  drivers/net/wireless/ath/ath10k/debug.c    | 18 +++++-------------
> >  drivers/net/wireless/ath/ath10k/debug.h    |  6 +++---
> >  drivers/net/wireless/ath/ath6kl/common.h   |  2 +-
> >  drivers/net/wireless/ath/ath6kl/debug.c    | 28 ++++++++--------------------
> >  drivers/net/wireless/ath/ath6kl/debug.h    | 13 ++++++-------
> 
> For ath6kl and ath10k:
> 
> Acked-by: Kalle Valo <kvalo at qca.qualcomm.com>
> 
> >  drivers/net/wireless/ath/wil6210/debug.c   | 14 ++++----------
> >  drivers/net/wireless/ath/wil6210/wil6210.h |  7 +++++--
> >  7 files changed, 32 insertions(+), 56 deletions(-)
> 
> John, as this patch also contains a wil6210 change how do you want to
> handle this?

I had presumed that you would merge it through the ath tree, so I
deleted it...

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 greearb at candelatech.com  Tue Sep 23 08:00:57 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 23 Sep 2014 08:00:57 -0700
Subject: [PATCH 1/2] ath10k: make firmware text debug messages more
 verbose.
In-Reply-To: <87zjdqcwef.fsf@kamboji.qca.qualcomm.com>
References: <1411419245-25799-1-git-send-email-greearb@candelatech.com>
 <87zjdqcwef.fsf@kamboji.qca.qualcomm.com>
Message-ID: <54218B29.40806@candelatech.com>



On 09/23/2014 06:13 AM, Kalle Valo wrote:
> greearb at candelatech.com writes:
>
>> From: Ben Greear <greearb at candelatech.com>
>>
>> There are not many of these messages producted by the
>> firmware, but they are generally fairly useful, so print
>> them at info level.
>>
>> Signed-off-by: Ben Greear <greearb at candelatech.com>
>> ---
>>   drivers/net/wireless/ath/ath10k/wmi.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
>> index cd60940..6be62ac 100644
>> --- a/drivers/net/wireless/ath/ath10k/wmi.c
>> +++ b/drivers/net/wireless/ath/ath10k/wmi.c
>> @@ -2050,7 +2050,7 @@ static void ath10k_wmi_event_debug_print(struct ath10k *ar,
>>   	/* the last byte is always reserved for the null character */
>>   	buf[i] = '\0';
>>
>> -	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug print '%s'\n", buf);
>> +	ath10k_info(ar, "wmi event debug print '%s'\n", buf);
>
> This does not bring any extra value to normal users, it's only useful to
> firmware engineers. That's why it needs to stay as a debug message.
> Maybe we should add a new debug level just for these events, would that
> help?

It will help users trying to tune the maximum resource combinations (vdevs + peers + tx-descriptors + skid-len, etc)
because my firmware prints out remaining RAM/IRAM after booting up.

But, a separate debug flag would be fine.

Thanks,
Ben

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


From kvalo at qca.qualcomm.com  Tue Sep 23 08:17:25 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 23 Sep 2014 18:17:25 +0300
Subject: [PATCH] ath: change logging functions to return void
In-Reply-To: <20140923144627.GG23806@tuxdriver.com> (John W. Linville's
 message of "Tue, 23 Sep 2014 10:46:27 -0400")
References: <1411407334.2952.46.camel@joe-AO725>
 <874mvzj7bu.fsf@kamboji.qca.qualcomm.com>
 <20140923144627.GG23806@tuxdriver.com>
Message-ID: <878ulacqnu.fsf@kamboji.qca.qualcomm.com>

"John W. Linville" <linville at tuxdriver.com> writes:

> On Tue, Sep 23, 2014 at 07:20:53AM +0300, Kalle Valo wrote:
>> Joe Perches <joe at perches.com> writes:
>> 
>> >  drivers/net/wireless/ath/wil6210/debug.c   | 14 ++++----------
>> >  drivers/net/wireless/ath/wil6210/wil6210.h |  7 +++++--
>> >  7 files changed, 32 insertions(+), 56 deletions(-)
>> 
>> John, as this patch also contains a wil6210 change how do you want to
>> handle this?
>
> I had presumed that you would merge it through the ath tree, so I
> deleted it...

That's a clear case then, I'll take it :)

-- 
Kalle Valo


From greearb at candelatech.com  Tue Sep 23 09:02:10 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 23 Sep 2014 09:02:10 -0700
Subject: Rate ctrl problem with 2x2 station.
In-Reply-To: <CA+BoTQ=21YJ=WC+T51J_15m1qtDKhWSVP0cYw-P6R-tEmLoLNQ@mail.gmail.com>
References: <5420BCDA.5010701@candelatech.com>
 <CA+BoTQ=21YJ=WC+T51J_15m1qtDKhWSVP0cYw-P6R-tEmLoLNQ@mail.gmail.com>
Message-ID: <54219982.8020204@candelatech.com>

On 09/23/2014 01:43 AM, Michal Kazior wrote:
> On 23 September 2014 02:20, Ben Greear <greearb at candelatech.com> wrote:
>> While testing the previously posted patches that fix up the
>> transmit rate for 3x3 NICs configured for 2x2 chainmask, I
>> noticed that an ath10k configured as 3x3 AP will use only
>> 1x1 rates when transmitting to a 2x2 station.
>>
>> From debugging so far, it appears the root cause is that
>> the method ath10k_peer_assoc_h_ht in mac.c is passed an
>> sta with rx_nss set to 3, when in fact the station *should*
>> be showing up as 2x2.
>>
>> Possibly station system is still messed up some how...
> 
> Am I understanding correctly that the 2x2 station is just a 3x3 ath10k
> device with "tx/rx_chainmask" being set to 0x3? If so then rx_nss
> being 3 is okay because setting chainmasks does not affect advertised
> capabilities and association sequences remain unaffected.

I was thinking the peer's rx-nss would be what the peer (ie, station)
can receive from the AP?  If so, then it should be 2 in this case
since that is what the station is (or should be) advertising.

> The problem might be  the hw rate control is unable to deal with the
> strange chainmask setup. Did you try 10.2? I've been told it contains
> some rate control improvements.

It could easily be the hw rate control, but I will try to work around
it in the driver, as it is very likely 10.1 has same issue as my
firmware.  Certainly my 10.1 based firmware craps out if nss does
not match reality (see previously posted patches).  Looks like same
general problem on the AP side.

I have not tried 10.2, the latest snapshot I can get is from last
December, so it does not appear anyone is actively working on it,
and if it took 8 months to get into the ath10k driver, it must not be
obviously better??

I will take a look at the difference between 10.2 and 10.1 and
try to merge them into my tree when I get a chance.

Thanks,
Ben

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



From greearb at candelatech.com  Tue Sep 23 09:06:06 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 23 Sep 2014 09:06:06 -0700
Subject: Using host's rate-ctrl in ath10k?
In-Reply-To: <CA+BoTQ=wwCbfFqdQqgYfu9RTLiuot-bNh3mNN0c3R=1R_FUTzQ@mail.gmail.com>
References: <54205FA0.5000802@candelatech.com>
 <CA+BoTQ=wwCbfFqdQqgYfu9RTLiuot-bNh3mNN0c3R=1R_FUTzQ@mail.gmail.com>
Message-ID: <54219A6E.6080902@candelatech.com>

On 09/23/2014 12:17 AM, Michal Kazior wrote:
> On 22 September 2014 19:42, Ben Greear <greearb at candelatech.com> wrote:
>> Has anyone looked into what it would take to use standard host OS's
>> rate control (minstrel_ht) with ath10k?
>>
>> I suspect the ath10k rate control logic in the firmware is
>> a bit dodgy, and it would be nice to use something with wider
>> testing such as minstrel_ht...
> 
> Correct me if I'm wrong but that would require tx completions to
> include tx retry information and a way to setup tx retries.

Something like that...I have not looked in detail.  It would
require a re-compile of the firmware at least.

I just don't like that we are depending on the firmware for something
something as tricky as rate control, especially when it seems buggy.

But, I don't have time to deal with trying to move it into
the driver now, and certainly not as a patch I would have to
carry forever in my own tree.

Thanks,
Ben


> I recall there's a WMI command to control tx retries in 10.1 but I
> think the WMI service bitmap doesn't indicate it as enabled (at least
> in official firmware binaries) so I guess it's just a no-op now.
> There's also HTT pktlog which is able to deliver tx descriptors to the
> host but these aren't public.
> 
> 
> Micha?
> 
> _______________________________________________
> 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 greearb at candelatech.com  Tue Sep 23 09:48:12 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 23 Sep 2014 09:48:12 -0700
Subject: [PATCH] ath10k: use configured nss instead of max nss.
In-Reply-To: <CA+BoTQn9sECMNZsxQpB4i3wHPxfVL+LXq9=2GBd-opH6+9TD=A@mail.gmail.com>
References: <1411426820-4047-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQn9sECMNZsxQpB4i3wHPxfVL+LXq9=2GBd-opH6+9TD=A@mail.gmail.com>
Message-ID: <5421A44C.8080307@candelatech.com>

On 09/23/2014 01:59 AM, Michal Kazior wrote:
> On 23 September 2014 01:00,  <greearb at candelatech.com> wrote:
>> From: Ben Greear <greearb at candelatech.com>
>>
>> When re-associating a station, the nss was set back to
>> maximum value even if user had configured small number
>> of tx chains.  So, pay attention to user's config in
>> this case as well.
>>
>> Signed-off-by: Ben Greear <greearb at candelatech.com>
>> ---
>>  drivers/net/wireless/ath/ath10k/mac.c | 11 +++++++++--
>>  1 file changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
>> index 855c71c..c5d31cc 100644
>> --- a/drivers/net/wireless/ath/ath10k/mac.c
>> +++ b/drivers/net/wireless/ath/ath10k/mac.c
>> @@ -4086,6 +4086,10 @@ ath10k_default_bitrate_mask(struct ath10k *ar,
>>         u32 legacy = 0x00ff;
>>         u8 ht = 0xff, i;
>>         u16 vht = 0x3ff;
>> +       u16 nrf = ar->num_rf_chains;
>> +
>> +       if (ar->cfg_tx_chainmask)
>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
> 
> Oh, so you do update the peer nss value here.

Yeah, I found this was needed in further testing yesterday...

> I think it might be a good idea to convey the limitation of tx/rx
> chainmask to the user: you can't change the tx/rx chainmask on the fly
> easily (while connected/have associated stations). Or do you plan to
> schedule peer reassoc in __ath10k_set_antenna() in a follow up
> patch(es) later?

My user-space tools assume you have to re-connect (requested from user-space)
after changing the chainmask.  I was under the impression that this
is how ath9k works, though I could be wrong.

I would rather keep this requirement in user-space...

I am not sure where to document this...just a comment in the code?

Thanks,
Ben


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



From greearb at candelatech.com  Tue Sep 23 09:57:48 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 23 Sep 2014 09:57:48 -0700
Subject: [PATCH 2/2] ath10k: apply chainmask settings to vdev on creation.
In-Reply-To: <CA+BoTQ=NtS3hOD+gVZ2whx+K2xsKrZUWBPUa=gfKxaNFcoTHEw@mail.gmail.com>
References: <1411419245-25799-1-git-send-email-greearb@candelatech.com>
 <1411419245-25799-2-git-send-email-greearb@candelatech.com>
 <CA+BoTQ=NtS3hOD+gVZ2whx+K2xsKrZUWBPUa=gfKxaNFcoTHEw@mail.gmail.com>
Message-ID: <5421A68C.8090508@candelatech.com>

On 09/23/2014 01:53 AM, Michal Kazior wrote:
> On 22 September 2014 22:54,  <greearb at candelatech.com> wrote:
>> From: Ben Greear <greearb at candelatech.com>
>>
>> It appears it takes more than just setting the
>> hardware's chainmask to make things work well.  Without
>> this patch, a vdev would only use 1x1 rates when chainmask
>> was set to 0x3.
>>
>> Setting the 'nss' (number of spatial streams) on the vdev
>> helps the firmware's rate-control algorithm work properly.
>>
>> Tested on CT firmware, but probably this works (and
>> is required) on normal firmware.
>>
>> Signed-off-by: Ben Greear <greearb at candelatech.com>
>> ---
>>  drivers/net/wireless/ath/ath10k/mac.c | 24 ++++++++++++++++++++++++
>>  1 file changed, 24 insertions(+)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
>> index 4dc5a40..855c71c 100644
>> --- a/drivers/net/wireless/ath/ath10k/mac.c
>> +++ b/drivers/net/wireless/ath/ath10k/mac.c
>> @@ -2767,6 +2767,17 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
>>         return ret;
>>  }
>>
>> +static u32 get_nss_from_chainmask(u16 chain_mask)
>> +{
>> +       if ((chain_mask & 0x15) == 0x15)
>> +               return 4;
>> +       else if ((chain_mask & 0x7) == 0x7)
>> +               return 3;
>> +       else if ((chain_mask & 0x3) == 0x3)
>> +               return 2;
>> +       return 1;
>> +}
> 
> So a chainmask of `BIT(0) | BIT(2) = 0x5` is nss=1?

That is how the firmware treats it.

> Why not just use `hweight16()` kernel macro? Or do we want to forbid
> odd chainmasks (in which case additional checks need to be added as
> well)?

Even after looking at the hweight16 code I don't know what it is supposed
to do.  I think open-coding is plenty adequate.

Maybe the driver should only allow a chainmask of 1, 3, 7, (and eventually 15 when 4x4 exists),
but maybe also that can just be on the user to get it right.  It is possible that there
is some use for having a different chainmask, but it would require someone with good knowledge
of the hardware to answer that I think.

>> +       if (ar->cfg_tx_chainmask) {
>> +               u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
>> +               vdev_param = ar->wmi.vdev_param->nss;
>> +               ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
>> +                                               nss);
>> +               if (ret) {
>> +                       ath10k_warn(ar, "failed to set vdev %i chainmask 0x%x, nss %i: %d\n",
>> +                                   arvif->vdev_id, ar->cfg_tx_chainmask, nss,
>> +                                   ret);
>> +                       goto err_vdev_delete;
>> +               }
>> +       }
>> +
> 
> If this is required won't setting up peer nss (after association) be
> necessary as well?
> 
> Shouldn't the vdev nss param be set in __ath10k_set_antenna() as well?
> What about peer nss (assuming it's necessary to update it) in that
> case?

Did the second patch address all of this?  I may have missed more cases,
but at least with the second patch it seems to work for me reliably.

Thanks,
Ben


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



From greearb at candelatech.com  Tue Sep 23 11:05:49 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 23 Sep 2014 11:05:49 -0700
Subject: Possible issue with firmware crash reporting.
Message-ID: <5421B67D.8060508@candelatech.com>

This kernel is basically linux-ath from a few days ago
plus a bunch of my patches, including my versions of the firmware
BSS and stack dump patches.
Problem could be mine alone, but likely the patches Kalle
is working on would be susceptible to the same sort of problem.

I produced this by purposefully crashing the firmware during
station registration while debugging some firmware issues.

This is just FYI, but if someone cares to do similar
testing, I can build a special firmware that crashes
in the same way and make it available.


=================================
[ INFO: inconsistent lock state ]
3.17.0-rc6+ #3 Not tainted
---------------------------------
inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
swapper/2/0 [HC0[0]:SC1[1]:HE1:SE0] takes:
 (uevent_sock_mutex){+.?.+.}, at: [<ffffffff8133d402>] kobject_uevent_env+0x2b8/0x5d7
{SOFTIRQ-ON-W} state was registered at:
  [<ffffffff81111f34>] __lock_acquire+0x352/0xe48
  [<ffffffff81112ef6>] lock_acquire+0xd2/0x120
  [<ffffffff8165c77c>] mutex_lock_nested+0x4f/0x3c7
  [<ffffffff8133d402>] kobject_uevent_env+0x2b8/0x5d7
  [<ffffffff8133d72c>] kobject_uevent+0xb/0xd
  [<ffffffff8133c970>] kset_register+0x30/0x3e
  [<ffffffff81431a7a>] bus_register+0xae/0x292
  [<ffffffff81d69174>] platform_bus_init+0x29/0x41
  [<ffffffff81d69202>] driver_init+0x27/0x33
  [<ffffffff81d1e0d9>] kernel_init_freeable+0x155/0x263
  [<ffffffff8164e95a>] kernel_init+0x9/0xda
  [<ffffffff8165f0bc>] ret_from_fork+0x7c/0xb0
irq event stamp: 3059841372
hardirqs last  enabled at (3059841372): [<ffffffff810dca25>] __local_bh_enable_ip+0xaa/0xd9
hardirqs last disabled at (3059841371): [<ffffffff810dc9cd>] __local_bh_enable_ip+0x52/0xd9
softirqs last  enabled at (3059840756): [<ffffffff810dc3e6>] _local_bh_enable+0x3e/0x40
softirqs last disabled at (3059840757): [<ffffffff810dcaf9>] irq_exit+0x43/0x99

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(uevent_sock_mutex);
  <Interrupt>
    lock(uevent_sock_mutex);

 *** DEADLOCK ***

no locks held by swapper/2/0.

stack backtrace:
CPU: 2 PID: 0 Comm: swapper/2 Not tainted 3.17.0-rc6+ #3
Hardware name: To be filled by O.E.M. To be filled by O.E.M./HURONRIVER, BIOS 4.6.5 05/02/2012
 ffffffff82351ba0 ffff88021eb03ab8 ffffffff81657366 0000000000000000
 ffff880215574360 ffff88021eb03b18 ffffffff81653c50 0000000000000001
 0000000000000001 ffff880200000000 ffffffff8101bcae ffff880215574b80
Call Trace:
 <IRQ>  [<ffffffff81657366>] dump_stack+0x4e/0x71
 [<ffffffff81653c50>] print_usage_bug+0x1ec/0x1fd
 [<ffffffff8101bcae>] ? save_stack_trace+0x27/0x44
 [<ffffffff81111457>] ? check_usage_backwards+0xa0/0xa0
 [<ffffffff81111aeb>] mark_lock+0x11b/0x212
 [<ffffffff81111ebe>] __lock_acquire+0x2dc/0xe48
 [<ffffffff81113215>] ? mark_held_locks+0x54/0x76
 [<ffffffff811904f3>] ? __free_pages_ok+0xb3/0xca
 [<ffffffff811133c9>] ? trace_hardirqs_on_caller+0x192/0x1a1
 [<ffffffff81112ef6>] lock_acquire+0xd2/0x120
 [<ffffffff8133d402>] ? kobject_uevent_env+0x2b8/0x5d7
 [<ffffffff8165c77c>] mutex_lock_nested+0x4f/0x3c7
 [<ffffffff8133d402>] ? kobject_uevent_env+0x2b8/0x5d7
 [<ffffffff8133d402>] ? kobject_uevent_env+0x2b8/0x5d7
 [<ffffffff81430f16>] ? dev_uevent+0x1d4/0x274
 [<ffffffff8133c147>] ? kobject_get_path+0x8c/0xdb
 [<ffffffff8133d402>] kobject_uevent_env+0x2b8/0x5d7
 [<ffffffff811133c9>] ? trace_hardirqs_on_caller+0x192/0x1a1
 [<ffffffffa069c70f>] ath10k_pci_fw_crashed_dump+0x456/0x535 [ath10k_pci]
 [<ffffffff81006432>] ? xen_set_domain_pte+0x37/0xe1
 [<ffffffffa069c854>] ath10k_pci_tasklet+0x27/0x5a [ath10k_pci]
 [<ffffffff810dcd4d>] tasklet_action+0xcb/0xdd
 [<ffffffff810dc745>] __do_softirq+0x111/0x2a1
 [<ffffffff810dcaf9>] irq_exit+0x43/0x99
 [<ffffffff81010357>] do_IRQ+0xa7/0xc2
 [<ffffffff8165fe72>] common_interrupt+0x72/0x72
 <EOI>  [<ffffffff8110fc0f>] ? trace_hardirqs_off_caller+0x37/0xa6
 [<ffffffff81546d7d>] ? cpuidle_enter_state+0x62/0xba
 [<ffffffff81546d79>] ? cpuidle_enter_state+0x5e/0xba
 [<ffffffff81546e76>] cpuidle_enter+0x12/0x14
 [<ffffffff8110ab6c>] cpu_startup_entry+0x1b6/0x27a
 [<ffffffff81035b74>] start_secondary+0x238/0x23a
ath10k_pci 0000:04:00.0: boot hif stop
ath10k_pci 0000:04:00.0: boot warm reset
ath10k_pci 0000:04:00.0: boot host cpu intr cause: 0x00047800
ath10k_pci 0000:04:00.0: boot target cpu intr cause: 0x00005008
ath10k_pci 0000:04:00.0: boot host cpu intr cause: 0x00000000
ath10k_pci 0000:04:00.0: boot target cpu intr cause: 0x00000008
ath10k_pci 0000:04:00.0: boot target reset state: 0x00000800
ath10k_pci 0000:04:00.0: boot warm reset complete
ieee80211 wiphy1: Hardware restart was requested
ath10k_pci 0000:04:00.0: failed to start hw scan: -11

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



From greearb at candelatech.com  Tue Sep 23 14:17:16 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 14:17:16 -0700
Subject: [PATCH v2 01/10] ath10k: use 64-bit vdev map.
Message-ID: <1411507045-18973-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

This can allow more than 32 stations to be supported
without over-running the bitmap.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

v2:  Change debug message.

 drivers/net/wireless/ath/ath10k/core.c |  4 ++--
 drivers/net/wireless/ath/ath10k/core.h |  2 +-
 drivers/net/wireless/ath/ath10k/mac.c  | 21 ++++++++++++---------
 3 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index cee18c8..37e3166 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -846,9 +846,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
 		goto err_hif_stop;
 
 	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-		ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1;
+		ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
 	else
-		ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
+		ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;
 
 	INIT_LIST_HEAD(&ar->arvifs);
 
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 8a997b6..2f1d509 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -482,7 +482,7 @@ struct ath10k {
 	/* current operating channel definition */
 	struct cfg80211_chan_def chandef;
 
-	int free_vdev_map;
+	unsigned long long free_vdev_map;
 	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 a99d919..02e0a45 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -624,9 +624,9 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar)
 		return -ENOMEM;
 	}
 
-	bit = ffs(ar->free_vdev_map);
+	bit = __ffs64(ar->free_vdev_map);
 
-	ar->monitor_vdev_id = bit - 1;
+	ar->monitor_vdev_id = bit;
 
 	ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id,
 				     WMI_VDEV_TYPE_MONITOR,
@@ -637,7 +637,7 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar)
 		return ret;
 	}
 
-	ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id);
+	ar->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
 	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n",
 		   ar->monitor_vdev_id);
 
@@ -657,7 +657,7 @@ static int ath10k_monitor_vdev_delete(struct ath10k *ar)
 		return ret;
 	}
 
-	ar->free_vdev_map |= 1 << ar->monitor_vdev_id;
+	ar->free_vdev_map |= 1LL << ar->monitor_vdev_id;
 
 	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n",
 		   ar->monitor_vdev_id);
@@ -2791,9 +2791,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 		ret = -EBUSY;
 		goto err;
 	}
-	bit = ffs(ar->free_vdev_map);
+	bit = __ffs64(ar->free_vdev_map);
 
-	arvif->vdev_id = bit - 1;
+	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac create vdev %i map %llx\n",
+		   bit, ar->free_vdev_map);
+
+	arvif->vdev_id = bit;
 	arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
 
 	if (ar->p2p)
@@ -2865,7 +2868,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 		goto err;
 	}
 
-	ar->free_vdev_map &= ~(1 << arvif->vdev_id);
+	ar->free_vdev_map &= ~(1LL << arvif->vdev_id);
 	list_add(&arvif->list, &ar->arvifs);
 
 	vdev_param = ar->wmi.vdev_param->def_keyid;
@@ -2958,7 +2961,7 @@ err_peer_delete:
 
 err_vdev_delete:
 	ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
-	ar->free_vdev_map |= 1 << arvif->vdev_id;
+	ar->free_vdev_map |= 1LL << arvif->vdev_id;
 	list_del(&arvif->list);
 
 err:
@@ -2993,7 +2996,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 		ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n",
 			    arvif->vdev_id, ret);
 
-	ar->free_vdev_map |= 1 << arvif->vdev_id;
+	ar->free_vdev_map |= 1LL << arvif->vdev_id;
 	list_del(&arvif->list);
 
 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
-- 
1.7.11.7



From greearb at candelatech.com  Tue Sep 23 14:17:20 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 14:17:20 -0700
Subject: [PATCH v2 05/10] ath10k: apply chainmask settings to vdev on creation.
In-Reply-To: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411507045-18973-5-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

It appears it takes more than just setting the
hardware's chainmask to make things work well.  Without
this patch, a vdev would only use 1x1 rates when chainmask
was set to 0x3.

Setting the 'nss' (number of spatial streams) on the vdev
helps the firmware's rate-control algorithm work properly.

Tested on CT firmware, but probably this works (and
is required) on normal firmware.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

v2:  Add warning if chainmask is set to probably-invalid configuration.
  Also, from a quick test, it appears you cannot even set the chainmask
  using 'iw' when vdevs are active.

 drivers/net/wireless/ath/ath10k/mac.c | 40 +++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 4bb3ef6..e75607d 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2427,12 +2427,27 @@ static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
 	return 0;
 }
 
+static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char* dbg)
+{
+	/* It is not clear that allowing gaps in chainmask
+	 * is helpful.  Probably it will not do what user
+	 * is hoping for, so warn in that case.
+	 */
+	if (cm == 15 || cm == 7 || cm == 3 || cm == 1 || cm == 0)
+		return;
+	ath10k_warn(ar, "mac %s antenna chainmask may be invalid: 0x%x.  Suggested values: 15, 7, 3, 1 or 0.\n",
+		    dbg, cm);
+}
+
 static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
 {
 	int ret;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
+	ath10k_check_chain_mask(ar, tx_ant, "tx");
+	ath10k_check_chain_mask(ar, rx_ant, "rx");
+	
 	ar->cfg_tx_chainmask = tx_ant;
 	ar->cfg_rx_chainmask = rx_ant;
 
@@ -2758,6 +2773,17 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
 	return ret;
 }
 
+static u32 get_nss_from_chainmask(u16 chain_mask)
+{
+	if ((chain_mask & 0x15) == 0x15)
+		return 4;
+	else if ((chain_mask & 0x7) == 0x7)
+		return 3;
+	else if ((chain_mask & 0x3) == 0x3)
+		return 2;
+	return 1;
+}
+
 /*
  * TODO:
  * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
@@ -2890,6 +2916,20 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 		goto err_vdev_delete;
 	}
 
+	if (ar->cfg_tx_chainmask) {
+		u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
+
+		vdev_param = ar->wmi.vdev_param->nss;
+		ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+						nss);
+		if (ret) {
+			ath10k_warn(ar, "failed to set vdev %i chainmask 0x%x, nss %i: %d\n",
+				    arvif->vdev_id, ar->cfg_tx_chainmask, nss,
+				    ret);
+			goto err_vdev_delete;
+		}
+	}
+
 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
 		ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr);
 		if (ret) {
-- 
1.7.11.7



From greearb at candelatech.com  Tue Sep 23 14:17:17 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 14:17:17 -0700
Subject: [PATCH v2 02/10] ath10k: add helper method to grab debug stats.
In-Reply-To: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411507045-18973-2-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

It can be nice to update the firmware's stats while
debugging other bits of the driver, so add helper method
to do this.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

v2:  No changes.

 drivers/net/wireless/ath/ath10k/debug.c | 26 +++++++++++++++++---------
 drivers/net/wireless/ath/ath10k/debug.h |  3 +++
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 101c6f9..c2c02ce 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -371,6 +371,21 @@ void ath10k_debug_read_target_stats(struct ath10k *ar,
 	complete(&ar->debug.event_stats_compl);
 }
 
+int ath10k_refresh_peer_stats(struct ath10k *ar)
+{
+	int ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
+	if (ret) {
+		ath10k_warn(ar, "could not request stats (%d)\n", ret);
+		return ret;
+	}
+
+	ret = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
+	if (ret <= 0)
+		return ret;
+
+	return 0;
+}
+
 static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
 				    size_t count, loff_t *ppos)
 {
@@ -379,7 +394,6 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
 	char *buf = NULL;
 	unsigned int len = 0, buf_len = 8000;
 	ssize_t ret_cnt = 0;
-	long left;
 	int i;
 	int ret;
 
@@ -394,14 +408,8 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
 	if (!buf)
 		goto exit;
 
-	ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
-	if (ret) {
-		ath10k_warn(ar, "could not request stats (%d)\n", ret);
-		goto exit;
-	}
-
-	left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
-	if (left <= 0)
+	ret = ath10k_refresh_peer_stats(ar);
+	if (ret)
 		goto exit;
 
 	spin_lock_bh(&ar->data_lock);
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index d6276fe..ba6d280 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -142,4 +142,7 @@ static inline void ath10k_dbg_dump(struct ath10k *ar,
 {
 }
 #endif /* CONFIG_ATH10K_DEBUG */
+
+int ath10k_refresh_peer_stats(struct ath10k *ar);
+
 #endif /* _DEBUG_H_ */
-- 
1.7.11.7



From greearb at candelatech.com  Tue Sep 23 14:17:18 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 14:17:18 -0700
Subject: [PATCH v2 03/10] ath10k: support ethtool stats.
In-Reply-To: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411507045-18973-3-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Add support for reading firmware stats through the ethtool
API.  This may be easier for applications to manipulate
compared to parsing a text based debugfs file.

This patch also adds and reports firmware reset and
crash counters.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

v2:  Add data-lock around assignment of the stats.
     Update changelog to mention firmware reset/crash
     counters.

 drivers/net/wireless/ath/ath10k/core.h  |   4 +
 drivers/net/wireless/ath/ath10k/debug.c | 146 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/debug.h |   9 ++
 drivers/net/wireless/ath/ath10k/mac.c   |   5 ++
 drivers/net/wireless/ath/ath10k/pci.c   |   4 +
 5 files changed, 168 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 2f1d509..7b220b1 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -541,6 +541,10 @@ struct ath10k {
 
 	struct dfs_pattern_detector *dfs_detector;
 
+	u32 fw_crash_counter;
+	u32 fw_warm_reset_counter;
+	u32 fw_cold_reset_counter;
+
 #ifdef CONFIG_ATH10K_DEBUGFS
 	struct ath10k_debug debug;
 #endif
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index c2c02ce..af1ca3e 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1037,6 +1037,152 @@ exit:
 	return ret;
 }
 
+#ifdef CONFIG_ATH10K_DEBUGFS
+/* TODO:  Would be nice to always support ethtool stats, would need to
+ * move the stats storage out of ath10k_debug, or always have ath10k_debug
+ * struct available..
+ */
+
+/* This generally cooresponds to the debugfs fw_stats file */
+static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"tx_pkts_nic",
+	"tx_bytes_nic",
+	"rx_pkts_nic",
+	"rx_bytes_nic",
+	"d_noise_floor",
+	"d_cycle_count",
+	"d_phy_error",
+	"d_rts_bad",
+	"d_rts_good",
+	"d_tx_power", /* in .5 dbM I think */
+	"d_rx_crc_err", /* fcs_bad */
+	"d_no_beacon",
+	"d_tx_mpdus_queued",
+	"d_tx_msdu_queued",
+	"d_tx_msdu_dropped",
+	"d_local_enqued",
+	"d_local_freed",
+	"d_tx_ppdu_hw_queued",
+	"d_tx_ppdu_reaped",
+	"d_tx_fifo_underrun",
+	"d_tx_ppdu_abort",
+	"d_tx_mpdu_requed",
+	"d_tx_excessive_retries",
+	"d_tx_hw_rate",
+	"d_tx_dropped_sw_retries",
+	"d_tx_illegal_rate",
+	"d_tx_continuous_xretries",
+	"d_tx_timeout",
+	"d_tx_mpdu_txop_limit",
+	"d_pdev_resets",
+	"d_rx_mid_ppdu_route_change",
+	"d_rx_status",
+	"d_rx_extra_frags_ring0",
+	"d_rx_extra_frags_ring1",
+	"d_rx_extra_frags_ring2",
+	"d_rx_extra_frags_ring3",
+	"d_rx_msdu_htt",
+	"d_rx_mpdu_htt",
+	"d_rx_msdu_stack",
+	"d_rx_mpdu_stack",
+	"d_rx_phy_err",
+	"d_rx_phy_err_drops",
+	"d_rx_mpdu_errors", /* FCS, MIC, ENC */
+	"d_fw_crash_count",
+	"d_fw_warm_reset_count",
+	"d_fw_cold_reset_count",
+};
+#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
+
+void ath10k_get_et_strings(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif,
+			   u32 sset, u8 *data)
+{
+	if (sset == ETH_SS_STATS)
+		memcpy(data, *ath10k_gstrings_stats,
+		       sizeof(ath10k_gstrings_stats));
+}
+
+int ath10k_get_et_sset_count(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif, int sset)
+{
+	if (sset == ETH_SS_STATS)
+		return ATH10K_SSTATS_LEN;
+	return 0;
+}
+
+void ath10k_get_et_stats(struct ieee80211_hw *hw,
+			 struct ieee80211_vif *vif,
+			 struct ethtool_stats *stats, u64 *data)
+{
+	struct ath10k *ar = hw->priv;
+	int i = 0;
+	struct ath10k_target_stats *fw_stats;
+
+	fw_stats = &ar->debug.target_stats;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state == ATH10K_STATE_ON)
+		ath10k_refresh_peer_stats(ar);
+
+	mutex_unlock(&ar->conf_mutex);
+
+	spin_lock_bh(&ar->data_lock);
+	data[i++] = fw_stats->hw_reaped; /* ppdu reaped */
+	data[i++] = 0; /* tx bytes */
+	data[i++] = fw_stats->htt_mpdus;
+	data[i++] = 0; /* rx bytes */
+	data[i++] = fw_stats->ch_noise_floor;
+	data[i++] = fw_stats->cycle_count;
+	data[i++] = fw_stats->phy_err_count;
+	data[i++] = fw_stats->rts_bad;
+	data[i++] = fw_stats->rts_good;
+	data[i++] = fw_stats->chan_tx_power;
+	data[i++] = fw_stats->fcs_bad;
+	data[i++] = fw_stats->no_beacons;
+	data[i++] = fw_stats->mpdu_enqued;
+	data[i++] = fw_stats->msdu_enqued;
+	data[i++] = fw_stats->wmm_drop;
+	data[i++] = fw_stats->local_enqued;
+	data[i++] = fw_stats->local_freed;
+	data[i++] = fw_stats->hw_queued;
+	data[i++] = fw_stats->hw_reaped;
+	data[i++] = fw_stats->underrun;
+	data[i++] = fw_stats->tx_abort;
+	data[i++] = fw_stats->mpdus_requed;
+	data[i++] = fw_stats->tx_ko;
+	data[i++] = fw_stats->data_rc;
+	data[i++] = fw_stats->sw_retry_failure;
+	data[i++] = fw_stats->illgl_rate_phy_err;
+	data[i++] = fw_stats->pdev_cont_xretry;
+	data[i++] = fw_stats->pdev_tx_timeout;
+	data[i++] = fw_stats->txop_ovf;
+	data[i++] = fw_stats->pdev_resets;
+	data[i++] = fw_stats->mid_ppdu_route_change;
+	data[i++] = fw_stats->status_rcvd;
+	data[i++] = fw_stats->r0_frags;
+	data[i++] = fw_stats->r1_frags;
+	data[i++] = fw_stats->r2_frags;
+	data[i++] = fw_stats->r3_frags;
+	data[i++] = fw_stats->htt_msdus;
+	data[i++] = fw_stats->htt_mpdus;
+	data[i++] = fw_stats->loc_msdus;
+	data[i++] = fw_stats->loc_mpdus;
+	data[i++] = fw_stats->phy_errs;
+	data[i++] = fw_stats->phy_err_drop;
+	data[i++] = fw_stats->mpdu_errs;
+	data[i++] = ar->fw_crash_counter;
+	data[i++] = ar->fw_warm_reset_counter;
+	data[i++] = ar->fw_cold_reset_counter;
+
+	spin_unlock_bh(&ar->data_lock);
+
+	WARN_ON(i != ATH10K_SSTATS_LEN);
+}
+
+#endif
+
 static const struct file_operations fops_fw_dbglog = {
 	.read = ath10k_read_fw_dbglog,
 	.write = ath10k_write_fw_dbglog,
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index ba6d280..39032e9 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -64,6 +64,15 @@ void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
 
 #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
 
+void ath10k_get_et_strings(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif,
+			   u32 sset, u8 *data);
+int ath10k_get_et_sset_count(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif, int sset);
+void ath10k_get_et_stats(struct ieee80211_hw *hw,
+			 struct ieee80211_vif *vif,
+			 struct ethtool_stats *stats, u64 *data);
+
 #else
 static inline int ath10k_debug_start(struct ath10k *ar)
 {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 02e0a45..4bb3ef6 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4515,6 +4515,11 @@ static const struct ieee80211_ops ath10k_ops = {
 	.suspend			= ath10k_suspend,
 	.resume				= ath10k_resume,
 #endif
+#ifdef CONFIG_ATH10K_DEBUGFS
+	.get_et_sset_count  = ath10k_get_et_sset_count,
+	.get_et_stats       = ath10k_get_et_stats,
+	.get_et_strings     = ath10k_get_et_strings,
+#endif
 };
 
 #define RATETAB_ENT(_rate, _rateid, _flags) { \
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 59e0ea8..38f7386 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -986,6 +986,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
 
 	spin_lock_bh(&ar->data_lock);
 
+	ar->fw_crash_counter++;
+
 	crash_data = ath10k_debug_get_new_fw_crash_data(ar);
 
 	if (crash_data)
@@ -1671,6 +1673,7 @@ static int ath10k_pci_warm_reset(struct ath10k *ar)
 	u32 val;
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
+	ar->fw_warm_reset_counter++;
 
 	/* debug */
 	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
@@ -2286,6 +2289,7 @@ static int ath10k_pci_cold_reset(struct ath10k *ar)
 	u32 val;
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
+	ar->fw_cold_reset_counter++;
 
 	/* Put Target, including PCIe, into RESET. */
 	val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS);
-- 
1.7.11.7



From greearb at candelatech.com  Tue Sep 23 14:17:19 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 14:17:19 -0700
Subject: [PATCH v2 04/10] ath10k: make firmware text debug messages more
 verbose.
In-Reply-To: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411507045-18973-4-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

There are not many of these messages producted by the
firmware, but they are generally fairly useful, so print
them at info level.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

v2:  Add and use a new debug-msg flag, change message
     preamble slightly.

 drivers/net/wireless/ath/ath10k/debug.h | 1 +
 drivers/net/wireless/ath/ath10k/wmi.c   | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 39032e9..8c3b898 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -35,6 +35,7 @@ enum ath10k_debug_mask {
 	ATH10K_DBG_BMI		= 0x00000400,
 	ATH10K_DBG_REGULATORY	= 0x00000800,
 	ATH10K_DBG_TESTMODE	= 0x00001000,
+	ATH10K_DBG_FW_MSG	= 0x00002000,
 	ATH10K_DBG_ANY		= 0xffffffff,
 };
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index bfc1fb3..f1515c0 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2070,7 +2070,7 @@ static void ath10k_wmi_event_debug_print(struct ath10k *ar,
 	/* the last byte is always reserved for the null character */
 	buf[i] = '\0';
 
-	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug print '%s'\n", buf);
+	ath10k_dbg(ar, ATH10K_DBG_FW_MSG, "wmi firmware message '%s'\n", buf);
 }
 
 static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb)
-- 
1.7.11.7



From greearb at candelatech.com  Tue Sep 23 14:17:24 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 14:17:24 -0700
Subject: [PATCH v2 09/10] ath10k: always request htc tx replenishment
In-Reply-To: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411507045-18973-9-git-send-email-greearb@candelatech.com>

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

This simplifies tx credit management and tries to
address a problem where driver runs out of credits
and is unable to recover when firmware stalls.

This also makes it a little more easy to track and
debug htc tx credit flow since there should be no
laziness involved.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
Tested-by: Ben Greear <greearb at candelatech.com>
---

v2:  This is Michal's patch originally.  I think only CT firmware
actually supports this properly, but should not hurt existing
firmware.

 drivers/net/wireless/ath/ath10k/htc.c | 17 +----------------
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 676bd4e..7a6b9b0 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -86,21 +86,6 @@ static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
 	ep->ep_ops.ep_tx_complete(ep->htc->ar, skb);
 }
 
-/* assumes tx_lock is held */
-static bool ath10k_htc_ep_need_credit_update(struct ath10k_htc_ep *ep)
-{
-	struct ath10k *ar = ep->htc->ar;
-
-	if (!ep->tx_credit_flow_enabled)
-		return false;
-	if (ep->tx_credits >= ep->tx_credits_per_max_message)
-		return false;
-
-	ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC: endpoint %d needs credit update\n",
-		   ep->eid);
-	return true;
-}
-
 static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
 				      struct sk_buff *skb)
 {
@@ -115,7 +100,7 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
 	spin_lock_bh(&ep->htc->tx_lock);
 	hdr->seq_no = ep->seq_no++;
 
-	if (ath10k_htc_ep_need_credit_update(ep))
+	if (ep->tx_credit_flow_enabled)
 		hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;
 
 	spin_unlock_bh(&ep->htc->tx_lock);
-- 
1.7.11.7



From greearb at candelatech.com  Tue Sep 23 14:17:23 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 14:17:23 -0700
Subject: [PATCH v2 08/10] ath10k: support CT firmware flag.
In-Reply-To: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411507045-18973-8-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

Add placeholder so CT firmware can more easily co-exist with upstream
kernel.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

v2:  Patch is same as last time, different subsequent patch added
  in case that justifies this better.  I have more, such as
  tx-status (ie, tx rate) reporting, but those are on top of
  the 32-stations patch logic, so have to get that sorted out
  before I can post those.

  If nothing else, can we add a 'do-no-use = 5' feature flag so at least
  I can keep some backward/forward compatability with existing
  CT firwmare and kernels patchs to utilize it?

 drivers/net/wireless/ath/ath10k/core.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 601d573..0d1813c 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -361,6 +361,9 @@ enum ath10k_fw_features {
 	 */
 	ATH10K_FW_FEATURE_WMI_10_2 = 4,
 
+	/* Firmware from Candela Technologies, enables more VIFs, etc */
+	ATH10K_FW_FEATURE_WMI_10X_CT = 5,
+
 	/* keep last */
 	ATH10K_FW_FEATURE_COUNT,
 };
-- 
1.7.11.7



From greearb at candelatech.com  Tue Sep 23 14:17:25 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 14:17:25 -0700
Subject: [PATCH v2 10/10] ath10k: request firmware flush in ath10k_flush.
In-Reply-To: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411507045-18973-10-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

CT firmware now supports flushing all tids for all
peers for all vdevs.  This appears to help the ath10k_flush
logic work faster and not cause timeouts.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

v2:  No changes, just added it to the series in case it
  helps justify adding the CT feature flag.

 drivers/net/wireless/ath/ath10k/mac.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 34ec992..bde3a2f 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3917,6 +3917,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	struct ath10k *ar = hw->priv;
 	bool skip;
 	int ret;
+	u8 peer_addr[ETH_ALEN] = {0};
 
 	/* mac80211 doesn't care if we really xmit queued frames or not
 	 * we'll collect those frames either way if we stop/delete vdevs */
@@ -3928,6 +3929,12 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	if (ar->state == ATH10K_STATE_WEDGED)
 		goto skip;
 
+	/* If we are CT firmware, ask it to flush all tids on all peers on
+	 * all vdevs.  Normal firmware will just crash if you do this.
+	 */
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
+		ath10k_wmi_peer_flush(ar, 0xFFFFFFFF, peer_addr, 0xFFFFFFFF);
+
 	ret = wait_event_timeout(ar->htt.empty_tx_wq, ({
 			bool empty;
 
-- 
1.7.11.7



From greearb at candelatech.com  Tue Sep 23 14:17:22 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 14:17:22 -0700
Subject: [PATCH v2 07/10] ath10k: add fw-powerup-fail to ethtool stats.
In-Reply-To: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411507045-18973-7-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

This gives user-space a normal-ish way to detect that
firmware has failed to start and that a reboot is
probably required.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

v2:  New patch for this series, goes well with the other
   ethtool patch.

 drivers/net/wireless/ath/ath10k/core.h  |  2 +-
 drivers/net/wireless/ath/ath10k/debug.c |  2 ++
 drivers/net/wireless/ath/ath10k/pci.c   | 12 +++++++++---
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 7b220b1..601d573 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -399,7 +399,7 @@ struct ath10k {
 	struct ieee80211_hw *hw;
 	struct device *dev;
 	u8 mac_addr[ETH_ALEN];
-
+	bool fw_powerup_failed; /* If true, might take reboot to recover. */
 	u32 chip_id;
 	u32 target_version;
 	u8 fw_version_major;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index af1ca3e..77b60f4 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1091,6 +1091,7 @@ static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
 	"d_fw_crash_count",
 	"d_fw_warm_reset_count",
 	"d_fw_cold_reset_count",
+	"d_fw_powerup_failed", /* boolean */
 };
 #define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
 
@@ -1175,6 +1176,7 @@ void ath10k_get_et_stats(struct ieee80211_hw *hw,
 	data[i++] = ar->fw_crash_counter;
 	data[i++] = ar->fw_warm_reset_counter;
 	data[i++] = ar->fw_cold_reset_counter;
+	data[i++] = ar->fw_powerup_failed;
 
 	spin_unlock_bh(&ar->data_lock);
 
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 38f7386..ebe2ee1 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1851,7 +1851,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
 			    ret);
 
 		if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY)
-			return ret;
+			goto out;
 
 		ath10k_warn(ar, "trying cold reset\n");
 
@@ -1859,11 +1859,17 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
 		if (ret) {
 			ath10k_err(ar, "failed to power up target using cold reset too (%d)\n",
 				   ret);
-			return ret;
+			goto out;
 		}
 	}
 
-	return 0;
+out:
+	/* If we have failed to power-up, it may take a reboot to
+	 * get the NIC back online.
+	 * Set flag accordinly so that user-space can know.
+	 */
+	ar->fw_powerup_failed = !!ret;
+	return ret;
 }
 
 static void ath10k_pci_hif_power_down(struct ath10k *ar)
-- 
1.7.11.7



From greearb at candelatech.com  Tue Sep 23 14:17:21 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 14:17:21 -0700
Subject: [PATCH v2 06/10] ath10k: use configured nss instead of max nss.
In-Reply-To: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411507045-18973-6-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

When re-associating a station, the nss was set back to
maximum value even if user had configured small number
of tx chains.  So, pay attention to user's config in
this case as well.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

v2:  No changes from v1.

 drivers/net/wireless/ath/ath10k/mac.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index e75607d..34ec992 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4114,6 +4114,10 @@ ath10k_default_bitrate_mask(struct ath10k *ar,
 	u32 legacy = 0x00ff;
 	u8 ht = 0xff, i;
 	u16 vht = 0x3ff;
+	u16 nrf = ar->num_rf_chains;
+
+	if (ar->cfg_tx_chainmask)
+		nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
 
 	switch (band) {
 	case IEEE80211_BAND_2GHZ:
@@ -4129,11 +4133,11 @@ ath10k_default_bitrate_mask(struct ath10k *ar,
 	if (mask->control[band].legacy != legacy)
 		return false;
 
-	for (i = 0; i < ar->num_rf_chains; i++)
+	for (i = 0; i < nrf; i++)
 		if (mask->control[band].ht_mcs[i] != ht)
 			return false;
 
-	for (i = 0; i < ar->num_rf_chains; i++)
+	for (i = 0; i < nrf; i++)
 		if (mask->control[band].vht_mcs[i] != vht)
 			return false;
 
@@ -4384,6 +4388,9 @@ static int ath10k_set_bitrate_mask(struct ieee80211_hw *hw,
 	u8 fixed_nss = ar->num_rf_chains;
 	u8 force_sgi;
 
+	if (ar->cfg_tx_chainmask)
+		fixed_nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
+
 	force_sgi = mask->control[band].gi;
 	if (force_sgi == NL80211_TXRATE_FORCE_LGI)
 		return -EINVAL;
-- 
1.7.11.7



From apenwarr at gmail.com  Tue Sep 23 16:57:57 2014
From: apenwarr at gmail.com (Avery Pennarun)
Date: Tue, 23 Sep 2014 19:57:57 -0400
Subject: Rate ctrl problem with 2x2 station.
In-Reply-To: <54219982.8020204@candelatech.com>
References: <5420BCDA.5010701@candelatech.com>
 <CA+BoTQ=21YJ=WC+T51J_15m1qtDKhWSVP0cYw-P6R-tEmLoLNQ@mail.gmail.com>
 <54219982.8020204@candelatech.com>
Message-ID: <CAHqTa-3L+6cK_mtub9hCZmAYyZsGTMTAd=d+EG5u5xqAQWiukg@mail.gmail.com>

On Tue, Sep 23, 2014 at 12:02 PM, Ben Greear <greearb at candelatech.com> wrote:
> I have not tried 10.2, the latest snapshot I can get is from last
> December, so it does not appear anyone is actively working on it,
> and if it took 8 months to get into the ath10k driver, it must not be
> obviously better??

We tried the 10.2 firmware.  It definitely fixes some bugs that we've
run into (packet corruption), but it adds some even worse ones
(unexplained firmware crashes).

Certainly you could try the new firmware and see if your particular
bug is fixed.  But I also wouldn't say it's ready for prime time.


From greearb at candelatech.com  Tue Sep 23 17:26:23 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 17:26:23 -0700
Subject: [RFC 2/2] ath10k: re-config ht_caps when chainmask is modified.
In-Reply-To: <1411518383-32634-1-git-send-email-greearb@candelatech.com>
References: <1411518383-32634-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411518383-32634-2-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

This lets the mac80211 stack use the proper ht-caps when
negotiating with the peer.  Note that all vdevs are guaranteed
to be down when antenna changes, so we can set the ht_caps
without worrying about messing up existing stations.

This patch also moves the get_nss_from_chainmask up in
the file.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 57 ++++++++++++++++++++++++-----------
 1 file changed, 40 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index dbef84a..8bd47ea 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2408,18 +2408,34 @@ void ath10k_halt(struct ath10k *ar)
 	spin_unlock_bh(&ar->data_lock);
 }
 
-static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
+static u32 get_nss_from_chainmask(u16 chain_mask)
+{
+	if ((chain_mask & 0x15) == 0x15)
+		return 4;
+	else if ((chain_mask & 0x7) == 0x7)
+		return 3;
+	else if ((chain_mask & 0x3) == 0x3)
+		return 2;
+	return 1;
+}
+
+static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar,
+							  bool use_cfg_chains)
 {
 	struct ieee80211_sta_vht_cap vht_cap = {0};
 	u16 mcs_map;
 	int i;
+	int nrf = ar->num_rf_chains;
+
+	if (use_cfg_chains && ar->cfg_tx_chainmask)
+		nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
 
 	vht_cap.vht_supported = 1;
 	vht_cap.cap = ar->vht_cap_info;
 
 	mcs_map = 0;
 	for (i = 0; i < 8; i++) {
-		if (i < ar->num_rf_chains)
+		if (i < nrf)
 			mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
 		else
 			mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
@@ -2431,10 +2447,15 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
 	return vht_cap;
 }
 
-static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
+static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar,
+						     bool use_cfg_chains)
 {
 	int i;
 	struct ieee80211_sta_ht_cap ht_cap = {0};
+	int nrf = ar->num_rf_chains;
+
+	if (use_cfg_chains && ar->cfg_tx_chainmask)
+		nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
 
 	if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
 		return ht_cap;
@@ -2486,7 +2507,7 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
 	if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
 		ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
 
-	for (i = 0; i < ar->num_rf_chains; i++)
+	for (i = 0; i < nrf; i++)
 		ht_cap.mcs.rx_mask[i] = 0xFF;
 
 	ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
@@ -2528,6 +2549,8 @@ static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char* dbg)
 static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
 {
 	int ret;
+	struct ieee80211_sta_vht_cap vht_cap;
+	struct ieee80211_sta_ht_cap ht_cap;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
@@ -2537,6 +2560,17 @@ static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
 	ar->cfg_tx_chainmask = tx_ant;
 	ar->cfg_rx_chainmask = rx_ant;
 
+	ht_cap = ath10k_get_ht_cap(ar, true);
+	vht_cap = ath10k_create_vht_cap(ar, true);
+
+	if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY)
+		ar->mac.sbands[IEEE80211_BAND_2GHZ].ht_cap = ht_cap;
+
+	if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) {
+		ar->mac.sbands[IEEE80211_BAND_5GHZ].ht_cap = ht_cap;
+		ar->mac.sbands[IEEE80211_BAND_5GHZ].vht_cap = vht_cap;
+	}
+
 	if ((ar->state != ATH10K_STATE_ON) &&
 	    (ar->state != ATH10K_STATE_RESTARTED))
 		return 0;
@@ -2859,17 +2893,6 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
 	return ret;
 }
 
-static u32 get_nss_from_chainmask(u16 chain_mask)
-{
-	if ((chain_mask & 0x15) == 0x15)
-		return 4;
-	else if ((chain_mask & 0x7) == 0x7)
-		return 3;
-	else if ((chain_mask & 0x3) == 0x3)
-		return 2;
-	return 1;
-}
-
 /*
  * TODO:
  * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
@@ -4864,8 +4887,8 @@ int ath10k_mac_register(struct ath10k *ar)
 
 	SET_IEEE80211_DEV(ar->hw, ar->dev);
 
-	ht_cap = ath10k_get_ht_cap(ar);
-	vht_cap = ath10k_create_vht_cap(ar);
+	ht_cap = ath10k_get_ht_cap(ar, false);
+	vht_cap = ath10k_create_vht_cap(ar, false);
 
 	if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) {
 		channels = kmemdup(ath10k_2ghz_channels,
-- 
1.7.11.7



From greearb at candelatech.com  Tue Sep 23 17:26:22 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Tue, 23 Sep 2014 17:26:22 -0700
Subject: [RFC 1/2] ath10k: move create-ht-cap methods above set-antenna.
Message-ID: <1411518383-32634-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

We will need to use these in set-antenna, so move them
so that we do not have to define the method signatures.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---

This appears to work, but needs more testing before it should
be applied.  I'll do that testing tomorrow.

 drivers/net/wireless/ath/ath10k/mac.c | 172 +++++++++++++++++-----------------
 1 file changed, 86 insertions(+), 86 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index bde3a2f..dbef84a 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2408,6 +2408,92 @@ void ath10k_halt(struct ath10k *ar)
 	spin_unlock_bh(&ar->data_lock);
 }
 
+static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
+{
+	struct ieee80211_sta_vht_cap vht_cap = {0};
+	u16 mcs_map;
+	int i;
+
+	vht_cap.vht_supported = 1;
+	vht_cap.cap = ar->vht_cap_info;
+
+	mcs_map = 0;
+	for (i = 0; i < 8; i++) {
+		if (i < ar->num_rf_chains)
+			mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
+		else
+			mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
+	}
+
+	vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
+	vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
+
+	return vht_cap;
+}
+
+static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
+{
+	int i;
+	struct ieee80211_sta_ht_cap ht_cap = {0};
+
+	if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
+		return ht_cap;
+
+	ht_cap.ht_supported = 1;
+	ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+	ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
+	ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
+	ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
+
+	if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
+		ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
+
+	if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
+		ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+
+	if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
+		u32 smps;
+
+		smps   = WLAN_HT_CAP_SM_PS_DYNAMIC;
+		smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
+
+		ht_cap.cap |= smps;
+	}
+
+	if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
+		ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
+
+	if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
+		u32 stbc;
+
+		stbc   = ar->ht_cap_info;
+		stbc  &= WMI_HT_CAP_RX_STBC;
+		stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
+		stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
+		stbc  &= IEEE80211_HT_CAP_RX_STBC;
+
+		ht_cap.cap |= stbc;
+	}
+
+	if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
+		ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
+
+	if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
+		ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
+
+	/* max AMSDU is implicitly taken from vht_cap_info */
+	if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
+		ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
+
+	for (i = 0; i < ar->num_rf_chains; i++)
+		ht_cap.mcs.rx_mask[i] = 0xFF;
+
+	ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
+
+	return ht_cap;
+}
+
 static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
 {
 	struct ath10k *ar = hw->priv;
@@ -4735,92 +4821,6 @@ static const struct ieee80211_iface_combination ath10k_10x_if_comb[] = {
 	},
 };
 
-static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
-{
-	struct ieee80211_sta_vht_cap vht_cap = {0};
-	u16 mcs_map;
-	int i;
-
-	vht_cap.vht_supported = 1;
-	vht_cap.cap = ar->vht_cap_info;
-
-	mcs_map = 0;
-	for (i = 0; i < 8; i++) {
-		if (i < ar->num_rf_chains)
-			mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
-		else
-			mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
-	}
-
-	vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
-	vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
-
-	return vht_cap;
-}
-
-static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
-{
-	int i;
-	struct ieee80211_sta_ht_cap ht_cap = {0};
-
-	if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
-		return ht_cap;
-
-	ht_cap.ht_supported = 1;
-	ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
-	ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
-	ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
-	ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
-	ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
-
-	if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
-		ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
-
-	if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
-		ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
-
-	if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
-		u32 smps;
-
-		smps   = WLAN_HT_CAP_SM_PS_DYNAMIC;
-		smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
-
-		ht_cap.cap |= smps;
-	}
-
-	if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
-		ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
-
-	if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
-		u32 stbc;
-
-		stbc   = ar->ht_cap_info;
-		stbc  &= WMI_HT_CAP_RX_STBC;
-		stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
-		stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
-		stbc  &= IEEE80211_HT_CAP_RX_STBC;
-
-		ht_cap.cap |= stbc;
-	}
-
-	if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
-		ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
-
-	if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
-		ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
-
-	/* max AMSDU is implicitly taken from vht_cap_info */
-	if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
-		ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
-
-	for (i = 0; i < ar->num_rf_chains; i++)
-		ht_cap.mcs.rx_mask[i] = 0xFF;
-
-	ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
-
-	return ht_cap;
-}
-
 static void ath10k_get_arvif_iter(void *data, u8 *mac,
 				  struct ieee80211_vif *vif)
 {
-- 
1.7.11.7



From apenwarr at gmail.com  Tue Sep 23 17:38:40 2014
From: apenwarr at gmail.com (Avery Pennarun)
Date: Tue, 23 Sep 2014 20:38:40 -0400
Subject: Using host's rate-ctrl in ath10k?
In-Reply-To: <54219A6E.6080902@candelatech.com>
References: <54205FA0.5000802@candelatech.com>
 <CA+BoTQ=wwCbfFqdQqgYfu9RTLiuot-bNh3mNN0c3R=1R_FUTzQ@mail.gmail.com>
 <54219A6E.6080902@candelatech.com>
Message-ID: <CAHqTa-05-6xXfR9nhf4p=1ygWrcBv5WLrJFGbSQ-J=ME+RdZ8A@mail.gmail.com>

On Tue, Sep 23, 2014 at 12:06 PM, Ben Greear <greearb at candelatech.com> wrote:
> On 09/23/2014 12:17 AM, Michal Kazior wrote:
>> On 22 September 2014 19:42, Ben Greear <greearb at candelatech.com> wrote:
>>> Has anyone looked into what it would take to use standard host OS's
>>> rate control (minstrel_ht) with ath10k?
>>>
>>> I suspect the ath10k rate control logic in the firmware is
>>> a bit dodgy, and it would be nice to use something with wider
>>> testing such as minstrel_ht...
>>
>> Correct me if I'm wrong but that would require tx completions to
>> include tx retry information and a way to setup tx retries.
>
> Something like that...I have not looked in detail.  It would
> require a re-compile of the firmware at least.
>
> I just don't like that we are depending on the firmware for something
> something as tricky as rate control, especially when it seems buggy.

I definitely agree with this.  Once of the best things about the ath9k
driver is its excellent rate control, and the ability of others to
experiment on rate control to improve it further.  We've lost this
with the ath10k and it makes things significantly worse in some of our
benchmarks in non-ideal network conditions.


From michal.kazior at tieto.com  Tue Sep 23 23:50:38 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 24 Sep 2014 08:50:38 +0200
Subject: [PATCH] ath10k: request firmware flush in ath10k_flush.
In-Reply-To: <5421818A.9040501@candelatech.com>
References: <1411151304-31544-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQm1rZO+yBbYxihpgEvR1cGZWS4Pr0AP+KMODcG4jpd_jQ@mail.gmail.com>
 <5421818A.9040501@candelatech.com>
Message-ID: <CA+BoTQkZaGSkC9mhE8UF0He0RZWmPghDukdE1A5qiO1UNAZj5Q@mail.gmail.com>

On 23 September 2014 16:19, Ben Greear <greearb at candelatech.com> wrote:
> On 09/23/2014 02:16 AM, Michal Kazior wrote:
>> On 19 September 2014 20:28,  <greearb at candelatech.com> wrote:
>> [...]
>>>
>>> +       /* If we are CT firmware, ask it to flush all tids on all peers
>>> on
>>> +        * all vdevs.  Normal firmware will just crash if you do this.
>>> +        */
>>> +       if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
>>> +               ath10k_wmi_peer_flush(ar, 0xFFFFFFFF, peer_addr,
>>> 0xFFFFFFFF);
>>
>> I recall you've explained this some time ago, but can you refresh my
>> memory, please? Is this any different from iterating over all peers
>> and flushing each? Or does your firmware do so extra magic that is
>> impossible to do with normal firmware commands?
>
> My firmware does that iteration internally.
>
> You could probably do that in the driver, but it would be a lot
> of messages (for all vdevs, all peers, all tids)...
> I was not sure if there were limits to the number
> of commands you should attempt during the flush...

Thanks. I think ath10k should do this instead of having CT-specific
flush eventually.

I recall I actually did per-peer flushing in RFC patches a long time
ago but I didn't pursue getting them merged. I think Denton uses these
patches in his setup. They don't flush vdev self-peers though (do you
do that internally?).


Micha?


From michal.kazior at tieto.com  Tue Sep 23 23:58:56 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 24 Sep 2014 08:58:56 +0200
Subject: [PATCH v2 1/3] ath10k: don't enable interrupts for the diagnostic
 window
In-Reply-To: <20140923143219.23585.34114.stgit@potku.adurom.net>
References: <20140923143219.23585.34114.stgit@potku.adurom.net>
Message-ID: <CA+BoTQ=P2mKLbdPTQYM_c-ohMtsucTHbc_aukzqcdpQUwhwtvQ@mail.gmail.com>

On 23 September 2014 16:32, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
[...]
> -       for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
> +       /* Skip the last copy engine, CE7 the diagnostic window, as that
> +        * uses polling and isn't initialized for interrupts. */

Comment style :-)


Micha?


From michal.kazior at tieto.com  Wed Sep 24 00:00:39 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 24 Sep 2014 09:00:39 +0200
Subject: [PATCH v2 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <20140923143234.23585.2139.stgit@potku.adurom.net>
References: <20140923143219.23585.34114.stgit@potku.adurom.net>
 <20140923143234.23585.2139.stgit@potku.adurom.net>
Message-ID: <CA+BoTQ=O8j1x-71SCLq9ZiXBU28Ax9M7tyfbvB=mjsWUwgPSjw@mail.gmail.com>

On 23 September 2014 16:32, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
[...]
> diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
> index 101c6f9cf2a8..426341480262 100644
> --- a/drivers/net/wireless/ath/ath10k/debug.c
> +++ b/drivers/net/wireless/ath/ath10k/debug.c
[...]
> +static int ath10k_cal_data_open(struct inode *inode, struct file *file)

Shouldn't functions in debug.c have ath10k_debug_ prefix? I'm aware
other fops stuff doesn't include the _debug word as well so this is
somewhat consistent with the current code but is this okay in the
grand scheme of things? Just wondering.


Micha?


From michal.kazior at tieto.com  Wed Sep 24 00:09:13 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 24 Sep 2014 09:09:13 +0200
Subject: [PATCH] ath10k: use configured nss instead of max nss.
In-Reply-To: <5421A44C.8080307@candelatech.com>
References: <1411426820-4047-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQn9sECMNZsxQpB4i3wHPxfVL+LXq9=2GBd-opH6+9TD=A@mail.gmail.com>
 <5421A44C.8080307@candelatech.com>
Message-ID: <CA+BoTQ=mry3tPD-LK+gFD2bC6RU0KvY6LC9=FOAGTLi_1rzUog@mail.gmail.com>

On 23 September 2014 18:48, Ben Greear <greearb at candelatech.com> wrote:
> On 09/23/2014 01:59 AM, Michal Kazior wrote:
>> On 23 September 2014 01:00,  <greearb at candelatech.com> wrote:
>>> From: Ben Greear <greearb at candelatech.com>
[...]
>>> @@ -4086,6 +4086,10 @@ ath10k_default_bitrate_mask(struct ath10k *ar,
>>>         u32 legacy = 0x00ff;
>>>         u8 ht = 0xff, i;
>>>         u16 vht = 0x3ff;
>>> +       u16 nrf = ar->num_rf_chains;
>>> +
>>> +       if (ar->cfg_tx_chainmask)
>>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
[...]
>> I think it might be a good idea to convey the limitation of tx/rx
>> chainmask to the user: you can't change the tx/rx chainmask on the fly
>> easily (while connected/have associated stations). Or do you plan to
>> schedule peer reassoc in __ath10k_set_antenna() in a follow up
>> patch(es) later?
>
> My user-space tools assume you have to re-connect (requested from user-space)
> after changing the chainmask.  I was under the impression that this
> is how ath9k works, though I could be wrong.

ath9k doesn't have firmware and it doesn't have a blackbox rate
control so maybe it doesn't need to worry about this as much as ath10k
needs to.

But then this is not something you normally use except some very
specific use cases so I think it might not be worth the hassle to
implement full-blown reconfig after chainmask is updated.


> I would rather keep this requirement in user-space...
>
> I am not sure where to document this...just a comment in the code?

Hmm.. Perhaps in ath10k_set_antenna? Or maybe we should just put it up
on the wiki?

But it's still probably a good idea to comment the quoted code chunk
above explaining why nrf is overriden by chainmask (i.e. due to
firmware rate control issues, right?).


Micha?


From michal.kazior at tieto.com  Wed Sep 24 00:44:26 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 24 Sep 2014 09:44:26 +0200
Subject: [PATCH v2 03/10] ath10k: support ethtool stats.
In-Reply-To: <1411507045-18973-3-git-send-email-greearb@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
 <1411507045-18973-3-git-send-email-greearb@candelatech.com>
Message-ID: <CA+BoTQkK=6NfPN9e-3qN2Qaq2RLVdEwrp5x03_T=E2ZLcBeiaA@mail.gmail.com>

On 23 September 2014 23:17,  <greearb at candelatech.com> wrote:
[...]
> +void ath10k_get_et_stats(struct ieee80211_hw *hw,
> +                        struct ieee80211_vif *vif,
> +                        struct ethtool_stats *stats, u64 *data)
> +{
> +       struct ath10k *ar = hw->priv;
> +       int i = 0;
> +       struct ath10k_target_stats *fw_stats;
> +
> +       fw_stats = &ar->debug.target_stats;
> +
> +       mutex_lock(&ar->conf_mutex);
> +
> +       if (ar->state == ATH10K_STATE_ON)
> +               ath10k_refresh_peer_stats(ar);
> +
> +       mutex_unlock(&ar->conf_mutex);

Just for correctness sake - it's probably a good idea to
mutex_unlock() at the end (i.e. after spin_unlock_bh()) to make sure
the stats are for this particular request. With your patch there's a
very slight chance that, e.g. fw_stats debug file is being read at the
same time and it updates fw stats between the above mutex_unlock() and
following spin_lock_bh().

> +       spin_lock_bh(&ar->data_lock);
> +       data[i++] = fw_stats->hw_reaped; /* ppdu reaped */
[...]
> +       spin_unlock_bh(&ar->data_lock);
> +
> +       WARN_ON(i != ATH10K_SSTATS_LEN);
> +}


Micha?


From michal.kazior at tieto.com  Wed Sep 24 00:51:39 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 24 Sep 2014 09:51:39 +0200
Subject: [RFC 2/2] ath10k: re-config ht_caps when chainmask is modified.
In-Reply-To: <1411518383-32634-2-git-send-email-greearb@candelatech.com>
References: <1411518383-32634-1-git-send-email-greearb@candelatech.com>
 <1411518383-32634-2-git-send-email-greearb@candelatech.com>
Message-ID: <CA+BoTQ=fS30xz9KcdBJcioNers6PovOFEeqPCCSFn52HkscXug@mail.gmail.com>

On 24 September 2014 02:26,  <greearb at candelatech.com> wrote:
[...]
> +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar,
> +                                                         bool use_cfg_chains)
>  {
>         struct ieee80211_sta_vht_cap vht_cap = {0};
>         u16 mcs_map;
>         int i;
> +       int nrf = ar->num_rf_chains;
> +
> +       if (use_cfg_chains && ar->cfg_tx_chainmask)
> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);

Is use_cfg_chains really necessary here? Is setting tx/rx chainmask to
0x0 make any sense at all? Shouldn't we deny it or make it fallback to
the supported tx/rx chainmask values?


Micha?


From kvalo at qca.qualcomm.com  Wed Sep 24 03:26:18 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 24 Sep 2014 13:26:18 +0300
Subject: [PATCH v2 1/3] ath10k: don't enable interrupts for the diagnostic
 window
In-Reply-To: <CA+BoTQ=P2mKLbdPTQYM_c-ohMtsucTHbc_aukzqcdpQUwhwtvQ@mail.gmail.com>
 (Michal Kazior's message of "Wed, 24 Sep 2014 08:58:56 +0200")
References: <20140923143219.23585.34114.stgit@potku.adurom.net>
 <CA+BoTQ=P2mKLbdPTQYM_c-ohMtsucTHbc_aukzqcdpQUwhwtvQ@mail.gmail.com>
Message-ID: <87d2al9uwl.fsf@kamboji.qca.qualcomm.com>

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

> On 23 September 2014 16:32, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> [...]
>> -       for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
>> +       /* Skip the last copy engine, CE7 the diagnostic window, as that
>> +        * uses polling and isn't initialized for interrupts. */
>
> Comment style :-)

Argh, I never learn. This new comment style is so unnatural for me that
I guess I need to completely convert ath10k to use the new style so that
I can use checkpatch to catch these :)

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Sep 24 04:00:37 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 24 Sep 2014 14:00:37 +0300
Subject: [PATCH v2 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <CA+BoTQ=O8j1x-71SCLq9ZiXBU28Ax9M7tyfbvB=mjsWUwgPSjw@mail.gmail.com>
 (Michal Kazior's message of "Wed, 24 Sep 2014 09:00:39 +0200")
References: <20140923143219.23585.34114.stgit@potku.adurom.net>
 <20140923143234.23585.2139.stgit@potku.adurom.net>
 <CA+BoTQ=O8j1x-71SCLq9ZiXBU28Ax9M7tyfbvB=mjsWUwgPSjw@mail.gmail.com>
Message-ID: <87egv18eqy.fsf@kamboji.qca.qualcomm.com>

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

> On 23 September 2014 16:32, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> [...]
>> diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
>> index 101c6f9cf2a8..426341480262 100644
>> --- a/drivers/net/wireless/ath/ath10k/debug.c
>> +++ b/drivers/net/wireless/ath/ath10k/debug.c
> [...]
>> +static int ath10k_cal_data_open(struct inode *inode, struct file *file)
>
> Shouldn't functions in debug.c have ath10k_debug_ prefix? I'm aware
> other fops stuff doesn't include the _debug word as well so this is
> somewhat consistent with the current code but is this okay in the
> grand scheme of things? Just wondering.

IMHO we should use ath10k_debug_ with fops functions as well, I just
haven't been that picky about that.

I'll change this as well and send v3. Thanks for review!

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Wed Sep 24 04:16:39 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 24 Sep 2014 14:16:39 +0300
Subject: [PATCH v3 0/3] ath10k: export calibration data to user space
Message-ID: <20140924111416.6539.95299.stgit@potku.adurom.net>

Here's a small patchset exporting firmware calibration data to user space. This
makes it easier to debug various calibration data related problems.

Please comment.

v3:

* patch 1: fix comment style (Michal)

* patch 3: use ath10k_debug_ prefix (Michal)

v2:

* never unmask the diagnostic window copy engine pipe in
  ath10k_ce_enable_interrupts()

* add locking for diag_read_mem()/diag_write_mem()

---

Kalle Valo (3):
      ath10k: don't enable interrupts for the diagnostic window
      ath10k: add diag_read() to hif ops
      ath10k: add cal_data debugfs file


 drivers/net/wireless/ath/ath10k/ce.c    |   27 ++++++----
 drivers/net/wireless/ath/ath10k/ce.h    |   13 +++++
 drivers/net/wireless/ath/ath10k/debug.c |   82 +++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hif.h   |   10 ++++
 drivers/net/wireless/ath/ath10k/hw.h    |    2 +
 drivers/net/wireless/ath/ath10k/pci.c   |   51 ++++++++++++-------
 6 files changed, 155 insertions(+), 30 deletions(-)



From kvalo at qca.qualcomm.com  Wed Sep 24 04:16:46 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 24 Sep 2014 14:16:46 +0300
Subject: [PATCH v3 1/3] ath10k: don't enable interrupts for the diagnostic
 window
In-Reply-To: <20140924111416.6539.95299.stgit@potku.adurom.net>
References: <20140924111416.6539.95299.stgit@potku.adurom.net>
Message-ID: <20140924111646.6539.44330.stgit@potku.adurom.net>

The diagnostic window (CE7) uses polling and is not initiliased to retrieve
interrupts so disable interrupts altogether for CE7. Otherwise ath10k crashes
when using the diagnostic window while the firmware is running due to NULL
dereference and polling reads timeout.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/ce.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 101cadb6e4ba..09ef03e7af89 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -817,7 +817,10 @@ void ath10k_ce_enable_interrupts(struct ath10k *ar)
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	int ce_id;
 
-	for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
+	/* Skip the last copy engine, CE7 the diagnostic window, as that
+	 * uses polling and isn't initialized for interrupts.
+	 */
+	for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++)
 		ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]);
 }
 



From kvalo at qca.qualcomm.com  Wed Sep 24 04:16:52 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 24 Sep 2014 14:16:52 +0300
Subject: [PATCH v3 2/3] ath10k: add diag_read() to hif ops
In-Reply-To: <20140924111416.6539.95299.stgit@potku.adurom.net>
References: <20140924111416.6539.95299.stgit@potku.adurom.net>
Message-ID: <20140924111652.6539.45946.stgit@potku.adurom.net>

diag_read() is used for reading from firmware memory via the diagnose window.
First user will be cal_data debugfs file.

To serialise diagnostic window access and make it safe to use while firmware is
running take ce_lock both in ath10k_pci_diag_write_mem() and
ath10k_pci_diag_read_mem(). Because of that all the CE calls had to be changed
to _nolock variants.

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/ce.c  |   22 +++++++-------
 drivers/net/wireless/ath/ath10k/ce.h  |   13 ++++++++
 drivers/net/wireless/ath/ath10k/hif.h |   10 ++++++
 drivers/net/wireless/ath/ath10k/pci.c |   51 +++++++++++++++++++++------------
 4 files changed, 67 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 09ef03e7af89..4745ef2a6f01 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -443,12 +443,12 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
  * Guts of ath10k_ce_completed_recv_next.
  * The caller takes responsibility for any necessary locking.
  */
-static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
-						void **per_transfer_contextp,
-						u32 *bufferp,
-						unsigned int *nbytesp,
-						unsigned int *transfer_idp,
-						unsigned int *flagsp)
+int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
+					 void **per_transfer_contextp,
+					 u32 *bufferp,
+					 unsigned int *nbytesp,
+					 unsigned int *transfer_idp,
+					 unsigned int *flagsp)
 {
 	struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
 	unsigned int nentries_mask = dest_ring->nentries_mask;
@@ -576,11 +576,11 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
  * Guts of ath10k_ce_completed_send_next.
  * The caller takes responsibility for any necessary locking.
  */
-static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
-						void **per_transfer_contextp,
-						u32 *bufferp,
-						unsigned int *nbytesp,
-						unsigned int *transfer_idp)
+int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
+					 void **per_transfer_contextp,
+					 u32 *bufferp,
+					 unsigned int *nbytesp,
+					 unsigned int *transfer_idp)
 {
 	struct ath10k_ce_ring *src_ring = ce_state->src_ring;
 	u32 ctrl_addr = ce_state->ctrl_addr;
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index 329b7340fa72..608262ab964e 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -192,6 +192,12 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
 				  unsigned int *nbytesp,
 				  unsigned int *transfer_idp);
 
+int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
+					 void **per_transfer_contextp,
+					 u32 *bufferp,
+					 unsigned int *nbytesp,
+					 unsigned int *transfer_idp);
+
 /*==================CE Engine Initialization=======================*/
 
 int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
@@ -213,6 +219,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
 			       void **per_transfer_contextp,
 			       u32 *bufferp);
 
+int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
+					 void **per_transfer_contextp,
+					 u32 *bufferp,
+					 unsigned int *nbytesp,
+					 unsigned int *transfer_idp,
+					 unsigned int *flagsp);
+
 /*
  * Support clean shutdown by allowing the caller to cancel
  * pending sends.  Target DMA must be stopped before using
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 62323fea27e1..30301f5b6051 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -43,6 +43,10 @@ struct ath10k_hif_ops {
 	int (*tx_sg)(struct ath10k *ar, u8 pipe_id,
 		     struct ath10k_hif_sg_item *items, int n_items);
 
+	/* read firmware memory through the diagnose interface */
+	int (*diag_read)(struct ath10k *ar, u32 address, void *buf,
+			 size_t buf_len);
+
 	/*
 	 * API to handle HIF-specific BMI message exchanges, this API is
 	 * synchronous and only allowed to be called from a context that
@@ -98,6 +102,12 @@ static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
 	return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items);
 }
 
+static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
+				       size_t buf_len)
+{
+	return ar->hif.ops->diag_read(ar, address, buf, buf_len);
+}
+
 static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
 					      void *request, u32 request_len,
 					      void *response, u32 *response_len)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 59e0ea83be50..0784b48b04ce 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -485,6 +485,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 	void *data_buf = NULL;
 	int i;
 
+	spin_lock_bh(&ar_pci->ce_lock);
+
 	ce_diag = ar_pci->ce_diag;
 
 	/*
@@ -511,7 +513,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 		nbytes = min_t(unsigned int, remaining_bytes,
 			       DIAG_TRANSFER_LIMIT);
 
-		ret = ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
+		ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
 		if (ret != 0)
 			goto done;
 
@@ -527,15 +529,15 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 		address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem,
 						     address);
 
-		ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0,
-				     0);
+		ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0,
+					    0);
 		if (ret)
 			goto done;
 
 		i = 0;
-		while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
-						     &completed_nbytes,
-						     &id) != 0) {
+		while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
+							    &completed_nbytes,
+							    &id) != 0) {
 			mdelay(1);
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
 				ret = -EBUSY;
@@ -554,9 +556,9 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 		}
 
 		i = 0;
-		while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
-						     &completed_nbytes,
-						     &id, &flags) != 0) {
+		while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
+							    &completed_nbytes,
+							    &id, &flags) != 0) {
 			mdelay(1);
 
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -591,6 +593,8 @@ done:
 		dma_free_coherent(ar->dev, orig_nbytes, data_buf,
 				  ce_data_base);
 
+	spin_unlock_bh(&ar_pci->ce_lock);
+
 	return ret;
 }
 
@@ -648,6 +652,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 	dma_addr_t ce_data_base = 0;
 	int i;
 
+	spin_lock_bh(&ar_pci->ce_lock);
+
 	ce_diag = ar_pci->ce_diag;
 
 	/*
@@ -688,7 +694,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 		nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT);
 
 		/* Set up to receive directly into Target(!) address */
-		ret = ath10k_ce_rx_post_buf(ce_diag, NULL, address);
+		ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address);
 		if (ret != 0)
 			goto done;
 
@@ -696,15 +702,15 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 		 * Request CE to send caller-supplied data that
 		 * was copied to bounce buffer to Target(!) address.
 		 */
-		ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data,
-				     nbytes, 0, 0);
+		ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data,
+					    nbytes, 0, 0);
 		if (ret != 0)
 			goto done;
 
 		i = 0;
-		while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
-						     &completed_nbytes,
-						     &id) != 0) {
+		while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
+							    &completed_nbytes,
+							    &id) != 0) {
 			mdelay(1);
 
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -724,9 +730,9 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 		}
 
 		i = 0;
-		while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
-						     &completed_nbytes,
-						     &id, &flags) != 0) {
+		while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
+							    &completed_nbytes,
+							    &id, &flags) != 0) {
 			mdelay(1);
 
 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -760,6 +766,8 @@ done:
 		ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n",
 			    address, ret);
 
+	spin_unlock_bh(&ar_pci->ce_lock);
+
 	return ret;
 }
 
@@ -936,6 +944,12 @@ err:
 	return err;
 }
 
+static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
+				    size_t buf_len)
+{
+	return ath10k_pci_diag_read_mem(ar, address, buf, buf_len);
+}
+
 static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
 {
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -1921,6 +1935,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
 
 static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
 	.tx_sg			= ath10k_pci_hif_tx_sg,
+	.diag_read		= ath10k_pci_hif_diag_read,
 	.exchange_bmi_msg	= ath10k_pci_hif_exchange_bmi_msg,
 	.start			= ath10k_pci_hif_start,
 	.stop			= ath10k_pci_hif_stop,



From kvalo at qca.qualcomm.com  Wed Sep 24 04:16:58 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Wed, 24 Sep 2014 14:16:58 +0300
Subject: [PATCH v3 3/3] ath10k: add cal_data debugfs file
In-Reply-To: <20140924111416.6539.95299.stgit@potku.adurom.net>
References: <20140924111416.6539.95299.stgit@potku.adurom.net>
Message-ID: <20140924111658.6539.73760.stgit@potku.adurom.net>

Provide calibration data used by the firmware to user space via a debugfs file.
This makes it easier to debug calibration related problems.

Example:

sudo cp /sys/kernel/debug/ieee80211/phy0/ath10k/cal_data 1.cal

Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/debug.c |   82 +++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hw.h    |    2 +
 2 files changed, 84 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 101c6f9cf2a8..f70c0aa59950 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -23,6 +23,7 @@
 
 #include "core.h"
 #include "debug.h"
+#include "hif.h"
 
 /* ms */
 #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
@@ -1037,6 +1038,84 @@ static const struct file_operations fops_fw_dbglog = {
 	.llseek = default_llseek,
 };
 
+static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
+{
+	struct ath10k *ar = inode->i_private;
+	void *buf;
+	u32 hi_addr;
+	__le32 addr;
+	int ret;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_ON &&
+	    ar->state != ATH10K_STATE_UTF) {
+		ret = -ENETDOWN;
+		goto err;
+	}
+
+	buf = vmalloc(QCA988X_CAL_DATA_LEN);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
+
+	ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
+	if (ret) {
+		ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
+		goto err_vfree;
+	}
+
+	ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
+				   QCA988X_CAL_DATA_LEN);
+	if (ret) {
+		ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
+		goto err_vfree;
+	}
+
+	file->private_data = buf;
+
+	mutex_unlock(&ar->conf_mutex);
+
+	return 0;
+
+err_vfree:
+	vfree(buf);
+
+err:
+	mutex_unlock(&ar->conf_mutex);
+
+	return ret;
+}
+
+static ssize_t ath10k_debug_cal_data_read(struct file *file,
+					  char __user *user_buf,
+					  size_t count, loff_t *ppos)
+{
+	void *buf = file->private_data;
+
+	return simple_read_from_buffer(user_buf, count, ppos,
+				       buf, QCA988X_CAL_DATA_LEN);
+}
+
+static int ath10k_debug_cal_data_release(struct inode *inode,
+					 struct file *file)
+{
+	vfree(file->private_data);
+
+	return 0;
+}
+
+static const struct file_operations fops_cal_data = {
+	.open = ath10k_debug_cal_data_open,
+	.read = ath10k_debug_cal_data_read,
+	.release = ath10k_debug_cal_data_release,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 int ath10k_debug_start(struct ath10k *ar)
 {
 	int ret;
@@ -1210,6 +1289,9 @@ int ath10k_debug_register(struct ath10k *ar)
 	debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
 			    ar, &fops_fw_dbglog);
 
+	debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
+			    ar, &fops_cal_data);
+
 	if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
 		debugfs_create_file("dfs_simulate_radar", S_IWUSR,
 				    ar->debug.debugfs_phy, ar,
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 3cf5702c1e7e..006a9cbc60b2 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -43,6 +43,8 @@
 
 #define REG_DUMP_COUNT_QCA988X 60
 
+#define QCA988X_CAL_DATA_LEN		2116
+
 struct ath10k_fw_ie {
 	__le32 id;
 	__le32 len;



From greearb at candelatech.com  Wed Sep 24 07:35:59 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 24 Sep 2014 07:35:59 -0700
Subject: [RFC 2/2] ath10k: re-config ht_caps when chainmask is modified.
In-Reply-To: <CA+BoTQ=fS30xz9KcdBJcioNers6PovOFEeqPCCSFn52HkscXug@mail.gmail.com>
References: <1411518383-32634-1-git-send-email-greearb@candelatech.com>	<1411518383-32634-2-git-send-email-greearb@candelatech.com>
 <CA+BoTQ=fS30xz9KcdBJcioNers6PovOFEeqPCCSFn52HkscXug@mail.gmail.com>
Message-ID: <5422D6CF.10408@candelatech.com>



On 09/24/2014 12:51 AM, Michal Kazior wrote:
> On 24 September 2014 02:26,  <greearb at candelatech.com> wrote:
> [...]
>> +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar,
>> +                                                         bool use_cfg_chains)
>>   {
>>          struct ieee80211_sta_vht_cap vht_cap = {0};
>>          u16 mcs_map;
>>          int i;
>> +       int nrf = ar->num_rf_chains;
>> +
>> +       if (use_cfg_chains && ar->cfg_tx_chainmask)
>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
>
> Is use_cfg_chains really necessary here? Is setting tx/rx chainmask to
> 0x0 make any sense at all? Shouldn't we deny it or make it fallback to
> the supported tx/rx chainmask values?

It would cause the logic to flip back to the defaults, so seems mildly useful.  I'm not sure
upper layers would ever let it be < 1 though.

Thanks,
Ben

>
>
> Micha?
>

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


From greearb at candelatech.com  Wed Sep 24 07:37:19 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 24 Sep 2014 07:37:19 -0700
Subject: [PATCH v2 03/10] ath10k: support ethtool stats.
In-Reply-To: <CA+BoTQkK=6NfPN9e-3qN2Qaq2RLVdEwrp5x03_T=E2ZLcBeiaA@mail.gmail.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>	<1411507045-18973-3-git-send-email-greearb@candelatech.com>
 <CA+BoTQkK=6NfPN9e-3qN2Qaq2RLVdEwrp5x03_T=E2ZLcBeiaA@mail.gmail.com>
Message-ID: <5422D71F.7080809@candelatech.com>



On 09/24/2014 12:44 AM, Michal Kazior wrote:
> On 23 September 2014 23:17,  <greearb at candelatech.com> wrote:
> [...]
>> +void ath10k_get_et_stats(struct ieee80211_hw *hw,
>> +                        struct ieee80211_vif *vif,
>> +                        struct ethtool_stats *stats, u64 *data)
>> +{
>> +       struct ath10k *ar = hw->priv;
>> +       int i = 0;
>> +       struct ath10k_target_stats *fw_stats;
>> +
>> +       fw_stats = &ar->debug.target_stats;
>> +
>> +       mutex_lock(&ar->conf_mutex);
>> +
>> +       if (ar->state == ATH10K_STATE_ON)
>> +               ath10k_refresh_peer_stats(ar);
>> +
>> +       mutex_unlock(&ar->conf_mutex);
>
> Just for correctness sake - it's probably a good idea to
> mutex_unlock() at the end (i.e. after spin_unlock_bh()) to make sure
> the stats are for this particular request. With your patch there's a
> very slight chance that, e.g. fw_stats debug file is being read at the
> same time and it updates fw stats between the above mutex_unlock() and
> following spin_lock_bh().

That makes no difference at all to the user though, and it is one less
set of nested locks to worry about.

I'd prefer to leave it as is.

Thanks,
Ben

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


From greearb at candelatech.com  Wed Sep 24 07:43:00 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 24 Sep 2014 07:43:00 -0700
Subject: [RFC 2/2] ath10k: re-config ht_caps when chainmask is modified.
In-Reply-To: <CA+BoTQ=fS30xz9KcdBJcioNers6PovOFEeqPCCSFn52HkscXug@mail.gmail.com>
References: <1411518383-32634-1-git-send-email-greearb@candelatech.com>	<1411518383-32634-2-git-send-email-greearb@candelatech.com>
 <CA+BoTQ=fS30xz9KcdBJcioNers6PovOFEeqPCCSFn52HkscXug@mail.gmail.com>
Message-ID: <5422D874.1030007@candelatech.com>



On 09/24/2014 12:51 AM, Michal Kazior wrote:
> On 24 September 2014 02:26,  <greearb at candelatech.com> wrote:
> [...]
>> +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar,
>> +                                                         bool use_cfg_chains)
>>   {
>>          struct ieee80211_sta_vht_cap vht_cap = {0};
>>          u16 mcs_map;
>>          int i;
>> +       int nrf = ar->num_rf_chains;
>> +
>> +       if (use_cfg_chains && ar->cfg_tx_chainmask)
>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
>
> Is use_cfg_chains really necessary here? Is setting tx/rx chainmask to
> 0x0 make any sense at all? Shouldn't we deny it or make it fallback to
> the supported tx/rx chainmask values?

I was thinking we should register with supported values, instead of
configured values.  That is the intention of the code.  In case we
ever re-register after user has configured the system, this should
retain that functionality.  If it is impossible to re-register the
wiphy, then this extra use_cfg_chains logic could go away.

On startup, before user ever configures anything (and most users never will),
the cfg-tx-chainmask is 0, so it would stay with chip's defaults.

Thanks,
Ben

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

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


From michal.kazior at tieto.com  Wed Sep 24 08:05:50 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Wed, 24 Sep 2014 17:05:50 +0200
Subject: [RFC 2/2] ath10k: re-config ht_caps when chainmask is modified.
In-Reply-To: <5422D6CF.10408@candelatech.com>
References: <1411518383-32634-1-git-send-email-greearb@candelatech.com>
 <1411518383-32634-2-git-send-email-greearb@candelatech.com>
 <CA+BoTQ=fS30xz9KcdBJcioNers6PovOFEeqPCCSFn52HkscXug@mail.gmail.com>
 <5422D6CF.10408@candelatech.com>
Message-ID: <CA+BoTQk=X2qVJsY64ZH88h29L6+Y5M9K07nLtzo=0ga1bUsXGw@mail.gmail.com>

On 24 September 2014 16:35, Ben Greear <greearb at candelatech.com> wrote:
> On 09/24/2014 12:51 AM, Michal Kazior wrote:
>> On 24 September 2014 02:26,  <greearb at candelatech.com> wrote:
>> [...]
>>>
>>> +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k
>>> *ar,
>>> +                                                         bool
>>> use_cfg_chains)
>>>   {
>>>          struct ieee80211_sta_vht_cap vht_cap = {0};
>>>          u16 mcs_map;
>>>          int i;
>>> +       int nrf = ar->num_rf_chains;
>>> +
>>> +       if (use_cfg_chains && ar->cfg_tx_chainmask)
>>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
>>
>>
>> Is use_cfg_chains really necessary here? Is setting tx/rx chainmask to
>> 0x0 make any sense at all? Shouldn't we deny it or make it fallback to
>> the supported tx/rx chainmask values?
>
> It would cause the logic to flip back to the defaults, so seems mildly
> useful.  I'm not sure
> upper layers would ever let it be < 1 though.

0 is a valid argument as far as upper layers are concerned and should
be treated as "use all available antennas" (see `iw list` output
before ever setting antenna, after setting to, e.g. 1 and then to 0).

This implies current set_antenna() implementation is actually buggy
(pdev param should involve using supp_tx/rx_chainmask). Your
assumption in recent patches is also incorrect as antenna mask = 0
should imply max nss, not 1.


Micha?


From greearb at candelatech.com  Wed Sep 24 08:15:30 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 24 Sep 2014 08:15:30 -0700
Subject: [RFC 2/2] ath10k: re-config ht_caps when chainmask is modified.
In-Reply-To: <CA+BoTQk=X2qVJsY64ZH88h29L6+Y5M9K07nLtzo=0ga1bUsXGw@mail.gmail.com>
References: <1411518383-32634-1-git-send-email-greearb@candelatech.com>	<1411518383-32634-2-git-send-email-greearb@candelatech.com>	<CA+BoTQ=fS30xz9KcdBJcioNers6PovOFEeqPCCSFn52HkscXug@mail.gmail.com>	<5422D6CF.10408@candelatech.com>
 <CA+BoTQk=X2qVJsY64ZH88h29L6+Y5M9K07nLtzo=0ga1bUsXGw@mail.gmail.com>
Message-ID: <5422E012.1030003@candelatech.com>



On 09/24/2014 08:05 AM, Michal Kazior wrote:
> On 24 September 2014 16:35, Ben Greear <greearb at candelatech.com> wrote:
>> On 09/24/2014 12:51 AM, Michal Kazior wrote:
>>> On 24 September 2014 02:26,  <greearb at candelatech.com> wrote:
>>> [...]
>>>>
>>>> +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k
>>>> *ar,
>>>> +                                                         bool
>>>> use_cfg_chains)
>>>>    {
>>>>           struct ieee80211_sta_vht_cap vht_cap = {0};
>>>>           u16 mcs_map;
>>>>           int i;
>>>> +       int nrf = ar->num_rf_chains;
>>>> +
>>>> +       if (use_cfg_chains && ar->cfg_tx_chainmask)
>>>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
>>>
>>>
>>> Is use_cfg_chains really necessary here? Is setting tx/rx chainmask to
>>> 0x0 make any sense at all? Shouldn't we deny it or make it fallback to
>>> the supported tx/rx chainmask values?
>>
>> It would cause the logic to flip back to the defaults, so seems mildly
>> useful.  I'm not sure
>> upper layers would ever let it be < 1 though.
>
> 0 is a valid argument as far as upper layers are concerned and should
> be treated as "use all available antennas" (see `iw list` output
> before ever setting antenna, after setting to, e.g. 1 and then to 0).
>
> This implies current set_antenna() implementation is actually buggy
> (pdev param should involve using supp_tx/rx_chainmask). Your
> assumption in recent patches is also incorrect as antenna mask = 0
> should imply max nss, not 1.

I will test, but I think you are mis-understanding the logic in my
patches.  I should be using the max nss whenever configured value
is 0.

Thanks,
Ben

>
>
> Micha?
>

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


From greearb at candelatech.com  Wed Sep 24 09:09:14 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 24 Sep 2014 09:09:14 -0700
Subject: [PATCH] ath10k: use configured nss instead of max nss.
In-Reply-To: <CA+BoTQ=mry3tPD-LK+gFD2bC6RU0KvY6LC9=FOAGTLi_1rzUog@mail.gmail.com>
References: <1411426820-4047-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQn9sECMNZsxQpB4i3wHPxfVL+LXq9=2GBd-opH6+9TD=A@mail.gmail.com>
 <5421A44C.8080307@candelatech.com>
 <CA+BoTQ=mry3tPD-LK+gFD2bC6RU0KvY6LC9=FOAGTLi_1rzUog@mail.gmail.com>
Message-ID: <5422ECAA.6050600@candelatech.com>

On 09/24/2014 12:09 AM, Michal Kazior wrote:
> On 23 September 2014 18:48, Ben Greear <greearb at candelatech.com> wrote:
>> On 09/23/2014 01:59 AM, Michal Kazior wrote:
>>> On 23 September 2014 01:00,  <greearb at candelatech.com> wrote:
>>>> From: Ben Greear <greearb at candelatech.com>
> [...]
>>>> @@ -4086,6 +4086,10 @@ ath10k_default_bitrate_mask(struct ath10k *ar,
>>>>         u32 legacy = 0x00ff;
>>>>         u8 ht = 0xff, i;
>>>>         u16 vht = 0x3ff;
>>>> +       u16 nrf = ar->num_rf_chains;
>>>> +
>>>> +       if (ar->cfg_tx_chainmask)
>>>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
> [...]
>>> I think it might be a good idea to convey the limitation of tx/rx
>>> chainmask to the user: you can't change the tx/rx chainmask on the fly
>>> easily (while connected/have associated stations). Or do you plan to
>>> schedule peer reassoc in __ath10k_set_antenna() in a follow up
>>> patch(es) later?
>>
>> My user-space tools assume you have to re-connect (requested from user-space)
>> after changing the chainmask.  I was under the impression that this
>> is how ath9k works, though I could be wrong.
> 
> ath9k doesn't have firmware and it doesn't have a blackbox rate
> control so maybe it doesn't need to worry about this as much as ath10k
> needs to.
> 
> But then this is not something you normally use except some very
> specific use cases so I think it might not be worth the hassle to
> implement full-blown reconfig after chainmask is updated.

See this in net/mac80211/cfg.c:

static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
{
	struct ieee80211_local *local = wiphy_priv(wiphy);

	if (local->started)
		return -EOPNOTSUPP;

	return drv_set_antenna(local, tx_ant, rx_ant);
}


It ensures there are no active vdevs when this change is made, so
you should not have to worry about block-ack or anything similar.


> But it's still probably a good idea to comment the quoted code chunk
> above explaining why nrf is overriden by chainmask (i.e. due to
> firmware rate control issues, right?).

I am not certain it is a bug in the firmware.  The driver should not configure
nss incorrectly as it was doing previous to my recent patches.

Thanks,
Ben

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



From greearb at candelatech.com  Wed Sep 24 09:13:08 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 24 Sep 2014 09:13:08 -0700
Subject: [PATCH] ath10k: request firmware flush in ath10k_flush.
In-Reply-To: <CA+BoTQkZaGSkC9mhE8UF0He0RZWmPghDukdE1A5qiO1UNAZj5Q@mail.gmail.com>
References: <1411151304-31544-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQm1rZO+yBbYxihpgEvR1cGZWS4Pr0AP+KMODcG4jpd_jQ@mail.gmail.com>
 <5421818A.9040501@candelatech.com>
 <CA+BoTQkZaGSkC9mhE8UF0He0RZWmPghDukdE1A5qiO1UNAZj5Q@mail.gmail.com>
Message-ID: <5422ED94.60402@candelatech.com>

On 09/23/2014 11:50 PM, Michal Kazior wrote:
> On 23 September 2014 16:19, Ben Greear <greearb at candelatech.com> wrote:
>> On 09/23/2014 02:16 AM, Michal Kazior wrote:
>>> On 19 September 2014 20:28,  <greearb at candelatech.com> wrote:
>>> [...]
>>>>
>>>> +       /* If we are CT firmware, ask it to flush all tids on all peers
>>>> on
>>>> +        * all vdevs.  Normal firmware will just crash if you do this.
>>>> +        */
>>>> +       if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
>>>> +               ath10k_wmi_peer_flush(ar, 0xFFFFFFFF, peer_addr,
>>>> 0xFFFFFFFF);
>>>
>>> I recall you've explained this some time ago, but can you refresh my
>>> memory, please? Is this any different from iterating over all peers
>>> and flushing each? Or does your firmware do so extra magic that is
>>> impossible to do with normal firmware commands?
>>
>> My firmware does that iteration internally.
>>
>> You could probably do that in the driver, but it would be a lot
>> of messages (for all vdevs, all peers, all tids)...
>> I was not sure if there were limits to the number
>> of commands you should attempt during the flush...
> 
> Thanks. I think ath10k should do this instead of having CT-specific
> flush eventually.

Yes, though I would still like the optimization enabled if my
firmware is running...

> I recall I actually did per-peer flushing in RFC patches a long time
> ago but I didn't pursue getting them merged. I think Denton uses these
> patches in his setup. They don't flush vdev self-peers though (do you
> do that internally?).

I think I do.  Let me check, and send you some details privately.

Thanks,
Ben


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



From greearb at candelatech.com  Wed Sep 24 09:30:58 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 24 Sep 2014 09:30:58 -0700
Subject: [RFC 2/2] ath10k: re-config ht_caps when chainmask is modified.
In-Reply-To: <CA+BoTQk=X2qVJsY64ZH88h29L6+Y5M9K07nLtzo=0ga1bUsXGw@mail.gmail.com>
References: <1411518383-32634-1-git-send-email-greearb@candelatech.com>
 <1411518383-32634-2-git-send-email-greearb@candelatech.com>
 <CA+BoTQ=fS30xz9KcdBJcioNers6PovOFEeqPCCSFn52HkscXug@mail.gmail.com>
 <5422D6CF.10408@candelatech.com>
 <CA+BoTQk=X2qVJsY64ZH88h29L6+Y5M9K07nLtzo=0ga1bUsXGw@mail.gmail.com>
Message-ID: <5422F1C2.4090100@candelatech.com>

On 09/24/2014 08:05 AM, Michal Kazior wrote:
> On 24 September 2014 16:35, Ben Greear <greearb at candelatech.com> wrote:
>> On 09/24/2014 12:51 AM, Michal Kazior wrote:
>>> On 24 September 2014 02:26,  <greearb at candelatech.com> wrote:
>>> [...]
>>>>
>>>> +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k
>>>> *ar,
>>>> +                                                         bool
>>>> use_cfg_chains)
>>>>   {
>>>>          struct ieee80211_sta_vht_cap vht_cap = {0};
>>>>          u16 mcs_map;
>>>>          int i;
>>>> +       int nrf = ar->num_rf_chains;
>>>> +
>>>> +       if (use_cfg_chains && ar->cfg_tx_chainmask)
>>>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
>>>
>>>
>>> Is use_cfg_chains really necessary here? Is setting tx/rx chainmask to
>>> 0x0 make any sense at all? Shouldn't we deny it or make it fallback to
>>> the supported tx/rx chainmask values?
>>
>> It would cause the logic to flip back to the defaults, so seems mildly
>> useful.  I'm not sure
>> upper layers would ever let it be < 1 though.
> 
> 0 is a valid argument as far as upper layers are concerned and should
> be treated as "use all available antennas" (see `iw list` output
> before ever setting antenna, after setting to, e.g. 1 and then to 0).
> 
> This implies current set_antenna() implementation is actually buggy
> (pdev param should involve using supp_tx/rx_chainmask). Your
> assumption in recent patches is also incorrect as antenna mask = 0
> should imply max nss, not 1.

I tested this using:

iw phy wiphy1 set antenna 0 0

This flips it back to 3x3 (I had previously configured it for 2x2),
so I think the patches are working properly.

Thanks,
Ben

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



From greearb at candelatech.com  Wed Sep 24 09:35:06 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Wed, 24 Sep 2014 09:35:06 -0700
Subject: [PATCH 2/2] ath10k: re-config ht_caps when chainmask is modified.
In-Reply-To: <1411576506-11815-1-git-send-email-greearb@candelatech.com>
References: <1411576506-11815-1-git-send-email-greearb@candelatech.com>
Message-ID: <1411576506-11815-2-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

This lets the mac80211 stack use the proper ht-caps when
negotiating with the peer.  Note that all vdevs are guaranteed
to be down when antenna changes, so we can set the ht_caps
without worrying about messing up existing stations.

This patch also moves the get_nss_from_chainmask up in
the file.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 57 ++++++++++++++++++++++++-----------
 1 file changed, 40 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index dbef84a..8bd47ea 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2408,18 +2408,34 @@ void ath10k_halt(struct ath10k *ar)
 	spin_unlock_bh(&ar->data_lock);
 }
 
-static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
+static u32 get_nss_from_chainmask(u16 chain_mask)
+{
+	if ((chain_mask & 0x15) == 0x15)
+		return 4;
+	else if ((chain_mask & 0x7) == 0x7)
+		return 3;
+	else if ((chain_mask & 0x3) == 0x3)
+		return 2;
+	return 1;
+}
+
+static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar,
+							  bool use_cfg_chains)
 {
 	struct ieee80211_sta_vht_cap vht_cap = {0};
 	u16 mcs_map;
 	int i;
+	int nrf = ar->num_rf_chains;
+
+	if (use_cfg_chains && ar->cfg_tx_chainmask)
+		nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
 
 	vht_cap.vht_supported = 1;
 	vht_cap.cap = ar->vht_cap_info;
 
 	mcs_map = 0;
 	for (i = 0; i < 8; i++) {
-		if (i < ar->num_rf_chains)
+		if (i < nrf)
 			mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
 		else
 			mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
@@ -2431,10 +2447,15 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
 	return vht_cap;
 }
 
-static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
+static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar,
+						     bool use_cfg_chains)
 {
 	int i;
 	struct ieee80211_sta_ht_cap ht_cap = {0};
+	int nrf = ar->num_rf_chains;
+
+	if (use_cfg_chains && ar->cfg_tx_chainmask)
+		nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
 
 	if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
 		return ht_cap;
@@ -2486,7 +2507,7 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
 	if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
 		ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
 
-	for (i = 0; i < ar->num_rf_chains; i++)
+	for (i = 0; i < nrf; i++)
 		ht_cap.mcs.rx_mask[i] = 0xFF;
 
 	ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
@@ -2528,6 +2549,8 @@ static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char* dbg)
 static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
 {
 	int ret;
+	struct ieee80211_sta_vht_cap vht_cap;
+	struct ieee80211_sta_ht_cap ht_cap;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
@@ -2537,6 +2560,17 @@ static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
 	ar->cfg_tx_chainmask = tx_ant;
 	ar->cfg_rx_chainmask = rx_ant;
 
+	ht_cap = ath10k_get_ht_cap(ar, true);
+	vht_cap = ath10k_create_vht_cap(ar, true);
+
+	if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY)
+		ar->mac.sbands[IEEE80211_BAND_2GHZ].ht_cap = ht_cap;
+
+	if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) {
+		ar->mac.sbands[IEEE80211_BAND_5GHZ].ht_cap = ht_cap;
+		ar->mac.sbands[IEEE80211_BAND_5GHZ].vht_cap = vht_cap;
+	}
+
 	if ((ar->state != ATH10K_STATE_ON) &&
 	    (ar->state != ATH10K_STATE_RESTARTED))
 		return 0;
@@ -2859,17 +2893,6 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
 	return ret;
 }
 
-static u32 get_nss_from_chainmask(u16 chain_mask)
-{
-	if ((chain_mask & 0x15) == 0x15)
-		return 4;
-	else if ((chain_mask & 0x7) == 0x7)
-		return 3;
-	else if ((chain_mask & 0x3) == 0x3)
-		return 2;
-	return 1;
-}
-
 /*
  * TODO:
  * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
@@ -4864,8 +4887,8 @@ int ath10k_mac_register(struct ath10k *ar)
 
 	SET_IEEE80211_DEV(ar->hw, ar->dev);
 
-	ht_cap = ath10k_get_ht_cap(ar);
-	vht_cap = ath10k_create_vht_cap(ar);
+	ht_cap = ath10k_get_ht_cap(ar, false);
+	vht_cap = ath10k_create_vht_cap(ar, false);
 
 	if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) {
 		channels = kmemdup(ath10k_2ghz_channels,
-- 
1.7.11.7



From greearb at candelatech.com  Wed Sep 24 09:35:05 2014
From: greearb at candelatech.com (greearb at candelatech.com)
Date: Wed, 24 Sep 2014 09:35:05 -0700
Subject: [PATCH 1/2] ath10k: move create-ht-cap methods above set-antenna.
Message-ID: <1411576506-11815-1-git-send-email-greearb@candelatech.com>

From: Ben Greear <greearb at candelatech.com>

We will need to use these in set-antenna, so move them
so that we do not have to define the method signatures.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 172 +++++++++++++++++-----------------
 1 file changed, 86 insertions(+), 86 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index bde3a2f..dbef84a 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2408,6 +2408,92 @@ void ath10k_halt(struct ath10k *ar)
 	spin_unlock_bh(&ar->data_lock);
 }
 
+static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
+{
+	struct ieee80211_sta_vht_cap vht_cap = {0};
+	u16 mcs_map;
+	int i;
+
+	vht_cap.vht_supported = 1;
+	vht_cap.cap = ar->vht_cap_info;
+
+	mcs_map = 0;
+	for (i = 0; i < 8; i++) {
+		if (i < ar->num_rf_chains)
+			mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
+		else
+			mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
+	}
+
+	vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
+	vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
+
+	return vht_cap;
+}
+
+static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
+{
+	int i;
+	struct ieee80211_sta_ht_cap ht_cap = {0};
+
+	if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
+		return ht_cap;
+
+	ht_cap.ht_supported = 1;
+	ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+	ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
+	ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
+	ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
+
+	if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
+		ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
+
+	if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
+		ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+
+	if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
+		u32 smps;
+
+		smps   = WLAN_HT_CAP_SM_PS_DYNAMIC;
+		smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
+
+		ht_cap.cap |= smps;
+	}
+
+	if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
+		ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
+
+	if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
+		u32 stbc;
+
+		stbc   = ar->ht_cap_info;
+		stbc  &= WMI_HT_CAP_RX_STBC;
+		stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
+		stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
+		stbc  &= IEEE80211_HT_CAP_RX_STBC;
+
+		ht_cap.cap |= stbc;
+	}
+
+	if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
+		ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
+
+	if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
+		ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
+
+	/* max AMSDU is implicitly taken from vht_cap_info */
+	if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
+		ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
+
+	for (i = 0; i < ar->num_rf_chains; i++)
+		ht_cap.mcs.rx_mask[i] = 0xFF;
+
+	ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
+
+	return ht_cap;
+}
+
 static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
 {
 	struct ath10k *ar = hw->priv;
@@ -4735,92 +4821,6 @@ static const struct ieee80211_iface_combination ath10k_10x_if_comb[] = {
 	},
 };
 
-static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
-{
-	struct ieee80211_sta_vht_cap vht_cap = {0};
-	u16 mcs_map;
-	int i;
-
-	vht_cap.vht_supported = 1;
-	vht_cap.cap = ar->vht_cap_info;
-
-	mcs_map = 0;
-	for (i = 0; i < 8; i++) {
-		if (i < ar->num_rf_chains)
-			mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
-		else
-			mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
-	}
-
-	vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
-	vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
-
-	return vht_cap;
-}
-
-static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
-{
-	int i;
-	struct ieee80211_sta_ht_cap ht_cap = {0};
-
-	if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
-		return ht_cap;
-
-	ht_cap.ht_supported = 1;
-	ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
-	ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
-	ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
-	ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
-	ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
-
-	if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
-		ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
-
-	if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
-		ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
-
-	if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
-		u32 smps;
-
-		smps   = WLAN_HT_CAP_SM_PS_DYNAMIC;
-		smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
-
-		ht_cap.cap |= smps;
-	}
-
-	if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
-		ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
-
-	if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
-		u32 stbc;
-
-		stbc   = ar->ht_cap_info;
-		stbc  &= WMI_HT_CAP_RX_STBC;
-		stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
-		stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
-		stbc  &= IEEE80211_HT_CAP_RX_STBC;
-
-		ht_cap.cap |= stbc;
-	}
-
-	if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
-		ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
-
-	if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
-		ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
-
-	/* max AMSDU is implicitly taken from vht_cap_info */
-	if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
-		ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
-
-	for (i = 0; i < ar->num_rf_chains; i++)
-		ht_cap.mcs.rx_mask[i] = 0xFF;
-
-	ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
-
-	return ht_cap;
-}
-
 static void ath10k_get_arvif_iter(void *data, u8 *mac,
 				  struct ieee80211_vif *vif)
 {
-- 
1.7.11.7



From greearb at candelatech.com  Wed Sep 24 16:54:01 2014
From: greearb at candelatech.com (Ben Greear)
Date: Wed, 24 Sep 2014 16:54:01 -0700
Subject: More fun with firmware crashes.
Message-ID: <54235999.1020600@candelatech.com>

Here's a fun case:  Firmware crashed before device could register,
so there is no debugfs to grab the binary crash dump...hope it
can be decoded from what is printed in the logs!

ath10k_pci 0000:04:00.0: firmware 10.1.467-ct-swcrypt-diet-012 booted
ath10k_pci 0000:04:00.0: firmware crashed! (uuid 31d718ad-2aec-4f41-bc2a-3d127a15d86d)
ath10k_pci 0000:04:00.0: qca988x hw2.0 (0x4100016c, 0x043202ff) fw 10.1.467-ct-swcrypt-diet-012 api 2 htt 0.0
ath10k_pci 0000:04:00.0: debug 1 debugfs 1 tracing 1 dfs 1 testmode 1
ath10k_pci 0000:04:00.0: firmware register dump:
ath10k_pci 0000:04:00.0: [00]: 0x4100016C 0x000015B3 0x009B4260 0x00955B31
ath10k_pci 0000:04:00.0: [04]: 0x009B4260 0x00060730 0x00000005 0x00000003
ath10k_pci 0000:04:00.0: [08]: 0x0044E6C4 0x00000E50 0x00000000 0x0044E5A4
ath10k_pci 0000:04:00.0: [12]: 0x00000009 0x00000000 0x00958360 0x0095836B
ath10k_pci 0000:04:00.0: [16]: 0x00958080 0x0094085D 0x00000000 0x00000000
ath10k_pci 0000:04:00.0: [20]: 0x409B4260 0x0040AC84 0x00000001 0x00000000
ath10k_pci 0000:04:00.0: [24]: 0x809AD621 0x0040ACE4 0x00000000 0xC09B4260
ath10k_pci 0000:04:00.0: [28]: 0x809897A2 0x0040AD24 0x0040AD44 0x0040F668
ath10k_pci 0000:04:00.0: [32]: 0x80988342 0x0040AD44 0x0040F668 0x0040F828
ath10k_pci 0000:04:00.0: [36]: 0x8098927D 0x0040AD74 0x0040F668 0x00000001
ath10k_pci 0000:04:00.0: [40]: 0x809AC99E 0x0040ADB4 0x0040F668 0x0000A000
ath10k_pci 0000:04:00.0: [44]: 0x809A8FFA 0x0040ADD4 0x00400000 0x0041578C
ath10k_pci 0000:04:00.0: [48]: 0x809A8783 0x0040AE24 0x0040AE48 0x00410ECC
ath10k_pci 0000:04:00.0: [52]: 0x809486FA 0x0040AE44 0x00000001 0x00000000
ath10k_pci 0000:04:00.0: [56]: 0x80948E2C 0x0040AEA4 0x0041D508 0x004115F4
ath10k_pci 0000:04:00.0: wmi unified ready event not received
ath10k_pci 0000:04:00.0: boot hif stop
ath10k_pci 0000:04:00.0: boot warm reset
ath10k_pci 0000:04:00.0: boot host cpu intr cause: 0x00047800
ath10k_pci 0000:04:00.0: boot target cpu intr cause: 0x00006000
ath10k_pci 0000:04:00.0: boot host cpu intr cause: 0x00000000
ath10k_pci 0000:04:00.0: boot target cpu intr cause: 0x00000000
ath10k_pci 0000:04:00.0: boot target reset state: 0x00000800
ath10k_pci 0000:04:00.0: boot warm reset complete
ath10k_pci 0000:04:00.0: could not init core (-110)
ath10k_pci 0000:04:00.0: boot hif power down
ath10k_pci 0000:04:00.0: boot warm reset
ath10k_pci 0000:04:00.0: boot host cpu intr cause: 0x00000000
ath10k_pci 0000:04:00.0: boot target cpu intr cause: 0x00000000
ath10k_pci 0000:04:00.0: boot host cpu intr cause: 0x00000000
ath10k_pci 0000:04:00.0: boot target cpu intr cause: 0x00000000
ath10k_pci 0000:04:00.0: boot target reset state: 0x00000800
ath10k_pci 0000:04:00.0: boot warm reset complete
ath10k_pci 0000:04:00.0: could not probe fw (-110)
ath10k_pci 0000:04:00.0: cannot restart a device that hasn't been started

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



From michal.kazior at tieto.com  Wed Sep 24 23:16:03 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 25 Sep 2014 08:16:03 +0200
Subject: [PATCH] ath10k: use configured nss instead of max nss.
In-Reply-To: <5422ECAA.6050600@candelatech.com>
References: <1411426820-4047-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQn9sECMNZsxQpB4i3wHPxfVL+LXq9=2GBd-opH6+9TD=A@mail.gmail.com>
 <5421A44C.8080307@candelatech.com>
 <CA+BoTQ=mry3tPD-LK+gFD2bC6RU0KvY6LC9=FOAGTLi_1rzUog@mail.gmail.com>
 <5422ECAA.6050600@candelatech.com>
Message-ID: <CA+BoTQnLbJ7cnyUo-o6Ebx9pAxGyAHv8W8eKE8BEd7Kh8f+uTw@mail.gmail.com>

On 24 September 2014 18:09, Ben Greear <greearb at candelatech.com> wrote:
> On 09/24/2014 12:09 AM, Michal Kazior wrote:
>> On 23 September 2014 18:48, Ben Greear <greearb at candelatech.com> wrote:
>>> On 09/23/2014 01:59 AM, Michal Kazior wrote:
>>>> On 23 September 2014 01:00,  <greearb at candelatech.com> wrote:
>>>>> From: Ben Greear <greearb at candelatech.com>
>> [...]
>>>>> @@ -4086,6 +4086,10 @@ ath10k_default_bitrate_mask(struct ath10k *ar,
>>>>>         u32 legacy = 0x00ff;
>>>>>         u8 ht = 0xff, i;
>>>>>         u16 vht = 0x3ff;
>>>>> +       u16 nrf = ar->num_rf_chains;
>>>>> +
>>>>> +       if (ar->cfg_tx_chainmask)
>>>>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
>> [...]
>>>> I think it might be a good idea to convey the limitation of tx/rx
>>>> chainmask to the user: you can't change the tx/rx chainmask on the fly
>>>> easily (while connected/have associated stations). Or do you plan to
>>>> schedule peer reassoc in __ath10k_set_antenna() in a follow up
>>>> patch(es) later?
[...]
> See this in net/mac80211/cfg.c:
>
> static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
> {
>         struct ieee80211_local *local = wiphy_priv(wiphy);
>
>         if (local->started)
>                 return -EOPNOTSUPP;

Ah, thanks! So my argument is invalid :)


>> But it's still probably a good idea to comment the quoted code chunk
>> above explaining why nrf is overriden by chainmask (i.e. due to
>> firmware rate control issues, right?).
>
> I am not certain it is a bug in the firmware.  The driver should not configure
> nss incorrectly as it was doing previous to my recent patches.

Since firmware does rate control it just seems redundant for the
driver to update both chainmask and nss (the first implies the other).
But maybe that's just me.


Micha?


From michal.kazior at tieto.com  Wed Sep 24 23:23:35 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 25 Sep 2014 08:23:35 +0200
Subject: [RFC 2/2] ath10k: re-config ht_caps when chainmask is modified.
In-Reply-To: <5422F1C2.4090100@candelatech.com>
References: <1411518383-32634-1-git-send-email-greearb@candelatech.com>
 <1411518383-32634-2-git-send-email-greearb@candelatech.com>
 <CA+BoTQ=fS30xz9KcdBJcioNers6PovOFEeqPCCSFn52HkscXug@mail.gmail.com>
 <5422D6CF.10408@candelatech.com>
 <CA+BoTQk=X2qVJsY64ZH88h29L6+Y5M9K07nLtzo=0ga1bUsXGw@mail.gmail.com>
 <5422F1C2.4090100@candelatech.com>
Message-ID: <CA+BoTQkncctvMFx7U0Qzq7+7W2o9Vo5qKcDEi6DUdJTEQWDfAA@mail.gmail.com>

On 24 September 2014 18:30, Ben Greear <greearb at candelatech.com> wrote:
> On 09/24/2014 08:05 AM, Michal Kazior wrote:
>> On 24 September 2014 16:35, Ben Greear <greearb at candelatech.com> wrote:
>>> On 09/24/2014 12:51 AM, Michal Kazior wrote:
>>>> On 24 September 2014 02:26,  <greearb at candelatech.com> wrote:
>>>> [...]
>>>>>
>>>>> +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k
>>>>> *ar,
>>>>> +                                                         bool
>>>>> use_cfg_chains)
>>>>>   {
>>>>>          struct ieee80211_sta_vht_cap vht_cap = {0};
>>>>>          u16 mcs_map;
>>>>>          int i;
>>>>> +       int nrf = ar->num_rf_chains;
>>>>> +
>>>>> +       if (use_cfg_chains && ar->cfg_tx_chainmask)
>>>>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
>>>>
>>>>
>>>> Is use_cfg_chains really necessary here? Is setting tx/rx chainmask to
>>>> 0x0 make any sense at all? Shouldn't we deny it or make it fallback to
>>>> the supported tx/rx chainmask values?
>>>
>>> It would cause the logic to flip back to the defaults, so seems mildly
>>> useful.  I'm not sure
>>> upper layers would ever let it be < 1 though.
>>
>> 0 is a valid argument as far as upper layers are concerned and should
>> be treated as "use all available antennas" (see `iw list` output
>> before ever setting antenna, after setting to, e.g. 1 and then to 0).
>>
>> This implies current set_antenna() implementation is actually buggy
>> (pdev param should involve using supp_tx/rx_chainmask). Your
>> assumption in recent patches is also incorrect as antenna mask = 0
>> should imply max nss, not 1.
>
> I tested this using:
>
> iw phy wiphy1 set antenna 0 0
>
> This flips it back to 3x3 (I had previously configured it for 2x2),
> so I think the patches are working properly.

Mea culpa. It will flip back indeed.

But I still don't see why use_cfg_chains is necessary. I don't see how
cfg_tx_chainmask could be non-zero when ath10k is registering to mac.


Micha?


From michal.kazior at tieto.com  Thu Sep 25 03:33:46 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 25 Sep 2014 12:33:46 +0200
Subject: [PATCH 0/4] ath10k: fix/cleanup fw stats
Message-ID: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>

Hi,

This cleans up and fixes fw stats aggregation.


Michal Kazior (4):
  ath10k: split wmi stats parsing
  ath10k: rename fw_stats related stuff
  ath10k: request fw_stats once on open
  ath10k: fix fw stats processing

 drivers/net/wireless/ath/ath10k/core.h  |  26 +-
 drivers/net/wireless/ath/ath10k/debug.c | 476 ++++++++++++++++++--------------
 drivers/net/wireless/ath/ath10k/debug.h |   7 +-
 drivers/net/wireless/ath/ath10k/wmi.c   | 190 ++++++++++++-
 drivers/net/wireless/ath/ath10k/wmi.h   |  24 +-
 5 files changed, 483 insertions(+), 240 deletions(-)

-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 25 03:33:48 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 25 Sep 2014 12:33:48 +0200
Subject: [PATCH 2/4] ath10k: rename fw_stats related stuff
In-Reply-To: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411641230-18785-3-git-send-email-michal.kazior@tieto.com>

The naming was a bit inconsistent.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h  | 11 +++++------
 drivers/net/wireless/ath/ath10k/debug.c | 18 +++++++++---------
 drivers/net/wireless/ath/ath10k/debug.h |  6 +++---
 drivers/net/wireless/ath/ath10k/wmi.c   | 12 ++++++------
 drivers/net/wireless/ath/ath10k/wmi.h   |  4 ++--
 5 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 8a997b6..082a8dad 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -116,14 +116,14 @@ struct ath10k_wmi {
 	struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
 };
 
-struct ath10k_peer_stat {
+struct ath10k_fw_stats_peer {
 	u8 peer_macaddr[ETH_ALEN];
 	u32 peer_rssi;
 	u32 peer_tx_rate;
 	u32 peer_rx_rate; /* 10x only */
 };
 
-struct ath10k_target_stats {
+struct ath10k_fw_stats {
 	/* PDEV stats */
 	s32 ch_noise_floor;
 	u32 tx_frame_count;
@@ -183,7 +183,7 @@ struct ath10k_target_stats {
 
 	/* PEER STATS */
 	u8 peers;
-	struct ath10k_peer_stat peer_stat[TARGET_NUM_PEERS];
+	struct ath10k_fw_stats_peer peer_stat[TARGET_NUM_PEERS];
 
 	/* TODO: Beacon filter stats */
 
@@ -292,11 +292,10 @@ struct ath10k_fw_crash_data {
 struct ath10k_debug {
 	struct dentry *debugfs_phy;
 
-	struct ath10k_target_stats target_stats;
+	struct ath10k_fw_stats fw_stats;
+	struct completion fw_stats_complete;
 	DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
 
-	struct completion event_stats_compl;
-
 	unsigned long htt_stats_mask;
 	struct delayed_work htt_stats_dwork;
 	struct ath10k_dfs_stats dfs_stats;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 0afd1aa..97b5c16 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -242,29 +242,29 @@ static const struct file_operations fops_wmi_services = {
 	.llseek = default_llseek,
 };
 
-void ath10k_debug_read_target_stats(struct ath10k *ar, struct sk_buff *skb)
+void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
 {
 	int ret;
 
 	spin_lock_bh(&ar->data_lock);
 
-	ret = ath10k_wmi_pull_fw_stats(ar, skb, &ar->debug.target_stats);
+	ret = ath10k_wmi_pull_fw_stats(ar, skb, &ar->debug.fw_stats);
 	if (ret) {
 		ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
 		goto unlock;
 	}
 
-	complete(&ar->debug.event_stats_compl);
+	complete(&ar->debug.fw_stats_complete);
 
 unlock:
 	spin_unlock_bh(&ar->data_lock);
 }
 
-static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
+static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
 				    size_t count, loff_t *ppos)
 {
 	struct ath10k *ar = file->private_data;
-	struct ath10k_target_stats *fw_stats;
+	struct ath10k_fw_stats *fw_stats;
 	char *buf = NULL;
 	unsigned int len = 0, buf_len = 8000;
 	ssize_t ret_cnt = 0;
@@ -272,7 +272,7 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
 	int i;
 	int ret;
 
-	fw_stats = &ar->debug.target_stats;
+	fw_stats = &ar->debug.fw_stats;
 
 	mutex_lock(&ar->conf_mutex);
 
@@ -289,7 +289,7 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
 		goto exit;
 	}
 
-	left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
+	left = wait_for_completion_timeout(&ar->debug.fw_stats_complete, 1*HZ);
 	if (left <= 0)
 		goto exit;
 
@@ -448,7 +448,7 @@ exit:
 }
 
 static const struct file_operations fops_fw_stats = {
-	.read = ath10k_read_fw_stats,
+	.read = ath10k_fw_stats_read,
 	.open = simple_open,
 	.owner = THIS_MODULE,
 	.llseek = default_llseek,
@@ -1072,7 +1072,7 @@ int ath10k_debug_register(struct ath10k *ar)
 	INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
 			  ath10k_debug_htt_stats_dwork);
 
-	init_completion(&ar->debug.event_stats_compl);
+	init_completion(&ar->debug.fw_stats_complete);
 
 	debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
 			    &fops_fw_stats);
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index f7e8131..8d15bce 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -55,7 +55,7 @@ void ath10k_debug_unregister(struct ath10k *ar);
 void ath10k_debug_read_service_map(struct ath10k *ar,
 				   const void *service_map,
 				   size_t map_size);
-void ath10k_debug_read_target_stats(struct ath10k *ar, struct sk_buff *skb);
+void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
 struct ath10k_fw_crash_data *
 ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
 
@@ -97,8 +97,8 @@ static inline void ath10k_debug_read_service_map(struct ath10k *ar,
 {
 }
 
-static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
-						  struct sk_buff *skb)
+static inline void ath10k_debug_fw_stats_process(struct ath10k *ar,
+						 struct sk_buff *skb)
 {
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 8e2d021..c4640aa 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1330,7 +1330,7 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
 }
 
 static void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src,
-				       struct ath10k_target_stats *dst)
+				       struct ath10k_fw_stats *dst)
 {
 	const struct wal_dbg_tx_stats *tx = &src->wal.tx;
 	const struct wal_dbg_rx_stats *rx = &src->wal.rx;
@@ -1383,7 +1383,7 @@ static void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src,
 }
 
 static void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
-				       struct ath10k_peer_stat *dst)
+				       struct ath10k_fw_stats_peer *dst)
 {
 	ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
 	dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
@@ -1392,7 +1392,7 @@ static void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
 
 static int ath10k_wmi_main_pull_fw_stats(struct ath10k *ar,
 					 struct sk_buff *skb,
-					 struct ath10k_target_stats *stats)
+					 struct ath10k_fw_stats *stats)
 {
 	const struct wmi_stats_event *ev = (void *)skb->data;
 	u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
@@ -1432,7 +1432,7 @@ static int ath10k_wmi_main_pull_fw_stats(struct ath10k *ar,
 
 static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar,
 					struct sk_buff *skb,
-					struct ath10k_target_stats *stats)
+					struct ath10k_fw_stats *stats)
 {
 	const struct wmi_stats_event *ev = (void *)skb->data;
 	u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
@@ -1481,7 +1481,7 @@ static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar,
 }
 
 int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
-			     struct ath10k_target_stats *stats)
+			     struct ath10k_fw_stats *stats)
 {
 	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
 		return ath10k_wmi_10x_pull_fw_stats(ar, skb, stats);
@@ -1493,7 +1493,7 @@ static void ath10k_wmi_event_update_stats(struct ath10k *ar,
 					  struct sk_buff *skb)
 {
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
-	ath10k_debug_read_target_stats(ar, skb);
+	ath10k_debug_fw_stats_process(ar, skb);
 }
 
 static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 4ce8e3c..6243dbe 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -4573,7 +4573,7 @@ struct wmi_svc_rdy_ev_arg {
 
 struct ath10k;
 struct ath10k_vif;
-struct ath10k_target_stats;
+struct ath10k_fw_stats;
 
 int ath10k_wmi_attach(struct ath10k *ar);
 void ath10k_wmi_detach(struct ath10k *ar);
@@ -4646,6 +4646,6 @@ int ath10k_wmi_force_fw_hang(struct ath10k *ar,
 int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb);
 int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable);
 int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
-			     struct ath10k_target_stats *stats);
+			     struct ath10k_fw_stats *stats);
 
 #endif /* _WMI_H_ */
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 25 03:33:47 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 25 Sep 2014 12:33:47 +0200
Subject: [PATCH 1/4] ath10k: split wmi stats parsing
In-Reply-To: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411641230-18785-2-git-send-email-michal.kazior@tieto.com>

The parsing function was rather complex. Simplify
by splitting it up into firmware branch specific
implementations.

While at it move the parsing code into wmi.c where
it belongs.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/debug.c | 127 ++----------------------
 drivers/net/wireless/ath/ath10k/debug.h |   5 +-
 drivers/net/wireless/ath/ath10k/wmi.c   | 165 +++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/wmi.h   |  24 ++---
 4 files changed, 180 insertions(+), 141 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 101c6f9..0afd1aa 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -242,133 +242,22 @@ static const struct file_operations fops_wmi_services = {
 	.llseek = default_llseek,
 };
 
-void ath10k_debug_read_target_stats(struct ath10k *ar,
-				    struct wmi_stats_event *ev)
+void ath10k_debug_read_target_stats(struct ath10k *ar, struct sk_buff *skb)
 {
-	u8 *tmp = ev->data;
-	struct ath10k_target_stats *stats;
-	int num_pdev_stats, num_vdev_stats, num_peer_stats;
-	struct wmi_pdev_stats_10x *ps;
-	int i;
+	int ret;
 
 	spin_lock_bh(&ar->data_lock);
 
-	stats = &ar->debug.target_stats;
-
-	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); /* 0 or 1 */
-	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); /* 0 or max vdevs */
-	num_peer_stats = __le32_to_cpu(ev->num_peer_stats); /* 0 or max peers */
-
-	if (num_pdev_stats) {
-		ps = (struct wmi_pdev_stats_10x *)tmp;
-
-		stats->ch_noise_floor = __le32_to_cpu(ps->chan_nf);
-		stats->tx_frame_count = __le32_to_cpu(ps->tx_frame_count);
-		stats->rx_frame_count = __le32_to_cpu(ps->rx_frame_count);
-		stats->rx_clear_count = __le32_to_cpu(ps->rx_clear_count);
-		stats->cycle_count = __le32_to_cpu(ps->cycle_count);
-		stats->phy_err_count = __le32_to_cpu(ps->phy_err_count);
-		stats->chan_tx_power = __le32_to_cpu(ps->chan_tx_pwr);
-
-		stats->comp_queued = __le32_to_cpu(ps->wal.tx.comp_queued);
-		stats->comp_delivered =
-			__le32_to_cpu(ps->wal.tx.comp_delivered);
-		stats->msdu_enqued = __le32_to_cpu(ps->wal.tx.msdu_enqued);
-		stats->mpdu_enqued = __le32_to_cpu(ps->wal.tx.mpdu_enqued);
-		stats->wmm_drop = __le32_to_cpu(ps->wal.tx.wmm_drop);
-		stats->local_enqued = __le32_to_cpu(ps->wal.tx.local_enqued);
-		stats->local_freed = __le32_to_cpu(ps->wal.tx.local_freed);
-		stats->hw_queued = __le32_to_cpu(ps->wal.tx.hw_queued);
-		stats->hw_reaped = __le32_to_cpu(ps->wal.tx.hw_reaped);
-		stats->underrun = __le32_to_cpu(ps->wal.tx.underrun);
-		stats->tx_abort = __le32_to_cpu(ps->wal.tx.tx_abort);
-		stats->mpdus_requed = __le32_to_cpu(ps->wal.tx.mpdus_requed);
-		stats->tx_ko = __le32_to_cpu(ps->wal.tx.tx_ko);
-		stats->data_rc = __le32_to_cpu(ps->wal.tx.data_rc);
-		stats->self_triggers = __le32_to_cpu(ps->wal.tx.self_triggers);
-		stats->sw_retry_failure =
-			__le32_to_cpu(ps->wal.tx.sw_retry_failure);
-		stats->illgl_rate_phy_err =
-			__le32_to_cpu(ps->wal.tx.illgl_rate_phy_err);
-		stats->pdev_cont_xretry =
-			__le32_to_cpu(ps->wal.tx.pdev_cont_xretry);
-		stats->pdev_tx_timeout =
-			__le32_to_cpu(ps->wal.tx.pdev_tx_timeout);
-		stats->pdev_resets = __le32_to_cpu(ps->wal.tx.pdev_resets);
-		stats->phy_underrun = __le32_to_cpu(ps->wal.tx.phy_underrun);
-		stats->txop_ovf = __le32_to_cpu(ps->wal.tx.txop_ovf);
-
-		stats->mid_ppdu_route_change =
-			__le32_to_cpu(ps->wal.rx.mid_ppdu_route_change);
-		stats->status_rcvd = __le32_to_cpu(ps->wal.rx.status_rcvd);
-		stats->r0_frags = __le32_to_cpu(ps->wal.rx.r0_frags);
-		stats->r1_frags = __le32_to_cpu(ps->wal.rx.r1_frags);
-		stats->r2_frags = __le32_to_cpu(ps->wal.rx.r2_frags);
-		stats->r3_frags = __le32_to_cpu(ps->wal.rx.r3_frags);
-		stats->htt_msdus = __le32_to_cpu(ps->wal.rx.htt_msdus);
-		stats->htt_mpdus = __le32_to_cpu(ps->wal.rx.htt_mpdus);
-		stats->loc_msdus = __le32_to_cpu(ps->wal.rx.loc_msdus);
-		stats->loc_mpdus = __le32_to_cpu(ps->wal.rx.loc_mpdus);
-		stats->oversize_amsdu =
-			__le32_to_cpu(ps->wal.rx.oversize_amsdu);
-		stats->phy_errs = __le32_to_cpu(ps->wal.rx.phy_errs);
-		stats->phy_err_drop = __le32_to_cpu(ps->wal.rx.phy_err_drop);
-		stats->mpdu_errs = __le32_to_cpu(ps->wal.rx.mpdu_errs);
-
-		if (test_bit(ATH10K_FW_FEATURE_WMI_10X,
-			     ar->fw_features)) {
-			stats->ack_rx_bad = __le32_to_cpu(ps->ack_rx_bad);
-			stats->rts_bad = __le32_to_cpu(ps->rts_bad);
-			stats->rts_good = __le32_to_cpu(ps->rts_good);
-			stats->fcs_bad = __le32_to_cpu(ps->fcs_bad);
-			stats->no_beacons = __le32_to_cpu(ps->no_beacons);
-			stats->mib_int_count = __le32_to_cpu(ps->mib_int_count);
-			tmp += sizeof(struct wmi_pdev_stats_10x);
-		} else {
-			tmp += sizeof(struct wmi_pdev_stats_old);
-		}
-	}
-
-	/* 0 or max vdevs */
-	/* Currently firmware does not support VDEV stats */
-	if (num_vdev_stats) {
-		struct wmi_vdev_stats *vdev_stats;
-
-		for (i = 0; i < num_vdev_stats; i++) {
-			vdev_stats = (struct wmi_vdev_stats *)tmp;
-			tmp += sizeof(struct wmi_vdev_stats);
-		}
+	ret = ath10k_wmi_pull_fw_stats(ar, skb, &ar->debug.target_stats);
+	if (ret) {
+		ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
+		goto unlock;
 	}
 
-	if (num_peer_stats) {
-		struct wmi_peer_stats_10x *peer_stats;
-		struct ath10k_peer_stat *s;
-
-		stats->peers = num_peer_stats;
-
-		for (i = 0; i < num_peer_stats; i++) {
-			peer_stats = (struct wmi_peer_stats_10x *)tmp;
-			s = &stats->peer_stat[i];
-
-			memcpy(s->peer_macaddr, &peer_stats->peer_macaddr.addr,
-			       ETH_ALEN);
-			s->peer_rssi = __le32_to_cpu(peer_stats->peer_rssi);
-			s->peer_tx_rate =
-				__le32_to_cpu(peer_stats->peer_tx_rate);
-			if (test_bit(ATH10K_FW_FEATURE_WMI_10X,
-				     ar->fw_features)) {
-				s->peer_rx_rate =
-					__le32_to_cpu(peer_stats->peer_rx_rate);
-				tmp += sizeof(struct wmi_peer_stats_10x);
-
-			} else {
-				tmp += sizeof(struct wmi_peer_stats_old);
-			}
-		}
-	}
+	complete(&ar->debug.event_stats_compl);
 
+unlock:
 	spin_unlock_bh(&ar->data_lock);
-	complete(&ar->debug.event_stats_compl);
 }
 
 static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index d6276fe..f7e8131 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -55,8 +55,7 @@ void ath10k_debug_unregister(struct ath10k *ar);
 void ath10k_debug_read_service_map(struct ath10k *ar,
 				   const void *service_map,
 				   size_t map_size);
-void ath10k_debug_read_target_stats(struct ath10k *ar,
-				    struct wmi_stats_event *ev);
+void ath10k_debug_read_target_stats(struct ath10k *ar, struct sk_buff *skb);
 struct ath10k_fw_crash_data *
 ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
 
@@ -99,7 +98,7 @@ static inline void ath10k_debug_read_service_map(struct ath10k *ar,
 }
 
 static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
-						  struct wmi_stats_event *ev)
+						  struct sk_buff *skb)
 {
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index bfc1fb3..8e2d021 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1329,14 +1329,171 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
 	return 0;
 }
 
+static void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src,
+				       struct ath10k_target_stats *dst)
+{
+	const struct wal_dbg_tx_stats *tx = &src->wal.tx;
+	const struct wal_dbg_rx_stats *rx = &src->wal.rx;
+
+	dst->ch_noise_floor = __le32_to_cpu(src->chan_nf);
+	dst->tx_frame_count = __le32_to_cpu(src->tx_frame_count);
+	dst->rx_frame_count = __le32_to_cpu(src->rx_frame_count);
+	dst->rx_clear_count = __le32_to_cpu(src->rx_clear_count);
+	dst->cycle_count = __le32_to_cpu(src->cycle_count);
+	dst->phy_err_count = __le32_to_cpu(src->phy_err_count);
+	dst->chan_tx_power = __le32_to_cpu(src->chan_tx_pwr);
+
+	dst->comp_queued = __le32_to_cpu(tx->comp_queued);
+	dst->comp_delivered = __le32_to_cpu(tx->comp_delivered);
+	dst->msdu_enqued = __le32_to_cpu(tx->msdu_enqued);
+	dst->mpdu_enqued = __le32_to_cpu(tx->mpdu_enqued);
+	dst->wmm_drop = __le32_to_cpu(tx->wmm_drop);
+	dst->local_enqued = __le32_to_cpu(tx->local_enqued);
+	dst->local_freed = __le32_to_cpu(tx->local_freed);
+	dst->hw_queued = __le32_to_cpu(tx->hw_queued);
+	dst->hw_reaped = __le32_to_cpu(tx->hw_reaped);
+	dst->underrun = __le32_to_cpu(tx->underrun);
+	dst->tx_abort = __le32_to_cpu(tx->tx_abort);
+	dst->mpdus_requed = __le32_to_cpu(tx->mpdus_requed);
+	dst->tx_ko = __le32_to_cpu(tx->tx_ko);
+	dst->data_rc = __le32_to_cpu(tx->data_rc);
+	dst->self_triggers = __le32_to_cpu(tx->self_triggers);
+	dst->sw_retry_failure = __le32_to_cpu(tx->sw_retry_failure);
+	dst->illgl_rate_phy_err = __le32_to_cpu(tx->illgl_rate_phy_err);
+	dst->pdev_cont_xretry = __le32_to_cpu(tx->pdev_cont_xretry);
+	dst->pdev_tx_timeout = __le32_to_cpu(tx->pdev_tx_timeout);
+	dst->pdev_resets = __le32_to_cpu(tx->pdev_resets);
+	dst->phy_underrun = __le32_to_cpu(tx->phy_underrun);
+	dst->txop_ovf = __le32_to_cpu(tx->txop_ovf);
+
+	dst->mid_ppdu_route_change = __le32_to_cpu(rx->mid_ppdu_route_change);
+	dst->status_rcvd = __le32_to_cpu(rx->status_rcvd);
+	dst->r0_frags = __le32_to_cpu(rx->r0_frags);
+	dst->r1_frags = __le32_to_cpu(rx->r1_frags);
+	dst->r2_frags = __le32_to_cpu(rx->r2_frags);
+	dst->r3_frags = __le32_to_cpu(rx->r3_frags);
+	dst->htt_msdus = __le32_to_cpu(rx->htt_msdus);
+	dst->htt_mpdus = __le32_to_cpu(rx->htt_mpdus);
+	dst->loc_msdus = __le32_to_cpu(rx->loc_msdus);
+	dst->loc_mpdus = __le32_to_cpu(rx->loc_mpdus);
+	dst->oversize_amsdu = __le32_to_cpu(rx->oversize_amsdu);
+	dst->phy_errs = __le32_to_cpu(rx->phy_errs);
+	dst->phy_err_drop = __le32_to_cpu(rx->phy_err_drop);
+	dst->mpdu_errs = __le32_to_cpu(rx->mpdu_errs);
+}
+
+static void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
+				       struct ath10k_peer_stat *dst)
+{
+	ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
+	dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
+	dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
+}
+
+static int ath10k_wmi_main_pull_fw_stats(struct ath10k *ar,
+					 struct sk_buff *skb,
+					 struct ath10k_target_stats *stats)
+{
+	const struct wmi_stats_event *ev = (void *)skb->data;
+	u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
+	int i;
+
+	if (!skb_pull(skb, sizeof(*ev)))
+		return -EPROTO;
+
+	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
+	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
+	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
+
+	if (num_pdev_stats) {
+		const struct wmi_pdev_stats *src;
+
+		src = (void *)skb->data;
+		if (!skb_pull(skb, sizeof(*src)))
+			return -EPROTO;
+
+		ath10k_wmi_pull_pdev_stats(src, stats);
+	}
+
+	/* fw doesn't implement vdev stats */
+
+	for (i = 0; i < num_peer_stats; i++) {
+		const struct wmi_peer_stats *src;
+
+		src = (void *)skb->data;
+		if (!skb_pull(skb, sizeof(*src)))
+			return -EPROTO;
+
+		ath10k_wmi_pull_peer_stats(src, &stats->peer_stat[i]);
+	}
+
+	return 0;
+}
+
+static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar,
+					struct sk_buff *skb,
+					struct ath10k_target_stats *stats)
+{
+	const struct wmi_stats_event *ev = (void *)skb->data;
+	u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
+	int i;
+
+	if (!skb_pull(skb, sizeof(*ev)))
+		return -EPROTO;
+
+	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
+	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
+	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
+
+	if (num_pdev_stats) {
+		const struct wmi_10x_pdev_stats *src;
+
+		src = (void *)skb->data;
+		if (!skb_pull(skb, sizeof(*src)))
+			return -EPROTO;
+
+		ath10k_wmi_pull_pdev_stats(&src->old, stats);
+
+		stats->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad);
+		stats->rts_bad = __le32_to_cpu(src->rts_bad);
+		stats->rts_good = __le32_to_cpu(src->rts_good);
+		stats->fcs_bad = __le32_to_cpu(src->fcs_bad);
+		stats->no_beacons = __le32_to_cpu(src->no_beacons);
+		stats->mib_int_count = __le32_to_cpu(src->mib_int_count);
+	}
+
+	/* fw doesn't implement vdev stats */
+
+	for (i = 0; i < num_peer_stats; i++) {
+		const struct wmi_10x_peer_stats *src;
+
+		src = (void *)skb->data;
+		if (!skb_pull(skb, sizeof(*src)))
+			return -EPROTO;
+
+		ath10k_wmi_pull_peer_stats(&src->old, &stats->peer_stat[i]);
+
+		stats->peer_stat[i].peer_rx_rate =
+				__le32_to_cpu(src->peer_rx_rate);
+	}
+
+	return 0;
+}
+
+int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
+			     struct ath10k_target_stats *stats)
+{
+	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+		return ath10k_wmi_10x_pull_fw_stats(ar, skb, stats);
+	else
+		return ath10k_wmi_main_pull_fw_stats(ar, skb, stats);
+}
+
 static void ath10k_wmi_event_update_stats(struct ath10k *ar,
 					  struct sk_buff *skb)
 {
-	struct wmi_stats_event *ev = (struct wmi_stats_event *)skb->data;
-
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
-
-	ath10k_debug_read_target_stats(ar, ev);
+	ath10k_debug_read_target_stats(ar, skb);
 }
 
 static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 55d8317..4ce8e3c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3021,7 +3021,7 @@ struct wmi_stats_event {
  * PDEV statistics
  * TODO: add all PDEV stats here
  */
-struct wmi_pdev_stats_old {
+struct wmi_pdev_stats {
 	__le32 chan_nf;        /* Channel noise floor */
 	__le32 tx_frame_count; /* TX frame count */
 	__le32 rx_frame_count; /* RX frame count */
@@ -3032,15 +3032,8 @@ struct wmi_pdev_stats_old {
 	struct wal_dbg_stats wal; /* WAL dbg stats */
 } __packed;
 
-struct wmi_pdev_stats_10x {
-	__le32 chan_nf;        /* Channel noise floor */
-	__le32 tx_frame_count; /* TX frame count */
-	__le32 rx_frame_count; /* RX frame count */
-	__le32 rx_clear_count; /* rx clear count */
-	__le32 cycle_count;    /* cycle count */
-	__le32 phy_err_count;  /* Phy error count */
-	__le32 chan_tx_pwr;    /* channel tx power */
-	struct wal_dbg_stats wal; /* WAL dbg stats */
+struct wmi_10x_pdev_stats {
+	struct wmi_pdev_stats old;
 	__le32 ack_rx_bad;
 	__le32 rts_bad;
 	__le32 rts_good;
@@ -3061,16 +3054,14 @@ struct wmi_vdev_stats {
  * peer statistics.
  * TODO: add more stats
  */
-struct wmi_peer_stats_old {
+struct wmi_peer_stats {
 	struct wmi_mac_addr peer_macaddr;
 	__le32 peer_rssi;
 	__le32 peer_tx_rate;
 } __packed;
 
-struct wmi_peer_stats_10x {
-	struct wmi_mac_addr peer_macaddr;
-	__le32 peer_rssi;
-	__le32 peer_tx_rate;
+struct wmi_10x_peer_stats {
+	struct wmi_peer_stats old;
 	__le32 peer_rx_rate;
 } __packed;
 
@@ -4582,6 +4573,7 @@ struct wmi_svc_rdy_ev_arg {
 
 struct ath10k;
 struct ath10k_vif;
+struct ath10k_target_stats;
 
 int ath10k_wmi_attach(struct ath10k *ar);
 void ath10k_wmi_detach(struct ath10k *ar);
@@ -4653,5 +4645,7 @@ int ath10k_wmi_force_fw_hang(struct ath10k *ar,
 			     enum wmi_force_fw_hang_type type, u32 delay_ms);
 int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb);
 int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable);
+int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
+			     struct ath10k_target_stats *stats);
 
 #endif /* _WMI_H_ */
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 25 03:33:50 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 25 Sep 2014 12:33:50 +0200
Subject: [PATCH 4/4] ath10k: fix fw stats processing
In-Reply-To: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411641230-18785-5-git-send-email-michal.kazior@tieto.com>

If stat data exceeds wmi-htc buffer limits
firmware splits it into many wmi stats update
events which are delivered in a ping-pong fashion
triggered by wmi stats request command.

Since there's only an implicit start-of-data and
no end-of-data indications the driver has to
perform some trickery to get complete stat data.

Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h  |  19 +--
 drivers/net/wireless/ath/ath10k/debug.c | 273 +++++++++++++++++++++++---------
 drivers/net/wireless/ath/ath10k/wmi.c   |  55 +++++--
 3 files changed, 252 insertions(+), 95 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 082a8dad..674e38c 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -117,13 +117,17 @@ struct ath10k_wmi {
 };
 
 struct ath10k_fw_stats_peer {
+	struct list_head list;
+
 	u8 peer_macaddr[ETH_ALEN];
 	u32 peer_rssi;
 	u32 peer_tx_rate;
 	u32 peer_rx_rate; /* 10x only */
 };
 
-struct ath10k_fw_stats {
+struct ath10k_fw_stats_pdev {
+	struct list_head list;
+
 	/* PDEV stats */
 	s32 ch_noise_floor;
 	u32 tx_frame_count;
@@ -178,15 +182,11 @@ struct ath10k_fw_stats {
 	s32 phy_errs;
 	s32 phy_err_drop;
 	s32 mpdu_errs;
+};
 
-	/* VDEV STATS */
-
-	/* PEER STATS */
-	u8 peers;
-	struct ath10k_fw_stats_peer peer_stat[TARGET_NUM_PEERS];
-
-	/* TODO: Beacon filter stats */
-
+struct ath10k_fw_stats {
+	struct list_head pdevs;
+	struct list_head peers;
 };
 
 struct ath10k_dfs_stats {
@@ -294,6 +294,7 @@ struct ath10k_debug {
 
 	struct ath10k_fw_stats fw_stats;
 	struct completion fw_stats_complete;
+	bool fw_stats_done;
 	DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
 
 	unsigned long htt_stats_mask;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 1ab0f10..4724172 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -242,39 +242,154 @@ static const struct file_operations fops_wmi_services = {
 	.llseek = default_llseek,
 };
 
+static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
+{
+	struct ath10k_fw_stats_pdev *i, *tmp;
+
+	list_for_each_entry_safe(i, tmp, head, list) {
+		list_del(&i->list);
+		kfree(i);
+	}
+}
+
+static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
+{
+	struct ath10k_fw_stats_peer *i, *tmp;
+
+	list_for_each_entry_safe(i, tmp, head, list) {
+		list_del(&i->list);
+		kfree(i);
+	}
+}
+
+static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
+{
+	spin_lock_bh(&ar->data_lock);
+	ar->debug.fw_stats_done = false;
+	ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
+	ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
+	spin_unlock_bh(&ar->data_lock);
+}
+
+static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
+{
+	struct ath10k_fw_stats_peer *i;
+	size_t num = 0;
+
+	list_for_each_entry(i, head, list)
+		++num;
+
+	return num;
+}
+
 void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
 {
+	struct ath10k_fw_stats stats = {};
+	bool is_start, is_started, is_end;
+	size_t num_peers;
 	int ret;
 
-	spin_lock_bh(&ar->data_lock);
+	INIT_LIST_HEAD(&stats.pdevs);
+	INIT_LIST_HEAD(&stats.peers);
 
-	ret = ath10k_wmi_pull_fw_stats(ar, skb, &ar->debug.fw_stats);
+	spin_lock_bh(&ar->data_lock);
+	ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
 	if (ret) {
 		ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
 		goto unlock;
 	}
 
+	/* Stat data may exceed htc-wmi buffer limit. In such case firmware
+	 * splits the stats data and delivers it in a ping-pong fashion of
+	 * request cmd-update event.
+	 *
+	 * However there is no explicit end-of-data. Instead start-of-data is
+	 * used as an implicit one. This works as follows:
+	 *  a) discard stat update events until one with pdev stats is
+	 *     delivered - this skips session started at end of (b)
+	 *  b) consume stat update events until another one with pdev stats is
+	 *     delivered which is treated as end-of-data and is itself discarded
+	 */
+
+	if (ar->debug.fw_stats_done) {
+		ath10k_warn(ar, "received unsolicited stats update event\n");
+		goto free;
+	}
+
+	num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
+	is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
+		    !list_empty(&stats.pdevs));
+	is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
+		  !list_empty(&stats.pdevs));
+
+	if (is_start)
+		list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
+
+	if (is_end)
+		ar->debug.fw_stats_done = true;
+
+	is_started = !list_empty(&ar->debug.fw_stats.pdevs);
+
+	if (is_started && !is_end) {
+		if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
+			/* Although this is unlikely impose a sane limit to
+			 * prevent firmware from DoS-ing the host.
+			 */
+			ath10k_warn(ar, "dropping fw peer stats\n");
+			goto free;
+		}
+
+		list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
+	}
+
 	complete(&ar->debug.fw_stats_complete);
 
+free:
+	/* In some cases lists have been spliced and cleared. Free up
+	 * resouruces if that is not the case.
+	 */
+	ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
+	ath10k_debug_fw_stats_peers_free(&stats.peers);
+
 unlock:
 	spin_unlock_bh(&ar->data_lock);
 }
 
-static int ath10k_fw_stats_request(struct ath10k *ar)
+static int ath10k_debug_fw_stats_request(struct ath10k *ar)
 {
+	unsigned long timeout;
 	int ret;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
-	ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
-	if (ret) {
-		ath10k_warn(ar, "failed to fw stat request command: %d\n", ret);
-		return ret;
-	}
+	timeout = jiffies + msecs_to_jiffies(1*HZ);
+
+	ath10k_debug_fw_stats_reset(ar);
+
+	for (;;) {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+
+		reinit_completion(&ar->debug.fw_stats_complete);
+
+		ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
+		if (ret) {
+			ath10k_warn(ar, "could not request stats (%d)\n", ret);
+			return ret;
+		}
 
-	ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete, 1*HZ);
-	if (ret <= 0)
-		return -ETIMEDOUT;
+		ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete,
+						  1*HZ);
+		if (ret <= 0)
+			return -ETIMEDOUT;
+
+		spin_lock_bh(&ar->data_lock);
+		if (ar->debug.fw_stats_done) {
+			spin_unlock_bh(&ar->data_lock);
+			break;
+		}
+		spin_unlock_bh(&ar->data_lock);
+	}
 
 	return 0;
 }
@@ -288,9 +403,21 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,
 {
 	unsigned int len = 0;
 	unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
-	int i;
+	const struct ath10k_fw_stats_pdev *pdev;
+	const struct ath10k_fw_stats_peer *peer;
+	size_t num_peers;
 
 	spin_lock_bh(&ar->data_lock);
+
+	pdev = list_first_entry_or_null(&fw_stats->pdevs,
+					struct ath10k_fw_stats_pdev, list);
+	if (!pdev) {
+		ath10k_warn(ar, "failed to get pdev stats\n");
+		goto unlock;
+	}
+
+	num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
+
 	len += scnprintf(buf + len, buf_len - len, "\n");
 	len += scnprintf(buf + len, buf_len - len, "%30s\n",
 			 "ath10k PDEV stats");
@@ -298,29 +425,29 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,
 				 "=================");
 
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Channel noise floor", fw_stats->ch_noise_floor);
+			 "Channel noise floor", pdev->ch_noise_floor);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "Channel TX power", fw_stats->chan_tx_power);
+			 "Channel TX power", pdev->chan_tx_power);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "TX frame count", fw_stats->tx_frame_count);
+			 "TX frame count", pdev->tx_frame_count);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "RX frame count", fw_stats->rx_frame_count);
+			 "RX frame count", pdev->rx_frame_count);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "RX clear count", fw_stats->rx_clear_count);
+			 "RX clear count", pdev->rx_clear_count);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "Cycle count", fw_stats->cycle_count);
+			 "Cycle count", pdev->cycle_count);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "PHY error count", fw_stats->phy_err_count);
+			 "PHY error count", pdev->phy_err_count);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "RTS bad count", fw_stats->rts_bad);
+			 "RTS bad count", pdev->rts_bad);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "RTS good count", fw_stats->rts_good);
+			 "RTS good count", pdev->rts_good);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "FCS bad count", fw_stats->fcs_bad);
+			 "FCS bad count", pdev->fcs_bad);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "No beacon count", fw_stats->no_beacons);
+			 "No beacon count", pdev->no_beacons);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-			 "MIB int count", fw_stats->mib_int_count);
+			 "MIB int count", pdev->mib_int_count);
 
 	len += scnprintf(buf + len, buf_len - len, "\n");
 	len += scnprintf(buf + len, buf_len - len, "%30s\n",
@@ -329,51 +456,51 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,
 				 "=================");
 
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "HTT cookies queued", fw_stats->comp_queued);
+			 "HTT cookies queued", pdev->comp_queued);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "HTT cookies disp.", fw_stats->comp_delivered);
+			 "HTT cookies disp.", pdev->comp_delivered);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MSDU queued", fw_stats->msdu_enqued);
+			 "MSDU queued", pdev->msdu_enqued);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDU queued", fw_stats->mpdu_enqued);
+			 "MPDU queued", pdev->mpdu_enqued);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MSDUs dropped", fw_stats->wmm_drop);
+			 "MSDUs dropped", pdev->wmm_drop);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Local enqued", fw_stats->local_enqued);
+			 "Local enqued", pdev->local_enqued);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Local freed", fw_stats->local_freed);
+			 "Local freed", pdev->local_freed);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "HW queued", fw_stats->hw_queued);
+			 "HW queued", pdev->hw_queued);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PPDUs reaped", fw_stats->hw_reaped);
+			 "PPDUs reaped", pdev->hw_reaped);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Num underruns", fw_stats->underrun);
+			 "Num underruns", pdev->underrun);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PPDUs cleaned", fw_stats->tx_abort);
+			 "PPDUs cleaned", pdev->tx_abort);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDUs requed", fw_stats->mpdus_requed);
+			 "MPDUs requed", pdev->mpdus_requed);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Excessive retries", fw_stats->tx_ko);
+			 "Excessive retries", pdev->tx_ko);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "HW rate", fw_stats->data_rc);
+			 "HW rate", pdev->data_rc);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Sched self tiggers", fw_stats->self_triggers);
+			 "Sched self tiggers", pdev->self_triggers);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
 			 "Dropped due to SW retries",
-			 fw_stats->sw_retry_failure);
+			 pdev->sw_retry_failure);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
 			 "Illegal rate phy errors",
-			 fw_stats->illgl_rate_phy_err);
+			 pdev->illgl_rate_phy_err);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Pdev continous xretry", fw_stats->pdev_cont_xretry);
+			 "Pdev continous xretry", pdev->pdev_cont_xretry);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "TX timeout", fw_stats->pdev_tx_timeout);
+			 "TX timeout", pdev->pdev_tx_timeout);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PDEV resets", fw_stats->pdev_resets);
+			 "PDEV resets", pdev->pdev_resets);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PHY underrun", fw_stats->phy_underrun);
+			 "PHY underrun", pdev->phy_underrun);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDU is more than txop limit", fw_stats->txop_ovf);
+			 "MPDU is more than txop limit", pdev->txop_ovf);
 
 	len += scnprintf(buf + len, buf_len - len, "\n");
 	len += scnprintf(buf + len, buf_len - len, "%30s\n",
@@ -383,54 +510,53 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,
 
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
 			 "Mid PPDU route change",
-			 fw_stats->mid_ppdu_route_change);
+			 pdev->mid_ppdu_route_change);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Tot. number of statuses", fw_stats->status_rcvd);
+			 "Tot. number of statuses", pdev->status_rcvd);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Extra frags on rings 0", fw_stats->r0_frags);
+			 "Extra frags on rings 0", pdev->r0_frags);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Extra frags on rings 1", fw_stats->r1_frags);
+			 "Extra frags on rings 1", pdev->r1_frags);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Extra frags on rings 2", fw_stats->r2_frags);
+			 "Extra frags on rings 2", pdev->r2_frags);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Extra frags on rings 3", fw_stats->r3_frags);
+			 "Extra frags on rings 3", pdev->r3_frags);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MSDUs delivered to HTT", fw_stats->htt_msdus);
+			 "MSDUs delivered to HTT", pdev->htt_msdus);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDUs delivered to HTT", fw_stats->htt_mpdus);
+			 "MPDUs delivered to HTT", pdev->htt_mpdus);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MSDUs delivered to stack", fw_stats->loc_msdus);
+			 "MSDUs delivered to stack", pdev->loc_msdus);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDUs delivered to stack", fw_stats->loc_mpdus);
+			 "MPDUs delivered to stack", pdev->loc_mpdus);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "Oversized AMSUs", fw_stats->oversize_amsdu);
+			 "Oversized AMSUs", pdev->oversize_amsdu);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PHY errors", fw_stats->phy_errs);
+			 "PHY errors", pdev->phy_errs);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "PHY errors drops", fw_stats->phy_err_drop);
+			 "PHY errors drops", pdev->phy_err_drop);
 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-			 "MPDU errors (FCS, MIC, ENC)", fw_stats->mpdu_errs);
+			 "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
 
 	len += scnprintf(buf + len, buf_len - len, "\n");
-	len += scnprintf(buf + len, buf_len - len, "%30s (%d)\n",
-			 "ath10k PEER stats", fw_stats->peers);
+	len += scnprintf(buf + len, buf_len - len, "%30s (%lu)\n",
+			 "ath10k PEER stats", num_peers);
 	len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
 				 "=================");
 
-	for (i = 0; i < fw_stats->peers; i++) {
+	list_for_each_entry(peer, &fw_stats->peers, list) {
 		len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
-				 "Peer MAC address",
-				 fw_stats->peer_stat[i].peer_macaddr);
+				 "Peer MAC address", peer->peer_macaddr);
 		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-				 "Peer RSSI", fw_stats->peer_stat[i].peer_rssi);
+				 "Peer RSSI", peer->peer_rssi);
 		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-				 "Peer TX rate",
-				 fw_stats->peer_stat[i].peer_tx_rate);
+				 "Peer TX rate", peer->peer_tx_rate);
 		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-				 "Peer RX rate",
-				 fw_stats->peer_stat[i].peer_rx_rate);
+				 "Peer RX rate", peer->peer_rx_rate);
 		len += scnprintf(buf + len, buf_len - len, "\n");
 	}
+
+unlock:
 	spin_unlock_bh(&ar->data_lock);
 
 	if (len >= buf_len)
@@ -458,7 +584,7 @@ static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
 		goto err_unlock;
 	}
 
-	ret = ath10k_fw_stats_request(ar);
+	ret = ath10k_debug_fw_stats_request(ar);
 	if (ret) {
 		ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
 		goto err_free;
@@ -1097,6 +1223,9 @@ int ath10k_debug_create(struct ath10k *ar)
 	if (!ar->debug.fw_crash_data)
 		return -ENOMEM;
 
+	INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
+	INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
+
 	return 0;
 }
 
@@ -1104,6 +1233,8 @@ void ath10k_debug_destroy(struct ath10k *ar)
 {
 	vfree(ar->debug.fw_crash_data);
 	ar->debug.fw_crash_data = NULL;
+
+	ath10k_debug_fw_stats_reset(ar);
 }
 
 int ath10k_debug_register(struct ath10k *ar)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index c4640aa..f65032f 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1330,7 +1330,7 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
 }
 
 static void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src,
-				       struct ath10k_fw_stats *dst)
+				       struct ath10k_fw_stats_pdev *dst)
 {
 	const struct wal_dbg_tx_stats *tx = &src->wal.tx;
 	const struct wal_dbg_rx_stats *rx = &src->wal.rx;
@@ -1405,26 +1405,38 @@ static int ath10k_wmi_main_pull_fw_stats(struct ath10k *ar,
 	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
 	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
 
-	if (num_pdev_stats) {
+	for (i = 0; i < num_pdev_stats; i++) {
 		const struct wmi_pdev_stats *src;
+		struct ath10k_fw_stats_pdev *dst;
 
 		src = (void *)skb->data;
 		if (!skb_pull(skb, sizeof(*src)))
 			return -EPROTO;
 
-		ath10k_wmi_pull_pdev_stats(src, stats);
+		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+		if (!dst)
+			continue;
+
+		ath10k_wmi_pull_pdev_stats(src, dst);
+		list_add_tail(&dst->list, &stats->pdevs);
 	}
 
 	/* fw doesn't implement vdev stats */
 
 	for (i = 0; i < num_peer_stats; i++) {
 		const struct wmi_peer_stats *src;
+		struct ath10k_fw_stats_peer *dst;
 
 		src = (void *)skb->data;
 		if (!skb_pull(skb, sizeof(*src)))
 			return -EPROTO;
 
-		ath10k_wmi_pull_peer_stats(src, &stats->peer_stat[i]);
+		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+		if (!dst)
+			continue;
+
+		ath10k_wmi_pull_peer_stats(src, dst);
+		list_add_tail(&dst->list, &stats->peers);
 	}
 
 	return 0;
@@ -1445,36 +1457,49 @@ static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar,
 	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
 	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
 
-	if (num_pdev_stats) {
+	for (i = 0; i < num_pdev_stats; i++) {
 		const struct wmi_10x_pdev_stats *src;
+		struct ath10k_fw_stats_pdev *dst;
 
 		src = (void *)skb->data;
 		if (!skb_pull(skb, sizeof(*src)))
 			return -EPROTO;
 
-		ath10k_wmi_pull_pdev_stats(&src->old, stats);
+		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+		if (!dst)
+			continue;
+
+		ath10k_wmi_pull_pdev_stats(&src->old, dst);
+
+		dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad);
+		dst->rts_bad = __le32_to_cpu(src->rts_bad);
+		dst->rts_good = __le32_to_cpu(src->rts_good);
+		dst->fcs_bad = __le32_to_cpu(src->fcs_bad);
+		dst->no_beacons = __le32_to_cpu(src->no_beacons);
+		dst->mib_int_count = __le32_to_cpu(src->mib_int_count);
 
-		stats->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad);
-		stats->rts_bad = __le32_to_cpu(src->rts_bad);
-		stats->rts_good = __le32_to_cpu(src->rts_good);
-		stats->fcs_bad = __le32_to_cpu(src->fcs_bad);
-		stats->no_beacons = __le32_to_cpu(src->no_beacons);
-		stats->mib_int_count = __le32_to_cpu(src->mib_int_count);
+		list_add_tail(&dst->list, &stats->pdevs);
 	}
 
 	/* fw doesn't implement vdev stats */
 
 	for (i = 0; i < num_peer_stats; i++) {
 		const struct wmi_10x_peer_stats *src;
+		struct ath10k_fw_stats_peer *dst;
 
 		src = (void *)skb->data;
 		if (!skb_pull(skb, sizeof(*src)))
 			return -EPROTO;
 
-		ath10k_wmi_pull_peer_stats(&src->old, &stats->peer_stat[i]);
+		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+		if (!dst)
+			continue;
+
+		ath10k_wmi_pull_peer_stats(&src->old, dst);
+
+		dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
 
-		stats->peer_stat[i].peer_rx_rate =
-				__le32_to_cpu(src->peer_rx_rate);
+		list_add_tail(&dst->list, &stats->peers);
 	}
 
 	return 0;
-- 
1.8.5.3



From michal.kazior at tieto.com  Thu Sep 25 03:33:49 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Thu, 25 Sep 2014 12:33:49 +0200
Subject: [PATCH 3/4] ath10k: request fw_stats once on open
In-Reply-To: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <1411641230-18785-4-git-send-email-michal.kazior@tieto.com>

Stats were requested and processed for each read
call. This caused inconsistent readings.

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

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 97b5c16..1ab0f10 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -260,38 +260,35 @@ unlock:
 	spin_unlock_bh(&ar->data_lock);
 }
 
-static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
-				    size_t count, loff_t *ppos)
+static int ath10k_fw_stats_request(struct ath10k *ar)
 {
-	struct ath10k *ar = file->private_data;
-	struct ath10k_fw_stats *fw_stats;
-	char *buf = NULL;
-	unsigned int len = 0, buf_len = 8000;
-	ssize_t ret_cnt = 0;
-	long left;
-	int i;
 	int ret;
 
-	fw_stats = &ar->debug.fw_stats;
-
-	mutex_lock(&ar->conf_mutex);
-
-	if (ar->state != ATH10K_STATE_ON)
-		goto exit;
-
-	buf = kzalloc(buf_len, GFP_KERNEL);
-	if (!buf)
-		goto exit;
+	lockdep_assert_held(&ar->conf_mutex);
 
 	ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
 	if (ret) {
-		ath10k_warn(ar, "could not request stats (%d)\n", ret);
-		goto exit;
+		ath10k_warn(ar, "failed to fw stat request command: %d\n", ret);
+		return ret;
 	}
 
-	left = wait_for_completion_timeout(&ar->debug.fw_stats_complete, 1*HZ);
-	if (left <= 0)
-		goto exit;
+	ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete, 1*HZ);
+	if (ret <= 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/* FIXME: How to calculate the buffer size sanely? */
+#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
+
+static void ath10k_fw_stats_fill(struct ath10k *ar,
+				 struct ath10k_fw_stats *fw_stats,
+				 char *buf)
+{
+	unsigned int len = 0;
+	unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
+	int i;
 
 	spin_lock_bh(&ar->data_lock);
 	len += scnprintf(buf + len, buf_len - len, "\n");
@@ -436,20 +433,71 @@ static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
 	}
 	spin_unlock_bh(&ar->data_lock);
 
-	if (len > buf_len)
-		len = buf_len;
+	if (len >= buf_len)
+		buf[len - 1] = 0;
+	else
+		buf[len] = 0;
+}
 
-	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
+{
+	struct ath10k *ar = inode->i_private;
+	void *buf = NULL;
+	int ret;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH10K_STATE_ON) {
+		ret = -ENETDOWN;
+		goto err_unlock;
+	}
+
+	buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto err_unlock;
+	}
+
+	ret = ath10k_fw_stats_request(ar);
+	if (ret) {
+		ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
+		goto err_free;
+	}
+
+	ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
+	file->private_data = buf;
 
-exit:
 	mutex_unlock(&ar->conf_mutex);
-	kfree(buf);
-	return ret_cnt;
+	return 0;
+
+err_free:
+	vfree(buf);
+
+err_unlock:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
+}
+
+static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
+{
+	vfree(file->private_data);
+
+	return 0;
+}
+
+static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	const char *buf = file->private_data;
+	unsigned int len = strlen(buf);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
 static const struct file_operations fops_fw_stats = {
+	.open = ath10k_fw_stats_open,
+	.release = ath10k_fw_stats_release,
 	.read = ath10k_fw_stats_read,
-	.open = simple_open,
 	.owner = THIS_MODULE,
 	.llseek = default_llseek,
 };
-- 
1.8.5.3



From greearb at candelatech.com  Thu Sep 25 06:22:19 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 25 Sep 2014 06:22:19 -0700
Subject: [PATCH] ath10k: use configured nss instead of max nss.
In-Reply-To: <CA+BoTQnLbJ7cnyUo-o6Ebx9pAxGyAHv8W8eKE8BEd7Kh8f+uTw@mail.gmail.com>
References: <1411426820-4047-1-git-send-email-greearb@candelatech.com>	<CA+BoTQn9sECMNZsxQpB4i3wHPxfVL+LXq9=2GBd-opH6+9TD=A@mail.gmail.com>	<5421A44C.8080307@candelatech.com>	<CA+BoTQ=mry3tPD-LK+gFD2bC6RU0KvY6LC9=FOAGTLi_1rzUog@mail.gmail.com>	<5422ECAA.6050600@candelatech.com>
 <CA+BoTQnLbJ7cnyUo-o6Ebx9pAxGyAHv8W8eKE8BEd7Kh8f+uTw@mail.gmail.com>
Message-ID: <5424170B.2010409@candelatech.com>



On 09/24/2014 11:16 PM, Michal Kazior wrote:
> On 24 September 2014 18:09, Ben Greear <greearb at candelatech.com> wrote:
>> On 09/24/2014 12:09 AM, Michal Kazior wrote:
>>> On 23 September 2014 18:48, Ben Greear <greearb at candelatech.com> wrote:
>>>> On 09/23/2014 01:59 AM, Michal Kazior wrote:
>>>>> On 23 September 2014 01:00,  <greearb at candelatech.com> wrote:
>>>>>> From: Ben Greear <greearb at candelatech.com>
>>> [...]
>>>>>> @@ -4086,6 +4086,10 @@ ath10k_default_bitrate_mask(struct ath10k *ar,
>>>>>>          u32 legacy = 0x00ff;
>>>>>>          u8 ht = 0xff, i;
>>>>>>          u16 vht = 0x3ff;
>>>>>> +       u16 nrf = ar->num_rf_chains;
>>>>>> +
>>>>>> +       if (ar->cfg_tx_chainmask)
>>>>>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
>>> [...]
>>>>> I think it might be a good idea to convey the limitation of tx/rx
>>>>> chainmask to the user: you can't change the tx/rx chainmask on the fly
>>>>> easily (while connected/have associated stations). Or do you plan to
>>>>> schedule peer reassoc in __ath10k_set_antenna() in a follow up
>>>>> patch(es) later?
> [...]
>> See this in net/mac80211/cfg.c:
>>
>> static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
>> {
>>          struct ieee80211_local *local = wiphy_priv(wiphy);
>>
>>          if (local->started)
>>                  return -EOPNOTSUPP;
>
> Ah, thanks! So my argument is invalid :)
>
>
>>> But it's still probably a good idea to comment the quoted code chunk
>>> above explaining why nrf is overriden by chainmask (i.e. due to
>>> firmware rate control issues, right?).
>>
>> I am not certain it is a bug in the firmware.  The driver should not configure
>> nss incorrectly as it was doing previous to my recent patches.
>
> Since firmware does rate control it just seems redundant for the
> driver to update both chainmask and nss (the first implies the other).
> But maybe that's just me.

nss is really a per-station issue, where the chainmask is a per-radio issue.

Think of an AP with 2x2 and 3x3 stations connected, for instance.

Thanks,
Ben

>
>
> Micha?
>

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


From greearb at candelatech.com  Thu Sep 25 06:26:45 2014
From: greearb at candelatech.com (Ben Greear)
Date: Thu, 25 Sep 2014 06:26:45 -0700
Subject: [RFC 2/2] ath10k: re-config ht_caps when chainmask is modified.
In-Reply-To: <CA+BoTQkncctvMFx7U0Qzq7+7W2o9Vo5qKcDEi6DUdJTEQWDfAA@mail.gmail.com>
References: <1411518383-32634-1-git-send-email-greearb@candelatech.com>	<1411518383-32634-2-git-send-email-greearb@candelatech.com>	<CA+BoTQ=fS30xz9KcdBJcioNers6PovOFEeqPCCSFn52HkscXug@mail.gmail.com>	<5422D6CF.10408@candelatech.com>	<CA+BoTQk=X2qVJsY64ZH88h29L6+Y5M9K07nLtzo=0ga1bUsXGw@mail.gmail.com>	<5422F1C2.4090100@candelatech.com>
 <CA+BoTQkncctvMFx7U0Qzq7+7W2o9Vo5qKcDEi6DUdJTEQWDfAA@mail.gmail.com>
Message-ID: <54241815.6030000@candelatech.com>



On 09/24/2014 11:23 PM, Michal Kazior wrote:
> On 24 September 2014 18:30, Ben Greear <greearb at candelatech.com> wrote:
>> On 09/24/2014 08:05 AM, Michal Kazior wrote:
>>> On 24 September 2014 16:35, Ben Greear <greearb at candelatech.com> wrote:
>>>> On 09/24/2014 12:51 AM, Michal Kazior wrote:
>>>>> On 24 September 2014 02:26,  <greearb at candelatech.com> wrote:
>>>>> [...]
>>>>>>
>>>>>> +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k
>>>>>> *ar,
>>>>>> +                                                         bool
>>>>>> use_cfg_chains)
>>>>>>    {
>>>>>>           struct ieee80211_sta_vht_cap vht_cap = {0};
>>>>>>           u16 mcs_map;
>>>>>>           int i;
>>>>>> +       int nrf = ar->num_rf_chains;
>>>>>> +
>>>>>> +       if (use_cfg_chains && ar->cfg_tx_chainmask)
>>>>>> +               nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
>>>>>
>>>>>
>>>>> Is use_cfg_chains really necessary here? Is setting tx/rx chainmask to
>>>>> 0x0 make any sense at all? Shouldn't we deny it or make it fallback to
>>>>> the supported tx/rx chainmask values?
>>>>
>>>> It would cause the logic to flip back to the defaults, so seems mildly
>>>> useful.  I'm not sure
>>>> upper layers would ever let it be < 1 though.
>>>
>>> 0 is a valid argument as far as upper layers are concerned and should
>>> be treated as "use all available antennas" (see `iw list` output
>>> before ever setting antenna, after setting to, e.g. 1 and then to 0).
>>>
>>> This implies current set_antenna() implementation is actually buggy
>>> (pdev param should involve using supp_tx/rx_chainmask). Your
>>> assumption in recent patches is also incorrect as antenna mask = 0
>>> should imply max nss, not 1.
>>
>> I tested this using:
>>
>> iw phy wiphy1 set antenna 0 0
>>
>> This flips it back to 3x3 (I had previously configured it for 2x2),
>> so I think the patches are working properly.
>
> Mea culpa. It will flip back indeed.
>
> But I still don't see why use_cfg_chains is necessary. I don't see how
> cfg_tx_chainmask could be non-zero when ath10k is registering to mac.

I was thinking we might want to re-register someday, like after loading
a new firmware, or tuning firmware differently so that the vdev limits
changed.

If you are sure we currently only register once per module load, then
I agree that use_cfg_chains should not be needed currently.

But, considering my desire to allow to re-register in the future, I'd
prefer the patch to remain as is unless you disagree.

Thanks,
Ben

>
>
> Micha?
>

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


From kvalo at qca.qualcomm.com  Fri Sep 26 03:34:58 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 26 Sep 2014 13:34:58 +0300
Subject: [PATCH v2 0/3] ath10k: debug improvements
In-Reply-To: <1411460574-5424-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Tue, 23 Sep 2014 10:22:51 +0200")
References: <1411460574-5424-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87a95m6565.fsf@kamboji.qca.qualcomm.com>

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

> Hi,
>
> This adds extra prints and information for
> debugging purposes.
>
>
> v2:
>  * merge scnprintfs
>
> Michal Kazior (3):
>   ath10k: print wmi version info
>   ath10k: dump hex bytes with dev string prefix
>   ath10k: add debug dump for pci rx

Thanks, all three applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Fri Sep 26 03:36:34 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 26 Sep 2014 13:36:34 +0300
Subject: [PATCH v3 0/3] ath10k: export calibration data to user space
In-Reply-To: <20140924111416.6539.95299.stgit@potku.adurom.net> (Kalle Valo's
 message of "Wed, 24 Sep 2014 14:16:39 +0300")
References: <20140924111416.6539.95299.stgit@potku.adurom.net>
Message-ID: <8761ga653h.fsf@kamboji.qca.qualcomm.com>

Kalle Valo <kvalo at qca.qualcomm.com> writes:

> Here's a small patchset exporting firmware calibration data to user space. This
> makes it easier to debug various calibration data related problems.
>
> Please comment.
>
> v3:
>
> * patch 1: fix comment style (Michal)
>
> * patch 3: use ath10k_debug_ prefix (Michal)
>
> v2:
>
> * never unmask the diagnostic window copy engine pipe in
>   ath10k_ce_enable_interrupts()
>
> * add locking for diag_read_mem()/diag_write_mem()
>
> ---
>
> Kalle Valo (3):
>       ath10k: don't enable interrupts for the diagnostic window
>       ath10k: add diag_read() to hif ops
>       ath10k: add cal_data debugfs file

All three patches applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Fri Sep 26 04:06:42 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 26 Sep 2014 14:06:42 +0300
Subject: [PATCH 0/4] ath10k: fix/cleanup fw stats
In-Reply-To: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 25 Sep 2014 12:33:46 +0200")
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <871tqy63p9.fsf@kamboji.qca.qualcomm.com>

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

> Hi,
>
> This cleans up and fixes fw stats aggregation.
>
>
> Michal Kazior (4):
>   ath10k: split wmi stats parsing
>   ath10k: rename fw_stats related stuff
>   ath10k: request fw_stats once on open
>   ath10k: fix fw stats processing

I didn't review these yet but I saw new warnings:

drivers/net/wireless/ath/ath10k/debug.c: In function 'ath10k_fw_stats_fill':
drivers/net/wireless/ath/ath10k/debug.c:540:5: warning: format '%lu' expects argument of type 'long unsigned int', but argument 5 has type 'size_t' [-Wformat]

drivers/net/wireless/ath/ath10k/wmi.c:1513: WARNING: else is not generally useful after a break or return

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Fri Sep 26 04:10:05 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Fri, 26 Sep 2014 14:10:05 +0300
Subject: [PATCH] ath: change logging functions to return void
In-Reply-To: <1411407334.2952.46.camel@joe-AO725> (Joe Perches's message of
 "Mon, 22 Sep 2014 10:35:34 -0700")
References: <1411407334.2952.46.camel@joe-AO725>
Message-ID: <87wq8q4oz6.fsf@kamboji.qca.qualcomm.com>

Joe Perches <joe at perches.com> writes:

> The return values are not used by callers of these functions
> so change the functions to return void.
>
> Other miscellanea:
>
> o add __printf verification to wil6210 logging functions
>   No format/argument mismatches found
>
> Signed-off-by: Joe Perches <joe at perches.com>

While applying this to our ath-next-test branch for build testing I had
few conflicts in ath10k. Joe, can you please check my conflict
resolution:

https://github.com/kvalo/ath/commit/9c5bd0cb84e4189ca85c041021aacdc015f3a9a5

-- 
Kalle Valo


From michal.kazior at tieto.com  Fri Sep 26 04:14:35 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Fri, 26 Sep 2014 13:14:35 +0200
Subject: [PATCH 0/4] ath10k: fix/cleanup fw stats
In-Reply-To: <871tqy63p9.fsf@kamboji.qca.qualcomm.com>
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
 <871tqy63p9.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQmJ-HprccxTO3UrX+NkhOMVt2i2X7p4k0b5bs6TVrKrpw@mail.gmail.com>

On 26 September 2014 13:06, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
>> Hi,
>>
>> This cleans up and fixes fw stats aggregation.
>>
>>
>> Michal Kazior (4):
>>   ath10k: split wmi stats parsing
>>   ath10k: rename fw_stats related stuff
>>   ath10k: request fw_stats once on open
>>   ath10k: fix fw stats processing
>
> I didn't review these yet but I saw new warnings:
>
> drivers/net/wireless/ath/ath10k/debug.c: In function 'ath10k_fw_stats_fill':
> drivers/net/wireless/ath/ath10k/debug.c:540:5: warning: format '%lu' expects argument of type 'long unsigned int', but argument 5 has type 'size_t' [-Wformat]

Oh, I didn't see this one. I guess it should be %zu.


> drivers/net/wireless/ath/ath10k/wmi.c:1513: WARNING: else is not generally useful after a break or return

I'm aware of this one but the code looks nicer with the `else` to me though.


Micha?


From joe at perches.com  Fri Sep 26 07:14:21 2014
From: joe at perches.com (Joe Perches)
Date: Fri, 26 Sep 2014 07:14:21 -0700
Subject: [PATCH 0/4] ath10k: fix/cleanup fw stats
In-Reply-To: <CA+BoTQmJ-HprccxTO3UrX+NkhOMVt2i2X7p4k0b5bs6TVrKrpw@mail.gmail.com>
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
 <871tqy63p9.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQmJ-HprccxTO3UrX+NkhOMVt2i2X7p4k0b5bs6TVrKrpw@mail.gmail.com>
Message-ID: <1411740861.19443.6.camel@joe-AO725>

On Fri, 2014-09-26 at 13:14 +0200, Michal Kazior wrote:
> On 26 September 2014 13:06, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> > drivers/net/wireless/ath/ath10k/wmi.c:1513: WARNING: else is not generally useful after a break or return
> I'm aware of this one but the code looks nicer with the `else` to me though.

Yay Michal.

Always use your taste over any mindless style tool.

Ignore any checkpatch complaint you want.

btw: checkpatch shouldn't warn about this as of:

commit adefeef310ee8bd3923d41b67bc53c398bc53621
Author: Joe Perches <joe at perches.com>
Date:   Fri Sep 26 10:19:29 2014 +1000

    checkpatch: add exception to return then else test
    
    Add an exception to the return before else warning
    when the line following it is also a return like:
    
        if (foo)
                return bar;
        else
                return baz;
    
    This form of a test then return is at least as readable as
    
        if (foo)
                return bar;
        return baz;
    
    so don't emit a warning on the first form.
    
    Signed-off-by: Joe Perches <joe at perches.com>
    Reported-by: Al Viro <viro at ZenIV.linux.org.uk>
    Cc: Elshad Mustafayev <elshadimo at gmail.com>
    Signed-off-by: Andrew Morton <akpm at linux-foundation.org>




From joe at perches.com  Fri Sep 26 10:17:43 2014
From: joe at perches.com (Joe Perches)
Date: Fri, 26 Sep 2014 10:17:43 -0700
Subject: [PATCH] ath: change logging functions to return void
In-Reply-To: <87wq8q4oz6.fsf@kamboji.qca.qualcomm.com>
References: <1411407334.2952.46.camel@joe-AO725>
 <87wq8q4oz6.fsf@kamboji.qca.qualcomm.com>
Message-ID: <1411751863.19443.7.camel@joe-AO725>

On Fri, 2014-09-26 at 14:10 +0300, Kalle Valo wrote:
> Joe Perches <joe at perches.com> writes:
> 
> > The return values are not used by callers of these functions
> > so change the functions to return void.
> >
> > Other miscellanea:
> >
> > o add __printf verification to wil6210 logging functions
> >   No format/argument mismatches found
> >
> > Signed-off-by: Joe Perches <joe at perches.com>
> 
> While applying this to our ath-next-test branch for build testing I had
> few conflicts in ath10k. Joe, can you please check my conflict
> resolution:
> 
> https://github.com/kvalo/ath/commit/9c5bd0cb84e4189ca85c041021aacdc015f3a9a5
> 

I don't know what the conflicts were, but the
changes seem fine to me.



From linville at tuxdriver.com  Fri Sep 26 10:36:33 2014
From: linville at tuxdriver.com (John W. Linville)
Date: Fri, 26 Sep 2014 13:36:33 -0400
Subject: Pull request: ath 20140923
In-Reply-To: <8738big00t.fsf@kamboji.qca.qualcomm.com>
References: <8738big00t.fsf@kamboji.qca.qualcomm.com>
Message-ID: <20140926173633.GF22967@tuxdriver.com>

On Tue, Sep 23, 2014 at 12:26:58PM +0300, Kalle Valo wrote:
> Hi John,
> 
> a new pull request just with ath10k changes this time. Changelog below
> and please let me know if there are any problems.
> 
> ----------------------------------------------------------------------
> 
> The only new feature is testmode support from me. Ben added a new method
> to crash the firmware with an assert for debug purposes. As usual, we
> have lots of smaller fixes from Michal. Matteo fixed a Kconfig
> dependency with debugfs. I fixed some warnings recently added to
> checkpatch.
> 
> ----------------------------------------------------------------------
> 
> 
> The following changes since commit 6a5d088a923854569e20eac4f3f569926d5911ec:
> 
>   carl9170: tx: Replace rcu_assign_pointer() with RCU_INIT_POINTER() (2014-08-28 14:50:13 -0400)
> 
> are available in the git repository at:
> 
>   git://github.com/kvalo/ath.git for-linville
> 
> for you to fetch changes up to b25f32cb02155d68c690255ba846796a1c248fd3:
> 
>   ath10k: use ether_addr_copy() (2014-09-18 10:47:03 +0300)

Pulling now, but I don't plan to push it back out until Dave pulls my earlier batch...

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


From kvalo at qca.qualcomm.com  Sat Sep 27 01:01:23 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Sat, 27 Sep 2014 11:01:23 +0300
Subject: [PATCH 4/4] ath10k: fix fw stats processing
In-Reply-To: <1411641230-18785-5-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 25 Sep 2014 12:33:50 +0200")
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
 <1411641230-18785-5-git-send-email-michal.kazior@tieto.com>
Message-ID: <8761g94hm4.fsf@kamboji.qca.qualcomm.com>

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

> If stat data exceeds wmi-htc buffer limits
> firmware splits it into many wmi stats update
> events which are delivered in a ping-pong fashion
> triggered by wmi stats request command.
>
> Since there's only an implicit start-of-data and
> no end-of-data indications the driver has to
> perform some trickery to get complete stat data.
>
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>

I folded the patch below in ath-next-next. Please check:

https://github.com/kvalo/ath/commit/7071112c5ddaff761cd7d9bb3110c3f3d2f83bb8

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 0e6626282664..680d5088b6f3 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -343,7 +343,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
 
 free:
 	/* In some cases lists have been spliced and cleared. Free up
-	 * resouruces if that is not the case.
+	 * resources if that is not the case.
 	 */
 	ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
 	ath10k_debug_fw_stats_peers_free(&stats.peers);
@@ -536,7 +536,7 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,
 			 "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
 
 	len += scnprintf(buf + len, buf_len - len, "\n");
-	len += scnprintf(buf + len, buf_len - len, "%30s (%lu)\n",
+	len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
 			 "ath10k PEER stats", num_peers);
 	len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
 				 "=================");


-- 
Kalle Valo


From michal.kazior at tieto.com  Mon Sep 29 00:16:14 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Mon, 29 Sep 2014 09:16:14 +0200
Subject: [PATCH 4/4] ath10k: fix fw stats processing
In-Reply-To: <8761g94hm4.fsf@kamboji.qca.qualcomm.com>
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
 <1411641230-18785-5-git-send-email-michal.kazior@tieto.com>
 <8761g94hm4.fsf@kamboji.qca.qualcomm.com>
Message-ID: <CA+BoTQmC7vec3OW8ZbCvkx761cMtUTT6f+UAVp7dMXj2hNRKUA@mail.gmail.com>

On 27 September 2014 10:01, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
> Michal Kazior <michal.kazior at tieto.com> writes:
>
>> If stat data exceeds wmi-htc buffer limits
>> firmware splits it into many wmi stats update
>> events which are delivered in a ping-pong fashion
>> triggered by wmi stats request command.
>>
>> Since there's only an implicit start-of-data and
>> no end-of-data indications the driver has to
>> perform some trickery to get complete stat data.
>>
>> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
>
> I folded the patch below in ath-next-next. Please check:
>
> https://github.com/kvalo/ath/commit/7071112c5ddaff761cd7d9bb3110c3f3d2f83bb8
[...]

I think you meant:

  https://github.com/kvalo/ath/commit/5122a60f4fbf5a38e70a14578858b39058ee367a

It looks good. Thanks!


Micha?


From kvalo at qca.qualcomm.com  Mon Sep 29 00:38:59 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 10:38:59 +0300
Subject: [PATCH 4/4] ath10k: fix fw stats processing
In-Reply-To: <CA+BoTQmC7vec3OW8ZbCvkx761cMtUTT6f+UAVp7dMXj2hNRKUA@mail.gmail.com>
 (Michal Kazior's message of "Mon, 29 Sep 2014 09:16:14 +0200")
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
 <1411641230-18785-5-git-send-email-michal.kazior@tieto.com>
 <8761g94hm4.fsf@kamboji.qca.qualcomm.com>
 <CA+BoTQmC7vec3OW8ZbCvkx761cMtUTT6f+UAVp7dMXj2hNRKUA@mail.gmail.com>
Message-ID: <87iok63mgc.fsf@kamboji.qca.qualcomm.com>

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

> On 27 September 2014 10:01, Kalle Valo <kvalo at qca.qualcomm.com> wrote:
>> Michal Kazior <michal.kazior at tieto.com> writes:
>>
>>> If stat data exceeds wmi-htc buffer limits
>>> firmware splits it into many wmi stats update
>>> events which are delivered in a ping-pong fashion
>>> triggered by wmi stats request command.
>>>
>>> Since there's only an implicit start-of-data and
>>> no end-of-data indications the driver has to
>>> perform some trickery to get complete stat data.
>>>
>>> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
>>
>> I folded the patch below in ath-next-next. Please check:
>>
>> https://github.com/kvalo/ath/commit/7071112c5ddaff761cd7d9bb3110c3f3d2f83bb8
> [...]
>
> I think you meant:
>
>   https://github.com/kvalo/ath/commit/5122a60f4fbf5a38e70a14578858b39058ee367a

Indeed. Sorry for the mixup.

> It looks good. Thanks!

Thanks for checking.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 29 01:21:10 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 11:21:10 +0300
Subject: [PATCH v2 03/10] ath10k: support ethtool stats.
In-Reply-To: <5422D71F.7080809@candelatech.com> (Ben Greear's message of "Wed, 
 24 Sep 2014 07:37:19 -0700")
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
 <1411507045-18973-3-git-send-email-greearb@candelatech.com>
 <CA+BoTQkK=6NfPN9e-3qN2Qaq2RLVdEwrp5x03_T=E2ZLcBeiaA@mail.gmail.com>
 <5422D71F.7080809@candelatech.com>
Message-ID: <87eguu3ki1.fsf@kamboji.qca.qualcomm.com>

Ben Greear <greearb at candelatech.com> writes:

> On 09/24/2014 12:44 AM, Michal Kazior wrote:
>> On 23 September 2014 23:17,  <greearb at candelatech.com> wrote:
>> [...]
>>> +void ath10k_get_et_stats(struct ieee80211_hw *hw,
>>> +                        struct ieee80211_vif *vif,
>>> +                        struct ethtool_stats *stats, u64 *data)
>>> +{
>>> +       struct ath10k *ar = hw->priv;
>>> +       int i = 0;
>>> +       struct ath10k_target_stats *fw_stats;
>>> +
>>> +       fw_stats = &ar->debug.target_stats;
>>> +
>>> +       mutex_lock(&ar->conf_mutex);
>>> +
>>> +       if (ar->state == ATH10K_STATE_ON)
>>> +               ath10k_refresh_peer_stats(ar);
>>> +
>>> +       mutex_unlock(&ar->conf_mutex);
>>
>> Just for correctness sake - it's probably a good idea to
>> mutex_unlock() at the end (i.e. after spin_unlock_bh()) to make sure
>> the stats are for this particular request. With your patch there's a
>> very slight chance that, e.g. fw_stats debug file is being read at the
>> same time and it updates fw stats between the above mutex_unlock() and
>> following spin_lock_bh().
>
> That makes no difference at all to the user though, and it is one less
> set of nested locks to worry about.

I still do not want to have known races, especially when it's so easy to
fix. The ethtool patches patches conflict with Michal's fw_stats fixes.
Let me take the ethtool patches so that I can rebase them, fix this race
and do some other small changes as well. I'll send v2 soon.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 29 01:24:36 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 11:24:36 +0300
Subject: [PATCH v2 07/10] ath10k: add fw-powerup-fail to ethtool stats.
In-Reply-To: <1411507045-18973-7-git-send-email-greearb@candelatech.com>
 (greearb@candelatech.com's message of "Tue, 23 Sep 2014 14:17:22
 -0700")
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
 <1411507045-18973-7-git-send-email-greearb@candelatech.com>
Message-ID: <87a95i3kcb.fsf@kamboji.qca.qualcomm.com>

greearb at candelatech.com writes:

> From: Ben Greear <greearb at candelatech.com>
>
> This gives user-space a normal-ish way to detect that
> firmware has failed to start and that a reboot is
> probably required.
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>

[...]

> --- a/drivers/net/wireless/ath/ath10k/pci.c
> +++ b/drivers/net/wireless/ath/ath10k/pci.c
> @@ -1851,7 +1851,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
>  			    ret);
>  
>  		if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY)
> -			return ret;
> +			goto out;
>  
>  		ath10k_warn(ar, "trying cold reset\n");
>  
> @@ -1859,11 +1859,17 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
>  		if (ret) {
>  			ath10k_err(ar, "failed to power up target using cold reset too (%d)\n",
>  				   ret);
> -			return ret;
> +			goto out;
>  		}
>  	}
>  
> -	return 0;
> +out:
> +	/* If we have failed to power-up, it may take a reboot to
> +	 * get the NIC back online.
> +	 * Set flag accordinly so that user-space can know.
> +	 */
> +	ar->fw_powerup_failed = !!ret;
> +	return ret;
>  }

Would it be better to use ATH10K_STATE_WEDGED for this and then just
export the state value to user space? Or should we have two different
states, like FW_WEDGED and HW_WEDGED?

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 29 02:42:15 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 12:42:15 +0300
Subject: [PATCH v2 1/2] ath10k: add firmware crash counters
Message-ID: <20140929094214.12889.97523.stgit@potku.adurom.net>

From: Ben Greear <greearb at candelatech.com>

kvalo: split into it's own patch, add debugfs file and add locking

Signed-off-by: Ben Greear <greearb at candelatech.com>
Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/core.h  |    7 +++++
 drivers/net/wireless/ath/ath10k/debug.c |   44 +++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/pci.c   |   14 ++++++++++
 3 files changed, 65 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 674e38c219e6..5a1dc98375e1 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -563,6 +563,13 @@ struct ath10k {
 		bool utf_monitor;
 	} testmode;
 
+	struct {
+		/* protected by data_lock */
+		u32 fw_crash_counter;
+		u32 fw_warm_reset_counter;
+		u32 fw_cold_reset_counter;
+	} stats;
+
 	/* must be last */
 	u8 drv_priv[0] __aligned(sizeof(void *));
 };
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 680d5088b6f3..8d3db1c3f4a8 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -625,6 +625,47 @@ static const struct file_operations fops_fw_stats = {
 	.llseek = default_llseek,
 };
 
+static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	int ret, len, buf_len;
+	char *buf;
+
+	buf_len = 500;
+	buf = kmalloc(buf_len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	spin_lock_bh(&ar->data_lock);
+
+	len = 0;
+	len += scnprintf(buf + len, buf_len - len,
+			 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
+	len += scnprintf(buf + len, buf_len - len,
+			 "fw_warm_reset_counter\t\t%d\n",
+			 ar->stats.fw_warm_reset_counter);
+	len += scnprintf(buf + len, buf_len - len,
+			 "fw_cold_reset_counter\t\t%d\n",
+			 ar->stats.fw_cold_reset_counter);
+
+	spin_unlock_bh(&ar->data_lock);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+	kfree(buf);
+
+	return ret;
+}
+
+static const struct file_operations fops_fw_reset_stats = {
+	.open = simple_open,
+	.read = ath10k_debug_fw_reset_stats_read,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 /* This is a clean assert crash in firmware. */
 static int ath10k_debug_fw_assert(struct ath10k *ar)
 {
@@ -1331,6 +1372,9 @@ int ath10k_debug_register(struct ath10k *ar)
 	debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
 			    &fops_fw_stats);
 
+	debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy,
+			    ar, &fops_fw_reset_stats);
+
 	debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
 			    &fops_wmi_services);
 
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index ae961c6ff74e..8a04904cccee 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1006,6 +1006,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
 
 	spin_lock_bh(&ar->data_lock);
 
+	ar->stats.fw_crash_counter++;
+
 	crash_data = ath10k_debug_get_new_fw_crash_data(ar);
 
 	if (crash_data)
@@ -1692,6 +1694,12 @@ static int ath10k_pci_warm_reset(struct ath10k *ar)
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
 
+	spin_lock_bh(&ar->data_lock);
+
+	ar->stats.fw_warm_reset_counter++;
+
+	spin_unlock_bh(&ar->data_lock);
+
 	/* debug */
 	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
 				PCIE_INTR_CAUSE_ADDRESS);
@@ -2308,6 +2316,12 @@ static int ath10k_pci_cold_reset(struct ath10k *ar)
 
 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
 
+	spin_lock_bh(&ar->data_lock);
+
+	ar->stats.fw_cold_reset_counter++;
+
+	spin_unlock_bh(&ar->data_lock);
+
 	/* Put Target, including PCIe, into RESET. */
 	val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS);
 	val |= 1;



From kvalo at qca.qualcomm.com  Mon Sep 29 02:42:21 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 12:42:21 +0300
Subject: [PATCH v2 2/2] ath10k: support ethtool stats
In-Reply-To: <20140929094214.12889.97523.stgit@potku.adurom.net>
References: <20140929094214.12889.97523.stgit@potku.adurom.net>
Message-ID: <20140929094221.12889.84916.stgit@potku.adurom.net>

From: Ben Greear <greearb at candelatech.com>

Add support for reading firmware stats through the ethtool
API.  This may be easier for applications to manipulate
compared to parsing a text based debugfs file.

kvalo: remove unneeded ifdefs, call ath10k_debug_fw_stats_request() and added
simple error handling

Signed-off-by: Ben Greear <greearb at candelatech.com>
Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/debug.c |  160 +++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/debug.h |   13 +++
 drivers/net/wireless/ath/ath10k/mac.c   |    3 +
 3 files changed, 176 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 8d3db1c3f4a8..2bb894f31337 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1130,6 +1130,166 @@ exit:
 	return ret;
 }
 
+/* TODO:  Would be nice to always support ethtool stats, would need to
+ * move the stats storage out of ath10k_debug, or always have ath10k_debug
+ * struct available..
+ */
+
+/* This generally cooresponds to the debugfs fw_stats file */
+static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"tx_pkts_nic",
+	"tx_bytes_nic",
+	"rx_pkts_nic",
+	"rx_bytes_nic",
+	"d_noise_floor",
+	"d_cycle_count",
+	"d_phy_error",
+	"d_rts_bad",
+	"d_rts_good",
+	"d_tx_power", /* in .5 dbM I think */
+	"d_rx_crc_err", /* fcs_bad */
+	"d_no_beacon",
+	"d_tx_mpdus_queued",
+	"d_tx_msdu_queued",
+	"d_tx_msdu_dropped",
+	"d_local_enqued",
+	"d_local_freed",
+	"d_tx_ppdu_hw_queued",
+	"d_tx_ppdu_reaped",
+	"d_tx_fifo_underrun",
+	"d_tx_ppdu_abort",
+	"d_tx_mpdu_requed",
+	"d_tx_excessive_retries",
+	"d_tx_hw_rate",
+	"d_tx_dropped_sw_retries",
+	"d_tx_illegal_rate",
+	"d_tx_continuous_xretries",
+	"d_tx_timeout",
+	"d_tx_mpdu_txop_limit",
+	"d_pdev_resets",
+	"d_rx_mid_ppdu_route_change",
+	"d_rx_status",
+	"d_rx_extra_frags_ring0",
+	"d_rx_extra_frags_ring1",
+	"d_rx_extra_frags_ring2",
+	"d_rx_extra_frags_ring3",
+	"d_rx_msdu_htt",
+	"d_rx_mpdu_htt",
+	"d_rx_msdu_stack",
+	"d_rx_mpdu_stack",
+	"d_rx_phy_err",
+	"d_rx_phy_err_drops",
+	"d_rx_mpdu_errors", /* FCS, MIC, ENC */
+	"d_fw_crash_count",
+	"d_fw_warm_reset_count",
+	"d_fw_cold_reset_count",
+};
+
+#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
+
+void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
+				 struct ieee80211_vif *vif,
+				 u32 sset, u8 *data)
+{
+	if (sset == ETH_SS_STATS)
+		memcpy(data, *ath10k_gstrings_stats,
+		       sizeof(ath10k_gstrings_stats));
+}
+
+int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif, int sset)
+{
+	if (sset == ETH_SS_STATS)
+		return ATH10K_SSTATS_LEN;
+
+	return 0;
+}
+
+void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ethtool_stats *stats, u64 *data)
+{
+	struct ath10k *ar = hw->priv;
+	static const struct ath10k_fw_stats_pdev zero_stats = {};
+	const struct ath10k_fw_stats_pdev *pdev_stats;
+	int i = 0, ret;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state == ATH10K_STATE_ON) {
+		ret = ath10k_debug_fw_stats_request(ar);
+		if (ret) {
+			/* just print a warning and try to use older results */
+			ath10k_warn(ar,
+				    "failed to get fw stats for ethtool: %d\n",
+				    ret);
+		}
+	}
+
+	pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
+					      struct ath10k_fw_stats_pdev,
+					      list);
+	if (!pdev_stats) {
+		/* no results available so just return zeroes */
+		pdev_stats = &zero_stats;
+	}
+
+	spin_lock_bh(&ar->data_lock);
+
+	data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
+	data[i++] = 0; /* tx bytes */
+	data[i++] = pdev_stats->htt_mpdus;
+	data[i++] = 0; /* rx bytes */
+	data[i++] = pdev_stats->ch_noise_floor;
+	data[i++] = pdev_stats->cycle_count;
+	data[i++] = pdev_stats->phy_err_count;
+	data[i++] = pdev_stats->rts_bad;
+	data[i++] = pdev_stats->rts_good;
+	data[i++] = pdev_stats->chan_tx_power;
+	data[i++] = pdev_stats->fcs_bad;
+	data[i++] = pdev_stats->no_beacons;
+	data[i++] = pdev_stats->mpdu_enqued;
+	data[i++] = pdev_stats->msdu_enqued;
+	data[i++] = pdev_stats->wmm_drop;
+	data[i++] = pdev_stats->local_enqued;
+	data[i++] = pdev_stats->local_freed;
+	data[i++] = pdev_stats->hw_queued;
+	data[i++] = pdev_stats->hw_reaped;
+	data[i++] = pdev_stats->underrun;
+	data[i++] = pdev_stats->tx_abort;
+	data[i++] = pdev_stats->mpdus_requed;
+	data[i++] = pdev_stats->tx_ko;
+	data[i++] = pdev_stats->data_rc;
+	data[i++] = pdev_stats->sw_retry_failure;
+	data[i++] = pdev_stats->illgl_rate_phy_err;
+	data[i++] = pdev_stats->pdev_cont_xretry;
+	data[i++] = pdev_stats->pdev_tx_timeout;
+	data[i++] = pdev_stats->txop_ovf;
+	data[i++] = pdev_stats->pdev_resets;
+	data[i++] = pdev_stats->mid_ppdu_route_change;
+	data[i++] = pdev_stats->status_rcvd;
+	data[i++] = pdev_stats->r0_frags;
+	data[i++] = pdev_stats->r1_frags;
+	data[i++] = pdev_stats->r2_frags;
+	data[i++] = pdev_stats->r3_frags;
+	data[i++] = pdev_stats->htt_msdus;
+	data[i++] = pdev_stats->htt_mpdus;
+	data[i++] = pdev_stats->loc_msdus;
+	data[i++] = pdev_stats->loc_mpdus;
+	data[i++] = pdev_stats->phy_errs;
+	data[i++] = pdev_stats->phy_err_drop;
+	data[i++] = pdev_stats->mpdu_errs;
+	data[i++] = ar->stats.fw_crash_counter;
+	data[i++] = ar->stats.fw_warm_reset_counter;
+	data[i++] = ar->stats.fw_cold_reset_counter;
+
+	spin_unlock_bh(&ar->data_lock);
+
+	mutex_unlock(&ar->conf_mutex);
+
+	WARN_ON(i != ATH10K_SSTATS_LEN);
+}
+
 static const struct file_operations fops_fw_dbglog = {
 	.read = ath10k_read_fw_dbglog,
 	.write = ath10k_write_fw_dbglog,
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index efbcd29fe9a1..d6a565d2bb74 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -63,6 +63,15 @@ void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
 
 #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
 
+void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
+				 struct ieee80211_vif *vif,
+				 u32 sset, u8 *data);
+int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif, int sset);
+void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ethtool_stats *stats, u64 *data);
+
 #else
 static inline int ath10k_debug_start(struct ath10k *ar)
 {
@@ -115,6 +124,10 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
 
 #define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
 
+#define ath10k_debug_get_et_strings NULL
+#define ath10k_debug_get_et_sset_count NULL
+#define ath10k_debug_get_et_stats NULL
+
 #endif /* CONFIG_ATH10K_DEBUGFS */
 
 #ifdef CONFIG_ATH10K_DEBUG
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index a99d91947edc..4d1aef4b8cd4 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4505,6 +4505,9 @@ static const struct ieee80211_ops ath10k_ops = {
 	.sta_rc_update			= ath10k_sta_rc_update,
 	.get_tsf			= ath10k_get_tsf,
 	.ampdu_action			= ath10k_ampdu_action,
+	.get_et_sset_count		= ath10k_debug_get_et_sset_count,
+	.get_et_stats			= ath10k_debug_get_et_stats,
+	.get_et_strings			= ath10k_debug_get_et_strings,
 
 	CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
 



From kvalo at qca.qualcomm.com  Mon Sep 29 02:47:01 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 12:47:01 +0300
Subject: [PATCH v2 1/2] ath10k: add firmware crash counters
In-Reply-To: <20140929094214.12889.97523.stgit@potku.adurom.net> (Kalle Valo's
 message of "Mon, 29 Sep 2014 12:42:15 +0300")
References: <20140929094214.12889.97523.stgit@potku.adurom.net>
Message-ID: <8761g63giy.fsf@kamboji.qca.qualcomm.com>

Kalle Valo <kvalo at qca.qualcomm.com> writes:

> From: Ben Greear <greearb at candelatech.com>
>
> kvalo: split into it's own patch, add debugfs file and add locking
>
> Signed-off-by: Ben Greear <greearb at candelatech.com>
> Signed-off-by: Kalle Valo <kvalo at qca.qualcomm.com>

Oh, I forgot to add a commit log. I'm planning to add something like
this:

----------------------------------------------------------------------
Add three counters related to firmware crashes or resets.

Usage:

# cat /sys/kernel/debug/ieee80211/phy0/ath10k/fw_reset_stats 
fw_crash_counter                2
fw_warm_reset_counter           43
fw_cold_reset_counter           0
#

----------------------------------------------------------------------

Also I forgot to add the cover letter, here's the changelog for both
patches:

v2:

* remove unneeded ifdef from debug.c

* rebase on top of Michal's "ath10k: fix fw stats processing",
  dropping patch "ath10k: add helper method to grab debug stats"
  because it was not needed anymore

* remove ifdef from ath10k_ops with "#define foo NULL" hack

* hold mutex when reading pdev_stats in ath10k_debug_get_et_stats()

* move fw reset stats to struct ath10k::stats and add locking

* add fw_reset_stats debugfs file


-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 29 03:53:05 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 13:53:05 +0300
Subject: [PATCH] ath10k: request firmware flush in ath10k_flush.
In-Reply-To: <CA+BoTQkZaGSkC9mhE8UF0He0RZWmPghDukdE1A5qiO1UNAZj5Q@mail.gmail.com>
 (Michal Kazior's message of "Wed, 24 Sep 2014 08:50:38 +0200")
References: <1411151304-31544-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQm1rZO+yBbYxihpgEvR1cGZWS4Pr0AP+KMODcG4jpd_jQ@mail.gmail.com>
 <5421818A.9040501@candelatech.com>
 <CA+BoTQkZaGSkC9mhE8UF0He0RZWmPghDukdE1A5qiO1UNAZj5Q@mail.gmail.com>
Message-ID: <871tqu3dgu.fsf@kamboji.qca.qualcomm.com>

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

> On 23 September 2014 16:19, Ben Greear <greearb at candelatech.com> wrote:
>> On 09/23/2014 02:16 AM, Michal Kazior wrote:
>>> On 19 September 2014 20:28,  <greearb at candelatech.com> wrote:
>>> [...]
>>>>
>>>> +       /* If we are CT firmware, ask it to flush all tids on all peers
>>>> on
>>>> +        * all vdevs.  Normal firmware will just crash if you do this.
>>>> +        */
>>>> +       if (test_bit(ATH10K_FW_FEATURE_WMI_10X_CT, ar->fw_features))
>>>> +               ath10k_wmi_peer_flush(ar, 0xFFFFFFFF, peer_addr,
>>>> 0xFFFFFFFF);
>>>
>>> I recall you've explained this some time ago, but can you refresh my
>>> memory, please? Is this any different from iterating over all peers
>>> and flushing each? Or does your firmware do so extra magic that is
>>> impossible to do with normal firmware commands?
>>
>> My firmware does that iteration internally.
>>
>> You could probably do that in the driver, but it would be a lot
>> of messages (for all vdevs, all peers, all tids)...
>> I was not sure if there were limits to the number
>> of commands you should attempt during the flush...
>
> Thanks. I think ath10k should do this instead of having CT-specific
> flush eventually.

I agree. We should not be forking functionality unless absolutely
necessary.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 29 04:04:27 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 14:04:27 +0300
Subject: Possible issue with firmware crash reporting.
In-Reply-To: <5421B67D.8060508@candelatech.com> (Ben Greear's message of "Tue, 
 23 Sep 2014 11:05:49 -0700")
References: <5421B67D.8060508@candelatech.com>
Message-ID: <87wq8m1ydg.fsf@kamboji.qca.qualcomm.com>

Ben Greear <greearb at candelatech.com> writes:

> This kernel is basically linux-ath from a few days ago
> plus a bunch of my patches, including my versions of the firmware
> BSS and stack dump patches.
> Problem could be mine alone, but likely the patches Kalle
> is working on would be susceptible to the same sort of problem.
>
> I produced this by purposefully crashing the firmware during
> station registration while debugging some firmware issues.
>
> This is just FYI, but if someone cares to do similar
> testing, I can build a special firmware that crashes
> in the same way and make it available.
>
>
> =================================
> [ INFO: inconsistent lock state ]
> 3.17.0-rc6+ #3 Not tainted
> ---------------------------------
> inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
> swapper/2/0 [HC0[0]:SC1[1]:HE1:SE0] takes:
>  (uevent_sock_mutex){+.?.+.}, at: [<ffffffff8133d402>]
> kobject_uevent_env+0x2b8/0x5d7

[...]

> {SOFTIRQ-ON-W} state was registered at:
>   [<ffffffff81111f34>] __lock_acquire+0x352/0xe48
>   [<ffffffff81112ef6>] lock_acquire+0xd2/0x120
>   [<ffffffff8165c77c>] mutex_lock_nested+0x4f/0x3c7
>   [<ffffffff8133d402>] kobject_uevent_env+0x2b8/0x5d7
>   [<ffffffff8133d72c>] kobject_uevent+0xb/0xd
>   [<ffffffff8133c970>] kset_register+0x30/0x3e
>   [<ffffffff81431a7a>] bus_register+0xae/0x292
>   [<ffffffff81d69174>] platform_bus_init+0x29/0x41
>   [<ffffffff81d69202>] driver_init+0x27/0x33
>   [<ffffffff81d1e0d9>] kernel_init_freeable+0x155/0x263
>   [<ffffffff8164e95a>] kernel_init+0x9/0xda
>   [<ffffffff8165f0bc>] ret_from_fork+0x7c/0xb0

[...]

>  <IRQ>  [<ffffffff81657366>] dump_stack+0x4e/0x71
>  [<ffffffff81653c50>] print_usage_bug+0x1ec/0x1fd
>  [<ffffffff8101bcae>] ? save_stack_trace+0x27/0x44
>  [<ffffffff81111457>] ? check_usage_backwards+0xa0/0xa0
>  [<ffffffff81111aeb>] mark_lock+0x11b/0x212
>  [<ffffffff81111ebe>] __lock_acquire+0x2dc/0xe48
>  [<ffffffff81113215>] ? mark_held_locks+0x54/0x76
>  [<ffffffff811904f3>] ? __free_pages_ok+0xb3/0xca
>  [<ffffffff811133c9>] ? trace_hardirqs_on_caller+0x192/0x1a1
>  [<ffffffff81112ef6>] lock_acquire+0xd2/0x120
>  [<ffffffff8133d402>] ? kobject_uevent_env+0x2b8/0x5d7
>  [<ffffffff8165c77c>] mutex_lock_nested+0x4f/0x3c7
>  [<ffffffff8133d402>] ? kobject_uevent_env+0x2b8/0x5d7
>  [<ffffffff8133d402>] ? kobject_uevent_env+0x2b8/0x5d7
>  [<ffffffff81430f16>] ? dev_uevent+0x1d4/0x274
>  [<ffffffff8133c147>] ? kobject_get_path+0x8c/0xdb
>  [<ffffffff8133d402>] kobject_uevent_env+0x2b8/0x5d7
>  [<ffffffff811133c9>] ? trace_hardirqs_on_caller+0x192/0x1a1
>  [<ffffffffa069c70f>] ath10k_pci_fw_crashed_dump+0x456/0x535 [ath10k_pci]
>  [<ffffffff81006432>] ? xen_set_domain_pte+0x37/0xe1
>  [<ffffffffa069c854>] ath10k_pci_tasklet+0x27/0x5a [ath10k_pci]
>  [<ffffffff810dcd4d>] tasklet_action+0xcb/0xdd

If I'm reading this right, uevent_sock_mutex is by both
platform_bus_init() and and ath10k tasklet in
ath10k_pci_fw_crashed_dump() tries to acquire the same lock via
kobject_uevent_evn(). But I don't understand is how
ath10k_pci_fw_crashed_dump() ends up calling kobject_uevent_env(), I
just can't find a code path to do that.

Are you sure you don't have some custom patches which cause this, like
sending a uevent whenever firmware crashes?

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 29 04:18:05 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 14:18:05 +0300
Subject: Possible issue with firmware crash reporting.
In-Reply-To: <87wq8m1ydg.fsf@kamboji.qca.qualcomm.com> (Kalle Valo's message
 of "Mon, 29 Sep 2014 14:04:27 +0300")
References: <5421B67D.8060508@candelatech.com>
 <87wq8m1ydg.fsf@kamboji.qca.qualcomm.com>
Message-ID: <87lhp21xqq.fsf@kamboji.qca.qualcomm.com>

Kalle Valo <kvalo at qca.qualcomm.com> writes:

> If I'm reading this right, uevent_sock_mutex is by both
> platform_bus_init()

"uevent_sock_mutex is held by platform_bus_init()"


-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 29 04:28:42 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 14:28:42 +0300
Subject: [PATCH] ath: change logging functions to return void
In-Reply-To: <1411407334.2952.46.camel@joe-AO725> (Joe Perches's message of
 "Mon, 22 Sep 2014 10:35:34 -0700")
References: <1411407334.2952.46.camel@joe-AO725>
Message-ID: <87h9zq1x91.fsf@kamboji.qca.qualcomm.com>

Joe Perches <joe at perches.com> writes:

> The return values are not used by callers of these functions
> so change the functions to return void.
>
> Other miscellanea:
>
> o add __printf verification to wil6210 logging functions
>   No format/argument mismatches found
>
> Signed-off-by: Joe Perches <joe at perches.com>

Thanks, applied.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 29 04:32:23 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 14:32:23 +0300
Subject: [PATCH 0/4] ath10k: fix/cleanup fw stats
In-Reply-To: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
 (Michal Kazior's message of "Thu, 25 Sep 2014 12:33:46 +0200")
References: <1411641230-18785-1-git-send-email-michal.kazior@tieto.com>
Message-ID: <87d2ae1x2w.fsf@kamboji.qca.qualcomm.com>

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

> This cleans up and fixes fw stats aggregation.
>
>
> Michal Kazior (4):
>   ath10k: split wmi stats parsing
>   ath10k: rename fw_stats related stuff
>   ath10k: request fw_stats once on open
>   ath10k: fix fw stats processing

Thanks, applied.

And thank you for fixing this for good, it has been buggy for way too
long.

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 29 04:49:48 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Mon, 29 Sep 2014 14:49:48 +0300
Subject: checkpatch: CHECK: No space is necessary after a cast
Message-ID: <874mvq1w9v.fsf@kamboji.qca.qualcomm.com>

Hi Joe,

I have a problem with checkpatch. On ath10k we have this function:

static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb)
{
	BUILD_BUG_ON(sizeof(struct ath10k_skb_cb) >
		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
	return (struct ath10k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data;
}

And the BUILD_BUG_ON triggers this warning:

drivers/net/wireless/ath/ath10k/core.h:85: CHECK: No space is necessary after a cast

Any advice how to handle that?

-- 
Kalle Valo


From greearb at candelatech.com  Mon Sep 29 08:58:57 2014
From: greearb at candelatech.com (Ben Greear)
Date: Mon, 29 Sep 2014 08:58:57 -0700
Subject: [PATCH] ath10k: request firmware flush in ath10k_flush.
In-Reply-To: <871tqu3dgu.fsf@kamboji.qca.qualcomm.com>
References: <1411151304-31544-1-git-send-email-greearb@candelatech.com>
 <CA+BoTQm1rZO+yBbYxihpgEvR1cGZWS4Pr0AP+KMODcG4jpd_jQ@mail.gmail.com>
 <5421818A.9040501@candelatech.com>
 <CA+BoTQkZaGSkC9mhE8UF0He0RZWmPghDukdE1A5qiO1UNAZj5Q@mail.gmail.com>
 <871tqu3dgu.fsf@kamboji.qca.qualcomm.com>
Message-ID: <542981C1.7020000@candelatech.com>

On 09/29/2014 03:53 AM, Kalle Valo wrote:

>> Thanks. I think ath10k should do this instead of having CT-specific
>> flush eventually.
> 
> I agree. We should not be forking functionality unless absolutely
> necessary.

Ok, this patch is easy to carry in my own tree.

But, for things upstream firmware just cannot support,
like tx-rate-status and rx-software-crypt, how do you
want it flagged in the driver?  Can I get the CT firmware
flag in for that, or does it have to be some other way?

If you just will not accept any such patch, let me know so
I can quite bothering you about it.

Thanks,
Ben

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



From greearb at candelatech.com  Mon Sep 29 09:05:16 2014
From: greearb at candelatech.com (Ben Greear)
Date: Mon, 29 Sep 2014 09:05:16 -0700
Subject: [PATCH v2 07/10] ath10k: add fw-powerup-fail to ethtool stats.
In-Reply-To: <87a95i3kcb.fsf@kamboji.qca.qualcomm.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
 <1411507045-18973-7-git-send-email-greearb@candelatech.com>
 <87a95i3kcb.fsf@kamboji.qca.qualcomm.com>
Message-ID: <5429833C.60003@candelatech.com>

On 09/29/2014 01:24 AM, Kalle Valo wrote:
> greearb at candelatech.com writes:
> 
>> From: Ben Greear <greearb at candelatech.com>
>>
>> This gives user-space a normal-ish way to detect that
>> firmware has failed to start and that a reboot is
>> probably required.
>>
>> Signed-off-by: Ben Greear <greearb at candelatech.com>
> 
> [...]
> 
>> --- a/drivers/net/wireless/ath/ath10k/pci.c
>> +++ b/drivers/net/wireless/ath/ath10k/pci.c
>> @@ -1851,7 +1851,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
>>  			    ret);
>>  
>>  		if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY)
>> -			return ret;
>> +			goto out;
>>  
>>  		ath10k_warn(ar, "trying cold reset\n");
>>  
>> @@ -1859,11 +1859,17 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
>>  		if (ret) {
>>  			ath10k_err(ar, "failed to power up target using cold reset too (%d)\n",
>>  				   ret);
>> -			return ret;
>> +			goto out;
>>  		}
>>  	}
>>  
>> -	return 0;
>> +out:
>> +	/* If we have failed to power-up, it may take a reboot to
>> +	 * get the NIC back online.
>> +	 * Set flag accordinly so that user-space can know.
>> +	 */
>> +	ar->fw_powerup_failed = !!ret;
>> +	return ret;
>>  }
> 
> Would it be better to use ATH10K_STATE_WEDGED for this and then just
> export the state value to user space? Or should we have two different
> states, like FW_WEDGED and HW_WEDGED?

I didn't want to mess with the state machine.  This counter
is just a clue to users that things might be badly wrong.  Some systems
might recover with another hard reset, some will hang the entire
system hard, and some will just stick in this state unable to
recover.  Some of my systems exhibit this last behaviour, so at
least with this patch I can warn the user that they need to
reboot to regain wifi functionality.

If you want to tie it to a state machine, that is OK with me, but
I don't want to mess with it because that code is already tricky
enough.

Thanks,
Ben


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



From greearb at candelatech.com  Mon Sep 29 09:07:06 2014
From: greearb at candelatech.com (Ben Greear)
Date: Mon, 29 Sep 2014 09:07:06 -0700
Subject: [PATCH v2 03/10] ath10k: support ethtool stats.
In-Reply-To: <87eguu3ki1.fsf@kamboji.qca.qualcomm.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
 <1411507045-18973-3-git-send-email-greearb@candelatech.com>
 <CA+BoTQkK=6NfPN9e-3qN2Qaq2RLVdEwrp5x03_T=E2ZLcBeiaA@mail.gmail.com>
 <5422D71F.7080809@candelatech.com> <87eguu3ki1.fsf@kamboji.qca.qualcomm.com>
Message-ID: <542983AA.9040200@candelatech.com>

On 09/29/2014 01:21 AM, Kalle Valo wrote:
> Ben Greear <greearb at candelatech.com> writes:
> 
>> On 09/24/2014 12:44 AM, Michal Kazior wrote:
>>> On 23 September 2014 23:17,  <greearb at candelatech.com> wrote:
>>> [...]
>>>> +void ath10k_get_et_stats(struct ieee80211_hw *hw,
>>>> +                        struct ieee80211_vif *vif,
>>>> +                        struct ethtool_stats *stats, u64 *data)
>>>> +{
>>>> +       struct ath10k *ar = hw->priv;
>>>> +       int i = 0;
>>>> +       struct ath10k_target_stats *fw_stats;
>>>> +
>>>> +       fw_stats = &ar->debug.target_stats;
>>>> +
>>>> +       mutex_lock(&ar->conf_mutex);
>>>> +
>>>> +       if (ar->state == ATH10K_STATE_ON)
>>>> +               ath10k_refresh_peer_stats(ar);
>>>> +
>>>> +       mutex_unlock(&ar->conf_mutex);
>>>
>>> Just for correctness sake - it's probably a good idea to
>>> mutex_unlock() at the end (i.e. after spin_unlock_bh()) to make sure
>>> the stats are for this particular request. With your patch there's a
>>> very slight chance that, e.g. fw_stats debug file is being read at the
>>> same time and it updates fw stats between the above mutex_unlock() and
>>> following spin_lock_bh().
>>
>> That makes no difference at all to the user though, and it is one less
>> set of nested locks to worry about.
> 
> I still do not want to have known races, especially when it's so easy to
> fix. The ethtool patches patches conflict with Michal's fw_stats fixes.
> Let me take the ethtool patches so that I can rebase them, fix this race
> and do some other small changes as well. I'll send v2 soon.

Your v2 patches are fine with me.

Thanks,
Ben


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



From greearb at candelatech.com  Mon Sep 29 09:10:53 2014
From: greearb at candelatech.com (Ben Greear)
Date: Mon, 29 Sep 2014 09:10:53 -0700
Subject: Possible issue with firmware crash reporting.
In-Reply-To: <87wq8m1ydg.fsf@kamboji.qca.qualcomm.com>
References: <5421B67D.8060508@candelatech.com>
 <87wq8m1ydg.fsf@kamboji.qca.qualcomm.com>
Message-ID: <5429848D.6000706@candelatech.com>

On 09/29/2014 04:04 AM, Kalle Valo wrote:
> Ben Greear <greearb at candelatech.com> writes:
> 
>> This kernel is basically linux-ath from a few days ago
>> plus a bunch of my patches, including my versions of the firmware
>> BSS and stack dump patches.
>> Problem could be mine alone, but likely the patches Kalle
>> is working on would be susceptible to the same sort of problem.
>>
>> I produced this by purposefully crashing the firmware during
>> station registration while debugging some firmware issues.
>>
>> This is just FYI, but if someone cares to do similar
>> testing, I can build a special firmware that crashes
>> in the same way and make it available.
>>
>>
>> =================================
>> [ INFO: inconsistent lock state ]
>> 3.17.0-rc6+ #3 Not tainted
>> ---------------------------------
>> inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
>> swapper/2/0 [HC0[0]:SC1[1]:HE1:SE0] takes:
>>  (uevent_sock_mutex){+.?.+.}, at: [<ffffffff8133d402>]
>> kobject_uevent_env+0x2b8/0x5d7
> 
> [...]
> 
>> {SOFTIRQ-ON-W} state was registered at:
>>   [<ffffffff81111f34>] __lock_acquire+0x352/0xe48
>>   [<ffffffff81112ef6>] lock_acquire+0xd2/0x120
>>   [<ffffffff8165c77c>] mutex_lock_nested+0x4f/0x3c7
>>   [<ffffffff8133d402>] kobject_uevent_env+0x2b8/0x5d7
>>   [<ffffffff8133d72c>] kobject_uevent+0xb/0xd
>>   [<ffffffff8133c970>] kset_register+0x30/0x3e
>>   [<ffffffff81431a7a>] bus_register+0xae/0x292
>>   [<ffffffff81d69174>] platform_bus_init+0x29/0x41
>>   [<ffffffff81d69202>] driver_init+0x27/0x33
>>   [<ffffffff81d1e0d9>] kernel_init_freeable+0x155/0x263
>>   [<ffffffff8164e95a>] kernel_init+0x9/0xda
>>   [<ffffffff8165f0bc>] ret_from_fork+0x7c/0xb0
> 
> [...]
> 
>>  <IRQ>  [<ffffffff81657366>] dump_stack+0x4e/0x71
>>  [<ffffffff81653c50>] print_usage_bug+0x1ec/0x1fd
>>  [<ffffffff8101bcae>] ? save_stack_trace+0x27/0x44
>>  [<ffffffff81111457>] ? check_usage_backwards+0xa0/0xa0
>>  [<ffffffff81111aeb>] mark_lock+0x11b/0x212
>>  [<ffffffff81111ebe>] __lock_acquire+0x2dc/0xe48
>>  [<ffffffff81113215>] ? mark_held_locks+0x54/0x76
>>  [<ffffffff811904f3>] ? __free_pages_ok+0xb3/0xca
>>  [<ffffffff811133c9>] ? trace_hardirqs_on_caller+0x192/0x1a1
>>  [<ffffffff81112ef6>] lock_acquire+0xd2/0x120
>>  [<ffffffff8133d402>] ? kobject_uevent_env+0x2b8/0x5d7
>>  [<ffffffff8165c77c>] mutex_lock_nested+0x4f/0x3c7
>>  [<ffffffff8133d402>] ? kobject_uevent_env+0x2b8/0x5d7
>>  [<ffffffff8133d402>] ? kobject_uevent_env+0x2b8/0x5d7
>>  [<ffffffff81430f16>] ? dev_uevent+0x1d4/0x274
>>  [<ffffffff8133c147>] ? kobject_get_path+0x8c/0xdb
>>  [<ffffffff8133d402>] kobject_uevent_env+0x2b8/0x5d7
>>  [<ffffffff811133c9>] ? trace_hardirqs_on_caller+0x192/0x1a1
>>  [<ffffffffa069c70f>] ath10k_pci_fw_crashed_dump+0x456/0x535 [ath10k_pci]
>>  [<ffffffff81006432>] ? xen_set_domain_pte+0x37/0xe1
>>  [<ffffffffa069c854>] ath10k_pci_tasklet+0x27/0x5a [ath10k_pci]
>>  [<ffffffff810dcd4d>] tasklet_action+0xcb/0xdd
> 
> If I'm reading this right, uevent_sock_mutex is by both
> platform_bus_init() and and ath10k tasklet in
> ath10k_pci_fw_crashed_dump() tries to acquire the same lock via
> kobject_uevent_evn(). But I don't understand is how
> ath10k_pci_fw_crashed_dump() ends up calling kobject_uevent_env(), I
> just can't find a code path to do that.
> 
> Are you sure you don't have some custom patches which cause this, like
> sending a uevent whenever firmware crashes?

Well yes, I do have that patch in this kernel I think.

I'll remove it, I can key off of the ethtool stats for
firmware crash counts instead.

Thanks,
Ben


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



From joe at perches.com  Mon Sep 29 11:02:35 2014
From: joe at perches.com (Joe Perches)
Date: Mon, 29 Sep 2014 11:02:35 -0700
Subject: checkpatch: CHECK: No space is necessary after a cast
In-Reply-To: <874mvq1w9v.fsf@kamboji.qca.qualcomm.com>
References: <874mvq1w9v.fsf@kamboji.qca.qualcomm.com>
Message-ID: <1412013755.4302.45.camel@joe-AO725>

On Mon, 2014-09-29 at 14:49 +0300, Kalle Valo wrote:
> Hi Joe,
> 
> I have a problem with checkpatch. On ath10k we have this function:
> 
> static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb)
> {
> 	BUILD_BUG_ON(sizeof(struct ath10k_skb_cb) >
> 		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
> 	return (struct ath10k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data;
> }
> 
> And the BUILD_BUG_ON triggers this warning:
> 
> drivers/net/wireless/ath/ath10k/core.h:85: CHECK: No space is necessary after a cast
> 
> Any advice how to handle that?

It's a checkpatch false positive that could be fixed.

It needs something like another test to look for
sizeof(type) as not a cast and more arithmetic/comparison
uses.

Maybe you can test this?
---
 scripts/checkpatch.pl | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 52a223e..6132329 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2515,7 +2515,8 @@ sub process {
 			}
 		}
 
-		if ($line =~ /^\+.*\(\s*$Type\s*\)[ \t]+(?!$Assignment|$Arithmetic|{)/) {
+		if ($line =~ /^\+.*(\w+\s*)?\(\s*$Type\s*\)[ \t]+(?!$Assignment|$Arithmetic|[,;\({\[\<\>])/ &&
+		    (!defined($1) || $1 !~ /sizeof\s*/)) {
 			if (CHK("SPACING",
 				"No space is necessary after a cast\n" . $herecurr) &&
 			    $fix) {




From kvalo at qca.qualcomm.com  Mon Sep 29 22:35:32 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 30 Sep 2014 08:35:32 +0300
Subject: checkpatch: CHECK: No space is necessary after a cast
In-Reply-To: <1412013755.4302.45.camel@joe-AO725> (Joe Perches's message of
 "Mon, 29 Sep 2014 11:02:35 -0700")
References: <874mvq1w9v.fsf@kamboji.qca.qualcomm.com>
 <1412013755.4302.45.camel@joe-AO725>
Message-ID: <87bnpxy8kb.fsf@kamboji.qca.qualcomm.com>

Joe Perches <joe at perches.com> writes:

> On Mon, 2014-09-29 at 14:49 +0300, Kalle Valo wrote:
>> Hi Joe,
>> 
>> I have a problem with checkpatch. On ath10k we have this function:
>> 
>> static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb)
>> {
>> 	BUILD_BUG_ON(sizeof(struct ath10k_skb_cb) >
>> 		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
>> 	return (struct ath10k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data;
>> }
>> 
>> And the BUILD_BUG_ON triggers this warning:
>> 
>> drivers/net/wireless/ath/ath10k/core.h:85: CHECK: No space is necessary after a cast
>> 
>> Any advice how to handle that?
>
> It's a checkpatch false positive that could be fixed.
>
> It needs something like another test to look for
> sizeof(type) as not a cast and more arithmetic/comparison
> uses.
>
> Maybe you can test this?

It works, thank you!

Tested-by: Kalle Valo <kvalo at qca.qualcomm.com>

-- 
Kalle Valo


From kvalo at qca.qualcomm.com  Mon Sep 29 23:10:53 2014
From: kvalo at qca.qualcomm.com (Kalle Valo)
Date: Tue, 30 Sep 2014 09:10:53 +0300
Subject: checkpatch: long help string
Message-ID: <8738b9y6xe.fsf@kamboji.qca.qualcomm.com>

Hi Joe,

another checkpatch question. I have this warning in ath10k:

drivers/net/wireless/ath/ath10k/debug.c:656: WARNING: line over 83 characters

And it comes from this help string:

	const char buf[] =
		"To simulate firmware crash write one of the keywords to this file:\n"
		"`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
		"`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
		"`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n";

https://github.com/kvalo/ath/blob/ath-next/drivers/net/wireless/ath/ath10k/debug.c#L652

Any recommendations how to handle that?

-- 
Kalle Valo


From michal.kazior at tieto.com  Tue Sep 30 05:27:23 2014
From: michal.kazior at tieto.com (Michal Kazior)
Date: Tue, 30 Sep 2014 14:27:23 +0200
Subject: [PATCH v2 07/10] ath10k: add fw-powerup-fail to ethtool stats.
In-Reply-To: <5429833C.60003@candelatech.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
 <1411507045-18973-7-git-send-email-greearb@candelatech.com>
 <87a95i3kcb.fsf@kamboji.qca.qualcomm.com>
 <5429833C.60003@candelatech.com>
Message-ID: <CA+BoTQ=NG9to+Tv4Ci+Vu_dOGRgGVzxJUyb1bydWCc-EeWc_9g@mail.gmail.com>

On 29 September 2014 18:05, Ben Greear <greearb at candelatech.com> wrote:
> On 09/29/2014 01:24 AM, Kalle Valo wrote:
>> greearb at candelatech.com writes:
>>
>>> From: Ben Greear <greearb at candelatech.com>
>>>
>>> This gives user-space a normal-ish way to detect that
>>> firmware has failed to start and that a reboot is
>>> probably required.
>>>
>>> Signed-off-by: Ben Greear <greearb at candelatech.com>
[...]
>>> -    return 0;
>>> +out:
>>> +    /* If we have failed to power-up, it may take a reboot to
>>> +     * get the NIC back online.
>>> +     * Set flag accordinly so that user-space can know.
>>> +     */
>>> +    ar->fw_powerup_failed = !!ret;
>>> +    return ret;
>>>  }
>>
>> Would it be better to use ATH10K_STATE_WEDGED for this and then just
>> export the state value to user space? Or should we have two different
>> states, like FW_WEDGED and HW_WEDGED?

Current WEDGED state is more like ON. It assumes mac80211 will call
ath10k_stop().

Adding another state just for the sake of handling power up / reset
issues seems like an overkill to me.


> I didn't want to mess with the state machine.  This counter
> is just a clue to users that things might be badly wrong.  Some systems
> might recover with another hard reset, some will hang the entire
> system hard, and some will just stick in this state unable to
> recover.  Some of my systems exhibit this last behaviour, so at
> least with this patch I can warn the user that they need to
> reboot to regain wifi functionality.

If power up fails the error should propagate to `ifconfig wlanX up`
(or whatever calling drv_start) eventually so I don't see the point in
having this counter.


Micha?


From greearb at candelatech.com  Tue Sep 30 08:53:20 2014
From: greearb at candelatech.com (Ben Greear)
Date: Tue, 30 Sep 2014 08:53:20 -0700
Subject: [PATCH v2 07/10] ath10k: add fw-powerup-fail to ethtool stats.
In-Reply-To: <CA+BoTQ=NG9to+Tv4Ci+Vu_dOGRgGVzxJUyb1bydWCc-EeWc_9g@mail.gmail.com>
References: <1411507045-18973-1-git-send-email-greearb@candelatech.com>
 <1411507045-18973-7-git-send-email-greearb@candelatech.com>
 <87a95i3kcb.fsf@kamboji.qca.qualcomm.com> <5429833C.60003@candelatech.com>
 <CA+BoTQ=NG9to+Tv4Ci+Vu_dOGRgGVzxJUyb1bydWCc-EeWc_9g@mail.gmail.com>
Message-ID: <542AD1F0.8070308@candelatech.com>

On 09/30/2014 05:27 AM, Michal Kazior wrote:
> On 29 September 2014 18:05, Ben Greear <greearb at candelatech.com> wrote:
>> On 09/29/2014 01:24 AM, Kalle Valo wrote:
>>> greearb at candelatech.com writes:
>>>
>>>> From: Ben Greear <greearb at candelatech.com>
>>>>
>>>> This gives user-space a normal-ish way to detect that
>>>> firmware has failed to start and that a reboot is
>>>> probably required.
>>>>
>>>> Signed-off-by: Ben Greear <greearb at candelatech.com>
> [...]
>>>> -    return 0;
>>>> +out:
>>>> +    /* If we have failed to power-up, it may take a reboot to
>>>> +     * get the NIC back online.
>>>> +     * Set flag accordinly so that user-space can know.
>>>> +     */
>>>> +    ar->fw_powerup_failed = !!ret;
>>>> +    return ret;
>>>>  }
>>>
>>> Would it be better to use ATH10K_STATE_WEDGED for this and then just
>>> export the state value to user space? Or should we have two different
>>> states, like FW_WEDGED and HW_WEDGED?
> 
> Current WEDGED state is more like ON. It assumes mac80211 will call
> ath10k_stop().
> 
> Adding another state just for the sake of handling power up / reset
> issues seems like an overkill to me.
> 
> 
>> I didn't want to mess with the state machine.  This counter
>> is just a clue to users that things might be badly wrong.  Some systems
>> might recover with another hard reset, some will hang the entire
>> system hard, and some will just stick in this state unable to
>> recover.  Some of my systems exhibit this last behaviour, so at
>> least with this patch I can warn the user that they need to
>> reboot to regain wifi functionality.
> 
> If power up fails the error should propagate to `ifconfig wlanX up`
> (or whatever calling drv_start) eventually so I don't see the point in
> having this counter.

Supplicant manages this, and programatically it is not at all easy to
figure out that the network is failing to come up because the firmware
is broken-and-can't-be-fixed-without-reboot.

The counter I added can be queried by a management tool and propagate a
clear error to the end user.

Thanks,
Ben

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



