* Re: [PATCH v2 1/2] mac80211: Remove invalid flag operations in mesh TSF synchronization
From: Johannes Berg @ 2016-12-13 15:23 UTC (permalink / raw)
To: Masashi Honma, me; +Cc: linux-wireless
In-Reply-To: <1481159751-4097-1-git-send-email-masashi.honma@gmail.com>
On Thu, 2016-12-08 at 10:15 +0900, Masashi Honma wrote:
> mesh_sync_offset_adjust_tbtt() implements Extensible synchronization
> framework ([1] 13.13.2 Extensible synchronization framework). It
> shall
> not operate the flag "TBTT Adjusting subfield" ([1] 8.4.2.100.8 Mesh
> Capability), since it is used only for MBCA ([1] 13.13.4 Mesh beacon
> collision avoidance, see 13.13.4.4.3 TBTT scanning and adjustment
> procedures for detail). So this patch remove the flag operations.
>
Both applied; I changed this patch to remove ifmsh->adjusting_tbtt
completely since it was now unused.
johannes
^ permalink raw reply
* Re: [PATCH v2 2/2] net: rfkill: Add rfkill-any LED trigger
From: Johannes Berg @ 2016-12-13 15:18 UTC (permalink / raw)
To: Michał Kępień, David S . Miller
Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20161208073052.12988-2-kernel@kempniu.pl>
On Thu, 2016-12-08 at 08:30 +0100, Michał Kępień wrote:
> Add a new "global" (i.e. not per-rfkill device) LED trigger, rfkill-
> any,
> which may be useful on laptops with a single "radio LED" and multiple
> radio transmitters. The trigger is meant to turn a LED on whenever
> there is at least one radio transmitter active and turn it off
> otherwise.
>
Also applied, but I moved the discussion of the mutex into the recorded
commit log.
johannes
^ permalink raw reply
* Re: [PATCH v2 1/2] net: rfkill: Cleanup error handling in rfkill_init()
From: Johannes Berg @ 2016-12-13 15:16 UTC (permalink / raw)
To: Michał Kępień, David S . Miller
Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20161208073052.12988-1-kernel@kempniu.pl>
On Thu, 2016-12-08 at 08:30 +0100, Michał Kępień wrote:
> Use a separate label per error condition in rfkill_init() to make it
> a bit cleaner and easier to extend.
applied.
johannes
^ permalink raw reply
* Re: [PATCH v2] mac80211: Ensure enough headroom when forwarding mesh pkt
From: Johannes Berg @ 2016-12-13 15:09 UTC (permalink / raw)
To: Cedric Izoard, linux-wireless@vger.kernel.org
In-Reply-To: <1ffe01100a724290ab910d68980604ba@ceva-dsp.com>
On Wed, 2016-12-07 at 09:59 +0000, Cedric Izoard wrote:
> When a buffer is duplicated during MESH packet forwarding,
> this patch ensures that the new buffer has enough headroom.
Applied.
johannes
^ permalink raw reply
* Re: [PATCH] ath9k: unlock rcu read when returning early
From: Felix Fietkau @ 2016-12-13 13:52 UTC (permalink / raw)
To: Tobias Klausmann, kvalo, helgaas, linux-kernel, linux-pci,
marc.zyngier, Janusz.Dziedzic, rmanohar, ath9k-devel,
linux-wireless, rmanohar, bharat.kumar.gogada
In-Reply-To: <7b4b7748-06d6-92d4-228c-e7ebf00f8699@mni.thm.de>
On 2016-12-13 14:41, Tobias Klausmann wrote:
> On 13.12.2016 11:41, Felix Fietkau wrote:
>> On 2016-12-12 19:50, Tobias Klausmann wrote:
>>> diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
>>> index 52bfbb988611..857d5ae09a1d 100644
>>> --- a/drivers/net/wireless/ath/ath9k/xmit.c
>>> +++ b/drivers/net/wireless/ath/ath9k/xmit.c
>>> @@ -2787,6 +2787,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
>>> fifo_list = &txq->txq_fifo[txq->txq_tailidx];
>>> if (list_empty(fifo_list)) {
>>> ath_txq_unlock(sc, txq);
>>> + rcu_read_unlock();
>> Technically this is fine as well, but I'd prefer a fix where you replace
>> the 'return' with 'break', thus avoiding the duplication of
>> rcu_read_unlock()
>
> Actually if you want to avoid it, maybe skipping over the rest is better
> (as originally intended):
>
> ...
>
> ath_txq_unlock(sc, txq);
>
>
> goto unlock;
> }
> ...
>
> unlock:
> rcu_read_unlock();
There are already other places that skip to the rcu_read_unlock() part
by using 'break'. I don't see how adding an unnecessary goto makes
things any better.
- Felix
^ permalink raw reply
* Re: [RFC v2 05/11] ath10k: htc: refactorization
From: Michal Kazior @ 2016-12-13 13:52 UTC (permalink / raw)
To: Valo, Kalle
Cc: Erik Stromdahl, linux-wireless@vger.kernel.org,
ath10k@lists.infradead.org
In-Reply-To: <87inqoymd0.fsf@kamboji.qca.qualcomm.com>
On 13 December 2016 at 14:44, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
> Erik Stromdahl <erik.stromdahl@gmail.com> writes:
>
>> Code refactorization:
>>
>> Moved the code for ep 0 in ath10k_htc_rx_completion_handler
>> to ath10k_htc_control_rx_complete.
>>
>> This eases the implementation of SDIO/mbox significantly since
>> the ep_rx_complete cb is invoked directly from the SDIO/mbox
>> hif layer.
>>
>> Since the ath10k_htc_control_rx_complete already is present
>> (only containing a warning message) there is no reason for not
>> using it (instead of having a special case for ep 0 in
>> ath10k_htc_rx_completion_handler).
>>
>> Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
>
> I tested this on QCA988X PCI board just to see if there are any
> regressions. It crashes immediately during module load, every time, and
> bisected that the crashing starts on this patch:
>
> [ 1239.715325] ath10k_pci 0000:02:00.0: pci irq msi oper_irq_mode 2 irq_m=
ode 0 reset_mode 0
> [ 1239.885125] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/p=
re-cal-pci-0000:02:00.0.bin failed with error -2
> [ 1239.885260] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/c=
al-pci-0000:02:00.0.bin failed with error -2
> [ 1239.885687] ath10k_pci 0000:02:00.0: qca988x hw2.0 target 0x4100016c c=
hip_id 0x043202ff sub 0000:0000
> [ 1239.885699] ath10k_pci 0000:02:00.0: kconfig debug 1 debugfs 1 tracing=
1 dfs 1 testmode 1
> [ 1239.885899] ath10k_pci 0000:02:00.0: firmware ver 10.2.4.70.59-2 api 5=
features no-p2p,raw-mode,mfp,allows-mesh-bcast crc32 4159f498
> [ 1239.941836] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/Q=
CA988X/hw2.0/board-2.bin failed with error -2
> [ 1239.941993] ath10k_pci 0000:02:00.0: board_file api 1 bmi_id N/A crc32=
bebc7c08
> [ 1241.136693] BUG: unable to handle kernel NULL pointer dereference at =
(null)
> [ 1241.136738] IP: [< (null)>] (null)
> [ 1241.136759] *pdpt =3D 0000000000000000 *pde =3D f0002a55f0002a55 [ 124=
1.136781]
> [ 1241.136793] Oops: 0010 [#1] SMP
>
> What's odd is that when I added some printks on my own and enabled both
> boot and htc debug levels it doesn't crash anymore. After everything
> works normally after that, I can start AP mode and connect to it. Is it
> a race somewhere?
Yes. htc_wait_target() is called after hif_start(). The ep_rx_complete
is set in htc_wait_target() [changed patch 4, but still too late].
ep_rx_complete must be set prior to calling hif_start(). You probably
crash on end of ath10k_htc_rx_completion_handler() when trying to call
ep->ep_ops.ep_rx_complete(ar, skb).
Micha=C5=82
^ permalink raw reply
* Re: [RFC v2 05/11] ath10k: htc: refactorization
From: Valo, Kalle @ 2016-12-13 13:44 UTC (permalink / raw)
To: Erik Stromdahl; +Cc: linux-wireless@vger.kernel.org, ath10k@lists.infradead.org
In-Reply-To: <1479496971-19174-6-git-send-email-erik.stromdahl@gmail.com>
Erik Stromdahl <erik.stromdahl@gmail.com> writes:
> Code refactorization:
>
> Moved the code for ep 0 in ath10k_htc_rx_completion_handler
> to ath10k_htc_control_rx_complete.
>
> This eases the implementation of SDIO/mbox significantly since
> the ep_rx_complete cb is invoked directly from the SDIO/mbox
> hif layer.
>
> Since the ath10k_htc_control_rx_complete already is present
> (only containing a warning message) there is no reason for not
> using it (instead of having a special case for ep 0 in
> ath10k_htc_rx_completion_handler).
>
> Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
I tested this on QCA988X PCI board just to see if there are any
regressions. It crashes immediately during module load, every time, and
bisected that the crashing starts on this patch:
[ 1239.715325] ath10k_pci 0000:02:00.0: pci irq msi oper_irq_mode 2 irq_mod=
e 0 reset_mode 0
[ 1239.885125] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/pre=
-cal-pci-0000:02:00.0.bin failed with error -2
[ 1239.885260] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/cal=
-pci-0000:02:00.0.bin failed with error -2
[ 1239.885687] ath10k_pci 0000:02:00.0: qca988x hw2.0 target 0x4100016c chi=
p_id 0x043202ff sub 0000:0000
[ 1239.885699] ath10k_pci 0000:02:00.0: kconfig debug 1 debugfs 1 tracing 1=
dfs 1 testmode 1
[ 1239.885899] ath10k_pci 0000:02:00.0: firmware ver 10.2.4.70.59-2 api 5 f=
eatures no-p2p,raw-mode,mfp,allows-mesh-bcast crc32 4159f498
[ 1239.941836] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/QCA=
988X/hw2.0/board-2.bin failed with error -2
[ 1239.941993] ath10k_pci 0000:02:00.0: board_file api 1 bmi_id N/A crc32 b=
ebc7c08
[ 1241.136693] BUG: unable to handle kernel NULL pointer dereference at (=
null)
[ 1241.136738] IP: [< (null)>] (null)
[ 1241.136759] *pdpt =3D 0000000000000000 *pde =3D f0002a55f0002a55 [ 1241.=
136781]=20
[ 1241.136793] Oops: 0010 [#1] SMP
What's odd is that when I added some printks on my own and enabled both
boot and htc debug levels it doesn't crash anymore. After everything
works normally after that, I can start AP mode and connect to it. Is it
a race somewhere?
--=20
Kalle Valo=
^ permalink raw reply
* Re: [PATCH] ath9k: unlock rcu read when returning early
From: Tobias Klausmann @ 2016-12-13 13:41 UTC (permalink / raw)
To: Felix Fietkau, kvalo, helgaas, linux-kernel, linux-pci,
marc.zyngier, Janusz.Dziedzic, rmanohar, ath9k-devel,
linux-wireless, rmanohar, bharat.kumar.gogada
In-Reply-To: <e15c5efc-d548-8b32-ca86-5ec26506ff7c@nbd.name>
On 13.12.2016 11:41, Felix Fietkau wrote:
> On 2016-12-12 19:50, Tobias Klausmann wrote:
>> Starting with ath9k: use ieee80211_tx_status_noskb where possible
>> [d94a461d7a7df68991fb9663531173f60ef89c68] the driver uses rcu_read_lock() &&
>> rcu_read_unlock() yet on returning early in ath_tx_edma_tasklet() the unlock is
>> missing leading to stalls and suspicious RCU usage:
>>
>> ===============================
>> [ INFO: suspicious RCU usage. ]
>> 4.9.0-rc8 #11 Not tainted
>> -------------------------------
>> kernel/rcu/tree.c:705 Illegal idle entry in RCU read-side critical section.!
>>
>> other info that might help us debug this:
>>
>> RCU used illegally from idle CPU!
>> rcu_scheduler_active = 1, debug_locks = 0
>> RCU used illegally from extended quiescent state!
>> 1 lock held by swapper/7/0:
>> #0:
>> (
>> rcu_read_lock
>> ){......}
>> , at:
>> [<ffffffffa06ed110>] ath_tx_edma_tasklet+0x0/0x450 [ath9k]
>>
>> stack backtrace:
>> CPU: 7 PID: 0 Comm: swapper/7 Not tainted 4.9.0-rc8 #11
>> Hardware name: Acer Aspire V3-571G/VA50_HC_CR, BIOS V2.21 12/16/2013
>> ffff88025efc3f38 ffffffff8132b1e5 ffff88017ede4540 0000000000000001
>> ffff88025efc3f68 ffffffff810a25f7 ffff88025efcee60 ffff88017edebdd8
>> ffff88025eeb5400 0000000000000091 ffff88025efc3f88 ffffffff810c3cd4
>> Call Trace:
>> <IRQ>
>> [<ffffffff8132b1e5>] dump_stack+0x68/0x93
>> [<ffffffff810a25f7>] lockdep_rcu_suspicious+0xd7/0x110
>> [<ffffffff810c3cd4>] rcu_eqs_enter_common.constprop.85+0x154/0x200
>> [<ffffffff810c5a54>] rcu_irq_exit+0x44/0xa0
>> [<ffffffff81058631>] irq_exit+0x61/0xd0
>> [<ffffffff81018d25>] do_IRQ+0x65/0x110
>> [<ffffffff81672189>] common_interrupt+0x89/0x89
>> <EOI>
>> [<ffffffff814ffe11>] ? cpuidle_enter_state+0x151/0x200
>> [<ffffffff814ffee2>] cpuidle_enter+0x12/0x20
>> [<ffffffff8109a6ae>] call_cpuidle+0x1e/0x40
>> [<ffffffff8109a8f6>] cpu_startup_entry+0x146/0x220
>> [<ffffffff810336f8>] start_secondary+0x148/0x170
>>
>> Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann@mni.thm.de>
>> ---
>> drivers/net/wireless/ath/ath9k/xmit.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
>> index 52bfbb988611..857d5ae09a1d 100644
>> --- a/drivers/net/wireless/ath/ath9k/xmit.c
>> +++ b/drivers/net/wireless/ath/ath9k/xmit.c
>> @@ -2787,6 +2787,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
>> fifo_list = &txq->txq_fifo[txq->txq_tailidx];
>> if (list_empty(fifo_list)) {
>> ath_txq_unlock(sc, txq);
>> + rcu_read_unlock();
> Technically this is fine as well, but I'd prefer a fix where you replace
> the 'return' with 'break', thus avoiding the duplication of
> rcu_read_unlock()
Actually if you want to avoid it, maybe skipping over the rest is better
(as originally intended):
...
ath_txq_unlock(sc, txq);
goto unlock;
}
...
unlock:
rcu_read_unlock();
Thanks,
Tobias
>
> Thanks,
>
> - Felix
>
^ permalink raw reply
* Re: [RFC v2 11/11] ath10k: Added sdio support
From: Valo, Kalle @ 2016-12-13 13:10 UTC (permalink / raw)
To: Erik Stromdahl; +Cc: linux-wireless@vger.kernel.org, ath10k@lists.infradead.org
In-Reply-To: <1479496971-19174-12-git-send-email-erik.stromdahl@gmail.com>
Erik Stromdahl <erik.stromdahl@gmail.com> writes:
> Initial HIF sdio/mailbox implementation.
>
> Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
While testing this I noticed few new warnings:
drivers/net/wireless/ath/ath10k/sdio.c: In function ath10k_sdio_probe:
drivers/net/wireless/ath/ath10k/sdio.c:1723:6: warning: 'ret' may be used u=
ninitialized in this function [-Wuninitialized]
drivers/net/wireless/ath/ath10k/sdio.c:375:5: warning: symbol 'ath10k_sdio_=
mbox_rxmsg_pending_handler' was not declared. Should it be static?
drivers/net/wireless/ath/ath10k/sdio.c:1018:5: warning: symbol 'ath10k_sdio=
_hif_tx_sg' was not declared. Should it be static?
drivers/net/wireless/ath/ath10k/sdio.c:1415:5: warning: symbol 'ath10k_sdio=
_hif_exchange_bmi_msg' was not declared. Should it be static?
drivers/net/wireless/ath/ath10k/sdio.c:1555:5: warning: symbol 'ath10k_sdio=
_hif_map_service_to_pipe' was not declared. Should it be static?
drivers/net/wireless/ath/ath10k/sdio.c:1635:6: warning: symbol 'ath10k_sdio=
_hif_get_default_pipe' was not declared. Should it be static?
drivers/net/wireless/ath/ath10k/htc.c:265: line over 90 characters
drivers/net/wireless/ath/ath10k/htc.c:355: line over 90 characters
--=20
Kalle Valo=
^ permalink raw reply
* Re: [PATCH 1/2] ath10k: add accounting for the extended peer statistics
From: Christian Lamparter @ 2016-12-13 12:41 UTC (permalink / raw)
To: Mohammed Shafi Shajakhan; +Cc: linux-wireless, ath10k, Kalle Valo
In-Reply-To: <20161207062824.GA3404@atheros-ThinkPad-T61>
Hello,
It looks like google put your mail into the spam-can.
I'm sorry for not answering sooner.
On Wednesday, December 7, 2016 11:58:24 AM CET Mohammed Shafi Shajakhan wrote:
> On Mon, Dec 05, 2016 at 10:52:45PM +0100, Christian Lamparter wrote:
> > The 10.4 firmware adds extended peer information to the
> > firmware's statistics payload. This additional info is
> > stored as a separate data field and the elements are
> > stored in their own "peers_extd" list.
> >
> > These elements can pile up in the same way as the peer
> > information elements. This is because the
> > ath10k_wmi_10_4_op_pull_fw_stats() function tries to
> > pull the same amount (num_peer_stats) for every statistic
> > data unit.
> >
> > Fixes: 4a49ae94a448faa ("ath10k: fix 10.4 extended peer stats update")
> > Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
> > ---
> > drivers/net/wireless/ath/ath10k/debug.c | 7 +++++--
> > 1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
> > index 82a4c67f3672..4acd9eb65910 100644
> > --- a/drivers/net/wireless/ath/ath10k/debug.c
> > +++ b/drivers/net/wireless/ath/ath10k/debug.c
> > @@ -399,6 +399,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
> > * prevent firmware from DoS-ing the host.
> > */
> > ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
> > + ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
>
> [shafi] thanks for fixing this !
>
> > ath10k_warn(ar, "dropping fw peer stats\n");
> > goto free;
> > }
> > @@ -409,10 +410,12 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
> > goto free;
> > }
> >
> > + if (!list_empty(&stats.peers))
>
> [shafi] sorry please correct me if i am wrong, for 'extended peer stats' we are checking
> for normal 'peer stats' ? Is this the fix intended, i had started a build to
> check your change and we will keep you posted, does this fix displaying
> 'rx_duration' in ath10k fw_stats.
The idea is not to queue any "extended peer stats" when there where no "peer stats" to
begin with. Because otherwise, the function is still vulnerable to OOM since the
extended peers stats will be queued unchecked (not that this is currently a problem).
> > + list_splice_tail_init(&stats.peers_extd,
> > + &ar->debug.fw_stats.peers_extd);
> > +
> > list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
> > list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
> > - list_splice_tail_init(&stats.peers_extd,
> > - &ar->debug.fw_stats.peers_extd);
> > }
> >
> > complete(&ar->debug.fw_stats_complete);
Regards,
Christian
^ permalink raw reply
* Re: [PATCH v2 0/7] ath9k: EEPROM swapping improvements
From: Valo, Kalle @ 2016-12-13 12:03 UTC (permalink / raw)
To: Martin Blumenstingl
Cc: ath9k-devel, linux-wireless@vger.kernel.org,
ath9k-devel@lists.ath9k.org, devicetree@vger.kernel.org,
arnd@arndb.de, chunkeey@googlemail.com, nbd@nbd.name
In-Reply-To: <CAFBinCC6JWBhZwma=66fBi3_to2SaHOMNDQS23jHNhcc+RUcYQ@mail.gmail.com>
Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:
> Hello Kalle,
>
> On Fri, Nov 25, 2016 at 4:06 PM, Valo, Kalle <kvalo@qca.qualcomm.com> wro=
te:
>> Kalle Valo <kvalo@codeaurora.org> writes:
>>
>>> Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:
>>>
>>>> There are two types of swapping the EEPROM data in the ath9k driver.
>>>> Before this series one type of swapping could not be used without the
>>>> other.
>>>>
>>>> The first type of swapping looks at the "magic bytes" at the start of
>>>> the EEPROM data and performs swab16 on the EEPROM contents if needed.
>>>> The second type of swapping is EEPROM format specific and swaps
>>>> specific fields within the EEPROM itself (swab16, swab32 - depends on
>>>> the EEPROM format).
>>>>
>>>> With this series the second part now looks at the EEPMISC register
>>>> inside the EEPROM, which uses a bit to indicate if the EEPROM data
>>>> is Big Endian (this is also done by the FreeBSD kernel).
>>>> This has a nice advantage: currently there are some out-of-tree hacks
>>>> (in OpenWrt and LEDE) where the EEPROM has a Big Endian header on a
>>>> Big Endian system (=3D no swab16 is performed) but the EEPROM itself
>>>> indicates that it's data is Little Endian. Until now the out-of-tree
>>>> code simply did a swab16 before passing the data to ath9k, so ath9k
>>>> first did the swab16 - this also enabled the format specific swapping.
>>>> These out-of-tree hacks are still working with the new logic, but it
>>>> is recommended to remove them. This implementation is based on a
>>>> discussion with Arnd Bergmann who raised concerns about the
>>>> robustness and portability of the swapping logic in the original OF
>>>> support patch review, see [0].
>>>>
>>>> After a second round of patches (=3D v1 of this series) neither Arnd
>>>> Bergmann nor I were really happy with the complexity of the EEPROM
>>>> swapping logic. Based on a discussion (see [1] and [2]) we decided
>>>> that ath9k should use a defined format (specifying the endianness
>>>> of the data - I went with __le16 and __le32) when accessing the
>>>> EEPROM fields. A benefit of this is that we enable the EEPMISC based
>>>> swapping logic by default, just like the FreeBSD driver, see [3]. On
>>>> the devices which I have tested (see below) ath9k now works without
>>>> having to specify the "endian_check" field in ath9k_platform_data (or
>>>> a similar logic which could provide this via devicetree) as ath9k now
>>>> detects the endianness automatically. Only EEPROMs which are mangled
>>>> by some out-of-tree code still need the endian_check flag (or one can
>>>> simply remove that mangling from the out-of-tree code).
>>>>
>>>> Testing:
>>>> - tested by myself on AR9287 with Big Endian EEPROM
>>>> - tested by myself on AR9227 with Little Endian EEPROM
>>>> - tested by myself on AR9381 (using the ar9003_eeprom implementation,
>>>> which did not suffer from this whole problem)
>>>> - how do we proceed with testing? maybe we could keep this in a
>>>> feature-branch and add these patches to LEDE once we have an ACK to
>>>> get more people to test this
>>>>
>>>> This series depends on my other series (v7):
>>>> "add devicetree support to ath9k" - see [4]
>>>
>>> I think this looks pretty good. If there's a bug somewhere it should be
>>> quite easy to fix so I'm not that worried and would be willing to take
>>> these as soon as I have applied the dependency series. IIRC your
>>> devicetree patches will have at least one more review round so that wil=
l
>>> take some time still. In the meantime it would be great if LEDE folks
>>> could take a look at these and comment (or test).
>>
>> So are everyone happy with this? I haven't seen any comments. If I don't
>> here anything I'm planning to take these, most likely for 4.11.
>
> the patches have been in LEDE for almost two weeks now and I did not
> see any reports of ath9k breakage (footnote below).
>
> It seems that there are a few devices out there where the whole EEPROM
> is swab16'ed which switches the position of the 1-byte fields
> opCapFlags and eepMisc.
> those still work fine with the new code, however I had a second patch
> in LEDE [0] which results in ath9k_platform_data.endian_check NOT
> being set anymore.
> that endian_check flag was used before to swab16 the whole EEPROM, to
> correct the position of the 1-byte fields again.
> Currently we are fixing this in the firmware hotplug script: [1]
> This is definitely not a blocker for this series though (if we want to
> have a devicetree replacement for "ath9k_platform_data.endian_check"
> then I'd work on that within a separate series, but I somewhat
> consider these EEPROMs as "broken" so fixing them in
> userspace/firmware hotplug script is fine for me)
Sounds good to me, thanks for the thorough followup. I'm planning to
apply these any day.
--=20
Kalle Valo=
^ permalink raw reply
* Re: [PATCH] orinoco: Use shash instead of ahash for MIC calculations
From: Kalle Valo @ 2016-12-13 11:35 UTC (permalink / raw)
To: Andy Lutomirski
Cc: linux-kernel, linux-usb, linux-wireless, Eric Biggers,
linux-crypto, Herbert Xu, Stephan Mueller
In-Reply-To: <8818c45b9ec6a04d85fabf9bb437cf119fd23659.1481575835.git.luto@kernel.org>
Andy Lutomirski <luto@kernel.org> writes:
> Eric Biggers pointed out that the orinoco driver pointed scatterlists
> at the stack.
>
> Fix it by switching from ahash to shash. The result should be
> simpler, faster, and more correct.
>
> Cc: stable@vger.kernel.org # 4.9 only
> Reported-by: Eric Biggers <ebiggers3@gmail.com>
> Signed-off-by: Andy Lutomirski <luto@kernel.org>
"more correct"? Does this fix a real user visible bug or what? And why
just stable 4.9, does this maybe have something to do with
CONFIG_VMAP_STACK?
I'm just wondering should I push this to 4.10 or -next. This is a driver
for ancient hardware so I'm starting to lean for -next.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH] ath9k: unlock rcu read when returning early
From: Felix Fietkau @ 2016-12-13 10:41 UTC (permalink / raw)
To: Tobias Klausmann, kvalo, helgaas, linux-kernel, linux-pci,
marc.zyngier, Janusz.Dziedzic, rmanohar, ath9k-devel,
linux-wireless, rmanohar, bharat.kumar.gogada
In-Reply-To: <20161212185001.3857-1-tobias.johannes.klausmann@mni.thm.de>
On 2016-12-12 19:50, Tobias Klausmann wrote:
> Starting with ath9k: use ieee80211_tx_status_noskb where possible
> [d94a461d7a7df68991fb9663531173f60ef89c68] the driver uses rcu_read_lock() &&
> rcu_read_unlock() yet on returning early in ath_tx_edma_tasklet() the unlock is
> missing leading to stalls and suspicious RCU usage:
>
> ===============================
> [ INFO: suspicious RCU usage. ]
> 4.9.0-rc8 #11 Not tainted
> -------------------------------
> kernel/rcu/tree.c:705 Illegal idle entry in RCU read-side critical section.!
>
> other info that might help us debug this:
>
> RCU used illegally from idle CPU!
> rcu_scheduler_active = 1, debug_locks = 0
> RCU used illegally from extended quiescent state!
> 1 lock held by swapper/7/0:
> #0:
> (
> rcu_read_lock
> ){......}
> , at:
> [<ffffffffa06ed110>] ath_tx_edma_tasklet+0x0/0x450 [ath9k]
>
> stack backtrace:
> CPU: 7 PID: 0 Comm: swapper/7 Not tainted 4.9.0-rc8 #11
> Hardware name: Acer Aspire V3-571G/VA50_HC_CR, BIOS V2.21 12/16/2013
> ffff88025efc3f38 ffffffff8132b1e5 ffff88017ede4540 0000000000000001
> ffff88025efc3f68 ffffffff810a25f7 ffff88025efcee60 ffff88017edebdd8
> ffff88025eeb5400 0000000000000091 ffff88025efc3f88 ffffffff810c3cd4
> Call Trace:
> <IRQ>
> [<ffffffff8132b1e5>] dump_stack+0x68/0x93
> [<ffffffff810a25f7>] lockdep_rcu_suspicious+0xd7/0x110
> [<ffffffff810c3cd4>] rcu_eqs_enter_common.constprop.85+0x154/0x200
> [<ffffffff810c5a54>] rcu_irq_exit+0x44/0xa0
> [<ffffffff81058631>] irq_exit+0x61/0xd0
> [<ffffffff81018d25>] do_IRQ+0x65/0x110
> [<ffffffff81672189>] common_interrupt+0x89/0x89
> <EOI>
> [<ffffffff814ffe11>] ? cpuidle_enter_state+0x151/0x200
> [<ffffffff814ffee2>] cpuidle_enter+0x12/0x20
> [<ffffffff8109a6ae>] call_cpuidle+0x1e/0x40
> [<ffffffff8109a8f6>] cpu_startup_entry+0x146/0x220
> [<ffffffff810336f8>] start_secondary+0x148/0x170
>
> Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann@mni.thm.de>
> ---
> drivers/net/wireless/ath/ath9k/xmit.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
> index 52bfbb988611..857d5ae09a1d 100644
> --- a/drivers/net/wireless/ath/ath9k/xmit.c
> +++ b/drivers/net/wireless/ath/ath9k/xmit.c
> @@ -2787,6 +2787,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
> fifo_list = &txq->txq_fifo[txq->txq_tailidx];
> if (list_empty(fifo_list)) {
> ath_txq_unlock(sc, txq);
> + rcu_read_unlock();
Technically this is fine as well, but I'd prefer a fix where you replace
the 'return' with 'break', thus avoiding the duplication of
rcu_read_unlock()
Thanks,
- Felix
^ permalink raw reply
* Re: [PATCH] ath9k: unlock rcu read when returning early
From: Kalle Valo @ 2016-12-13 9:59 UTC (permalink / raw)
To: Tobias Klausmann
Cc: helgaas, linux-kernel, linux-pci, marc.zyngier, Janusz.Dziedzic,
rmanohar, ath9k-devel, linux-wireless, rmanohar,
bharat.kumar.gogada, Felix Fietkau
In-Reply-To: <20161212185001.3857-1-tobias.johannes.klausmann@mni.thm.de>
Tobias Klausmann <tobias.johannes.klausmann@mni.thm.de> writes:
> Starting with ath9k: use ieee80211_tx_status_noskb where possible
> [d94a461d7a7df68991fb9663531173f60ef89c68]
The correct format to reference a commit in the commit log is:
Starting with commit d94a461d7a7d ("ath9k: use ieee80211_tx_status_noskb
where possible") the...
> the driver uses rcu_read_lock() && rcu_read_unlock() yet on returning
> early in ath_tx_edma_tasklet() the unlock is missing leading to stalls
> and suspicious RCU usage:
>
> ===============================
> [ INFO: suspicious RCU usage. ]
> 4.9.0-rc8 #11 Not tainted
> -------------------------------
> kernel/rcu/tree.c:705 Illegal idle entry in RCU read-side critical section.!
>
> other info that might help us debug this:
>
> RCU used illegally from idle CPU!
> rcu_scheduler_active = 1, debug_locks = 0
> RCU used illegally from extended quiescent state!
> 1 lock held by swapper/7/0:
> #0:
> (
> rcu_read_lock
> ){......}
> , at:
> [<ffffffffa06ed110>] ath_tx_edma_tasklet+0x0/0x450 [ath9k]
>
> stack backtrace:
> CPU: 7 PID: 0 Comm: swapper/7 Not tainted 4.9.0-rc8 #11
> Hardware name: Acer Aspire V3-571G/VA50_HC_CR, BIOS V2.21 12/16/2013
> ffff88025efc3f38 ffffffff8132b1e5 ffff88017ede4540 0000000000000001
> ffff88025efc3f68 ffffffff810a25f7 ffff88025efcee60 ffff88017edebdd8
> ffff88025eeb5400 0000000000000091 ffff88025efc3f88 ffffffff810c3cd4
> Call Trace:
> <IRQ>
> [<ffffffff8132b1e5>] dump_stack+0x68/0x93
> [<ffffffff810a25f7>] lockdep_rcu_suspicious+0xd7/0x110
> [<ffffffff810c3cd4>] rcu_eqs_enter_common.constprop.85+0x154/0x200
> [<ffffffff810c5a54>] rcu_irq_exit+0x44/0xa0
> [<ffffffff81058631>] irq_exit+0x61/0xd0
> [<ffffffff81018d25>] do_IRQ+0x65/0x110
> [<ffffffff81672189>] common_interrupt+0x89/0x89
> <EOI>
> [<ffffffff814ffe11>] ? cpuidle_enter_state+0x151/0x200
> [<ffffffff814ffee2>] cpuidle_enter+0x12/0x20
> [<ffffffff8109a6ae>] call_cpuidle+0x1e/0x40
> [<ffffffff8109a8f6>] cpu_startup_entry+0x146/0x220
> [<ffffffff810336f8>] start_secondary+0x148/0x170
>
> Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann@mni.thm.de>
A fixes line and cc stable would be good to have:
Fixes: d94a461d7a7d ("ath9k: use ieee80211_tx_status_noskb where possible")
Cc: <stable@vger.kernel.org> # v4.9
I can add those.
I'm planning to push this to 4.10 but would prefer to see an ack from
Felix (the author of d94a461d7a7d) first. I added him to Cc.
--
Kalle Valo
^ permalink raw reply
* [PATCH] mac80211: don't call drv_set_default_unicast_key() for VLANs
From: Johannes Berg @ 2016-12-13 8:41 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
Since drivers know nothing about AP_VLAN interfaces, trying to
call drv_set_default_unicast_key() just results in a warning
and no call to the driver. Avoid the warning by not calling the
driver for this on AP_VLAN interfaces.
This means that drivers that somehow need this call for AP mode
will fail to work properly in the presence of VLAN interfaces,
but the current drivers don't seem to use it, and mac80211 will
select and indicate the key - so drivers should be OK now.
Reported-by: Jouni Malinen <j@w1.fi>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/key.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index edd6f2945f69..a98fc2b5e0dc 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -265,7 +265,8 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
if (uni) {
rcu_assign_pointer(sdata->default_unicast_key, key);
ieee80211_check_fast_xmit_iface(sdata);
- drv_set_default_unicast_key(sdata->local, sdata, idx);
+ if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
+ drv_set_default_unicast_key(sdata->local, sdata, idx);
}
if (multi)
--
2.9.3
^ permalink raw reply related
* [PATCH] rfkill: simplify rfkill_set_hw_state() slightly
From: Johannes Berg @ 2016-12-13 8:39 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
Simplify the two conditions gating the schedule_work() into
a single one and get rid of the additional exit point from
the function in doing so.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/rfkill/core.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 884027f62783..184bb711a06d 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -478,10 +478,7 @@ bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
rfkill_led_trigger_event(rfkill);
- if (!rfkill->registered)
- return ret;
-
- if (prev != blocked)
+ if (rfkill->registered && prev != blocked)
schedule_work(&rfkill->uevent_work);
return ret;
--
2.9.3
^ permalink raw reply related
* Re: [PATCH] orinoco: Use shash instead of ahash for MIC calculations
From: Eric Biggers @ 2016-12-13 7:54 UTC (permalink / raw)
To: Andy Lutomirski
Cc: linux-kernel, linux-usb, linux-wireless, linux-crypto, Herbert Xu,
Stephan Mueller
In-Reply-To: <8818c45b9ec6a04d85fabf9bb437cf119fd23659.1481575835.git.luto@kernel.org>
On Mon, Dec 12, 2016 at 12:55:55PM -0800, Andy Lutomirski wrote:
> +int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
> u8 *da, u8 *sa, u8 priority,
> u8 *data, size_t data_len, u8 *mic)
> {
> - AHASH_REQUEST_ON_STACK(req, tfm_michael);
> - struct scatterlist sg[2];
> + SHASH_DESC_ON_STACK(desc, tfm_michael);
> u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
> int err;
>
> @@ -67,18 +66,27 @@ int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key,
> hdr[ETH_ALEN * 2 + 2] = 0;
> hdr[ETH_ALEN * 2 + 3] = 0;
>
> - /* Use scatter gather to MIC header and data in one go */
> - sg_init_table(sg, 2);
> - sg_set_buf(&sg[0], hdr, sizeof(hdr));
> - sg_set_buf(&sg[1], data, data_len);
> + desc->tfm = tfm_michael;
> + desc->flags = 0;
>
> - if (crypto_ahash_setkey(tfm_michael, key, MIC_KEYLEN))
> - return -1;
> + err = crypto_shash_setkey(tfm_michael, key, MIC_KEYLEN);
> + if (err)
> + return err;
> +
> + err = crypto_shash_init(desc);
> + if (err)
> + return err;
> +
> + err = crypto_shash_update(desc, hdr, sizeof(hdr));
> + if (err)
> + return err;
> +
> + err = crypto_shash_update(desc, data, data_len);
> + if (err)
> + return err;
> +
> + err = crypto_shash_final(desc, mic);
> + shash_desc_zero(desc);
>
> - ahash_request_set_tfm(req, tfm_michael);
> - ahash_request_set_callback(req, 0, NULL, NULL);
> - ahash_request_set_crypt(req, sg, mic, data_len + sizeof(hdr));
> - err = crypto_ahash_digest(req);
> - ahash_request_zero(req);
> return err;
It's probably a good idea to always do shash_desc_zero(), even when something
above it fails. Otherwise this looks fine. Thanks for sending these patches!
Eric
^ permalink raw reply
* [PATCH] orinoco: Use shash instead of ahash for MIC calculations
From: Andy Lutomirski @ 2016-12-12 20:55 UTC (permalink / raw)
To: linux-kernel, linux-usb, linux-wireless
Cc: Eric Biggers, linux-crypto, Herbert Xu, Stephan Mueller,
Andy Lutomirski
In-Reply-To: <8c273c9c41f51b34bb3115086f1d776895580637.1481575835.git.luto@kernel.org>
Eric Biggers pointed out that the orinoco driver pointed scatterlists
at the stack.
Fix it by switching from ahash to shash. The result should be
simpler, faster, and more correct.
Cc: stable@vger.kernel.org # 4.9 only
Reported-by: Eric Biggers <ebiggers3@gmail.com>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
Compile-tested only.
drivers/net/wireless/intersil/orinoco/mic.c | 44 +++++++++++++++----------
drivers/net/wireless/intersil/orinoco/mic.h | 3 +-
drivers/net/wireless/intersil/orinoco/orinoco.h | 4 +--
3 files changed, 30 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/intersil/orinoco/mic.c b/drivers/net/wireless/intersil/orinoco/mic.c
index bc7397d709d3..08bc7822f820 100644
--- a/drivers/net/wireless/intersil/orinoco/mic.c
+++ b/drivers/net/wireless/intersil/orinoco/mic.c
@@ -16,7 +16,7 @@
/********************************************************************/
int orinoco_mic_init(struct orinoco_private *priv)
{
- priv->tx_tfm_mic = crypto_alloc_ahash("michael_mic", 0,
+ priv->tx_tfm_mic = crypto_alloc_shash("michael_mic", 0,
CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->tx_tfm_mic)) {
printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
@@ -25,7 +25,7 @@ int orinoco_mic_init(struct orinoco_private *priv)
return -ENOMEM;
}
- priv->rx_tfm_mic = crypto_alloc_ahash("michael_mic", 0,
+ priv->rx_tfm_mic = crypto_alloc_shash("michael_mic", 0,
CRYPTO_ALG_ASYNC);
if (IS_ERR(priv->rx_tfm_mic)) {
printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
@@ -40,17 +40,16 @@ int orinoco_mic_init(struct orinoco_private *priv)
void orinoco_mic_free(struct orinoco_private *priv)
{
if (priv->tx_tfm_mic)
- crypto_free_ahash(priv->tx_tfm_mic);
+ crypto_free_shash(priv->tx_tfm_mic);
if (priv->rx_tfm_mic)
- crypto_free_ahash(priv->rx_tfm_mic);
+ crypto_free_shash(priv->rx_tfm_mic);
}
-int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key,
+int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
u8 *da, u8 *sa, u8 priority,
u8 *data, size_t data_len, u8 *mic)
{
- AHASH_REQUEST_ON_STACK(req, tfm_michael);
- struct scatterlist sg[2];
+ SHASH_DESC_ON_STACK(desc, tfm_michael);
u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
int err;
@@ -67,18 +66,27 @@ int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key,
hdr[ETH_ALEN * 2 + 2] = 0;
hdr[ETH_ALEN * 2 + 3] = 0;
- /* Use scatter gather to MIC header and data in one go */
- sg_init_table(sg, 2);
- sg_set_buf(&sg[0], hdr, sizeof(hdr));
- sg_set_buf(&sg[1], data, data_len);
+ desc->tfm = tfm_michael;
+ desc->flags = 0;
- if (crypto_ahash_setkey(tfm_michael, key, MIC_KEYLEN))
- return -1;
+ err = crypto_shash_setkey(tfm_michael, key, MIC_KEYLEN);
+ if (err)
+ return err;
+
+ err = crypto_shash_init(desc);
+ if (err)
+ return err;
+
+ err = crypto_shash_update(desc, hdr, sizeof(hdr));
+ if (err)
+ return err;
+
+ err = crypto_shash_update(desc, data, data_len);
+ if (err)
+ return err;
+
+ err = crypto_shash_final(desc, mic);
+ shash_desc_zero(desc);
- ahash_request_set_tfm(req, tfm_michael);
- ahash_request_set_callback(req, 0, NULL, NULL);
- ahash_request_set_crypt(req, sg, mic, data_len + sizeof(hdr));
- err = crypto_ahash_digest(req);
- ahash_request_zero(req);
return err;
}
diff --git a/drivers/net/wireless/intersil/orinoco/mic.h b/drivers/net/wireless/intersil/orinoco/mic.h
index ce731d05cc98..e8724e889219 100644
--- a/drivers/net/wireless/intersil/orinoco/mic.h
+++ b/drivers/net/wireless/intersil/orinoco/mic.h
@@ -6,6 +6,7 @@
#define _ORINOCO_MIC_H_
#include <linux/types.h>
+#include <crypto/hash.h>
#define MICHAEL_MIC_LEN 8
@@ -15,7 +16,7 @@ struct crypto_ahash;
int orinoco_mic_init(struct orinoco_private *priv);
void orinoco_mic_free(struct orinoco_private *priv);
-int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key,
+int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
u8 *da, u8 *sa, u8 priority,
u8 *data, size_t data_len, u8 *mic);
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco.h b/drivers/net/wireless/intersil/orinoco/orinoco.h
index 2f0c84b1c440..5fa1c3e3713f 100644
--- a/drivers/net/wireless/intersil/orinoco/orinoco.h
+++ b/drivers/net/wireless/intersil/orinoco/orinoco.h
@@ -152,8 +152,8 @@ struct orinoco_private {
u8 *wpa_ie;
int wpa_ie_len;
- struct crypto_ahash *rx_tfm_mic;
- struct crypto_ahash *tx_tfm_mic;
+ struct crypto_shash *rx_tfm_mic;
+ struct crypto_shash *tx_tfm_mic;
unsigned int wpa_enabled:1;
unsigned int tkip_cm_active:1;
--
2.9.3
^ permalink raw reply related
* Re: [PATCH v2 0/7] ath9k: EEPROM swapping improvements
From: Martin Blumenstingl @ 2016-12-12 20:05 UTC (permalink / raw)
To: Valo, Kalle
Cc: ath9k-devel, linux-wireless@vger.kernel.org,
ath9k-devel@lists.ath9k.org, devicetree@vger.kernel.org,
arnd@arndb.de, chunkeey@googlemail.com, nbd@nbd.name
In-Reply-To: <871sxza9al.fsf@kamboji.qca.qualcomm.com>
Hello Kalle,
On Fri, Nov 25, 2016 at 4:06 PM, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
> Kalle Valo <kvalo@codeaurora.org> writes:
>
>> Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:
>>
>>> There are two types of swapping the EEPROM data in the ath9k driver.
>>> Before this series one type of swapping could not be used without the
>>> other.
>>>
>>> The first type of swapping looks at the "magic bytes" at the start of
>>> the EEPROM data and performs swab16 on the EEPROM contents if needed.
>>> The second type of swapping is EEPROM format specific and swaps
>>> specific fields within the EEPROM itself (swab16, swab32 - depends on
>>> the EEPROM format).
>>>
>>> With this series the second part now looks at the EEPMISC register
>>> inside the EEPROM, which uses a bit to indicate if the EEPROM data
>>> is Big Endian (this is also done by the FreeBSD kernel).
>>> This has a nice advantage: currently there are some out-of-tree hacks
>>> (in OpenWrt and LEDE) where the EEPROM has a Big Endian header on a
>>> Big Endian system (= no swab16 is performed) but the EEPROM itself
>>> indicates that it's data is Little Endian. Until now the out-of-tree
>>> code simply did a swab16 before passing the data to ath9k, so ath9k
>>> first did the swab16 - this also enabled the format specific swapping.
>>> These out-of-tree hacks are still working with the new logic, but it
>>> is recommended to remove them. This implementation is based on a
>>> discussion with Arnd Bergmann who raised concerns about the
>>> robustness and portability of the swapping logic in the original OF
>>> support patch review, see [0].
>>>
>>> After a second round of patches (= v1 of this series) neither Arnd
>>> Bergmann nor I were really happy with the complexity of the EEPROM
>>> swapping logic. Based on a discussion (see [1] and [2]) we decided
>>> that ath9k should use a defined format (specifying the endianness
>>> of the data - I went with __le16 and __le32) when accessing the
>>> EEPROM fields. A benefit of this is that we enable the EEPMISC based
>>> swapping logic by default, just like the FreeBSD driver, see [3]. On
>>> the devices which I have tested (see below) ath9k now works without
>>> having to specify the "endian_check" field in ath9k_platform_data (or
>>> a similar logic which could provide this via devicetree) as ath9k now
>>> detects the endianness automatically. Only EEPROMs which are mangled
>>> by some out-of-tree code still need the endian_check flag (or one can
>>> simply remove that mangling from the out-of-tree code).
>>>
>>> Testing:
>>> - tested by myself on AR9287 with Big Endian EEPROM
>>> - tested by myself on AR9227 with Little Endian EEPROM
>>> - tested by myself on AR9381 (using the ar9003_eeprom implementation,
>>> which did not suffer from this whole problem)
>>> - how do we proceed with testing? maybe we could keep this in a
>>> feature-branch and add these patches to LEDE once we have an ACK to
>>> get more people to test this
>>>
>>> This series depends on my other series (v7):
>>> "add devicetree support to ath9k" - see [4]
>>
>> I think this looks pretty good. If there's a bug somewhere it should be
>> quite easy to fix so I'm not that worried and would be willing to take
>> these as soon as I have applied the dependency series. IIRC your
>> devicetree patches will have at least one more review round so that will
>> take some time still. In the meantime it would be great if LEDE folks
>> could take a look at these and comment (or test).
>
> So are everyone happy with this? I haven't seen any comments. If I don't
> here anything I'm planning to take these, most likely for 4.11.
the patches have been in LEDE for almost two weeks now and I did not
see any reports of ath9k breakage (footnote below).
It seems that there are a few devices out there where the whole EEPROM
is swab16'ed which switches the position of the 1-byte fields
opCapFlags and eepMisc.
those still work fine with the new code, however I had a second patch
in LEDE [0] which results in ath9k_platform_data.endian_check NOT
being set anymore.
that endian_check flag was used before to swab16 the whole EEPROM, to
correct the position of the 1-byte fields again.
Currently we are fixing this in the firmware hotplug script: [1]
This is definitely not a blocker for this series though (if we want to
have a devicetree replacement for "ath9k_platform_data.endian_check"
then I'd work on that within a separate series, but I somewhat
consider these EEPROMs as "broken" so fixing them in
userspace/firmware hotplug script is fine for me)
Regards,
Martin
[0] https://git.lede-project.org/?p=source.git;a=commitdiff;h=a20616863d32d91163043b6657a63c836bd9c5ba
[1] https://git.lede-project.org/?p=source.git;a=commitdiff;h=afa37092663d00aa0abf8c61943d9a1b5558b144
^ permalink raw reply
* Re: [RFC V3 03/11] nl80211: add support for gscan
From: Arend Van Spriel @ 2016-12-12 20:01 UTC (permalink / raw)
To: Dan Williams, Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1481564592.6887.2.camel@redhat.com>
On 12-12-2016 18:43, Dan Williams wrote:
>> +
>> +/**
>> + * enum nl80211_bucket_band - GScan bucket band selection.
> Quite possibly this was already covered and somebody requested you to
> change this to the current name. If that's the case, ignore this.
Nope. You are the first ;-)
> But shouldn't this enum and bucket_event_report include "gscan" in
> their name, like the other gscan specific stuff does? Are these going
> to get used for something else too, and will that thing make sense with
> the word "bucket"? Just "nl80211_bucket_band" is pretty generic.
I figured the term bucket was making it gscan specific, but you are
right. Will change it.
Thanks,
Arend
^ permalink raw reply
* [PATCH] ath9k: unlock rcu read when returning early
From: Tobias Klausmann @ 2016-12-12 18:50 UTC (permalink / raw)
To: kvalo, helgaas, linux-kernel, linux-pci, marc.zyngier,
Janusz.Dziedzic, rmanohar, ath9k-devel, linux-wireless, rmanohar,
bharat.kumar.gogada
Cc: Tobias Klausmann
In-Reply-To: <1cFMHb-00BdWd-Ks>
Starting with ath9k: use ieee80211_tx_status_noskb where possible
[d94a461d7a7df68991fb9663531173f60ef89c68] the driver uses rcu_read_lock() &&
rcu_read_unlock() yet on returning early in ath_tx_edma_tasklet() the unlock is
missing leading to stalls and suspicious RCU usage:
===============================
[ INFO: suspicious RCU usage. ]
4.9.0-rc8 #11 Not tainted
-------------------------------
kernel/rcu/tree.c:705 Illegal idle entry in RCU read-side critical section.!
other info that might help us debug this:
RCU used illegally from idle CPU!
rcu_scheduler_active = 1, debug_locks = 0
RCU used illegally from extended quiescent state!
1 lock held by swapper/7/0:
#0:
(
rcu_read_lock
){......}
, at:
[<ffffffffa06ed110>] ath_tx_edma_tasklet+0x0/0x450 [ath9k]
stack backtrace:
CPU: 7 PID: 0 Comm: swapper/7 Not tainted 4.9.0-rc8 #11
Hardware name: Acer Aspire V3-571G/VA50_HC_CR, BIOS V2.21 12/16/2013
ffff88025efc3f38 ffffffff8132b1e5 ffff88017ede4540 0000000000000001
ffff88025efc3f68 ffffffff810a25f7 ffff88025efcee60 ffff88017edebdd8
ffff88025eeb5400 0000000000000091 ffff88025efc3f88 ffffffff810c3cd4
Call Trace:
<IRQ>
[<ffffffff8132b1e5>] dump_stack+0x68/0x93
[<ffffffff810a25f7>] lockdep_rcu_suspicious+0xd7/0x110
[<ffffffff810c3cd4>] rcu_eqs_enter_common.constprop.85+0x154/0x200
[<ffffffff810c5a54>] rcu_irq_exit+0x44/0xa0
[<ffffffff81058631>] irq_exit+0x61/0xd0
[<ffffffff81018d25>] do_IRQ+0x65/0x110
[<ffffffff81672189>] common_interrupt+0x89/0x89
<EOI>
[<ffffffff814ffe11>] ? cpuidle_enter_state+0x151/0x200
[<ffffffff814ffee2>] cpuidle_enter+0x12/0x20
[<ffffffff8109a6ae>] call_cpuidle+0x1e/0x40
[<ffffffff8109a8f6>] cpu_startup_entry+0x146/0x220
[<ffffffff810336f8>] start_secondary+0x148/0x170
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann@mni.thm.de>
---
drivers/net/wireless/ath/ath9k/xmit.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 52bfbb988611..857d5ae09a1d 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -2787,6 +2787,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
fifo_list = &txq->txq_fifo[txq->txq_tailidx];
if (list_empty(fifo_list)) {
ath_txq_unlock(sc, txq);
+ rcu_read_unlock();
return;
}
--
2.11.0
^ permalink raw reply related
* Re: [RFC V3 03/11] nl80211: add support for gscan
From: Dan Williams @ 2016-12-12 17:43 UTC (permalink / raw)
To: Arend van Spriel, Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1481543997-24624-4-git-send-email-arend.vanspriel@broadcom.com>
On Mon, 2016-12-12 at 11:59 +0000, Arend van Spriel wrote:
> This patch adds support for GScan which is a scan offload feature
> used in Android.
>
> Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
> Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.co
> m>
> Reviewed-by: Franky Lin <franky.lin@broadcom.com>
> Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> ---
> Changes:
> V2
> - remove pr_err() statement from nl80211.c
> - get rid of #if 0 code.
> V3
> - change and document storage type of gscan attributes.
> - remove base period attribute from nl80211.
> - bucket periods are changed to be seconds.
> - change NO_IR attribute to PASSIVE.
> - check for NL80211_ATTR_MAC{,_MASK} if random mac support is
> requested.
> - remove NL80211_SCAN_FLAG_IE_DATA.
> ---
> include/net/cfg80211.h | 91 +++++++++++
> include/uapi/linux/nl80211.h | 146 ++++++++++++++++++
> net/wireless/core.c | 31 ++++
> net/wireless/core.h | 4 +
> net/wireless/nl80211.c | 356
> ++++++++++++++++++++++++++++++++++++++++++-
> net/wireless/rdev-ops.h | 25 +++
> net/wireless/scan.c | 28 ++++
> net/wireless/trace.h | 9 ++
> 8 files changed, 685 insertions(+), 5 deletions(-)
>
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index b78377f..8bc8842 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -2453,6 +2453,92 @@ struct cfg80211_nan_func {
> };
>
> /**
> + * struct cfg80211_gscan_channel - GScan channel parameters.
> + *
> +
> + * @ch: specific channel.
> + * @dwell_time: hint for dwell time in milliseconds.
> + * @passive: indicates passive scan is requested.
> + */
> +struct cfg80211_gscan_channel {
> + struct ieee80211_channel *ch;
> + u8 dwell_time;
> + bool passive;
> +};
> +
> +/**
> + * struct cfg80211_gscan_bucket - GScan bucket parameters.
> + *
> + * @idx: unique bucket index.
> + * @band: bit flags for band(s) to use, see %enum
> nl80211_bucket_band.
> + * @report_events: This is a bit field according %enum
> nl80211_bucket_report_event.
> + * @period: period in which the bucket is scheduled to be scanned.
> If the
> + * period is too small for driver it should not fail but
> report results
> + * as fast as it can. For exponential backoff bucket this is
> the minimum
> + * period.
> + * @max_period: used only for the exponential backoff bucket whose
> scan period
> + * will grow exponentially to a maximum period of max_period.
> + * @exponent: used only for the exponential backoff bucket.
> + * @step_count: used only for the exponential backoff bucket.
> + * @n_channels: number of channels in @channels array.
> + * @channels: channels to scan which may include DFS channels.
> + */
> +struct cfg80211_gscan_bucket {
> + u32 idx;
> + u16 period;
> + u8 band;
> + u8 report_events;
> + u16 max_period;
> + u8 exponent;
> + u8 step_count;
> + u8 n_channels;
> + struct cfg80211_gscan_channel *channels;
> +};
> +
> +/**
> + * struct cfg80211_gscan_request - GScan request parameters.
> + *
> + * @flags: scan request flags according %enum nl80211_scan_flags.
> + * @base_period: base timer period in milliseconds.
> + * @max_ap_per_scan: number of APs to store in each scan entry in
> the BSSID/RSSI
> + * history buffer (keep APS with highest RSSI).
> + * @report_threshold_percent: wake up system when scan buffer is
> filled to this
> + * percentage.
> + * @report_threshold_num_scans: wake up system when this many scans
> are stored
> + * in scan buffer.
> + * @mac: MAC address used for randomisation.
> + * @mac_mask: MAC address mask. bits that are 0 in the mask should
> be
> + * randomised, bits that are 1 should be taken as is from
> @mac.
> + * @n_buckets: number of entries in @buckets array.
> + * @buckets: array of GScan buckets.
> + *
> + * @dev: net device for which GScan is requested.
> + * @rcu_head: RCU callback used to free the struct.
> + * @owner_nlportid: netlink port which initiated this request.
> + * @scan_start: start time of this scan in jiffies.
> + */
> +struct cfg80211_gscan_request {
> + u32 flags;
> + u16 base_period;
> + u8 max_ap_per_scan;
> + u8 report_threshold_percent;
> + u8 report_threshold_num_scans;
> + u8 mac[ETH_ALEN];
> + u8 mac_mask[ETH_ALEN];
> +
> + u8 n_buckets;
> +
> + /* internal */
> + struct net_device *dev;
> + struct rcu_head rcu_head;
> + u32 owner_nlportid;
> + unsigned long scan_start;
> +
> + /* keep last */
> + struct cfg80211_gscan_bucket buckets[0];
> +};
> +
> +/**
> * struct cfg80211_ops - backend description for wireless
> configuration
> *
> * This struct is registered by fullmac card drivers and/or wireless
> stacks
> @@ -2764,6 +2850,8 @@ struct cfg80211_nan_func {
> * All other parameters must be ignored.
> *
> * @set_multicast_to_unicast: configure multicast to unicast
> conversion for BSS
> + * @start_gscan: start the GSCAN scanning offload.
> + * @stop_gscan: stop the GSCAN scanning offload.
> */
> struct cfg80211_ops {
> int (*suspend)(struct wiphy *wiphy, struct
> cfg80211_wowlan *wow);
> @@ -3048,6 +3136,9 @@ struct cfg80211_ops {
> int (*set_multicast_to_unicast)(struct wiphy *wiphy,
> struct net_device *dev,
> const bool enabled);
> + int (*start_gscan)(struct wiphy *wiphy, struct
> net_device *dev,
> + struct cfg80211_gscan_request
> *gscan_req);
> + int (*stop_gscan)(struct wiphy *wiphy, struct
> net_device *dev);
> };
>
> /*
> diff --git a/include/uapi/linux/nl80211.h
> b/include/uapi/linux/nl80211.h
> index 01ab2f7..5e42383 100644
> --- a/include/uapi/linux/nl80211.h
> +++ b/include/uapi/linux/nl80211.h
> @@ -894,6 +894,12 @@
> * does not result in a change for the current association.
> Currently,
> * only the %NL80211_ATTR_IE data is used and updated with
> this command.
> *
> + * @NL80211_CMD_START_GSCAN: start GScan.
> + * @NL80211_CMD_STOP_GSCAN: request to stop current GScan.
> + * @NL80211_CMD_GSCAN_STOPPED: indicates that the currently running
> GScan
> + * has stopped. This event is generated upon
> @NL80211_CMD_STOP_GSCAN and
> + * the driver may issue this event at any time when a GScan
> is running.
> + *
> * @NL80211_CMD_MAX: highest used command number
> * @__NL80211_CMD_AFTER_LAST: internal use
> */
> @@ -1093,6 +1099,10 @@ enum nl80211_commands {
>
> NL80211_CMD_UPDATE_CONNECT_PARAMS,
>
> + NL80211_CMD_START_GSCAN,
> + NL80211_CMD_STOP_GSCAN,
> + NL80211_CMD_GSCAN_STOPPED,
> +
> /* add new commands above here */
>
> /* used to define NL80211_CMD_MAX below */
> @@ -2389,6 +2399,7 @@ enum nl80211_attrs {
>
> NL80211_ATTR_BSSID,
> NL80211_ATTR_GSCAN_CAPS,
> + NL80211_ATTR_GSCAN_PARAMS,
>
> /* add attributes here, update the policy in nl80211.c */
>
> @@ -5246,4 +5257,139 @@ enum nl80211_gscan_caps_attr {
> NL80211_GSCAN_CAPS_ATTR_MAX =
> __NL80211_GSCAN_CAPS_ATTR_AFTER_LAST - 1
> };
>
> +/**
> + * enum nl80211_gscan_attr - common GScan parameters.
> + *
> + * @__NL80211_GSCAN_ATTR_INVALID: reserved.
> + * @NL80211_GSCAN_ATTR_MAX_AP_PER_SCAN: number of APs that are kept
> per
> + * scan. The kept APs are the ones with strongest RSSI level
> (u8).
> + * @NL80211_GSCAN_ATTR_REPORT_PERC: threshold specifying percentage
> of
> + * scan cache filled that should trigger event for scan
> results (u8).
> + * @NL80211_GSCAN_ATTR_REPORT_SCANS: threshold specifying number of
> scans
> + * after which an event is expected for scan results (u8).
> + * @NL80211_GSCAN_ATTR_BUCKETS: nested attribute specifying
> + * per-bucket parameters for GScan. See %enum
> nl80211_gscan_bucket_attr
> + * for description.
> + * @NL80211_GSCAN_ATTR_MAX: highest GScan attribute.
> + * @__NL80211_GSCAN_ATTR_AFTER_LAST: internal use.
> + */
> +enum nl80211_gscan_attr {
> + __NL80211_GSCAN_ATTR_INVALID,
> + NL80211_GSCAN_ATTR_MAX_AP_PER_SCAN,
> + NL80211_GSCAN_ATTR_REPORT_PERC,
> + NL80211_GSCAN_ATTR_REPORT_SCANS,
> + NL80211_GSCAN_ATTR_BUCKETS,
> +
> + /* keep last */
> + __NL80211_GSCAN_ATTR_AFTER_LAST,
> + NL80211_GSCAN_ATTR_MAX = __NL80211_GSCAN_ATTR_AFTER_LAST - 1
> +};
> +
> +/**
> + * enum nl80211_gscan_bucket_attr - per-bucket GScan parameters.
> + *
> + * @__NL80211_GSCAN_BUCKET_ATTR_INVALID,
> + * @NL80211_GSCAN_BUCKET_ATTR_ID: unique bucket id (u32).
> + * @NL80211_GSCAN_BUCKET_ATTR_BAND: specifies the band to be scanned
> + * according %enum nl80211_bucket_band. If specified
> + * @NL80211_GSCAN_BUCKET_ATTR_CHANNELS is ignored (u8).
> + * @NL80211_GSCAN_BUCKET_ATTR_PERIOD: specifies the period between
> consecutive
> + * scans of this bucket in seconds. For the backoff bucket
> this is
> + * period(0) (u16).
> + * @NL80211_GSCAN_BUCKET_ATTR_REPORT: specifies reporting flags
> according
> + * %enum nl80211_bucket_report_event (u8).
> + * @NL80211_GSCAN_BUCKET_ATTR_MAX_PERIOD: maximum period between
> + * consecutive scans. If specified this is a backoff bucket
> in
> + * which the period increases according formula:
> + * period(N) = period(0) * (base ^ (N/step_count)) (u16)
> + * @NL80211_GSCAN_BUCKET_ATTR_EXPONENT: exponential base value as
> used
> + * in given formula. This attribute is required when
> + * @NL80211_GSCAN_BUCKET_ATTR_MAX_PERIOD is specified (u8).
> + * @NL80211_GSCAN_BUCKET_ATTR_STEPS: step count as used in given
> formula.
> + * This attribute is required when
> @NL80211_GSCAN_BUCKET_ATTR_MAX_PERIOD
> + * is specified (u8).
> + * @NL80211_GSCAN_BUCKET_ATTR_CHANNELS: nested attribute specifying
> the
> + * channels that are to be scanned for this bucket.
> + * @NL80211_GSCAN_BUCKET_ATTR_MAX: highest GScan bucket attribute.
> + * @__NL80211_GSCAN_BUCKET_ATTR_AFTER_LAST: internal use.
> + */
> +enum nl80211_gscan_bucket_attr {
> + __NL80211_GSCAN_BUCKET_ATTR_INVALID,
> + NL80211_GSCAN_BUCKET_ATTR_ID,
> + NL80211_GSCAN_BUCKET_ATTR_BAND,
> + NL80211_GSCAN_BUCKET_ATTR_PERIOD,
> + NL80211_GSCAN_BUCKET_ATTR_REPORT,
> + NL80211_GSCAN_BUCKET_ATTR_MAX_PERIOD,
> + NL80211_GSCAN_BUCKET_ATTR_EXPONENT,
> + NL80211_GSCAN_BUCKET_ATTR_STEPS,
> + NL80211_GSCAN_BUCKET_ATTR_CHANNELS,
> +
> + /* keep last */
> + __NL80211_GSCAN_BUCKET_ATTR_AFTER_LAST,
> + NL80211_GSCAN_BUCKET_ATTR_MAX =
> __NL80211_GSCAN_BUCKET_ATTR_AFTER_LAST - 1
> +};
> +
> +/**
> + * enum nl80211_gscan_chan_attr - GScan bucket channel parameters.
> + *
> + * @__NL80211_GSCAN_CHAN_ATTR_INVALID: reserved.
> + * @NL80211_GSCAN_CHAN_ATTR_FREQ: frequency of channel to be scanned
> (u32).
> + * @NL80211_GSCAN_CHAN_ATTR_DWELL_TIME: dwell time in milliseconds
> to stay
> + * on this channel during scanning (u8).
> + * @NL80211_GSCAN_CHAN_ATTR_PASSIVE: flag attribute indicating that
> scanning
> + * should be done passive for this channel.
> + * @NL80211_GSCAN_CHAN_ATTR_MAX: highest GScan channel attribute.
> + * @__NL80211_GSCAN_CHAN_ATTR_AFTER_LAST: internal use.
> + *
> + * Apart from the channel itself the attributes
> %NL80211_GSCAN_CHAN_ATTR_DWELL_TIME
> + * and %NL80211_GSCAN_CHAN_ATTR_PASSIVE are advisory values. The
> driver may or
> + * may not comply.
> + */
> +enum nl80211_gscan_chan_attr {
> + __NL80211_GSCAN_CHAN_ATTR_INVALID,
> + NL80211_GSCAN_CHAN_ATTR_FREQ,
> + NL80211_GSCAN_CHAN_ATTR_DWELL_TIME,
> + NL80211_GSCAN_CHAN_ATTR_PASSIVE,
> +
> + /* keep last */
> + __NL80211_GSCAN_CHAN_ATTR_AFTER_LAST,
> + NL80211_GSCAN_CHAN_ATTR_MAX =
> __NL80211_GSCAN_CHAN_ATTR_AFTER_LAST - 1
> +};
> +
> +/**
> + * enum nl80211_bucket_band - GScan bucket band selection.
Quite possibly this was already covered and somebody requested you to
change this to the current name. If that's the case, ignore this.
But shouldn't this enum and bucket_event_report include "gscan" in
their name, like the other gscan specific stuff does? Are these going
to get used for something else too, and will that thing make sense with
the word "bucket"? Just "nl80211_bucket_band" is pretty generic.
Dan
> + * @NL80211_BUCKET_BAND_2GHZ: consider all device supported channels
> + * in 2G band.
> + * @NL80211_BUCKET_BAND_5GHZ: consider all device supported channels
> + * in 5G band, ie. both DFS and non-DFS when
> @NL80211_BUCKET_BAND_NODFS
> + * and @NL80211_BUCKET_BAND_DFS_ONLY are not set.
> + * @NL80211_BUCKET_BAND_NODFS: only consider non-DFS channels. Only
> + * applicable when 5G band is selected, otherwise ignored.
> + * @NL80211_BUCKET_BAND_DFS_ONLY: only consider DFS channels. Only
> + * applicable when 5G band is selected, otherwise ignored.
> + *
> + * Setting both @NL80211_BUCKET_BAND_NODFS and
> @NL80211_BUCKET_BAND_DFS_ONLY
> + * is considerd invalid.
> + */
> +enum nl80211_bucket_band {
> + NL80211_BUCKET_BAND_2GHZ = (1 << 0),
> + NL80211_BUCKET_BAND_5GHZ = (1 << 1),
> + NL80211_BUCKET_BAND_NODFS = (1 << 2),
> + NL80211_BUCKET_BAND_DFS_ONLY = (1 << 3),
> +};
> +
> +/**
> + * enum nl80211_bucket_report_event - GScan bucket report flags.
> + *
> + * @NL80211_BUCKET_REPORT_EACH_SCAN: report each bucket scan
> completion.
> + * @NL80211_BUCKET_REPORT_FULL_RESULTS: report full scan results.
> + * @NL80211_BUCKET_REPORT_NO_BATCH: no batching required.
> + */
> +enum nl80211_bucket_report_event {
> + NL80211_BUCKET_REPORT_EACH_SCAN = (1 << 0),
> + NL80211_BUCKET_REPORT_FULL_RESULTS = (1 << 1),
> + NL80211_BUCKET_REPORT_NO_BATCH = (1 << 2),
> +};
> +
> #endif /* __LINUX_NL80211_H */
> diff --git a/net/wireless/core.c b/net/wireless/core.c
> index 158c59e..760a2fb 100644
> --- a/net/wireless/core.c
> +++ b/net/wireless/core.c
> @@ -357,6 +357,20 @@ static void cfg80211_sched_scan_stop_wk(struct
> work_struct *work)
> rtnl_unlock();
> }
>
> +static void cfg80211_gscan_stop_wk(struct work_struct *work)
> +{
> + struct cfg80211_registered_device *rdev;
> +
> + rdev = container_of(work, struct cfg80211_registered_device,
> + gscan_stop_wk);
> +
> + rtnl_lock();
> +
> + __cfg80211_stop_gscan(rdev, false);
> +
> + rtnl_unlock();
> +}
> +
> /* exported functions */
>
> struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int
> sizeof_priv,
> @@ -383,6 +397,7 @@ struct wiphy *wiphy_new_nm(const struct
> cfg80211_ops *ops, int sizeof_priv,
> WARN_ON(ops->remain_on_channel && !ops-
> >cancel_remain_on_channel);
> WARN_ON(ops->tdls_channel_switch && !ops-
> >tdls_cancel_channel_switch);
> WARN_ON(ops->add_tx_ts && !ops->del_tx_ts);
> + WARN_ON(ops->start_gscan && !ops->stop_gscan);
>
> alloc_size = sizeof(*rdev) + sizeof_priv;
>
> @@ -456,6 +471,7 @@ struct wiphy *wiphy_new_nm(const struct
> cfg80211_ops *ops, int sizeof_priv,
> spin_lock_init(&rdev->destroy_list_lock);
> INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
> INIT_WORK(&rdev->sched_scan_stop_wk,
> cfg80211_sched_scan_stop_wk);
> + INIT_WORK(&rdev->gscan_stop_wk, cfg80211_gscan_stop_wk);
>
> #ifdef CONFIG_CFG80211_DEFAULT_PS
> rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
> @@ -690,6 +706,12 @@ int wiphy_register(struct wiphy *wiphy)
> (wiphy->bss_select_support &
> ~(BIT(__NL80211_BSS_SELECT_ATTR_AFTER_LAST) - 2))))
> return -EINVAL;
>
> + /* buckets must have unique index and in nl80211 parsing
> + * a u32 is used to verify that hence this limit.
> + */
> + if (WARN_ON(wiphy->gscan && wiphy->gscan->max_scan_buckets >
> 32))
> + return -EINVAL;
> +
> if (wiphy->addresses)
> memcpy(wiphy->perm_addr, wiphy->addresses[0].addr,
> ETH_ALEN);
>
> @@ -1001,6 +1023,7 @@ void __cfg80211_leave(struct
> cfg80211_registered_device *rdev,
> {
> struct net_device *dev = wdev->netdev;
> struct cfg80211_sched_scan_request *sched_scan_req;
> + struct cfg80211_gscan_request *gscan_req;
>
> ASSERT_RTNL();
> ASSERT_WDEV_LOCK(wdev);
> @@ -1014,6 +1037,9 @@ void __cfg80211_leave(struct
> cfg80211_registered_device *rdev,
> sched_scan_req = rtnl_dereference(rdev-
> >sched_scan_req);
> if (sched_scan_req && dev == sched_scan_req->dev)
> __cfg80211_stop_sched_scan(rdev, false);
> + gscan_req = rtnl_dereference(rdev->gscan_req);
> + if (gscan_req && dev == gscan_req->dev)
> + __cfg80211_stop_gscan(rdev, false);
>
> #ifdef CONFIG_CFG80211_WEXT
> kfree(wdev->wext.ie);
> @@ -1089,6 +1115,7 @@ static int cfg80211_netdev_notifier_call(struct
> notifier_block *nb,
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> struct cfg80211_registered_device *rdev;
> struct cfg80211_sched_scan_request *sched_scan_req;
> + struct cfg80211_gscan_request *gscan_req;
>
> if (!wdev)
> return NOTIFY_DONE;
> @@ -1160,6 +1187,10 @@ static int
> cfg80211_netdev_notifier_call(struct notifier_block *nb,
> sched_scan_req->dev == wdev->netdev)) {
> __cfg80211_stop_sched_scan(rdev, false);
> }
> + gscan_req = rtnl_dereference(rdev->gscan_req);
> + if (WARN_ON(gscan_req && gscan_req->dev == wdev-
> >netdev)) {
> + __cfg80211_stop_gscan(rdev, false);
> + }
>
> rdev->opencount--;
> wake_up(&rdev->dev_wait);
> diff --git a/net/wireless/core.h b/net/wireless/core.h
> index ec5f333..ee1d162 100644
> --- a/net/wireless/core.h
> +++ b/net/wireless/core.h
> @@ -75,6 +75,7 @@ struct cfg80211_registered_device {
> struct cfg80211_scan_request *scan_req; /* protected by RTNL
> */
> struct sk_buff *scan_msg;
> struct cfg80211_sched_scan_request __rcu *sched_scan_req;
> + struct cfg80211_gscan_request __rcu *gscan_req;
> unsigned long suspend_at;
> struct work_struct scan_done_wk;
> struct work_struct sched_scan_results_wk;
> @@ -96,6 +97,7 @@ struct cfg80211_registered_device {
> struct work_struct destroy_work;
>
> struct work_struct sched_scan_stop_wk;
> + struct work_struct gscan_stop_wk;
>
> /* must be last because of the way we do wiphy_priv(),
> * and it should at least be aligned to NETDEV_ALIGN */
> @@ -422,6 +424,8 @@ void ___cfg80211_scan_done(struct
> cfg80211_registered_device *rdev,
> void __cfg80211_sched_scan_results(struct work_struct *wk);
> int __cfg80211_stop_sched_scan(struct cfg80211_registered_device
> *rdev,
> bool driver_initiated);
> +int __cfg80211_stop_gscan(struct cfg80211_registered_device *rdev,
> + bool driver_initiated);
> void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
> int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
> struct net_device *dev, enum
> nl80211_iftype ntype,
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 14e1940..4186ece 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -9,6 +9,7 @@
> #include <linux/if.h>
> #include <linux/module.h>
> #include <linux/err.h>
> +#include <linux/gcd.h>
> #include <linux/slab.h>
> #include <linux/list.h>
> #include <linux/if_ether.h>
> @@ -405,6 +406,7 @@ enum nl80211_multicast_groups {
> [NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN },
> [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type =
> NLA_FLAG, },
> [NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
> + [NL80211_ATTR_GSCAN_PARAMS] = { .type = NLA_NESTED },
> };
>
> /* policy for the key attributes */
> @@ -11860,6 +11862,322 @@ static int
> nl80211_set_multicast_to_unicast(struct sk_buff *skb,
> return rdev_set_multicast_to_unicast(rdev, dev, enabled);
> }
>
> +static const
> +struct nla_policy nl80211_gscan_policy[NL80211_GSCAN_ATTR_MAX + 1] =
> {
> + [NL80211_GSCAN_ATTR_MAX_AP_PER_SCAN] = { .type = NLA_U8 },
> + [NL80211_GSCAN_ATTR_REPORT_PERC] = { .type = NLA_U8 },
> + [NL80211_GSCAN_ATTR_REPORT_SCANS] = { .type = NLA_U8 },
> + [NL80211_GSCAN_ATTR_BUCKETS] = { .type = NLA_NESTED },
> +};
> +
> +static const struct nla_policy
> +nl80211_gscan_bucket_policy[NL80211_GSCAN_BUCKET_ATTR_MAX + 1] = {
> + [NL80211_GSCAN_BUCKET_ATTR_ID] = { .type = NLA_U32 },
> + [NL80211_GSCAN_BUCKET_ATTR_BAND] = { .type = NLA_U8 },
> + [NL80211_GSCAN_BUCKET_ATTR_PERIOD] = { .type = NLA_U16 },
> + [NL80211_GSCAN_BUCKET_ATTR_REPORT] = { .type = NLA_U8 },
> + [NL80211_GSCAN_BUCKET_ATTR_MAX_PERIOD] = { .type = NLA_U16
> },
> + [NL80211_GSCAN_BUCKET_ATTR_EXPONENT] = { .type = NLA_U8 },
> + [NL80211_GSCAN_BUCKET_ATTR_STEPS] = { .type = NLA_U8 },
> + [NL80211_GSCAN_BUCKET_ATTR_CHANNELS] = { .type = NLA_NESTED
> },
> +};
> +
> +static const struct nla_policy
> +nl80211_gscan_channel_policy[NL80211_GSCAN_CHAN_ATTR_MAX + 1] = {
> + [NL80211_GSCAN_CHAN_ATTR_FREQ] = { .type = NLA_U32 },
> + [NL80211_GSCAN_CHAN_ATTR_DWELL_TIME] = { .type = NLA_U8 },
> + [NL80211_GSCAN_CHAN_ATTR_PASSIVE] = { .type = NLA_FLAG },
> +};
> +
> +static int nl80211_parse_gscan_channel(struct
> cfg80211_registered_device *rdev,
> + struct nlattr *nattr,
> + struct cfg80211_gscan_channel
> *chan)
> +{
> + struct nlattr *tb[NL80211_GSCAN_CHAN_ATTR_MAX + 1];
> + struct ieee80211_channel *ch;
> + int err;
> +
> + err = nla_parse(tb, NL80211_GSCAN_CHAN_ATTR_MAX,
> nla_data(nattr),
> + nla_len(nattr),
> nl80211_gscan_channel_policy);
> + if (err)
> + return err;
> +
> + if (!tb[NL80211_GSCAN_CHAN_ATTR_FREQ])
> + return -EINVAL;
> +
> + ch = ieee80211_get_channel(&rdev->wiphy,
> + nla_get_u32(tb[NL80211_GSCAN_CHAN
> _ATTR_FREQ]));
> + if (!ch || (ch->flags & IEEE80211_CHAN_DISABLED))
> + return -EINVAL;
> +
> + chan->ch = ch;
> +
> + if (tb[NL80211_GSCAN_CHAN_ATTR_DWELL_TIME])
> + chan->dwell_time =
> nla_get_u8(tb[NL80211_GSCAN_CHAN_ATTR_DWELL_TIME]);
> +
> + chan->passive =
> nla_get_flag(tb[NL80211_GSCAN_CHAN_ATTR_PASSIVE]);
> + return 0;
> +}
> +
> +static int nl80211_parse_gscan_bucket(struct
> cfg80211_registered_device *rdev,
> + struct nlattr *nattr,
> + struct cfg80211_gscan_bucket
> *bucket,
> + struct cfg80211_gscan_channel
> *channels)
> +{
> + struct nlattr *tb[NL80211_GSCAN_BUCKET_ATTR_MAX + 1];
> + struct nlattr *chan;
> + struct cfg80211_gscan_channel *ch;
> + int err, rem;
> + int num_chans = 0;
> + u32 band_select = 0;
> + u32 dfs_invalid_mask;
> +
> + err = nla_parse(tb, NL80211_GSCAN_BUCKET_ATTR_MAX,
> nla_data(nattr),
> + nla_len(nattr),
> nl80211_gscan_bucket_policy);
> + if (err)
> + return err;
> +
> + if (!tb[NL80211_GSCAN_BUCKET_ATTR_ID] ||
> + !tb[NL80211_GSCAN_BUCKET_ATTR_PERIOD])
> + return -EINVAL;
> +
> + bucket->idx = nla_get_u32(tb[NL80211_GSCAN_BUCKET_ATTR_ID]);
> + if (tb[NL80211_GSCAN_BUCKET_ATTR_BAND]) {
> + band_select =
> nla_get_u8(tb[NL80211_GSCAN_BUCKET_ATTR_BAND]);
> +
> + /* only makes sense if a band is selected */
> + if (!(band_select & (NL80211_BUCKET_BAND_2GHZ |
> NL80211_BUCKET_BAND_5GHZ)))
> + return -EINVAL;
> + } else if (!tb[NL80211_GSCAN_BUCKET_ATTR_CHANNELS]) {
> + return -EINVAL;
> + }
> +
> + dfs_invalid_mask = NL80211_BUCKET_BAND_5GHZ |
> NL80211_BUCKET_BAND_NODFS |
> + NL80211_BUCKET_BAND_DFS_ONLY;
> + if ((band_select & dfs_invalid_mask) == dfs_invalid_mask)
> + return -EINVAL;
> +
> + bucket->band = band_select;
> + bucket->period =
> nla_get_u16(tb[NL80211_GSCAN_BUCKET_ATTR_PERIOD]);
> +
> + if (tb[NL80211_GSCAN_BUCKET_ATTR_REPORT])
> + bucket->report_events =
> nla_get_u8(tb[NL80211_GSCAN_BUCKET_ATTR_REPORT]);
> +
> + if (tb[NL80211_GSCAN_BUCKET_ATTR_MAX_PERIOD])
> + bucket->max_period =
> nla_get_u16(tb[NL80211_GSCAN_BUCKET_ATTR_MAX_PERIOD]);
> +
> + if (bucket->max_period) {
> + if (bucket->max_period < bucket->period)
> + return -EINVAL;
> + /* additional attributes required for backoff bucket
> */
> + if (bucket->max_period > bucket->period) {
> + if (!tb[NL80211_GSCAN_BUCKET_ATTR_EXPONENT]
> ||
> + !tb[NL80211_GSCAN_BUCKET_ATTR_STEPS])
> + return -EINVAL;
> +
> + bucket->exponent =
> nla_get_u8(tb[NL80211_GSCAN_BUCKET_ATTR_EXPONENT]);
> + bucket->step_count =
> nla_get_u8(tb[NL80211_GSCAN_BUCKET_ATTR_STEPS]);
> + }
> + }
> +
> + /* ignore channels if band is specified */
> + if (band_select)
> + return 0;
> +
> + nla_for_each_nested(chan,
> tb[NL80211_GSCAN_BUCKET_ATTR_CHANNELS], rem) {
> + num_chans++;
> + }
> + if (num_chans > 16)
> + return -EINVAL;
> +
> + bucket->n_channels = num_chans;
> + if (!num_chans)
> + return 0;
> +
> + bucket->channels = channels;
> + ch = &bucket->channels[0];
> + nla_for_each_nested(chan,
> tb[NL80211_GSCAN_BUCKET_ATTR_CHANNELS], rem) {
> + err = nl80211_parse_gscan_channel(rdev, chan, ch);
> + if (err) {
> + return err;
> + }
> + ch++;
> + }
> +
> + return 0;
> +}
> +
> +static struct cfg80211_gscan_request *
> +nl80211_alloc_gscan_request(struct cfg80211_registered_device *rdev,
> + struct nlattr *buckets_attr)
> +{
> + struct cfg80211_gscan_request *req;
> + struct cfg80211_gscan_bucket *b;
> + struct cfg80211_gscan_channel *ch;
> + int n_buckets, n_channels;
> + struct nlattr *attr, *bucket, *channel;
> + int rem, rem_b, rem_c;
> + size_t reqsize;
> +
> + if (!buckets_attr)
> + return ERR_PTR(-EINVAL);
> +
> + n_buckets = 0;
> + n_channels = 0;
> + nla_for_each_nested(bucket, buckets_attr, rem) {
> + n_buckets++;
> + if (n_buckets > rdev->wiphy.gscan->max_scan_buckets)
> + return ERR_PTR(-EINVAL);
> +
> + nla_for_each_nested(attr, bucket, rem_b) {
> + if (nla_type(attr) ==
> NL80211_GSCAN_BUCKET_ATTR_CHANNELS) {
> + nla_for_each_nested(channel, attr,
> rem_c)
> + n_channels++;
> + }
> + }
> + }
> +
> + reqsize = sizeof(*req) +
> + sizeof(*b) * n_buckets +
> + sizeof(*ch) * n_channels;
> +
> + req = kzalloc(reqsize, GFP_KERNEL);
> + if (!req)
> + return ERR_PTR(-ENOMEM);
> +
> + req->n_buckets = n_buckets;
> + return req;
> +}
> +
> +static int nl80211_parse_gscan_params(struct
> cfg80211_registered_device *rdev,
> + struct nlattr *attrs[],
> + struct cfg80211_gscan_request
> **request)
> +{
> + struct cfg80211_gscan_request *req;
> + struct nlattr *tb[NL80211_GSCAN_ATTR_MAX + 1];
> + struct nlattr *bucket;
> + struct cfg80211_gscan_bucket *b;
> + struct cfg80211_gscan_channel *ch;
> + int err, rem, i;
> + u32 bucket_map;
> +
> + if (!attrs[NL80211_ATTR_GSCAN_PARAMS])
> + return -EINVAL;
> +
> + err = nla_parse(tb, NL80211_GSCAN_ATTR_MAX,
> + nla_data(attrs[NL80211_ATTR_GSCAN_PARAMS]),
> + nla_len(attrs[NL80211_ATTR_GSCAN_PARAMS]),
> + nl80211_gscan_policy);
> + if (err)
> + return err;
> +
> + req = nl80211_alloc_gscan_request(rdev,
> tb[NL80211_GSCAN_ATTR_BUCKETS]);
> + if (IS_ERR(req))
> + return PTR_ERR(req);
> +
> + if (tb[NL80211_GSCAN_ATTR_MAX_AP_PER_SCAN])
> + req->max_ap_per_scan =
> nla_get_u8(tb[NL80211_GSCAN_ATTR_MAX_AP_PER_SCAN]);
> + if (tb[NL80211_GSCAN_ATTR_REPORT_PERC])
> + req->report_threshold_percent =
> nla_get_u8(tb[NL80211_GSCAN_ATTR_REPORT_PERC]);
> + if (tb[NL80211_GSCAN_ATTR_REPORT_SCANS])
> + req->report_threshold_num_scans =
> nla_get_u8(tb[NL80211_GSCAN_ATTR_REPORT_SCANS]);
> +
> + b = &req->buckets[0];
> + ch = (struct cfg80211_gscan_channel *)(&req->buckets[req-
> >n_buckets]);
> + nla_for_each_nested(bucket, tb[NL80211_GSCAN_ATTR_BUCKETS],
> rem) {
> + err = nl80211_parse_gscan_bucket(rdev, bucket, b,
> ch);
> + if (err)
> + goto free_req;
> + ch += b->n_channels;
> + b++;
> + }
> + bucket_map = 0;
> + for (i = 0; i < req->n_buckets; i++) {
> + if (BIT(req->buckets[i].idx) & bucket_map) {
> + err = -EINVAL;
> + goto free_req;
> + }
> + bucket_map |= BIT(req->buckets[i].idx);
> +
> + if (req->base_period)
> + req->base_period = gcd(req-
> >buckets[i].period,
> + req->base_period);
> + else
> + req->base_period = req->buckets[i].period;
> + }
> + *request = req;
> + return 0;
> +
> +free_req:
> + kfree(req);
> + return err;
> +}
> +
> +static int nl80211_start_gscan(struct sk_buff *skb, struct genl_info
> *info)
> +{
> + struct cfg80211_gscan_request *request;
> + struct cfg80211_registered_device *rdev = info->user_ptr[0];
> + struct net_device *dev = info->user_ptr[1];
> + struct wireless_dev *wdev = dev->ieee80211_ptr;
> + int err;
> +
> + if (!rdev->wiphy.gscan ||
> + !rdev->ops->start_gscan)
> + return -EOPNOTSUPP;
> +
> + if (rdev->gscan_req)
> + return -EINPROGRESS;
> +
> + err = nl80211_parse_gscan_params(rdev, info->attrs,
> &request);
> + if (err)
> + return err;
> +
> + if (info->attrs[NL80211_ATTR_MAC])
> + memcpy(request->mac, nla_data(info-
> >attrs[NL80211_ATTR_MAC]),
> + ETH_ALEN);
> + if (info->attrs[NL80211_ATTR_MAC_MASK])
> + memcpy(request->mac_mask,
> + nla_data(info->attrs[NL80211_ATTR_MAC_MASK]),
> ETH_ALEN);
> + if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
> + request->flags = nla_get_u32(info-
> >attrs[NL80211_ATTR_SCAN_FLAGS]);
> + if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR
> &&
> + (!info->attrs[NL80211_ATTR_MAC] ||
> + !info->attrs[NL80211_ATTR_MAC_MASK])) {
> + kfree(request);
> + return -EINVAL;
> + }
> + }
> +
> + wdev_lock(wdev);
> + err = rdev_start_gscan(rdev, dev, request);
> + wdev_unlock(wdev);
> + if (err) {
> + kfree(request);
> + return err;
> + }
> +
> + request->scan_start = jiffies;
> + request->dev = dev;
> + if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
> + request->owner_nlportid = info->snd_portid;
> +
> + rcu_assign_pointer(rdev->gscan_req, request);
> +
> + nl80211_send_scan_event(rdev, dev, NL80211_CMD_START_GSCAN);
> + return 0;
> +}
> +
> +static int nl80211_stop_gscan(struct sk_buff *skb, struct genl_info
> *info)
> +{
> + struct cfg80211_registered_device *rdev = info->user_ptr[0];
> +
> + if (!rdev->wiphy.gscan ||
> + !rdev->ops->stop_gscan)
> + return -EOPNOTSUPP;
> +
> + return __cfg80211_stop_gscan(rdev, false);
> +}
> +
> #define NL80211_FLAG_NEED_WIPHY 0x01
> #define NL80211_FLAG_NEED_NETDEV 0x02
> #define NL80211_FLAG_NEED_RTNL 0x04
> @@ -12735,6 +13053,22 @@ static void nl80211_post_doit(const struct
> genl_ops *ops, struct sk_buff *skb,
> .internal_flags = NL80211_FLAG_NEED_NETDEV |
> NL80211_FLAG_NEED_RTNL,
> },
> + {
> + .cmd = NL80211_CMD_START_GSCAN,
> + .doit = nl80211_start_gscan,
> + .policy = nl80211_policy,
> + .flags = GENL_UNS_ADMIN_PERM,
> + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
> + NL80211_FLAG_NEED_RTNL,
> + },
> + {
> + .cmd = NL80211_CMD_STOP_GSCAN,
> + .doit = nl80211_stop_gscan,
> + .policy = nl80211_policy,
> + .flags = GENL_UNS_ADMIN_PERM,
> + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
> + NL80211_FLAG_NEED_RTNL,
> + },
> };
>
> static struct genl_family nl80211_fam __ro_after_init = {
> @@ -14540,12 +14874,18 @@ static int nl80211_netlink_notify(struct
> notifier_block * nb,
> list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
> bool schedule_destroy_work = false;
> bool schedule_scan_stop = false;
> + bool schedule_gscan_stop = false;
> struct cfg80211_sched_scan_request *sched_scan_req =
> rcu_dereference(rdev->sched_scan_req);
> + struct cfg80211_gscan_request *gscan_req =
> + rcu_dereference(rdev->gscan_req);
>
> if (sched_scan_req && notify->portid &&
> sched_scan_req->owner_nlportid == notify-
> >portid)
> schedule_scan_stop = true;
> + if (gscan_req && notify->portid &&
> + gscan_req->owner_nlportid == notify->portid)
> + schedule_gscan_stop = true;
>
> list_for_each_entry_rcu(wdev, &rdev-
> >wiphy.wdev_list, list) {
> cfg80211_mlme_unregister_socket(wdev,
> notify->portid);
> @@ -14576,12 +14916,18 @@ static int nl80211_netlink_notify(struct
> notifier_block * nb,
> spin_unlock(&rdev-
> >destroy_list_lock);
> schedule_work(&rdev->destroy_work);
> }
> - } else if (schedule_scan_stop) {
> - sched_scan_req->owner_nlportid = 0;
> + } else {
> + if (schedule_scan_stop) {
> + sched_scan_req->owner_nlportid = 0;
>
> - if (rdev->ops->sched_scan_stop &&
> - rdev->wiphy.flags &
> WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
> - schedule_work(&rdev-
> >sched_scan_stop_wk);
> + if (rdev->ops->sched_scan_stop &&
> + rdev->wiphy.flags &
> WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
> + schedule_work(&rdev-
> >sched_scan_stop_wk);
> + }
> + if (schedule_gscan_stop) {
> + gscan_req->owner_nlportid = 0;
> + schedule_work(&rdev->gscan_stop_wk);
> + }
> }
> }
>
> diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
> index 2f42507..196e6a7 100644
> --- a/net/wireless/rdev-ops.h
> +++ b/net/wireless/rdev-ops.h
> @@ -1153,4 +1153,29 @@ static inline int rdev_set_qos_map(struct
> cfg80211_registered_device *rdev,
> trace_rdev_return_int(&rdev->wiphy, ret);
> return ret;
> }
> +
> +static inline int
> +rdev_start_gscan(struct cfg80211_registered_device *rdev,
> + struct net_device *dev,
> + struct cfg80211_gscan_request *request)
> +{
> + int ret;
> +
> + trace_rdev_start_gscan(&rdev->wiphy, dev);
> + ret = rdev->ops->start_gscan(&rdev->wiphy, dev, request);
> + trace_rdev_return_int(&rdev->wiphy, ret);
> + return ret;
> +}
> +
> +static inline int
> +rdev_stop_gscan(struct cfg80211_registered_device *rdev,
> + struct net_device *dev)
> +{
> + int ret;
> +
> + trace_rdev_stop_gscan(&rdev->wiphy, dev);
> + ret = rdev->ops->stop_gscan(&rdev->wiphy, dev);
> + trace_rdev_return_int(&rdev->wiphy, ret);
> + return ret;
> +}
> #endif /* __CFG80211_RDEV_OPS */
> diff --git a/net/wireless/scan.c b/net/wireless/scan.c
> index 174076b..8c141c2 100644
> --- a/net/wireless/scan.c
> +++ b/net/wireless/scan.c
> @@ -386,6 +386,34 @@ int __cfg80211_stop_sched_scan(struct
> cfg80211_registered_device *rdev,
> return 0;
> }
>
> +int __cfg80211_stop_gscan(struct cfg80211_registered_device *rdev,
> + bool driver_initiated)
> +{
> + struct cfg80211_gscan_request *gscan_req;
> + struct net_device *dev;
> +
> + ASSERT_RTNL();
> +
> + if (!rdev->gscan_req)
> + return -ENOENT;
> +
> + gscan_req = rtnl_dereference(rdev->gscan_req);
> + dev = gscan_req->dev;
> +
> + if (!driver_initiated) {
> + int err = rdev_stop_gscan(rdev, dev);
> + if (err)
> + return err;
> + }
> +
> + nl80211_send_scan_event(rdev, dev,
> NL80211_CMD_GSCAN_STOPPED);
> +
> + RCU_INIT_POINTER(rdev->gscan_req, NULL);
> + kfree_rcu(gscan_req, rcu_head);
> +
> + return 0;
> +}
> +
> void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
> unsigned long age_secs)
> {
> diff --git a/net/wireless/trace.h b/net/wireless/trace.h
> index ea1b47e..1d0fde9 100644
> --- a/net/wireless/trace.h
> +++ b/net/wireless/trace.h
> @@ -3067,6 +3067,15 @@
> WIPHY_PR_ARG, NETDEV_PR_ARG,
> BOOL_TO_STR(__entry->enabled))
> );
> +
> +DEFINE_EVENT(wiphy_netdev_evt, rdev_start_gscan,
> + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
> + TP_ARGS(wiphy, netdev)
> +);
> +DEFINE_EVENT(wiphy_netdev_evt, rdev_stop_gscan,
> + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
> + TP_ARGS(wiphy, netdev)
> +);
> #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
>
> #undef TRACE_INCLUDE_PATH
> --
> 1.9.1
>
^ permalink raw reply
* [PATCH v3] cfg80211: NL80211_ATTR_SOCKET_OWNER support for CMD_CONNECT
From: Andrew Zaborowski @ 2016-12-12 16:45 UTC (permalink / raw)
To: linux-wireless
Disconnect or deauthenticate when the owning socket is closed if this
flag is supplied to CMD_CONNECT or CMD_ASSOCIATE. This may be used
to ensure userspace daemon doesn't leave an unmanaged connection behind.
In some situations it would be possible to account for that, to some
degree, in the deamon restart code or in the up/down scripts without
the use of this attribute. But there will be systems where the daemon
can go away for varying periods without a warning due to local resource
management.
Signed-off-by: Andrew Zaborowski <andrew.zaborowski@intel.com>
---
changes in v2:
- add wdev.disconnect_bssid so we can deauthenticate from a BSS before
association finishes
- dropped CMD_AUTHENTICATE changes
changes in v3:
- commit message fix
---
include/net/cfg80211.h | 7 +++++++
include/uapi/linux/nl80211.h | 2 ++
net/wireless/core.c | 33 +++++++++++++++++++++++++++++++++
net/wireless/mlme.c | 2 ++
net/wireless/nl80211.c | 28 +++++++++++++++++++++++++++-
net/wireless/sme.c | 4 ++++
6 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bd19faa..ca2e252 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3764,6 +3764,9 @@ struct cfg80211_cached_keys;
* @conn: (private) cfg80211 software SME connection state machine data
* @connect_keys: (private) keys to set after connection is established
* @conn_bss_type: connecting/connected BSS type
+ * @conn_owner_nlportid: (private) connection owner socket port ID
+ * @disconnect_wk: (private) auto-disconnect work
+ * @disconnect_bssid: (private) the BSSID to use for auto-disconnect
* @ibss_fixed: (private) IBSS is using fixed BSSID
* @ibss_dfs_possible: (private) IBSS may change to a DFS channel
* @event_list: (private) list for internal event processing
@@ -3795,6 +3798,10 @@ struct wireless_dev {
struct cfg80211_conn *conn;
struct cfg80211_cached_keys *connect_keys;
enum ieee80211_bss_type conn_bss_type;
+ u32 conn_owner_nlportid;
+
+ struct work_struct disconnect_wk;
+ u8 disconnect_bssid[ETH_ALEN];
struct list_head event_list;
spinlock_t event_lock;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 56368e9..84db1f0 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1788,6 +1788,8 @@ enum nl80211_commands {
* and remove functions. NAN notifications will be sent in unicast to that
* socket. Without this attribute, any socket can add functions and the
* notifications will be sent to the %NL80211_MCGRP_NAN multicast group.
+ * If set during %NL80211_CMD_ASSOCIATE or %NL80211_CMD_CONNECT the
+ * station will deauthenticate when the socket is closed.
*
* @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
* the TDLS link initiator.
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 8201e6d..6b8fd68 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -357,6 +357,36 @@ static void cfg80211_sched_scan_stop_wk(struct work_struct *work)
rtnl_unlock();
}
+static void cfg80211_disconnect_wk(struct work_struct *work)
+{
+ struct cfg80211_registered_device *rdev;
+ struct wireless_dev *wdev;
+
+ wdev = container_of(work, struct wireless_dev, disconnect_wk);
+ rdev = wiphy_to_rdev(wdev->wiphy);
+
+ if (!wdev->netdev)
+ return;
+
+ wdev_lock(wdev);
+
+ if (wdev->conn_owner_nlportid) {
+ /*
+ * Use disconnect_bssid if still connecting and ops->disconnect
+ * not implemented. Otherwise we can use cfg80211_disconnect.
+ */
+ if (rdev->ops->disconnect || wdev->current_bss)
+ cfg80211_disconnect(rdev, wdev->netdev,
+ WLAN_REASON_DEAUTH_LEAVING, true);
+ else
+ cfg80211_mlme_deauth(rdev, wdev->netdev,
+ wdev->disconnect_bssid, NULL, 0,
+ WLAN_REASON_DEAUTH_LEAVING, false);
+ }
+
+ wdev_unlock(wdev);
+}
+
/* exported functions */
struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
@@ -1117,6 +1147,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
dev->priv_flags |= IFF_DONT_BRIDGE;
+ INIT_WORK(&wdev->disconnect_wk, cfg80211_disconnect_wk);
+
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
break;
case NETDEV_GOING_DOWN:
@@ -1205,6 +1237,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
#ifdef CONFIG_CFG80211_WEXT
kzfree(wdev->wext.keys);
#endif
+ flush_work(&wdev->disconnect_wk);
}
/*
* synchronise (so that we won't find this netdev
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index cbb48e2..9923244 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -328,6 +328,8 @@ int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
ASSERT_WDEV_LOCK(wdev);
+ wdev->conn_owner_nlportid = 0;
+
if (local_state_change &&
(!wdev->current_bss ||
!ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c510810..502ae92 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -8003,6 +8003,12 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
wdev_unlock(dev->ieee80211_ptr);
}
+ if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
+ dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
+
+ memcpy(dev->ieee80211_ptr->disconnect_bssid, bssid, ETH_ALEN);
+ }
+
return err;
}
@@ -8050,6 +8056,10 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
local_state_change);
wdev_unlock(dev->ieee80211_ptr);
+
+ if (!err)
+ dev->ieee80211_ptr->conn_owner_nlportid = 0;
+
return err;
}
@@ -8097,6 +8107,10 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
local_state_change);
wdev_unlock(dev->ieee80211_ptr);
+
+ if (!err)
+ dev->ieee80211_ptr->conn_owner_nlportid = 0;
+
return err;
}
@@ -8723,6 +8737,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
wdev_unlock(dev->ieee80211_ptr);
if (err)
kzfree(connkeys);
+
+ if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
+ dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
+
return err;
}
@@ -14425,13 +14443,21 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
spin_unlock(&rdev->destroy_list_lock);
schedule_work(&rdev->destroy_work);
}
- } else if (schedule_scan_stop) {
+
+ continue;
+ }
+
+ if (schedule_scan_stop) {
sched_scan_req->owner_nlportid = 0;
if (rdev->ops->sched_scan_stop &&
rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
schedule_work(&rdev->sched_scan_stop_wk);
}
+
+ list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list)
+ if (wdev->conn_owner_nlportid == notify->portid)
+ schedule_work(&wdev->disconnect_wk);
}
rcu_read_unlock();
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index a77db33..f5cc067 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -713,6 +713,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
kzfree(wdev->connect_keys);
wdev->connect_keys = NULL;
wdev->ssid_len = 0;
+ wdev->conn_owner_nlportid = 0;
if (bss) {
cfg80211_unhold_bss(bss_from_pub(bss));
cfg80211_put_bss(wdev->wiphy, bss);
@@ -941,6 +942,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
wdev->current_bss = NULL;
wdev->ssid_len = 0;
+ wdev->conn_owner_nlportid = 0;
nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
@@ -1084,6 +1086,8 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
kzfree(wdev->connect_keys);
wdev->connect_keys = NULL;
+ wdev->conn_owner_nlportid = 0;
+
if (wdev->conn)
err = cfg80211_sme_disconnect(wdev, reason);
else if (!rdev->ops->disconnect)
--
2.9.3
^ permalink raw reply related
* Re: [PATCH] ath10k: free host-mem with DMA_BIRECTIONAL flag.
From: Valo, Kalle @ 2016-12-12 16:35 UTC (permalink / raw)
To: greearb@candelatech.com
Cc: linux-wireless@vger.kernel.org, ath10k@lists.infradead.org
In-Reply-To: <1480962519-13027-1-git-send-email-greearb@candelatech.com>
greearb@candelatech.com writes:
> From: Ben Greear <greearb@candelatech.com>
>
> Hopefully this fixes the problem reported by Kalle:
>
> Noticed this in my log, but I don't have time to investigate this in
> detail right now:
>
> [ 413.795346] IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready
> [ 414.158755] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
> [ 477.439659] ath10k_pci 0000:02:00.0: could not get mac80211 beacon
> [ 481.666630] ------------[ cut here ]------------
> [ 481.666669] WARNING: CPU: 0 PID: 1978 at lib/dma-debug.c:1155 check_un=
map+0x320/0x8e0
> [ 481.666688] ath10k_pci 0000:02:00.0: DMA-API: device driver frees DMA =
memory with different direction [device address=3D0x000000002d130000] [size=
=3D63800 bytes] [mapped with DMA_BIDIRECTIONAL] [unmapped with DMA_TO_DEVIC=
E]
> [ 481.666703] Modules linked in: ctr ccm ath10k_pci(E-) ath10k_core(E) a=
th(E) mac80211(E) cfg80211(E) snd_hda_codec_hdmi snd_hda_codec_idt snd_hda_=
codec_generic snd_hda_intel snd_hda_codec snd_hda_core snd_hwdep snd_pcm sn=
d_seq_midi arc4 snd_rawmidi snd_seq_midi_event snd_seq btusb btintel snd_se=
q_device joydev coret
> [ 481.671468] CPU: 0 PID: 1978 Comm: rmmod Tainted: G E 4.9=
.0-rc7-wt+ #54
> [ 481.671478] Hardware name: Hewlett-Packard HP ProBook 6540b/1722, BIOS=
68CDD Ver. F.04 01/27/2010
> [ 481.671489] ef49dcec c842ee92 c8b5830e ef49dd34 ef49dd20 c80850f5 c8b=
5a13c ef49dd50
> [ 481.671560] 000007ba c8b5830e 00000483 c8461830 c8461830 00000483 ef4=
9ddcc f34e64b8
> [ 481.671641] c8b58360 ef49dd3c c80851bb 00000009 00000000 ef49dd34 c8b=
5a13c ef49dd50
> [ 481.671716] Call Trace:
> [ 481.671731] [<c842ee92>] dump_stack+0x76/0xb4
> [ 481.671745] [<c80850f5>] __warn+0xe5/0x100
> [ 481.671757] [<c8461830>] ? check_unmap+0x320/0x8e0
> [ 481.671769] [<c8461830>] ? check_unmap+0x320/0x8e0
> [ 481.671780] [<c80851bb>] warn_slowpath_fmt+0x3b/0x40
> [ 481.671791] [<c8461830>] check_unmap+0x320/0x8e0
> [ 481.671804] [<c8462054>] debug_dma_unmap_page+0x84/0xa0
> [ 481.671835] [<f937cd7a>] ath10k_wmi_free_host_mem+0x9a/0xe0 [ath10k_c=
ore]
> [ 481.671861] [<f9363400>] ath10k_core_destroy+0x50/0x60 [ath10k_core]
> [ 481.671875] [<f8e13969>] ath10k_pci_remove+0x79/0xa0 [ath10k_pci]
> [ 481.671889] [<c848d8d8>] pci_device_remove+0x38/0xb0
> [ 481.671901] [<c859fe4b>] __device_release_driver+0x7b/0x110
> [ 481.671913] [<c85a00e7>] driver_detach+0x97/0xa0
> [ 481.671923] [<c859ef8b>] bus_remove_driver+0x4b/0xb0
> [ 481.671934] [<c85a0cda>] driver_unregister+0x2a/0x60
> [ 481.671949] [<c848c888>] pci_unregister_driver+0x18/0x70
> [ 481.671965] [<f8e14dae>] ath10k_pci_exit+0xd/0x25f [ath10k_pci]
> [ 481.671979] [<c812bb84>] SyS_delete_module+0xf4/0x180
> [ 481.671995] [<c81f801b>] ? __might_fault+0x8b/0xa0
> [ 481.672009] [<c80037d0>] do_fast_syscall_32+0xa0/0x1e0
> [ 481.672025] [<c88d4c88>] sysenter_past_esp+0x45/0x74
> [ 481.672037] ---[ end trace 3fd23759e17e1622 ]---
> [ 481.672049] Mapped at:
> [ 481.672060] [ 481.672072] [<c846062c>] debug_dma_map_page.part.25+0x=
1c/0xf0
> [ 481.672083] [ 481.672095] [<c8460799>] debug_dma_map_page+0x99/0xc0
> [ 481.672106] [ 481.672132] [<f93745ec>] ath10k_wmi_alloc_chunk+0x12c/=
0x1f0 [ath10k_core]
> [ 481.672142] [ 481.672168] [<f937d0c4>] ath10k_wmi_event_service_read=
y_work+0x304/0x540 [ath10k_core]
> [ 481.672178] [ 481.672190] [<c80a3643>] process_one_work+0x1c3/0x670
> [ 482.137134] ath10k_pci 0000:02:00.0: pci irq msi oper_irq_mode 2 irq_m=
ode 0 reset_mode 0
> [ 482.313144] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/p=
re-cal-pci-0000:02:00.0.bin failed with error -2
> [ 482.313274] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/c=
al-pci-0000:02:00.0.bin failed with error -2
> [ 482.313768] ath10k_pci 0000:02:00.0: qca988x hw2.0 target 0x4100016c c=
hip_id 0x043202ff sub 0000:0000
> [ 482.313777] ath10k_pci 0000:02:00.0: kconfig debug 1 debugfs 1 tracing=
1 dfs 0 testmode 1
> [ 482.313974] ath10k_pci 0000:02:00.0: firmware ver 10.2.4.70.59-2 api 5=
features no-p2p,raw-mode,mfp,allows-mesh-bcast crc32 4159f498
> [ 482.369858] ath10k_pci 0000:02:00.0: Direct firmware load for ath10k/Q=
CA988X/hw2.0/board-2.bin failed with error -2
> [ 482.370011] ath10k_pci 0000:02:00.0: board_file api 1 bmi_id N/A crc32=
bebc7c08
> [ 483.596770] ath10k_pci 0000:02:00.0: htt-ver 2.1 wmi-op 5 htt-op 2 cal=
otp max-sta 128 raw 0 hwcrypto 1
> [ 483.701686] ath: EEPROM regdomain: 0x0
> [ 483.701706] ath: EEPROM indicates default country code should be used
> [ 483.701713] ath: doing EEPROM country->regdmn map search
> [ 483.701721] ath: country maps to regdmn code: 0x3a
> [ 483.701730] ath: Country alpha2 being used: US
> [ 483.701737] ath: Regpair used: 0x3a
>
> Reported-by: Kalle Valo <kvalo@qca.qualcomm.com>
> Signed-off-by: Ben Greear <greearb@candelatech.com>
Thanks, I don't see the warning anymore so this seems to be fixed. I'll
push this to 4.10.
--=20
Kalle Valo=
^ permalink raw reply
* Re: ATH9 driver issues on ARM64
From: Bjorn Helgaas @ 2016-12-12 16:31 UTC (permalink / raw)
To: Bharat Kumar Gogada
Cc: Tobias Klausmann, Kalle Valo, linux-kernel@vger.kernel.org,
linux-pci@vger.kernel.org, Marc Zyngier,
Janusz.Dziedzic@tieto.com, rmanohar@qti.qualcomm.com,
ath9k-devel@qca.qualcomm.com, linux-wireless@vger.kernel.org
In-Reply-To: <8520D5D51A55D047800579B094147198263A8EF9@XAP-PVEXMBX02.xlnx.xilinx.com>
On Sat, Dec 10, 2016 at 02:40:48PM +0000, Bharat Kumar Gogada wrote:
> Hi,
>
> After taking some more lecroy traces, we see that after 2nd ASSERT from EP on ARM64 we see continuous data movement of 32 dwords or 12 dwords and never sign of DEASSERT.
> Comparatively on working traces (x86) after 2nd assert there are only BAR register reads and writes and then DEASSERT, for almost most of the interrupts and we haven't seen 12 or 32 dwords data movement on this trace.
>
> I did not work on EP wifi/network drivers, any help why EP needs those many number of data at scan time ?
The device doesn't know whether it's in an x86 or an arm64 system. If
it works differently, it must be because the PCI core or the driver is
programming the device differently.
You should be able to match up Memory transactions from the host in
the trace with things the driver does. For example, if you see an
Assert_INTx message from the device, you should eventually see a
Memory Read from the host to get the ISR, i.e., some read done in the
bowels of ath9k_hw_getisr().
I don't know how the ath9k device works, but there must be some Memory
Read or Write done by the driver that tells the device "we've handled
this interrupt". The device should then send a Deassert_INTx; of
course, if the device still requires service, e.g., because it has
received more packets, it might leave the INTx asserted.
I doubt you'd see exactly the same traces on x86 and arm64 because
they aren't seeing the same network packets and the driver is
executing at different rates. But you should at least be able to
identify interrupt assertion and the actions of the driver's interrupt
service routine.
> > Hello there,
> >
> > as this is a thread about ath9k and ARM64, i'm not sure if i should answer here
> > or not, but i have similar "stalls" with ath9k on x86_64 (starting with 4.9rc), stack
> > trace is posted down below where the original ARM64 stall traces are.
> >
> > Greetings,
> >
> > Tobias
> >
> >
> > On 08.12.2016 18:36, Kalle Valo wrote:
> > > Bharat Kumar Gogada <bharat.kumar.gogada@xilinx.com> writes:
> > >
> > >> > [+cc Kalle, ath9k list]
> > > Thanks, but please also CC linux-wireless. Full thread below for the
> > > folks there.
> > >
> > >>> On Thu, Dec 08, 2016 at 01:49:42PM +0000, Bharat Kumar Gogada wrote:
> > >>>> Hi,
> > >>>>
> > >>>> Did anyone test Atheros ATH9
> > >>>> driver(drivers/net/wireless/ath/ath9k/)
> > >>>> on ARM64. The end point is TP link wifi card with which supports
> > >>>> only legacy interrupts.
> > >>> If it works on other arches and the arm64 PCI enumeration works, my
> > >>> first guess would be an INTx issue, e.g., maybe the driver is
> > >>> waiting for an interrupt that never arrives.
> > >> We are not sure for now.
> > >>>> We are trying to test it on ARM64 with
> > >>>> (drivers/pci/host/pcie-xilinx-nwl.c) as root port.
> > >>>>
> > >>>> EP is getting enumerated and able to link up.
> > >>>>
> > >>>> But when we start scan system gets hanged.
> > >>> When you say the system hangs when you start a scan, I assume you
> > >>> mean a wifi scan, not the PCI enumeration. A problem with a wifi
> > >>> scan might cause a *process* to hang, but it shouldn't hang the
> > >>> entire system.
> > >>>
> > >> Yes wifi scan.
> > >>>> When we took trace we see that after we start scan assert message
> > >>>> is sent but there is no de assert from end point.
> > >>> Are you talking about a trace from a PCIe analyzer? Do you see an
> > >>> Assert_INTx PCIe message on the link?
> > >>>
> > >> Yes lecroy trace, yes we do see Assert_INTx and Deassert_INTx happening
> > when we do interface link up.
> > >> When we have less debug prints in Atheros driver, and do wifi scan we
> > >> see Assert_INTx but never Deassert_INTx,
> > >>>> What might cause end point not sending de assert ?
> > >>> If the endpoint doesn't send a Deassert_INTx message, I expect that
> > >>> would mean the driver didn't service the interrupt and remove the
> > >>> condition that caused the device to assert the interrupt in the
> > >>> first place.
> > >>>
> > >>> If the driver didn't receive the interrupt, it couldn't service it,
> > >>> of course. You could add a printk in the ath9k interrupt service
> > >>> routine to see if you ever get there.
> > >>>
> > >> The interrupt behavior is changing w.r.t amount of debug prints we
> > >> add. (I kept many prints to aid debug) root@Xilinx-ZCU102-2016_3:~# iw dev
> > wlan0 scan
> > >> [ 83.064675] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.069486] ath9k: ath9k_ioread32 ffffff800a400024
> > >> [ 83.074257] ath9k_hw_kill_interrupts 793
> > >> [ 83.078260] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.083107] ath9k: ath9k_ioread32 ffffff800a400024
> > >> [ 83.087882] ath9k_hw_kill_interrupts 793
> > >> [ 83.095450] ath9k_hw_enable_interrupts 821
> > >> [ 83.099557] ath9k_hw_enable_interrupts 825
> > >> [ 83.103721] ath9k_hw_enable_interrupts 832
> > >> [ 83.107887] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.112748] AR_SREV_9100 0
> > >> [ 83.115438] ath9k_hw_enable_interrupts 848
> > >> [ 83.119607] ath9k: ath9k_ioread32 ffffff800a400024
> > >> [ 83.124389] ath9k_hw_intrpend 762
> > >> [ 83.127761] (AR_SREV_9340(ah) val 0
> > >> [ 83.131234] ath9k_hw_intrpend 767
> > >> [ 83.134628] ath_isr 603
> > >> [ 83.137134] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.141995] ath9k: ath9k_ioread32 ffffff800a400024
> > >> [ 83.146771] ath9k_hw_kill_interrupts 793
> > >> [ 83.150864] ath9k_hw_enable_interrupts 821
> > >> [ 83.154971] ath9k_hw_enable_interrupts 825
> > >> [ 83.159135] ath9k_hw_enable_interrupts 832
> > >> [ 83.163300] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.168161] AR_SREV_9100 0
> > >> [ 83.170852] ath9k_hw_enable_interrupts 848
> > >> [ 83.170855] ath9k_hw_intrpend 762
> > >> [ 83.178398] (AR_SREV_9340(ah) val 0
> > >> [ 83.181873] ath9k_hw_intrpend 767
> > >> [ 83.185265] ath_isr 603
> > >> [ 83.187773] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.192635] ath9k: ath9k_ioread32 ffffff800a400024
> > >> [ 83.197411] ath9k_hw_kill_interrupts 793
> > >> [ 83.201414] ath9k: ath9k_ioread32 ffffff800a400024
> > >> [ 83.206258] ath9k_hw_enable_interrupts 821
> > >> [ 83.210368] ath9k_hw_enable_interrupts 825
> > >> [ 83.214531] ath9k_hw_enable_interrupts 832
> > >> [ 83.218698] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.223558] AR_SREV_9100 0
> > >> [ 83.226243] ath9k_hw_enable_interrupts 848
> > >> [ 83.226246] ath9k_hw_intrpend 762
> > >> [ 83.233794] (AR_SREV_9340(ah) val 0
> > >> [ 83.237268] ath9k_hw_intrpend 767
> > >> [ 83.240661] ath_isr 603
> > >> [ 83.243169] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.248030] ath9k: ath9k_ioread32 ffffff800a400024
> > >> [ 83.252806] ath9k_hw_kill_interrupts 793
> > >> [ 83.256811] ath9k: ath9k_ioread32 ffffff800a400024
> > >> [ 83.261651] ath9k_hw_enable_interrupts 821
> > >> [ 83.265753] ath9k_hw_enable_interrupts 825
> > >> [ 83.269919] ath9k_hw_enable_interrupts 832
> > >> [ 83.274083] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.278945] AR_SREV_9100 0
> > >> [ 83.281630] ath9k_hw_enable_interrupts 848
> > >> [ 83.281633] ath9k_hw_intrpend 762
> > >> [ 83.281634] (AR_SREV_9340(ah) val 0
> > >> [ 83.281637] ath9k_hw_intrpend 767
> > >> [ 83.281648] ath_isr 603
> > >> [ 83.281649] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.281651] ath9k: ath9k_ioread32 ffffff800a400024
> > >> [ 83.281654] ath9k_hw_kill_interrupts 793
> > >> [ 83.312192] ath9k: ath9k_ioread32 ffffff800a400024
> > >> [ 83.317030] ath9k_hw_enable_interrupts 821
> > >> [ 83.321132] ath9k_hw_enable_interrupts 825
> > >> [ 83.325297] ath9k_hw_enable_interrupts 832
> > >> [ 83.329463] ath9k: ath9k_iowrite32 ffffff800a400024
> > >> [ 83.334324] AR_SREV_9100 0
> > >> [ 83.337014] ath9k_hw_enable_interrupts 848
> > >> ..
> > >> ..
> > >> This log continues until I turn off board without obtaining scanning result.
> > >>
> > >> In between I get following cpu stall outputs :
> > >> 230.457179] INFO: rcu_sched self-detected stall on CPU
> > >> [ 230.457185] 2-...: (31314 ticks this GP)
> > idle=2d1/140000000000001/0 softirq=1400/1400 fqs=36713
> > >> [ 230.457189] (t=36756 jiffies g=161 c=160 q=16169)
> > >> [ 230.457191] Task dump for CPU 2:
> > >> [ 230.457196] kworker/u8:4 R running task 0 1342 2 0x00000002
> > >> [ 230.457207] Workqueue: phy0 ieee80211_scan_work [ 230.457208]
> > >> Call trace:
> > >> [ 230.457214] [<ffffff8008089860>] dump_backtrace+0x0/0x198 [
> > >> 230.457219] [<ffffff8008089a0c>] show_stack+0x14/0x20 [ 230.457224]
> > >> [<ffffff80080c0930>] sched_show_task+0x98/0xf8 [ 230.457228]
> > >> [<ffffff80080c2628>] dump_cpu_task+0x40/0x50 [ 230.457233]
> > >> [<ffffff80080e14a8>] rcu_dump_cpu_stacks+0xa0/0xf0 [ 230.457239]
> > >> [<ffffff80080e4cd8>] rcu_check_callbacks+0x468/0x748 [ 230.457243]
> > >> [<ffffff80080e7cfc>] update_process_times+0x3c/0x68 [ 230.457249]
> > >> [<ffffff80080f6dfc>] tick_sched_handle.isra.5+0x3c/0x50
> > >> [ 230.457253] [<ffffff80080f6e54>] tick_sched_timer+0x44/0x90 [
> > >> 230.457257] [<ffffff80080e86b0>] __hrtimer_run_queues+0xf0/0x178
> > >> ** 10 printk messages dropped ** [ 230.457302] f8c0:
> > >> 0000000000000000 0000000005f5e0ff 000000000001379a
> > 3866666666666620 [
> > >> 230.457306] f8e0: ffffff800a1b4065 0000000000000006 ffffff800a129000
> > >> ffffffc87b8010a8 [ 230.457310] f900: ffffff808a1b4057
> > >> ffffff800a1c3000 ffffff800a1b3000 ffffff800a13b000 [ 230.457314]
> > >> f920: 0000000000000140 0000000000000006 ffffff800a1b3b10
> > >> ffffff800a1c39e8 [ 230.457318] f940: 000000000000002f
> > >> ffffff800a1b8a98 ffffff800a1b3ae8 ffffffc87b07f990 [ 230.457322]
> > >> f960: ffffff80080d6230 ffffffc87b07f990 ffffff80080d6234
> > >> 0000000060000145
> > >> ** 1 printk messages dropped ** [ 230.457329] [<ffffff8008085720>]
> > >> el1_irq+0xa0/0x100
> > >> ** 9 printk messages dropped ** [ 230.457373] [<ffffff800885ad60>]
> > >> ieee80211_hw_config+0x50/0x290 [ 230.457377] [<ffffff8008863690>]
> > >> ieee80211_scan_work+0x1f8/0x480 [ 230.457383] [<ffffff80080b15d0>]
> > >> process_one_work+0x120/0x378 [ 230.457386] [<ffffff80080b1870>]
> > >> worker_thread+0x48/0x4b0 [ 230.457391] [<ffffff80080b7108>]
> > >> kthread+0xd0/0xe8 [ 230.457395] [<ffffff8008085dd0>]
> > ret_from_fork+0x10/0x40
> > >> [ 230.480389] ath9k_hw_intrpend 762
> > >>
> > >>
> > >> [ 545.487987] ath9k: ath9k_ioread32 ffffff800a400024 [ 545.526189]
> > >> INFO: rcu_sched self-detected stall on CPU
> > >> [ 545.526195] 2-...: (97636 ticks this GP)
> > idle=2d1/140000000000001/0 softirq=1400/1400 fqs=115374
> > >> [ 545.526199] (t=115523 jiffies g=161 c=160 q=51066)
> > >> [ 545.526201] Task dump for CPU 2:
> > >> [ 545.526206] kworker/u8:4 R running task 0 1342 2 0x00000002
> > >> ** 3 printk messages dropped ** [ 545.526231] [<ffffff8008089a0c>]
> > >> show_stack+0x14/0x20
> > >> ** 9 printk messages dropped ** [ 545.526280] [<ffffff80086a71e8>]
> > >> arch_timer_handler_phys+0x30/0x40 [ 545.526284] [<ffffff80080dbe18>]
> > >> handle_percpu_devid_irq+0x78/0xa0 [ 545.526291] [<ffffff80080d760c>]
> > >> generic_handle_irq+0x24/0x38 [ 545.526296] [<ffffff80080d7944>]
> > >> __handle_domain_irq+0x5c/0xb8 [ 545.526299] [<ffffff80080824bc>]
> > >> gic_handle_irq+0x64/0xc0 [ 545.526302] Exception stack(0xffffffc87b07f870
> > to 0xffffffc87b07f990)
> > >> [ 545.526306] f860: 0000000000009732 ffffff800a1eaaa8
> > >> ** 8 printk messages dropped ** [ 545.526341] f980: ffffff800a1c39e8
> > >> 0000000000000036 [ 545.526345] [<ffffff8008085720>]
> > >> el1_irq+0xa0/0x100 [ 545.526349] [<ffffff80080d6234>]
> > >> console_unlock+0x384/0x5b0 [ 545.526353] [<ffffff80080d673c>]
> > >> vprintk_emit+0x2dc/0x4b0 [ 545.526357] [<ffffff80080d6a50>]
> > >> vprintk_default+0x38/0x40 [ 545.526362] [<ffffff8008129704>]
> > >> printk+0x58/0x60 [ 545.526366] [<ffffff800859e3e4>]
> > >> ath9k_iowrite32+0x9c/0xa8 [ 545.526372] [<ffffff80085c7ca8>]
> > >> ath9k_hw_kill_interrupts+0x28/0xf0
> > >> [ 545.526376] [<ffffff80085a18ec>] ath_reset+0x24/0x68
> > >> ** 2 printk messages dropped ** [ 545.526391] [<ffffff800885ad60>]
> > ieee80211_hw_config+0x50/0x290
> > >> ** 11 printk messages dropped ** [ 545.532834] ath9k_hw_kill_interrupts
> > 793
> > >> [ 545.532890] ath9k_hw_enable_interrupts 821
> >
> > [ 81.876902] INFO: rcu_preempt detected stalls on CPUs/tasks:
> > [ 81.876912] Tasks blocked on level-0 rcu_node (CPUs 0-7): P0
> > [ 81.876932] (detected by 4, t=60002 jiffies, g=1873, c=1872, q=4967)
> > [ 81.876936] swapper/4 R running task 0 0 1
> > 0x00000000
> > [ 81.876941] 0000000000000001 ffffffff810725f6 ffff88017edbc240
> > ffffffff81a3dc40
> > [ 81.876945] ffffffff81101e46 ffff88025ef173c0 ffffffff81a3dc40
> > ffffffff81a3dc40
> > [ 81.876948] 00000000ffffffff ffffffff810a7333 ffff88017ecee698
> > ffff88017edbc240
> > [ 81.876951] Call Trace:
> > [ 81.876970] <IRQ>
> > [ 81.876979] [<ffffffff810725f6>] ? sched_show_task+0xd6/0x140
> > [ 81.876983] [<ffffffff81101e46>] ?
> > rcu_print_detail_task_stall_rnp+0x40/0x61
> > [ 81.876989] [<ffffffff810a7333>] ? rcu_check_callbacks+0x6b3/0x8c0
> > [ 81.876993] [<ffffffff810b8350>] ? tick_sched_handle.isra.14+0x40/0x40
> > [ 81.876996] [<ffffffff810aa4c3>] ? update_process_times+0x23/0x50
> > [ 81.876999] [<ffffffff810b8383>] ? tick_sched_timer+0x33/0x60
> > [ 81.877002] [<ffffffff810aaf09>] ? __hrtimer_run_queues+0xb9/0x150
> > [ 81.877004] [<ffffffff810ab198>] ? hrtimer_interrupt+0x98/0x1a0
> > [ 81.877008] [<ffffffff81031b1e>] ?
> > smp_trace_apic_timer_interrupt+0x5e/0x90
> > [ 81.877012] [<ffffffff815b31bf>] ? apic_timer_interrupt+0x7f/0x90
> > [ 81.877013] <EOI>
> > [ 81.877017] [<ffffffff8147f28d>] ? cpuidle_enter_state+0x13d/0x1f0
> > [ 81.877019] [<ffffffff8147f289>] ? cpuidle_enter_state+0x139/0x1f0
> > [ 81.877021] [<ffffffff81088c19>] ? cpu_startup_entry+0x139/0x210
> > [ 81.877027] [<ffffffff8102fc9e>] ? start_secondary+0x13e/0x170
> > [ 81.877029] swapper/4 R running task 0 0 1
> > 0x00000000
> > [ 81.877032] 0000000000000001 ffffffff810725f6 ffff88017edbc240
> > ffffffff81a3dc40
> > [ 81.877035] ffffffff81101e46 ffff88025ef173c0 ffffffff81a3dc40
> > ffffffff81a3dc40
> > [ 81.877038] 00000000ffffffff ffffffff810a7368 ffff88017ecee698
> > ffff88017edbc240
> > [ 81.877041] Call Trace:
> > [ 81.877045] <IRQ>
> > [ 81.877049] [<ffffffff810725f6>] ? sched_show_task+0xd6/0x140
> > [ 81.877051] [<ffffffff81101e46>] ?
> > rcu_print_detail_task_stall_rnp+0x40/0x61
> > [ 81.877055] [<ffffffff810a7368>] ? rcu_check_callbacks+0x6e8/0x8c0
> > [ 81.877058] [<ffffffff810b8350>] ? tick_sched_handle.isra.14+0x40/0x40
> > [ 81.877060] [<ffffffff810aa4c3>] ? update_process_times+0x23/0x50
> > [ 81.877063] [<ffffffff810b8383>] ? tick_sched_timer+0x33/0x60
> > [ 81.877065] [<ffffffff810aaf09>] ? __hrtimer_run_queues+0xb9/0x150
> > [ 81.877068] [<ffffffff810ab198>] ? hrtimer_interrupt+0x98/0x1a0
> > [ 81.877070] [<ffffffff81031b1e>] ?
> > smp_trace_apic_timer_interrupt+0x5e/0x90
> > [ 81.877073] [<ffffffff815b31bf>] ? apic_timer_interrupt+0x7f/0x90
> > [ 81.877074] <EOI>
> > [ 81.877076] [<ffffffff8147f28d>] ? cpuidle_enter_state+0x13d/0x1f0
> > [ 81.877078] [<ffffffff8147f289>] ? cpuidle_enter_state+0x139/0x1f0
> > [ 81.877080] [<ffffffff81088c19>] ? cpu_startup_entry+0x139/0x210
> > [ 81.877084] [<ffffffff8102fc9e>] ? start_secondary+0x13e/0x170
> > [ 91.132787] INFO: rcu_preempt detected expedited stalls on
> > CPUs/tasks: { P0 } 63785 jiffies s: 505 root: 0x0/T
> > [ 91.132796] blocking rcu_node structures:
> >
> > >>
> > >>
> > >> But if we have less debug prints it does not reach EP handler
> > >> sometimes, due to following Condition in "kernel/irq/chip.c" in
> > >> function handle_simple_irq
> > >>
> > >> if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
> > >> desc->istate |= IRQS_PENDING;
> > >> goto out_unlock;
> > >> }
> > >> Here irqd_irq_disabled is being set to 1.
> > >>
> > >> With lesser debug prints it stops after following prints:
> > >> root@Xilinx-ZCU102-2016_3:~# iw dev wlan0 scan
> > >> [ 54.781045] ath9k_hw_kill_interrupts 793
> > >> [ 54.785007] ath9k_hw_kill_interrupts 793
> > >> [ 54.792535] ath9k_hw_enable_interrupts 821
> > >> [ 54.796642] ath9k_hw_enable_interrupts 825
> > >> [ 54.800807] ath9k_hw_enable_interrupts 832
> > >> [ 54.804973] AR_SREV_9100 0
> > >> [ 54.807663] ath9k_hw_enable_interrupts 848
> > >> [ 54.811843] ath9k_hw_intrpend 762
> > >> [ 54.815211] (AR_SREV_9340(ah) val 0
> > >> [ 54.818684] ath9k_hw_intrpend 767
> > >> [ 54.822078] ath_isr 603
> > >> [ 54.824587] ath9k_hw_kill_interrupts 793
> > >> [ 54.828601] ath9k_hw_enable_interrupts 821
> > >> [ 54.832750] ath9k_hw_enable_interrupts 825
> > >> [ 54.836916] ath9k_hw_enable_interrupts 832
> > >> [ 54.841082] AR_SREV_9100 0
> > >> [ 54.843772] ath9k_hw_enable_interrupts 848
> > >> [ 54.843775] ath9k_hw_intrpend 762
> > >> [ 54.851319] (AR_SREV_9340(ah) val 0
> > >> [ 54.854793] ath9k_hw_intrpend 767
> > >> [ 54.858185] ath_isr 603
> > >> [ 54.860696] ath9k_hw_kill_interrupts 793
> > >> [ 54.864776] ath9k_hw_enable_interrupts 821
> > >> [ 54.867061] ath9k_hw_kill_interrupts 793
> > >> [ 54.872870] ath9k_hw_enable_interrupts 825
> > >> [ 54.877036] ath9k_hw_enable_interrupts 832
> > >> [ 54.881202] AR_SREV_9100 0
> > >> [ 54.883892] ath9k_hw_enable_interrupts 848
> > >> [ 75.963129] INFO: rcu_sched detected stalls on CPUs/tasks:
> > >> [ 75.968602] 0-...: (2 GPs behind) idle=9d5/140000000000001/0
> > softirq=1103/1109 fqs=519
> > >> [ 75.976675] (detected by 2, t=5274 jiffies, g=64, c=63, q=11)
> > >> [ 75.982485] Task dump for CPU 0:
> > >> [ 75.985696] ksoftirqd/0 R running task 0 3 2 0x00000002
> > >> [ 75.992726] Call trace:
> > >> [ 75.995165] [<ffffff8008086b3c>] __switch_to+0xc4/0xd0
> > >> [ 76.000281] [<ffffffc87b830500>] 0xffffffc87b830500
> > >> [ 139.059027] INFO: rcu_sched detected stalls on CPUs/tasks:
> > >> [ 139.064430] 0-...: (2 GPs behind) idle=9d5/140000000000001/0
> > softirq=1103/1109 fqs=2097
> > >> [ 139.072593] (detected by 2, t=21049 jiffies, g=64, c=63, q=11)
> > >> [ 139.078489] Task dump for CPU 0:
> > >> [ 139.081700] ksoftirqd/0 R running task 0 3 2 0x00000002
> > >> [ 139.088731] Call trace:
> > >> [ 139.091165] [<ffffff8008086b3c>] __switch_to+0xc4/0xd0 [
> > >> 139.096285] [<ffffffc87b830500>] 0xffffffc87b830500
> > >>
> > >>
> > >>>> We are not seeing any issues on 32-bit ARM platform and X86
> > >>>> platform.
> > >>> Can you collect a dmesg log (or, if the system hang means you can't
> > >>> collect that, a console log with "ignore_loglevel"), and "lspci -vv"
> > >>> output as root? That should have clues about whether the INTx got
> > >>> routed correctly. /proc/interrupts should also show whether we're
> > >>> receiving interrupts from the device.
> > >> Here is the lspci output:
> > >> 00:00.0 PCI bridge: Xilinx Corporation Device d022 (prog-if 00 [Normal
> > decode])
> > >> Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop-
> > ParErr- Stepping- SERR- FastB2B- DisINTx-
> > >> Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
> > <TAbort- <MAbort- >SERR- <PERR- INTx-
> > >> Latency: 0
> > >> Interrupt: pin A routed to IRQ 224
> > >> Bus: primary=00, secondary=01, subordinate=0c, sec-latency=0
> > >> I/O behind bridge: 00000000-00000fff
> > >> Memory behind bridge: e0000000-e00fffff
> > >> Prefetchable memory behind bridge: 00000000fff00000-
> > 00000000000fffff
> > >> Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort-
> > <TAbort- <MAbort- <SERR- <PERR-
> > >> BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
> > >> PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
> > >> Capabilities: [40] Power Management version 3
> > >> Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA
> > PME(D0+,D1+,D2+,D3hot+,D3cold-)
> > >> Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
> > >> Capabilities: [60] Express (v2) Root Port (Slot-), MSI 00
> > >> DevCap: MaxPayload 256 bytes, PhantFunc 0
> > >> ExtTag- RBE+
> > >> DevCtl: Report errors: Correctable- Non-Fatal- Fatal-
> > Unsupported-
> > >> RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
> > >> MaxPayload 128 bytes, MaxReadReq 512 bytes
> > >> DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr-
> > TransPend+
> > >> LnkCap: Port #0, Speed 5GT/s, Width x2, ASPM not supported,
> > Exit Latency L0s unlimited, L1 unlimited
> > >> ClockPM- Surprise- LLActRep- BwNot+ ASPMOptComp+
> > >> LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk-
> > >> ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
> > >> LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+
> > DLActive- BWMgmt- ABWMgmt-
> > >> RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna-
> > CRSVisible+
> > >> RootCap: CRSVisible+
> > >> RootSta: PME ReqID 0000, PMEStatus- PMEPending-
> > >> DevCap2: Completion Timeout: Range B, TimeoutDis+, LTR-,
> > OBFF Not Supported ARIFwd-
> > >> DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-,
> > OBFF Disabled ARIFwd-
> > >> LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
> > >> Transmit Margin: Normal Operating Range,
> > EnterModifiedCompliance- ComplianceSOS-
> > >> Compliance De-emphasis: -6dB
> > >> LnkSta2: Current De-emphasis Level: -3.5dB,
> > EqualizationComplete-, EqualizationPhase1-
> > >> EqualizationPhase2-, EqualizationPhase3-,
> > LinkEqualizationRequest-
> > >> Capabilities: [100 v1] Device Serial Number 00-00-00-00-00-00-00-00
> > >> Capabilities: [10c v1] Virtual Channel
> > >> Caps: LPEVC=0 RefClk=100ns PATEntryBits=1
> > >> Arb: Fixed- WRR32- WRR64- WRR128-
> > >> Ctrl: ArbSelect=Fixed
> > >> Status: InProgress-
> > >> VC0: Caps: PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
> > >> Arb: Fixed- WRR32- WRR64- WRR128- TWRR128-
> > WRR256-
> > >> Ctrl: Enable+ ID=0 ArbSelect=Fixed TC/VC=ff
> > >> Status: NegoPending- InProgress-
> > >> Capabilities: [128 v1] Vendor Specific Information: ID=1234 Rev=1
> > >> Len=018 <?>
> > >>
> > >> 01:00.0 Network controller: Qualcomm Atheros AR93xx Wireless Network
> > Adapter (rev 01)
> > >> Subsystem: Qualcomm Atheros Device 3112
> > >> Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop-
> > ParErr- Stepping- SERR- FastB2B- DisINTx-
> > >> Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
> > <TAbort- <MAbort- >SERR- <PERR- INTx-
> > >> Latency: 0, Cache Line Size: 128 bytes
> > >> Interrupt: pin A routed to IRQ 224
> > >> Region 0: Memory at e0000000 (64-bit, non-prefetchable) [size=128K]
> > >> [virtual] Expansion ROM at e0020000 [disabled] [size=64K]
> > >> Capabilities: [40] Power Management version 3
> > >> Flags: PMEClk- DSI- D1+ D2- AuxCurrent=375mA
> > PME(D0+,D1+,D2-,D3hot+,D3cold-)
> > >> Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
> > >> Capabilities: [50] MSI: Enable- Count=1/4 Maskable+ 64bit+
> > >> Address: 0000000000000000 Data: 0000
> > >> Masking: 00000000 Pending: 00000000
> > >> Capabilities: [70] Express (v2) Endpoint, MSI 00
> > >> DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency
> > L0s <1us, L1 <8us
> > >> ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-
> > SlotPowerLimit 0.000W
> > >> DevCtl: Report errors: Correctable- Non-Fatal- Fatal-
> > Unsupported-
> > >> RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop-
> > >> MaxPayload 128 bytes, MaxReadReq 512 bytes
> > >> DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr-
> > TransPend-
> > >> LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s L1, Exit
> > Latency L0s <2us, L1 <64us
> > >> ClockPM- Surprise- LLActRep- BwNot- ASPMOptComp-
> > >> LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk-
> > >> ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
> > >> LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+
> > DLActive- BWMgmt- ABWMgmt-
> > >> DevCap2: Completion Timeout: Not Supported, TimeoutDis+,
> > LTR-, OBFF Not Supported
> > >> DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-,
> > OBFF Disabled
> > >> LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance-
> > SpeedDis-
> > >> Transmit Margin: Normal Operating Range,
> > EnterModifiedCompliance- ComplianceSOS-
> > >> Compliance De-emphasis: -6dB
> > >> LnkSta2: Current De-emphasis Level: -6dB,
> > EqualizationComplete-, EqualizationPhase1-
> > >> EqualizationPhase2-, EqualizationPhase3-,
> > LinkEqualizationRequest-
> > >> Capabilities: [100 v1] Advanced Error Reporting
> > >> UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt-
> > RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
> > >> UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt-
> > RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
> > >> UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt-
> > RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
> > >> CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout-
> > NonFatalErr-
> > >> CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout-
> > NonFatalErr+
> > >> AERCap: First Error Pointer: 00, GenCap- CGenEn-
> > ChkCap- ChkEn-
> > >> Capabilities: [140 v1] Virtual Channel
> > >> Caps: LPEVC=0 RefClk=100ns PATEntryBits=1
> > >> Arb: Fixed- WRR32- WRR64- WRR128-
> > >> Ctrl: ArbSelect=Fixed
> > >> Status: InProgress-
> > >> VC0: Caps: PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
> > >> Arb: Fixed- WRR32- WRR64- WRR128- TWRR128-
> > WRR256-
> > >> Ctrl: Enable+ ID=0 ArbSelect=Fixed TC/VC=ff
> > >> Status: NegoPending- InProgress-
> > >> Capabilities: [300 v1] Device Serial Number 00-00-00-00-00-00-00-00
> > >> Kernel driver in use: ath9k
> > >>
> > >> Here is the cat /proc/interrupts (after we do interface up):
> > >>
> > >> root@:~# ifconfig wlan0 up
> > >> [ 1548.926601] IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready
> > >> root@Xilinx-ZCU102-2016_3:~# cat /proc/interrupts
> > >> CPU0 CPU1 CPU2 CPU3
> > >> 1: 0 0 0 0 GICv2 29 Edge arch_timer
> > >> 2: 19873 20058 19089 17435 GICv2 30 Edge arch_timer
> > >> 12: 0 0 0 0 GICv2 156 Level zynqmp-dma
> > >> 13: 0 0 0 0 GICv2 157 Level zynqmp-dma
> > >> 14: 0 0 0 0 GICv2 158 Level zynqmp-dma
> > >> 15: 0 0 0 0 GICv2 159 Level zynqmp-dma
> > >> 16: 0 0 0 0 GICv2 160 Level zynqmp-dma
> > >> 17: 0 0 0 0 GICv2 161 Level zynqmp-dma
> > >> 18: 0 0 0 0 GICv2 162 Level zynqmp-dma
> > >> 19: 0 0 0 0 GICv2 163 Level zynqmp-dma
> > >> 20: 0 0 0 0 GICv2 164 Level Mali_GP_MMU,
> > Mali_GP, Mali_PP0_MMU, Mali_PP0, Mali_PP1_MMU, Mali_PP1
> > >> 30: 0 0 0 0 GICv2 95 Level eth0, eth0
> > >> 206: 314 0 0 0 GICv2 49 Level cdns-i2c
> > >> 207: 40 0 0 0 GICv2 50 Level cdns-i2c
> > >> 209: 0 0 0 0 GICv2 150 Level nwl_pcie:misc
> > >> 214: 12 0 0 0 GICv2 47 Level ff0f0000.spi
> > >> 215: 0 0 0 0 GICv2 58 Level ffa60000.rtc
> > >> 216: 0 0 0 0 GICv2 59 Level ffa60000.rtc
> > >> 217: 0 0 0 0 GICv2 165 Level ahci-
> > ceva[fd0c0000.ahci]
> > >> 218: 61 0 0 0 GICv2 81 Level mmc0
> > >> 219: 0 0 0 0 GICv2 187 Level arm-smmu global fault
> > >> 220: 471 0 0 0 GICv2 53 Level xuartps
> > >> 223: 0 0 0 0 GICv2 154 Level fd4c0000.dma
> > >> 224: 3 0 0 0 dummy 1 Edge ath9k
> > >> 225: 0 0 0 0 GICv2 97 Level xhci-hcd:usb1
> > >>
> > >> Regards,
> > >> Bharat
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox