Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH] brcmfmac: print firmware messages after a firmware crash
From: Arend Van Spriel @ 2019-04-28 21:06 UTC (permalink / raw)
  To: Rafał Miłecki, Kalle Valo
  Cc: linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Rafał Miłecki
In-Reply-To: <20190427183008.27111-1-zajec5@gmail.com>

On 4/27/2019 8:30 PM, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
> 
> Normally firmware messages are printed with debugging enabled only. It's
> a good idea as firmware may print a lot of messages that normal users
> don't need to care about.
> 
> However, on firmware crash, it may be very helpful to log all recent
> messages. There is almost always a backtrace available as well as rought
> info on the latest actions/state.

nice... there is one minor nit below, but other than that...

Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
> ---
>   .../broadcom/brcm80211/brcmfmac/pcie.c        | 24 ++++++++++++++-----
>   1 file changed, 18 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
> index 637973fe8928..f519b050aff3 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
> @@ -764,15 +764,22 @@ static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)
>   		  console->base_addr, console->buf_addr, console->bufsize);
>   }
>   
> -
> -static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo)
> +/**
> + * brcmf_pcie_bus_console_read - reads firmware messages
> + *
> + * @error: specifies if error has occurred (prints messages unconditionally)
> + */
> +static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
> +					int error)

Given how it is called I would say 'bool error' makes a bit more sense.

Gr. AvS

^ permalink raw reply

* [PATCH V2] brcmfmac: print firmware messages after a firmware crash
From: Rafał Miłecki @ 2019-04-28 21:38 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Arend van Spriel, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Rafał Miłecki
In-Reply-To: <20190427183008.27111-1-zajec5@gmail.com>

From: Rafał Miłecki <rafal@milecki.pl>

Normally firmware messages are printed with debugging enabled only. It's
a good idea as firmware may print a lot of messages that normal users
don't need to care about.

However, on firmware crash, it may be very helpful to log all recent
messages. There is almost always a backtrace available as well as rought
info on the latest actions/state.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
---
V2: Use "bool" for brcmf_pcie_bus_console_read() error argument
---
 .../broadcom/brcm80211/brcmfmac/pcie.c        | 24 ++++++++++++++-----
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 637973fe8928..594c14be5df0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -764,15 +764,22 @@ static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)
 		  console->base_addr, console->buf_addr, console->bufsize);
 }
 
-
-static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo)
+/**
+ * brcmf_pcie_bus_console_read - reads firmware messages
+ *
+ * @error: specifies if error has occurred (prints messages unconditionally)
+ */
+static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
+					bool error)
 {
+	struct pci_dev *pdev = devinfo->pdev;
+	struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
 	struct brcmf_pcie_console *console;
 	u32 addr;
 	u8 ch;
 	u32 newidx;
 
-	if (!BRCMF_FWCON_ON())
+	if (!error && !BRCMF_FWCON_ON())
 		return;
 
 	console = &devinfo->shared.console;
@@ -796,7 +803,10 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo)
 		}
 		if (ch == '\n') {
 			console->log_str[console->log_idx] = 0;
-			pr_debug("CONSOLE: %s", console->log_str);
+			if (error)
+				brcmf_err(bus, "CONSOLE: %s", console->log_str);
+			else
+				pr_debug("CONSOLE: %s", console->log_str);
 			console->log_idx = 0;
 		}
 	}
@@ -857,7 +867,7 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
 							&devinfo->pdev->dev);
 		}
 	}
-	brcmf_pcie_bus_console_read(devinfo);
+	brcmf_pcie_bus_console_read(devinfo, false);
 	if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
 		brcmf_pcie_intr_enable(devinfo);
 	devinfo->in_irq = false;
@@ -1426,6 +1436,8 @@ static int brcmf_pcie_reset(struct device *dev)
 	struct brcmf_fw_request *fwreq;
 	int err;
 
+	brcmf_pcie_bus_console_read(devinfo, true);
+
 	brcmf_detach(dev);
 
 	brcmf_pcie_release_irq(devinfo);
@@ -1824,7 +1836,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
 	if (brcmf_attach(&devinfo->pdev->dev, devinfo->settings) == 0)
 		return;
 
-	brcmf_pcie_bus_console_read(devinfo);
+	brcmf_pcie_bus_console_read(devinfo, false);
 
 fail:
 	device_release_driver(dev);
-- 
2.21.0


^ permalink raw reply related

* Re: [PATCH] brcmfmac: print firmware messages after a firmware crash
From: Rafał Miłecki @ 2019-04-28 21:35 UTC (permalink / raw)
  To: Arend Van Spriel
  Cc: Rafał Miłecki, Kalle Valo, linux-wireless,
	brcm80211-dev-list.pdl, brcm80211-dev-list
In-Reply-To: <2ccb4482-7561-0812-92dc-5de3d639cc3e@broadcom.com>

On 2019-04-28 23:06, Arend Van Spriel wrote:
> On 4/27/2019 8:30 PM, Rafał Miłecki wrote:
>> From: Rafał Miłecki <rafal@milecki.pl>
>> 
>> Normally firmware messages are printed with debugging enabled only. 
>> It's
>> a good idea as firmware may print a lot of messages that normal users
>> don't need to care about.
>> 
>> However, on firmware crash, it may be very helpful to log all recent
>> messages. There is almost always a backtrace available as well as 
>> rought
>> info on the latest actions/state.
> 
> nice... there is one minor nit below, but other than that...
> 
> Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
>> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
>> ---
>>   .../broadcom/brcm80211/brcmfmac/pcie.c        | 24 
>> ++++++++++++++-----
>>   1 file changed, 18 insertions(+), 6 deletions(-)
>> 
>> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c 
>> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
>> index 637973fe8928..f519b050aff3 100644
>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
>> @@ -764,15 +764,22 @@ static void brcmf_pcie_bus_console_init(struct 
>> brcmf_pciedev_info *devinfo)
>>   		  console->base_addr, console->buf_addr, console->bufsize);
>>   }
>>   -
>> -static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info 
>> *devinfo)
>> +/**
>> + * brcmf_pcie_bus_console_read - reads firmware messages
>> + *
>> + * @error: specifies if error has occurred (prints messages 
>> unconditionally)
>> + */
>> +static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info 
>> *devinfo,
>> +					int error)
> 
> Given how it is called I would say 'bool error' makes a bit more sense.

I even call that function passing "true" or "false" as argument. Nice
catch!

^ permalink raw reply

* linux-next: manual merge of the net-next tree with the wireless-drivers tree
From: Stephen Rothwell @ 2019-04-29  1:54 UTC (permalink / raw)
  To: David Miller, Networking, Kalle Valo, Wireless
  Cc: Linux Next Mailing List, Linux Kernel Mailing List,
	Greg Kroah-Hartman, Luca Coelho

[-- Attachment #1: Type: text/plain, Size: 959 bytes --]

Hi all,

Today's linux-next merge of the net-next tree got a conflict in:

  drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c

between commits:

  154d4899e411 ("iwlwifi: mvm: properly check debugfs dentry before using it")
  d156e67d3f58 ("iwlwifi: mvm: fix merge damage in iwl_mvm_vif_dbgfs_register()")

from the wireless-drivers tree and commit:

  c9af7528c331 ("iwlwifi: mvm: no need to check return value of debugfs_create functions")

from the net-next tree.

I fixed it up (the latter removed the code modified by the former, so I
just did that) and can carry the fix as necessary. This is now fixed as
far as linux-next is concerned, but any non trivial conflicts should be
mentioned to your upstream maintainer when your tree is submitted for
merging.  You may also want to consider cooperating with the maintainer
of the conflicting tree to minimise any particularly complex conflicts.

-- 
Cheers,
Stephen Rothwell

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH] brcmfmac: allocate msgbuf pktid from 1 to pktids array size
From: Wright Feng @ 2019-04-29  4:50 UTC (permalink / raw)
  To: Arend Van Spriel, franky.lin@broadcom.com,
	hante.meuleman@broadcom.com, kvalo@codeaurora.org, Chi-Hsien Lin
  Cc: linux-wireless@vger.kernel.org,
	brcm80211-dev-list.pdl@broadcom.com
In-Reply-To: <66165629-aa4d-afbe-5b09-3a592ff44a82@broadcom.com>



On 2019/4/25 下午 07:22, Arend Van Spriel wrote:
> On 4/25/2019 10:04 AM, Wright Feng wrote:
>> Some PCIE firmwares drop txstatus if pktid is 0 and make packet held in
>> host side and not be released. If that packet type is 802.1x, the
>> pend_8021x_cnt value will be always greater than 0 and show "Timed out
>> waiting for no pending 802.1x packets" error message when sending key to
>> dongle.
>>
>> To be compatible with all firmwares, host should allocate msgbuf pktid
>> from 1 instead of from 0.
> 
> looking at it we are wasting entry 0 with this patch. Could we avoid that?
> 
> Regards,
> Arend
> 
Hi Arend,

Thanks for the suggestion.
To avoid wasting index zero entry, I just increase request ID in TXflow
and decrease request ID when handling txstatus. I've posted patch v2.

Regards,
Wright
>> Signed-off-by: Wright Feng <wright.feng@cypress.com>
>> ---
>>   drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c 
>> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
>> index d3780ea..b2fab3c 100644
>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
>> @@ -348,7 +348,7 @@ brcmf_msgbuf_alloc_pktid(struct device *dev,
>>       do {
>>           (*idx)++;
>>           if (*idx == pktids->array_size)
>> -            *idx = 0;
>> +            *idx = 1;
>>           if (array[*idx].allocated.counter == 0)
>>               if (atomic_cmpxchg(&array[*idx].allocated, 0, 1) == 0)
>>                   break;
>>

^ permalink raw reply

* Re: linux-next: manual merge of the net-next tree with the wireless-drivers tree
From: Luca Coelho @ 2019-04-29  5:19 UTC (permalink / raw)
  To: Stephen Rothwell, David Miller, Networking, Kalle Valo, Wireless
  Cc: Linux Next Mailing List, Linux Kernel Mailing List,
	Greg Kroah-Hartman
In-Reply-To: <20190429115338.5decb50b@canb.auug.org.au>

Hi Stephen,

On Mon, 2019-04-29 at 11:54 +1000, Stephen Rothwell wrote:
> Hi all,
> 
> Today's linux-next merge of the net-next tree got a conflict in:
> 
>   drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
> 
> between commits:
> 
>   154d4899e411 ("iwlwifi: mvm: properly check debugfs dentry before using it")
>   d156e67d3f58 ("iwlwifi: mvm: fix merge damage in iwl_mvm_vif_dbgfs_register()")
> 
> from the wireless-drivers tree and commit:
> 
>   c9af7528c331 ("iwlwifi: mvm: no need to check return value of debugfs_create functions")
> 
> from the net-next tree.
> 
> I fixed it up (the latter removed the code modified by the former, so I
> just did that) and can carry the fix as necessary. This is now fixed as
> far as linux-next is concerned, but any non trivial conflicts should be
> mentioned to your upstream maintainer when your tree is submitted for
> merging.  You may also want to consider cooperating with the maintainer
> of the conflicting tree to minimise any particularly complex conflicts.

I checked your merge and it looks good, thanks!

--
Cheers,
Luca.


^ permalink raw reply

* Re: [PATCH] ath10k: add support for simulate crash on SDIO chip
From: Nicolas Boichat @ 2019-04-29  5:20 UTC (permalink / raw)
  To: Wen Gong; +Cc: ath10k, linux-wireless, Claire Chang
In-Reply-To: <1555406865-21514-1-git-send-email-wgong@codeaurora.org>

On Tue, Apr 16, 2019 at 5:28 PM Wen Gong <wgong@codeaurora.org> wrote:
>
> The command to simulate firmware crash:
> echo soft > /sys/kernel/debug/ieee80211/phy0/ath10k/simulate_fw_crash
>
> It will send WMI_FORCE_FW_HANG_ASSERT to firmware, then it will trigger
> CPU interrupt status register for SDIO chip, ath10k driver need to
> configure it while enable SDIO interrupt, otherwise ath10k driver will
> not get the assert error info.
>
> After this change, it will success for simulate firmware crash.
>
> Tested with QCA6174 SDIO with firmware
> WLAN.RMH.4.4.1-00007-QCARMSWP-1.
>
> Signed-off-by: Wen Gong <wgong@codeaurora.org>
> ---
>  drivers/net/wireless/ath/ath10k/hw.h   | 1 +
>  drivers/net/wireless/ath/ath10k/sdio.c | 8 ++++++--
>  2 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
> index 7131499..60521ed 100644
> --- a/drivers/net/wireless/ath/ath10k/hw.h
> +++ b/drivers/net/wireless/ath/ath10k/hw.h
> @@ -1095,6 +1095,7 @@ struct ath10k_hw_ops {
>  #define MBOX_CPU_INT_STATUS_ENABLE_ADDRESS     0x00000819
>  #define MBOX_CPU_INT_STATUS_ENABLE_BIT_LSB     0
>  #define MBOX_CPU_INT_STATUS_ENABLE_BIT_MASK    0x000000ff
> +#define MBOX_CPU_STATUS_ENABLE_ASSERT_MASK 0x00000001
>  #define MBOX_ERROR_STATUS_ENABLE_ADDRESS       0x0000081a
>  #define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB  1
>  #define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002
> diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
> index fae56c6..78a2f3b 100644
> --- a/drivers/net/wireless/ath/ath10k/sdio.c
> +++ b/drivers/net/wireless/ath/ath10k/sdio.c
> @@ -850,6 +850,8 @@ static int ath10k_sdio_mbox_proc_cpu_intr(struct ath10k *ar)
>
>  out:
>         mutex_unlock(&irq_data->mtx);
> +       ath10k_err(ar, "firmware crashed!\n");
> +       queue_work(ar->workqueue, &ar->restart_work);

Err, so you consider _any_ CPU interrupt to be caused by the FW
crashing? Is that correct? If so, please at least add a comment.

Otherwise, maybe you should run this only if
MBOX_CPU_STATUS_ENABLE_ASSERT_MASK is set in cpu_int_status?

>         return ret;
>  }
>
> @@ -1495,8 +1497,10 @@ static int ath10k_sdio_hif_enable_intrs(struct ath10k *ar)
>         regs->int_status_en |=
>                 FIELD_PREP(MBOX_INT_STATUS_ENABLE_MBOX_DATA_MASK, 1);
>
> -       /* Set up the CPU Interrupt status Register */
> -       regs->cpu_int_status_en = 0;
> +       /* Set up the CPU Interrupt Status Register, enable CPU sourced interrupt #0
> +        * #0 is used for report assertion from target
> +        */
> +       regs->cpu_int_status_en = FIELD_PREP(MBOX_CPU_STATUS_ENABLE_ASSERT_MASK, 1);
>
>         /* Set up the Error Interrupt status Register */
>         regs->err_int_status_en =
> --
> 1.9.1
>

^ permalink raw reply

* Re: [PATCH v8 12/15] kvm/vmx: Emulate MSR TEST_CTL
From: Xiaoyao Li @ 2019-04-29  5:21 UTC (permalink / raw)
  To: Thomas Gleixner, Xiaoyao Li, Paolo Bonzini
  Cc: Fenghua Yu, Ingo Molnar, Borislav Petkov, H Peter Anvin,
	Dave Hansen, Ashok Raj, Peter Zijlstra, Ravi V Shankar,
	Christopherson Sean J, Kalle Valo, Michael Chan, linux-kernel,
	x86, kvm, netdev, linux-wireless
In-Reply-To: <alpine.DEB.2.21.1904280903520.1757@nanos.tec.linutronix.de>

Hi, Thomas,

Base on your comments, I plan to make the design as following:

1) When host enables this feature, there is no switch between host and 
guest that guest running with it enabled by force. Since #AC in 
exception bitmap is set in current kvm, every #AC in guest will be 
trapped. And in handle_exception() handler in kvm, if #AC is caused by 
alignment check, kvm injects #AC back to guest; if #AC is caused by 
split lock, kvm sends a SIGBUS to userspace.

2) When host disables this feature, there needs atomic switch between 
host and guest if different. And in handle_exception() handler in kvm, 
we can just inject #AC back to guest, and let guest to handle it.

Besides, I think there might be an optimization for case #1.
When host has it enabled and guest also has it enabled, I think it's OK 
to inject #AC back to guest, not directly kill the guest.
Because guest kernel has it enabled means it knows what this feature is 
and it also want to get aware of and fault every split lock.
At this point, if guest has it enabled, we can leave it to guest. Only 
when guest's configuration is having it disabled, can it be regards as 
potentially harmful that we kill the guest once there is a #AC due to 
split lock.

How do you think about the design and this optimization?

Hi, Paolo,

What's your opinion about this design of split lock in KVM?

Thanks.

On 4/28/2019 3:09 PM, Thomas Gleixner wrote:
> On Sat, 27 Apr 2019, Xiaoyao Li wrote:
>> On Thu, 2019-04-25 at 09:42 +0200, Thomas Gleixner wrote:
>>> But the way more interesting question is why are you exposing the MSR and
>>> the bit to the guest at all if the host has split lock detection enabled?
>>>
>>> That does not make any sense as you basically allow the guest to switch it
>>> off and then launch a slowdown attack. If the host has it enabled, then a
>>> guest has to be treated like any other process and the #AC trap has to be
>>> caught by the hypervisor which then kills the guest.
>>>
>>> Only if the host has split lock detection disabled, then you can expose it
>>> and allow the guest to turn it on and handle it on its own.
>>
>> Indeed, if we use split lock detection for protection purpose, when host
>> has it enabled we should directly pass it to guest and forbid guest from
>> disabling it.  And only when host disables split lock detection, we can
>> expose it and allow the guest to turn it on.
> ?
>> If it is used for protection purpose, then it should follow what you said and
>> this feature needs to be disabled by default. Because there are split lock
>> issues in old/current kernels and BIOS. That will cause the existing guest
>> booting failure and killed due to those split lock.
> 
> Rightfully so.
> 
>> If it is only used for debug purpose, I think it might be OK to enable this
>> feature by default and make it indepedent between host and guest?
> 
> No. It does not make sense.
> 
>> So I think how to handle this feature between host and guest depends on how we
>> use it? Once you give me a decision, I will follow it in next version.
> 
> As I said: The host kernel makes the decision.
> 
> If the host kernel has it enabled then the guest is not allowed to change
> it. If the guest triggers an #AC it will be killed.
> 
> If the host kernel has it disabled then the guest can enable it for it's
> own purposes.
> 
> Thanks,
> 
> 	tglx
> 

^ permalink raw reply

* Re: [PATCH v8 12/15] kvm/vmx: Emulate MSR TEST_CTL
From: Thomas Gleixner @ 2019-04-29  7:31 UTC (permalink / raw)
  To: Xiaoyao Li
  Cc: Fenghua Yu, Ingo Molnar, Borislav Petkov, H Peter Anvin,
	Paolo Bonzini, Dave Hansen, Ashok Raj, Peter Zijlstra,
	Ravi V Shankar, Christopherson Sean J, Kalle Valo, Michael Chan,
	linux-kernel, x86, kvm, netdev, linux-wireless
In-Reply-To: <87ef9a01-fc99-20be-ec20-2c65e6a012a1@linux.intel.com>

On Sun, 28 Apr 2019, Xiaoyao Li wrote:
> On 4/28/2019 3:09 PM, Thomas Gleixner wrote:
> > On Sat, 27 Apr 2019, Xiaoyao Li wrote:
> > > Indeed, if we use split lock detection for protection purpose, when host
> > > has it enabled we should directly pass it to guest and forbid guest from
> > > disabling it.  And only when host disables split lock detection, we can
> > > expose it and allow the guest to turn it on.
> > ?
> > > If it is used for protection purpose, then it should follow what you said
> > > and
> > > this feature needs to be disabled by default. Because there are split lock
> > > issues in old/current kernels and BIOS. That will cause the existing guest
> > > booting failure and killed due to those split lock.
> > 
> > Rightfully so.
> 
> So, the patch 13 "Enable split lock detection by default" needs to be removed?

Why? No. We enable it by default and everything which violates the rules
gets what it deserves. If there is an issue, boot with ac_splitlock_off and
be done with it.

Thanks,

	tglx

^ permalink raw reply

* [PATCH v2] ath10k: add support for simulate crash on SDIO chip
From: Wen Gong @ 2019-04-29  7:54 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless

The command to simulate firmware crash:
echo soft > /sys/kernel/debug/ieee80211/phy0/ath10k/simulate_fw_crash

It will send WMI_FORCE_FW_HANG_ASSERT to firmware, then it will trigger
CPU interrupt status register for SDIO chip, ath10k driver need to
configure it while enable SDIO interrupt, otherwise ath10k driver will
not get the assert error info.

After this change, it will success for simulate firmware crash.

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00007-QCARMSWP-1.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
v2: add MBOX_CPU_STATUS_ENABLE_ASSERT_MASK for fw assert check
 drivers/net/wireless/ath/ath10k/hw.h   |  1 +
 drivers/net/wireless/ath/ath10k/sdio.c | 10 ++++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 7131499..60521ed 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -1095,6 +1095,7 @@ struct ath10k_hw_ops {
 #define MBOX_CPU_INT_STATUS_ENABLE_ADDRESS	0x00000819
 #define MBOX_CPU_INT_STATUS_ENABLE_BIT_LSB	0
 #define MBOX_CPU_INT_STATUS_ENABLE_BIT_MASK	0x000000ff
+#define MBOX_CPU_STATUS_ENABLE_ASSERT_MASK 0x00000001
 #define MBOX_ERROR_STATUS_ENABLE_ADDRESS	0x0000081a
 #define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB  1
 #define MBOX_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index fae56c6..1a3a7bf 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -850,6 +850,10 @@ static int ath10k_sdio_mbox_proc_cpu_intr(struct ath10k *ar)
 
 out:
 	mutex_unlock(&irq_data->mtx);
+	if (cpu_int_status & MBOX_CPU_STATUS_ENABLE_ASSERT_MASK) {
+		ath10k_err(ar, "firmware crashed!\n");
+		queue_work(ar->workqueue, &ar->restart_work);
+	}
 	return ret;
 }
 
@@ -1495,8 +1499,10 @@ static int ath10k_sdio_hif_enable_intrs(struct ath10k *ar)
 	regs->int_status_en |=
 		FIELD_PREP(MBOX_INT_STATUS_ENABLE_MBOX_DATA_MASK, 1);
 
-	/* Set up the CPU Interrupt status Register */
-	regs->cpu_int_status_en = 0;
+	/* Set up the CPU Interrupt Status Register, enable CPU sourced interrupt #0
+	 * #0 is used for report assertion from target
+	 */
+	regs->cpu_int_status_en = FIELD_PREP(MBOX_CPU_STATUS_ENABLE_ASSERT_MASK, 1);
 
 	/* Set up the Error Interrupt status Register */
 	regs->err_int_status_en =
-- 
1.9.1


^ permalink raw reply related

* [PATCH v2 0/5] mt76: move common beacon code in mt76 module
From: Lorenzo Bianconi @ 2019-04-29  8:12 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sgruszka

Move beacon data structures shared between mt76x02 and mt7603 drivers
in mt76_dev.
Enable/disable pre_tbtt_tasklet tasklet in mt7603_set_channel

Changes since v1:
- added new patch: 'mt76: do not enable/disable pre_tbtt_tasklet in
  scan_start/scan_complete'

Lorenzo Bianconi (5):
  mt76: do not enable/disable pre_tbtt_tasklet in
    scan_start/scan_complete
  mt76: move beacon_int in mt76_dev
  mt76: move beacon_mask in mt76_dev
  mt76: move pre_tbtt_tasklet in mt76_dev
  mt76: mt7603: enable/disable pre_tbtt_tasklet in mt7603_set_channel

 drivers/net/wireless/mediatek/mt76/mt76.h     |  4 ++++
 .../wireless/mediatek/mt76/mt7603/beacon.c    | 19 ++++++++++---------
 .../net/wireless/mediatek/mt76/mt7603/core.c  |  2 +-
 .../net/wireless/mediatek/mt76/mt7603/init.c  |  4 ++--
 .../net/wireless/mediatek/mt76/mt7603/mac.c   |  6 +++---
 .../net/wireless/mediatek/mt76/mt7603/main.c  | 11 +++++++----
 .../wireless/mediatek/mt76/mt7603/mt7603.h    |  5 -----
 .../net/wireless/mediatek/mt76/mt76x0/pci.c   |  2 +-
 drivers/net/wireless/mediatek/mt76/mt76x02.h  |  3 ---
 .../wireless/mediatek/mt76/mt76x02_beacon.c   | 18 +++++++++---------
 .../net/wireless/mediatek/mt76/mt76x02_mac.c  |  2 +-
 .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 18 +++++++++---------
 .../wireless/mediatek/mt76/mt76x02_usb_core.c | 11 ++++++-----
 .../net/wireless/mediatek/mt76/mt76x02_util.c |  7 +------
 .../wireless/mediatek/mt76/mt76x2/pci_init.c  |  2 +-
 .../wireless/mediatek/mt76/mt76x2/pci_main.c  |  4 ++--
 16 files changed, 57 insertions(+), 61 deletions(-)

-- 
2.20.1


^ permalink raw reply

* [PATCH v2 1/5] mt76: do not enable/disable pre_tbtt_tasklet in scan_start/scan_complete
From: Lorenzo Bianconi @ 2019-04-29  8:12 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sgruszka
In-Reply-To: <cover.1556525110.git.lorenzo@kernel.org>

Do not enable/disable pre_tbtt_tasklet tasklet in
mt76x02_sw_scan/mt76x02_sw_scan_complete since it is already done
setting the operating channel

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index ad8a53def7f7..5d656fea1dde 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -593,8 +593,6 @@ void mt76x02_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 {
 	struct mt76x02_dev *dev = hw->priv;
 
-	if (mt76_is_mmio(dev))
-		tasklet_disable(&dev->pre_tbtt_tasklet);
 	set_bit(MT76_SCANNING, &dev->mt76.state);
 }
 EXPORT_SYMBOL_GPL(mt76x02_sw_scan);
@@ -605,9 +603,6 @@ void mt76x02_sw_scan_complete(struct ieee80211_hw *hw,
 	struct mt76x02_dev *dev = hw->priv;
 
 	clear_bit(MT76_SCANNING, &dev->mt76.state);
-	if (mt76_is_mmio(dev))
-		tasklet_enable(&dev->pre_tbtt_tasklet);
-
 	if (dev->cal.gain_init_done) {
 		/* Restore AGC gain and resume calibration after scanning. */
 		dev->cal.low_gain = -1;
-- 
2.20.1


^ permalink raw reply related

* [PATCH v2 2/5] mt76: move beacon_int in mt76_dev
From: Lorenzo Bianconi @ 2019-04-29  8:12 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sgruszka
In-Reply-To: <cover.1556525110.git.lorenzo@kernel.org>

Move beacon_int in mt76_dev data structure since it is used by
all drivers

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt76.h             | 2 ++
 drivers/net/wireless/mediatek/mt76/mt7603/beacon.c    | 2 +-
 drivers/net/wireless/mediatek/mt76/mt7603/mac.c       | 2 +-
 drivers/net/wireless/mediatek/mt76/mt7603/main.c      | 2 +-
 drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h    | 1 -
 drivers/net/wireless/mediatek/mt76/mt76x02.h          | 1 -
 drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c   | 2 +-
 drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 4 ++--
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c     | 2 +-
 9 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 75a0d150a224..be0ca4af7254 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -469,6 +469,8 @@ struct mt76_dev {
 	u8 antenna_mask;
 	u16 chainmask;
 
+	int beacon_int;
+
 	struct mt76_sband sband_2g;
 	struct mt76_sband sband_5g;
 	struct debugfs_blob_wrapper eeprom;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
index 1b6c3f32bc1b..64e15d566283 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
@@ -156,7 +156,7 @@ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)
 		return;
 	}
 
-	dev->beacon_int = intval;
+	dev->mt76.beacon_int = intval;
 	mt76_wr(dev, MT_TBTT,
 		FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
index 2fd63597d305..a5a881738d83 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -1268,7 +1268,7 @@ static void mt7603_dma_sched_reset(struct mt7603_dev *dev)
 
 static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
 {
-	int beacon_int = dev->beacon_int;
+	int beacon_int = dev->mt76.beacon_int;
 	u32 mask = dev->mt76.mmio.irqmask;
 	int i;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index 18a33d921601..9be9ae02103e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -544,7 +544,7 @@ mt7603_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	struct mt7603_dev *dev = hw->priv;
 
 	clear_bit(MT76_SCANNING, &dev->mt76.state);
-	mt7603_beacon_set_timer(dev, -1, dev->beacon_int);
+	mt7603_beacon_set_timer(dev, -1, dev->mt76.beacon_int);
 }
 
 static void
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
index 3816f1e8ae70..a2cda08ca70b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
@@ -109,7 +109,6 @@ struct mt7603_dev {
 
 	ktime_t survey_time;
 	ktime_t ed_time;
-	int beacon_int;
 
 	struct mt76_queue q_rx;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index dfd3a4f1a624..dde1f64390ce 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -106,7 +106,6 @@ struct mt76x02_dev {
 	u8 beacon_data_mask;
 
 	u8 tbtt_count;
-	u16 beacon_int;
 
 	u32 tx_hang_reset;
 	u8 tx_hang_check;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
index 0c232d02f189..985a9b5d0e45 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -167,7 +167,7 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
 void
 mt76x02_resync_beacon_timer(struct mt76x02_dev *dev)
 {
-	u32 timer_val = dev->beacon_int << 4;
+	u32 timer_val = dev->mt76.beacon_int << 4;
 
 	dev->tbtt_count++;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 818b96064dec..81cebd92a4e8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -147,7 +147,7 @@ static void mt76x02u_restart_pre_tbtt_timer(struct mt76x02_dev *dev)
 	dev_dbg(dev->mt76.dev, "TSF: %llu us TBTT %u us\n", tsf, tbtt);
 
 	/* Convert beacon interval in TU (1024 usec) to nsec */
-	time = ((1000000000ull * dev->beacon_int) >> 10);
+	time = ((1000000000ull * dev->mt76.beacon_int) >> 10);
 
 	/* Adjust time to trigger hrtimer 8ms before TBTT */
 	if (tbtt < PRE_TBTT_USEC)
@@ -217,7 +217,7 @@ static void mt76x02u_beacon_enable(struct mt76x02_dev *dev, bool en)
 {
 	int i;
 
-	if (WARN_ON_ONCE(!dev->beacon_int))
+	if (WARN_ON_ONCE(!dev->mt76.beacon_int))
 		return;
 
 	if (en) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 5d656fea1dde..ad5323447ed4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -645,7 +645,7 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
 		mt76_rmw_field(dev, MT_BEACON_TIME_CFG,
 			       MT_BEACON_TIME_CFG_INTVAL,
 			       info->beacon_int << 4);
-		dev->beacon_int = info->beacon_int;
+		dev->mt76.beacon_int = info->beacon_int;
 	}
 
 	if (changed & BSS_CHANGED_BEACON_ENABLED)
-- 
2.20.1


^ permalink raw reply related

* [PATCH v2 3/5] mt76: move beacon_mask in mt76_dev
From: Lorenzo Bianconi @ 2019-04-29  8:13 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sgruszka
In-Reply-To: <cover.1556525110.git.lorenzo@kernel.org>

Move beacon_mask in mt76_dev data structure since it is used by
all drivers

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt76.h       |  1 +
 .../net/wireless/mediatek/mt76/mt7603/beacon.c  | 17 +++++++++--------
 .../net/wireless/mediatek/mt76/mt7603/mt7603.h  |  2 --
 drivers/net/wireless/mediatek/mt76/mt76x02.h    |  1 -
 .../net/wireless/mediatek/mt76/mt76x02_beacon.c | 16 ++++++++--------
 .../net/wireless/mediatek/mt76/mt76x02_mac.c    |  2 +-
 .../net/wireless/mediatek/mt76/mt76x02_mmio.c   |  6 +++---
 .../wireless/mediatek/mt76/mt76x02_usb_core.c   |  7 ++++---
 8 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index be0ca4af7254..fb0ba1500d89 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -470,6 +470,7 @@ struct mt76_dev {
 	u16 chainmask;
 
 	int beacon_int;
+	u8 beacon_mask;
 
 	struct mt76_sband sband_2g;
 	struct mt76_sband sband_5g;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
index 64e15d566283..f3e7406e731f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
@@ -16,7 +16,7 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
 	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
 	struct sk_buff *skb = NULL;
 
-	if (!(dev->beacon_mask & BIT(mvif->idx)))
+	if (!(dev->mt76.beacon_mask & BIT(mvif->idx)))
 		return;
 
 	skb = ieee80211_beacon_get(mt76_hw(dev), vif);
@@ -48,7 +48,7 @@ mt7603_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)
 	struct ieee80211_tx_info *info;
 	struct sk_buff *skb;
 
-	if (!(dev->beacon_mask & BIT(mvif->idx)))
+	if (!(dev->mt76.beacon_mask & BIT(mvif->idx)))
 		return;
 
 	skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif);
@@ -134,7 +134,7 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg)
 out:
 	mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false);
 	if (dev->mt76.q_tx[MT_TXQ_BEACON].q->queued >
-	    hweight8(dev->beacon_mask))
+	    hweight8(dev->mt76.beacon_mask))
 		dev->beacon_check++;
 }
 
@@ -144,12 +144,12 @@ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)
 
 	if (idx >= 0) {
 		if (intval)
-			dev->beacon_mask |= BIT(idx);
+			dev->mt76.beacon_mask |= BIT(idx);
 		else
-			dev->beacon_mask &= ~BIT(idx);
+			dev->mt76.beacon_mask &= ~BIT(idx);
 	}
 
-	if (!dev->beacon_mask || (!intval && idx < 0)) {
+	if (!dev->mt76.beacon_mask || (!intval && idx < 0)) {
 		mt7603_irq_disable(dev, MT_INT_MAC_IRQ3);
 		mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK);
 		mt76_wr(dev, MT_HW_INT_MASK(3), 0);
@@ -174,10 +174,11 @@ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)
 
 	mt76_set(dev, MT_WF_ARB_BCN_START,
 		 MT_WF_ARB_BCN_START_BSSn(0) |
-		 ((dev->beacon_mask >> 1) * MT_WF_ARB_BCN_START_BSS0n(1)));
+		 ((dev->mt76.beacon_mask >> 1) *
+		  MT_WF_ARB_BCN_START_BSS0n(1)));
 	mt7603_irq_enable(dev, MT_INT_MAC_IRQ3);
 
-	if (dev->beacon_mask & ~BIT(0))
+	if (dev->mt76.beacon_mask & ~BIT(0))
 		mt76_set(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN);
 	else
 		mt76_clear(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
index a2cda08ca70b..8f5ae1644a92 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
@@ -125,8 +125,6 @@ struct mt7603_dev {
 
 	s8 sensitivity;
 
-	u8 beacon_mask;
-
 	u8 beacon_check;
 	u8 tx_hang_check;
 	u8 tx_dma_check;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index dde1f64390ce..f754790dada4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -102,7 +102,6 @@ struct mt76x02_dev {
 	u32 aggr_stats[32];
 
 	struct sk_buff *beacons[8];
-	u8 beacon_mask;
 	u8 beacon_data_mask;
 
 	u8 tbtt_count;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
index 985a9b5d0e45..e196b9c0a686 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -119,23 +119,23 @@ static void
 __mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
 				bool val, struct sk_buff *skb)
 {
-	u8 old_mask = dev->beacon_mask;
+	u8 old_mask = dev->mt76.beacon_mask;
 	bool en;
 	u32 reg;
 
 	if (val) {
-		dev->beacon_mask |= BIT(vif_idx);
+		dev->mt76.beacon_mask |= BIT(vif_idx);
 		if (skb)
 			mt76x02_mac_set_beacon(dev, vif_idx, skb);
 	} else {
-		dev->beacon_mask &= ~BIT(vif_idx);
+		dev->mt76.beacon_mask &= ~BIT(vif_idx);
 		mt76x02_mac_set_beacon(dev, vif_idx, NULL);
 	}
 
-	if (!!old_mask == !!dev->beacon_mask)
+	if (!!old_mask == !!dev->mt76.beacon_mask)
 		return;
 
-	en = dev->beacon_mask;
+	en = dev->mt76.beacon_mask;
 
 	reg = MT_BEACON_TIME_CFG_BEACON_TX |
 	      MT_BEACON_TIME_CFG_TBTT_EN |
@@ -156,7 +156,7 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
 	if (mt76_is_usb(dev))
 		skb = ieee80211_beacon_get(mt76_hw(dev), vif);
 
-	if (!dev->beacon_mask)
+	if (!dev->mt76.beacon_mask)
 		dev->tbtt_count = 0;
 
 	__mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb);
@@ -203,7 +203,7 @@ mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
 	struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
 	struct sk_buff *skb = NULL;
 
-	if (!(dev->beacon_mask & BIT(mvif->idx)))
+	if (!(dev->mt76.beacon_mask & BIT(mvif->idx)))
 		return;
 
 	skb = ieee80211_beacon_get(mt76_hw(dev), vif);
@@ -223,7 +223,7 @@ mt76x02_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)
 	struct ieee80211_tx_info *info;
 	struct sk_buff *skb;
 
-	if (!(dev->beacon_mask & BIT(mvif->idx)))
+	if (!(dev->mt76.beacon_mask & BIT(mvif->idx)))
 		return;
 
 	skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index 28851060aa0f..8e0294bfce9c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -1044,7 +1044,7 @@ void mt76x02_mac_work(struct work_struct *work)
 		dev->aggr_stats[idx++] += val >> 16;
 	}
 
-	if (!dev->beacon_mask)
+	if (!dev->mt76.beacon_mask)
 		mt76x02_check_mac_err(dev);
 
 	if (dev->ed_monitor)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index 644706ab2893..31e0d4b03f6b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -415,7 +415,7 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev)
 	}
 
 	dev->vif_mask = 0;
-	dev->beacon_mask = 0;
+	dev->mt76.beacon_mask = 0;
 }
 
 static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
@@ -438,7 +438,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
 	if (restart)
 		mt76x02_reset_state(dev);
 
-	if (dev->beacon_mask)
+	if (dev->mt76.beacon_mask)
 		mt76_clear(dev, MT_BEACON_TIME_CFG,
 			   MT_BEACON_TIME_CFG_BEACON_TX |
 			   MT_BEACON_TIME_CFG_TBTT_EN);
@@ -470,7 +470,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
 	if (dev->ed_monitor)
 		mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
 
-	if (dev->beacon_mask && !restart)
+	if (dev->mt76.beacon_mask && !restart)
 		mt76_set(dev, MT_BEACON_TIME_CFG,
 			 MT_BEACON_TIME_CFG_BEACON_TX |
 			 MT_BEACON_TIME_CFG_TBTT_EN);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 81cebd92a4e8..5b6ac1b364e1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -175,7 +175,7 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
 	struct sk_buff *skb;
 	int i, nbeacons;
 
-	if (!dev->beacon_mask)
+	if (!dev->mt76.beacon_mask)
 		return;
 
 	mt76x02_resync_beacon_timer(dev);
@@ -184,7 +184,7 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
 		IEEE80211_IFACE_ITER_RESUME_ALL,
 		mt76x02_update_beacon_iter, dev);
 
-	nbeacons = hweight8(dev->beacon_mask);
+	nbeacons = hweight8(dev->mt76.beacon_mask);
 	mt76x02_enqueue_buffered_bc(dev, &data, N_BCN_SLOTS - nbeacons);
 
 	for (i = nbeacons; i < N_BCN_SLOTS; i++) {
@@ -207,7 +207,8 @@ static enum hrtimer_restart mt76x02u_pre_tbtt_interrupt(struct hrtimer *timer)
 
 static void mt76x02u_pre_tbtt_enable(struct mt76x02_dev *dev, bool en)
 {
-	if (en && dev->beacon_mask && !hrtimer_active(&dev->pre_tbtt_timer))
+	if (en && dev->mt76.beacon_mask &&
+	    !hrtimer_active(&dev->pre_tbtt_timer))
 		mt76x02u_start_pre_tbtt_timer(dev);
 	if (!en)
 		mt76x02u_stop_pre_tbtt_timer(dev);
-- 
2.20.1


^ permalink raw reply related

* [PATCH v2 4/5] mt76: move pre_tbtt_tasklet in mt76_dev
From: Lorenzo Bianconi @ 2019-04-29  8:13 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sgruszka
In-Reply-To: <cover.1556525110.git.lorenzo@kernel.org>

Move pre_tbtt_tasklet tasklet in mt76_dev data structure since
it is used by all drivers

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt76.h            |  1 +
 drivers/net/wireless/mediatek/mt76/mt7603/core.c     |  2 +-
 drivers/net/wireless/mediatek/mt76/mt7603/init.c     |  4 ++--
 drivers/net/wireless/mediatek/mt76/mt7603/mac.c      |  4 ++--
 drivers/net/wireless/mediatek/mt76/mt7603/main.c     |  4 ++--
 drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h   |  2 --
 drivers/net/wireless/mediatek/mt76/mt76x0/pci.c      |  2 +-
 drivers/net/wireless/mediatek/mt76/mt76x02.h         |  1 -
 drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c    | 12 ++++++------
 drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c |  2 +-
 drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c |  4 ++--
 11 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index fb0ba1500d89..859c9f019323 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -469,6 +469,7 @@ struct mt76_dev {
 	u8 antenna_mask;
 	u16 chainmask;
 
+	struct tasklet_struct pre_tbtt_tasklet;
 	int beacon_int;
 	u8 beacon_mask;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c
index 0d06ff67ce44..37e5644b45ef 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c
@@ -27,7 +27,7 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance)
 
 		mt76_wr(dev, MT_HW_INT_STATUS(3), hwintr);
 		if (hwintr & MT_HW_INT3_PRE_TBTT0)
-			tasklet_schedule(&dev->pre_tbtt_tasklet);
+			tasklet_schedule(&dev->mt76.pre_tbtt_tasklet);
 
 		if ((hwintr & MT_HW_INT3_TBTT0) && dev->mt76.csa_complete)
 			mt76_csa_finish(&dev->mt76);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
index d394839f1bd8..c3c295919020 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
@@ -514,7 +514,7 @@ int mt7603_register_device(struct mt7603_dev *dev)
 	spin_lock_init(&dev->ps_lock);
 
 	INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7603_mac_work);
-	tasklet_init(&dev->pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet,
+	tasklet_init(&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet,
 		     (unsigned long)dev);
 
 	/* Check for 7688, which only has 1SS */
@@ -573,7 +573,7 @@ int mt7603_register_device(struct mt7603_dev *dev)
 
 void mt7603_unregister_device(struct mt7603_dev *dev)
 {
-	tasklet_disable(&dev->pre_tbtt_tasklet);
+	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
 	mt76_unregister_device(&dev->mt76);
 	mt7603_mcu_exit(dev);
 	mt7603_dma_cleanup(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
index a5a881738d83..ad517e1af75b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -1279,7 +1279,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
 	mt76_txq_schedule_all(&dev->mt76);
 
 	tasklet_disable(&dev->mt76.tx_tasklet);
-	tasklet_disable(&dev->pre_tbtt_tasklet);
+	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
 	napi_disable(&dev->mt76.napi[0]);
 	napi_disable(&dev->mt76.napi[1]);
 
@@ -1328,7 +1328,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
 	tasklet_enable(&dev->mt76.tx_tasklet);
 	tasklet_schedule(&dev->mt76.tx_tasklet);
 
-	tasklet_enable(&dev->pre_tbtt_tasklet);
+	tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
 	mt7603_beacon_set_timer(dev, -1, beacon_int);
 
 	napi_enable(&dev->mt76.napi[0]);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index 9be9ae02103e..be5d43050100 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -294,9 +294,9 @@ mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_INT)) {
 		int beacon_int = !!info->enable_beacon * info->beacon_int;
 
-		tasklet_disable(&dev->pre_tbtt_tasklet);
+		tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
 		mt7603_beacon_set_timer(dev, mvif->idx, beacon_int);
-		tasklet_enable(&dev->pre_tbtt_tasklet);
+		tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
 	}
 
 	mutex_unlock(&dev->mt76.mutex);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
index 8f5ae1644a92..56ef73e41a5a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
@@ -140,8 +140,6 @@ struct mt7603_dev {
 	u32 reset_test;
 
 	unsigned int reset_cause[__RESET_CAUSE_MAX];
-
-	struct tasklet_struct pre_tbtt_tasklet;
 };
 
 extern const struct mt76_driver_ops mt7603_drv_ops;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index f106dbfa665f..6a8fe82ab9ad 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -219,7 +219,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 static void mt76x0e_cleanup(struct mt76x02_dev *dev)
 {
 	clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
-	tasklet_disable(&dev->pre_tbtt_tasklet);
+	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
 	mt76x0_chip_onoff(dev, false, false);
 	mt76x0e_stop_hw(dev);
 	mt76x02_dma_cleanup(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index f754790dada4..07579a951dd9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -90,7 +90,6 @@ struct mt76x02_dev {
 	struct sk_buff *rx_head;
 
 	struct tasklet_struct tx_tasklet;
-	struct tasklet_struct pre_tbtt_tasklet;
 	struct delayed_work cal_work;
 	struct delayed_work wdt_work;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index 31e0d4b03f6b..c4ead6a76766 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -68,9 +68,9 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
 static void mt76x02e_pre_tbtt_enable(struct mt76x02_dev *dev, bool en)
 {
 	if (en)
-		tasklet_enable(&dev->pre_tbtt_tasklet);
+		tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
 	else
-		tasklet_disable(&dev->pre_tbtt_tasklet);
+		tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
 }
 
 static void mt76x02e_beacon_enable(struct mt76x02_dev *dev, bool en)
@@ -184,7 +184,7 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
 
 	tasklet_init(&dev->mt76.tx_tasklet, mt76x02_tx_tasklet,
 		     (unsigned long) dev);
-	tasklet_init(&dev->pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet,
+	tasklet_init(&dev->mt76.pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet,
 		     (unsigned long)dev);
 
 	kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size);
@@ -267,7 +267,7 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance)
 	}
 
 	if (intr & MT_INT_PRE_TBTT)
-		tasklet_schedule(&dev->pre_tbtt_tasklet);
+		tasklet_schedule(&dev->mt76.pre_tbtt_tasklet);
 
 	/* send buffered multicast frames now */
 	if (intr & MT_INT_TBTT) {
@@ -427,7 +427,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
 	ieee80211_stop_queues(dev->mt76.hw);
 	set_bit(MT76_RESET, &dev->mt76.state);
 
-	tasklet_disable(&dev->pre_tbtt_tasklet);
+	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
 	tasklet_disable(&dev->mt76.tx_tasklet);
 
 	for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++)
@@ -484,7 +484,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
 	tasklet_enable(&dev->mt76.tx_tasklet);
 	tasklet_schedule(&dev->mt76.tx_tasklet);
 
-	tasklet_enable(&dev->pre_tbtt_tasklet);
+	tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
 
 	for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) {
 		napi_enable(&dev->mt76.napi[i]);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
index 90c1a0489294..71aea2832644 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
@@ -300,7 +300,7 @@ void mt76x2_stop_hardware(struct mt76x02_dev *dev)
 void mt76x2_cleanup(struct mt76x02_dev *dev)
 {
 	tasklet_disable(&dev->dfs_pd.dfs_tasklet);
-	tasklet_disable(&dev->pre_tbtt_tasklet);
+	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
 	mt76x2_stop_hardware(dev);
 	mt76x02_dma_cleanup(dev);
 	mt76x02_mcu_cleanup(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
index 77f63cb14f35..93ad12391e33 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
@@ -66,7 +66,7 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
 
 	mt76_set_channel(&dev->mt76);
 
-	tasklet_disable(&dev->pre_tbtt_tasklet);
+	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
 	tasklet_disable(&dev->dfs_pd.dfs_tasklet);
 
 	mt76x2_mac_stop(dev, true);
@@ -80,7 +80,7 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
 
 	mt76x2_mac_resume(dev);
 	tasklet_enable(&dev->dfs_pd.dfs_tasklet);
-	tasklet_enable(&dev->pre_tbtt_tasklet);
+	tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
 
 	clear_bit(MT76_RESET, &dev->mt76.state);
 
-- 
2.20.1


^ permalink raw reply related

* [PATCH v2 5/5] mt76: mt7603: enable/disable pre_tbtt_tasklet in mt7603_set_channel
From: Lorenzo Bianconi @ 2019-04-29  8:13 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sgruszka
In-Reply-To: <cover.1556525110.git.lorenzo@kernel.org>

Disable pre_tbtt_tasklet tasklet before setting the operating channel.
Enable/disable beacon_timer in mt7603_set_channel

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7603/main.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index be5d43050100..d879efc5a216 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -133,10 +133,12 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
 	bool failed = false;
 
 	cancel_delayed_work_sync(&dev->mt76.mac_work);
+	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
 
 	mutex_lock(&dev->mt76.mutex);
 	set_bit(MT76_RESET, &dev->mt76.state);
 
+	mt7603_beacon_set_timer(dev, -1, 0);
 	mt76_set_channel(&dev->mt76);
 	mt7603_mac_stop(dev);
 
@@ -186,8 +188,11 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
 	mt7603_init_edcca(dev);
 
 out:
+	mt7603_beacon_set_timer(dev, -1, dev->mt76.beacon_int);
 	mutex_unlock(&dev->mt76.mutex);
 
+	tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
+
 	if (failed)
 		mt7603_mac_work(&dev->mt76.mac_work.work);
 
@@ -535,7 +540,6 @@ mt7603_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	struct mt7603_dev *dev = hw->priv;
 
 	set_bit(MT76_SCANNING, &dev->mt76.state);
-	mt7603_beacon_set_timer(dev, -1, 0);
 }
 
 static void
@@ -544,7 +548,6 @@ mt7603_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	struct mt7603_dev *dev = hw->priv;
 
 	clear_bit(MT76_SCANNING, &dev->mt76.state);
-	mt7603_beacon_set_timer(dev, -1, dev->mt76.beacon_int);
 }
 
 static void
-- 
2.20.1


^ permalink raw reply related

* Re: [PATCH] ath10k: Drop WARN_ON()s that always trigger during system resume
From: Rafael J. Wysocki @ 2019-04-29  8:48 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Brian Norris, Rafael J. Wysocki, Claire Chang, Sriram R, Linux PM,
	Pradeep Kumar Chitrapu, open list:NETWORKING DRIVERS (WIRELESS),
	ath10k, Srinivas Pandruvada, Todd Brandt
In-Reply-To: <87o94tutdz.fsf@kamboji.qca.qualcomm.com>

On Fri, Apr 26, 2019 at 9:18 AM Kalle Valo <kvalo@codeaurora.org> wrote:
>
> Brian Norris <briannorris@chromium.org> writes:
>
> > + Sriram, Pradeep, Claire
> >
> > On Sun, Mar 03, 2019 at 06:24:33PM +0100, Rafael J. Wysocki wrote:
> >
> > Ooh, exactly 1 month ago!
> >
> >> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >>
> >> ath10k_mac_vif_chan() always returns an error for the given vif
> >> during system-wide resume which reliably triggers two WARN_ON()s
> >> in ath10k_bss_info_changed() and they are not particularly
> >> useful in that code path, so drop them.
> >>
> >
> > Particularly, when WOWLAN isn't enabled, we get called during resume via
> > ieee80211_reconfig(), where we're not associated and don't have any
> > channel contexts. AFAICT, we shouldn't need to communicate anything in
> > particular to the firmware here, and so failing the 'if' is definitely
> > not worth WARN-ing about.
> >
> > I'd love to see this get applied with:
> >
> > Fixes: cd93b83ad927 ("ath10k: support for multicast rate control")
> > Fixes: f279294e9ee2 ("ath10k: add support for configuring management packet rate")
> >
> > and sent to stable. This has been bugging people since 4.19. Spurious
> > WARN_ON()s can trigger reports to various crash trackers, and on some
> > systems appear as user-visible warnings ("System problem detected").
> >
> >> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Reviewed-by: Brian Norris <briannorris@chromium.org>
> > Tested-by: Brian Norris <briannorris@chromium.org>
>
> I added these now to the commit log, thanks Brian.
>
> Rafael, could you please provide the hardware and firmware versions you
> tested this on? We have so many different firmware branches to support
> that I prefer to have that documented in the commit log. Providing
> ath10k startup messages in dmesg are enough,

There you go:

[    4.695349] ath10k_pci 0000:3a:00.0: enabling device (0000 -> 0002)
[    4.698165] ath10k_pci 0000:3a:00.0: pci irq msi oper_irq_mode 2
irq_mode 0 reset_mode 0
[    4.912240] ath10k_pci 0000:3a:00.0: qca6174 hw3.2 target
0x05030000 chip_id 0x00340aff sub 1a56:1535
[    4.912255] ath10k_pci 0000:3a:00.0: kconfig debug 0 debugfs 0
tracing 0 dfs 0 testmode 0
[    4.912716] ath10k_pci 0000:3a:00.0: firmware ver
WLAN.RM.2.0-00180-QCARMSWPZ-1 api 4 features
wowlan,ignore-otp,no-4addr-pad crc32 75dee6c5
[    4.982563] ath10k_pci 0000:3a:00.0: board_file api 2 bmi_id N/A
crc32 19644295

> I can then add it to the commit log.

Still, I'm quite sure that the WARN_ON()s trigger during system resume
regardless of the hw/fw combination.

^ permalink raw reply

* Re: [PATCH] ath10k: add peer id check in ath10k_peer_find_by_id
From: Nicolas Boichat @ 2019-04-29 10:30 UTC (permalink / raw)
  To: Wen Gong; +Cc: ath10k, linux-wireless, Claire Chang
In-Reply-To: <1554260478-4161-1-git-send-email-wgong@codeaurora.org>

On Wed, Apr 3, 2019 at 3:01 AM Wen Gong <wgong@codeaurora.org> wrote:
>
> For some SDIO chip, the peer id is 65535 for MPDU with error status,
> then test_bit will trigger buffer overflow for peer's memory, if kasan
> enabled, it will report error.
>
> Add check for overflow the size of peer's peer_ids will avoid the buffer
> overflow access.
>
> Call trace of kasan:
> dump_backtrace+0x0/0x2ec
> show_stack+0x20/0x2c
> __dump_stack+0x20/0x28
> dump_stack+0xc8/0xec
> print_address_description+0x74/0x240
> kasan_report+0x250/0x26c
> __asan_report_load8_noabort+0x20/0x2c
> ath10k_peer_find_by_id+0x180/0x1e4 [ath10k_core]
> ath10k_htt_t2h_msg_handler+0x100c/0x2fd4 [ath10k_core]
> ath10k_htt_htc_t2h_msg_handler+0x20/0x34 [ath10k_core]
> ath10k_sdio_irq_handler+0xcc8/0x1678 [ath10k_sdio]
> process_sdio_pending_irqs+0xec/0x370
> sdio_run_irqs+0x68/0xe4
> sdio_irq_work+0x1c/0x28
> process_one_work+0x3d8/0x8b0
> worker_thread+0x508/0x7cc
> kthread+0x24c/0x264
> ret_from_fork+0x10/0x18
>
> Tested with QCA6174 SDIO with firmware
> WLAN.RMH.4.4.1-00007-QCARMSWP-1.
>
> Signed-off-by: Wen Gong <wgong@codeaurora.org>
> ---
>  drivers/net/wireless/ath/ath10k/txrx.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
> index 23606b6..33de9e1 100644
> --- a/drivers/net/wireless/ath/ath10k/txrx.c
> +++ b/drivers/net/wireless/ath/ath10k/txrx.c
> @@ -157,6 +157,9 @@ struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
>  {
>         struct ath10k_peer *peer;
>
> +       if (peer_id >= sizeof(peer->peer_ids) * BITS_PER_BYTE)

I'd use >= BITS_PER_TYPE(peer->peer_ids).

> +               return NULL;
> +
>         lockdep_assert_held(&ar->data_lock);
>
>         list_for_each_entry(peer, &ar->peers, list)

^ permalink raw reply

* Re: [PATCH] ath10k: Drop WARN_ON()s that always trigger during system resume
From: Claire Chang @ 2019-04-29 10:41 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Kalle Valo, Brian Norris, Rafael J. Wysocki, Sriram R, Linux PM,
	Pradeep Kumar Chitrapu, open list:NETWORKING DRIVERS (WIRELESS),
	ath10k, Srinivas Pandruvada, Todd Brandt
In-Reply-To: <CAJZ5v0ifD=DATprUeeO2_LGs04aEEhPB6AcGVPxWUdQaOma+ww@mail.gmail.com>

Tested-by: Claire Chang <tientzu@chromium.org>

> Still, I'm quite sure that the WARN_ON()s trigger during system resume
> regardless of the hw/fw combination.

Also see this on sido:

[    4.925278] ath10k_sdio mmc1:0001:1: qca6174 hw3.2 sdio target
0x05030000 chip_id 0x00000000 sub 0000:0000
[    4.935721] ath10k_sdio mmc1:0001:1: kconfig debug 1 debugfs 1
tracing 1 dfs 0 testmode 1
[    4.948750] ath10k_sdio mmc1:0001:1: firmware ver
WLAN.RMH.4.4.1-00007-QCARMSWP-1 api 6 features wowlan,ignore-otp crc32
b98adaf8
[    5.132728] ath10k_sdio mmc1:0001:1: board_file api 2 bmi_id 0:4
crc32 6364cfcc

^ permalink raw reply

* [RFC/RFT 0/7] rt2800: add experimental watchdog implementation
From: Stanislaw Gruszka @ 2019-04-29 10:54 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin

Add watchdog to address some remaining problems of Ralink devices
random hungs.

Stanislaw Gruszka (7):
  rt2x00: allow to specify watchdog interval
  rt2800: add helpers for reading dma done index
  rt2800: initial watchdog implementation
  rt2800: add pre_reset_hw callback
  rt2800: do not nullify initialization vector data
  rt2x00: add restart hw
  rt2800: do not enable watchdog by default

 drivers/net/wireless/ralink/rt2x00/rt2800lib.c   | 96 ++++++++++++++++++++++--
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h   | 11 +++
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.c  | 31 ++++++++
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.h  |  2 +
 drivers/net/wireless/ralink/rt2x00/rt2800pci.c   |  3 +
 drivers/net/wireless/ralink/rt2x00/rt2800soc.c   |  3 +
 drivers/net/wireless/ralink/rt2x00/rt2800usb.c   | 11 +++
 drivers/net/wireless/ralink/rt2x00/rt2x00.h      | 10 +++
 drivers/net/wireless/ralink/rt2x00/rt2x00debug.c | 35 +++++++++
 drivers/net/wireless/ralink/rt2x00/rt2x00dev.c   | 10 ++-
 drivers/net/wireless/ralink/rt2x00/rt2x00link.c  | 15 ++--
 drivers/net/wireless/ralink/rt2x00/rt2x00queue.h |  6 ++
 12 files changed, 221 insertions(+), 12 deletions(-)

-- 
2.7.5


^ permalink raw reply

* [RFC/RFT 1/7] rt2x00: allow to specify watchdog interval
From: Stanislaw Gruszka @ 2019-04-29 10:54 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556535270-3551-1-git-send-email-sgruszka@redhat.com>

Allow subdriver to change watchdog interval by intialize
link->watchdog_interval value before rt2x00link_register().

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/ralink/rt2x00/rt2x00.h     |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2x00link.c | 13 +++++++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 4b1744e9fb78..a241efa0a4f5 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -336,6 +336,7 @@ struct link {
 	 * to bring the device/driver back into the desired state.
 	 */
 	struct delayed_work watchdog_work;
+	unsigned int watchdog_interval;
 
 	/*
 	 * Work structure for scheduling periodic AGC adjustments.
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
index 2010a7715f21..fcc59553918f 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
@@ -398,7 +398,7 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
 	    rt2x00dev->ops->lib->watchdog)
 		ieee80211_queue_delayed_work(rt2x00dev->hw,
 					     &link->watchdog_work,
-					     WATCHDOG_INTERVAL);
+					     link->watchdog_interval);
 }
 
 void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -424,11 +424,16 @@ static void rt2x00link_watchdog(struct work_struct *work)
 	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
 		ieee80211_queue_delayed_work(rt2x00dev->hw,
 					     &link->watchdog_work,
-					     WATCHDOG_INTERVAL);
+					     link->watchdog_interval);
 }
 
 void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
 {
-	INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
-	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
+	struct link *link = &rt2x00dev->link;
+
+	INIT_DELAYED_WORK(&link->work, rt2x00link_tuner);
+	INIT_DELAYED_WORK(&link->watchdog_work, rt2x00link_watchdog);
+
+	if (link->watchdog_interval == 0)
+		link->watchdog_interval = WATCHDOG_INTERVAL;
 }
-- 
2.7.5


^ permalink raw reply related

* [RFC/RFT 2/7] rt2800: add helpers for reading dma done index
From: Stanislaw Gruszka @ 2019-04-29 10:54 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556535270-3551-1-git-send-email-sgruszka@redhat.com>

For mmio we do not properlly trace dma done Q_INDEX_DMA_DONE index
for TX queues. That would require implementing INT_SOURCE_CSR_*_DMA_DONE
interrupts, what is rather not worth to do due to adding extra
CPU load (small but still somewhat not necessary otherwise).

We can just read TX DMA done indexes from registers directly. What
will be used by watchdog.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h  |  8 +++++++
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 31 +++++++++++++++++++++++++
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.h |  2 ++
 drivers/net/wireless/ralink/rt2x00/rt2800pci.c  |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2800soc.c  |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2800usb.c  |  9 +++++++
 6 files changed, 52 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index 0dff2c7b3010..b3e6e15d34e5 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -76,6 +76,7 @@ struct rt2800_ops {
 				  const u8 *data, const size_t len);
 	int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
 	__le32 *(*drv_get_txwi)(struct queue_entry *entry);
+	unsigned int (*drv_get_dma_done)(struct data_queue *queue);
 };
 
 static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev,
@@ -177,6 +178,13 @@ static inline __le32 *rt2800_drv_get_txwi(struct queue_entry *entry)
 	return rt2800ops->drv_get_txwi(entry);
 }
 
+static inline unsigned int rt2800_drv_get_dma_done(struct data_queue *queue)
+{
+	const struct rt2800_ops *rt2800ops = queue->rt2x00dev->ops->drv;
+
+	return rt2800ops->drv_get_dma_done(queue);
+}
+
 void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
 			const u8 command, const u8 token,
 			const u8 arg0, const u8 arg1);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
index ddb88cfeace2..27d2d97c2317 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
@@ -36,6 +36,37 @@
 #include "rt2800lib.h"
 #include "rt2800mmio.h"
 
+unsigned int rt2800mmio_get_dma_done(struct data_queue *queue)
+{
+	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+	struct queue_entry *entry;
+	int idx, qid;
+
+	switch (queue->qid) {
+	case QID_AC_VO:
+	case QID_AC_VI:
+	case QID_AC_BE:
+	case QID_AC_BK:
+		qid = queue->qid;
+		idx = rt2x00mmio_register_read(rt2x00dev, TX_DTX_IDX(qid));
+		break;
+	case QID_MGMT:
+		idx = rt2x00mmio_register_read(rt2x00dev, TX_DTX_IDX(5));
+		break;
+	case QID_RX:
+		entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
+		idx = entry->entry_idx;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		idx = 0;
+		break;
+	}
+
+	return idx;
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_get_dma_done);
+
 /*
  * TX descriptor initialization
  */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
index 3a513273f414..fa90e3c29707 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
@@ -126,6 +126,8 @@
 #define RXD_W3_PLCP_SIGNAL		FIELD32(0x00020000)
 #define RXD_W3_PLCP_RSSI		FIELD32(0x00040000)
 
+unsigned int rt2800mmio_get_dma_done(struct data_queue *queue);
+
 /* TX descriptor initialization */
 __le32 *rt2800mmio_get_txwi(struct queue_entry *entry);
 void rt2800mmio_write_tx_desc(struct queue_entry *entry,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
index 0291441ac548..f22260dc2eb4 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -337,6 +337,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
 	.drv_write_firmware	= rt2800pci_write_firmware,
 	.drv_init_registers	= rt2800mmio_init_registers,
 	.drv_get_txwi		= rt2800mmio_get_txwi,
+	.drv_get_dma_done	= rt2800mmio_get_dma_done,
 };
 
 static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
index 9c74be82e2be..5c4a745a7489 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
@@ -183,6 +183,7 @@ static const struct rt2800_ops rt2800soc_rt2800_ops = {
 	.drv_write_firmware	= rt2800soc_write_firmware,
 	.drv_init_registers	= rt2800mmio_init_registers,
 	.drv_get_txwi		= rt2800mmio_get_txwi,
+	.drv_get_dma_done	= rt2800mmio_get_dma_done,
 };
 
 static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
index 19eabf16147b..1ec9b1eebedb 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
@@ -406,6 +406,14 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 	return retval;
 }
 
+static unsigned int rt2800usb_get_dma_done(struct data_queue *queue)
+{
+	struct queue_entry *entry;
+
+	entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
+	return entry->entry_idx;
+}
+
 /*
  * TX descriptor initialization
  */
@@ -688,6 +696,7 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = {
 	.drv_write_firmware	= rt2800usb_write_firmware,
 	.drv_init_registers	= rt2800usb_init_registers,
 	.drv_get_txwi		= rt2800usb_get_txwi,
+	.drv_get_dma_done	= rt2800usb_get_dma_done,
 };
 
 static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
-- 
2.7.5


^ permalink raw reply related

* [RFC/RFT 3/7] rt2800: initial watchdog implementation
From: Stanislaw Gruszka @ 2019-04-29 10:54 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556535270-3551-1-git-send-email-sgruszka@redhat.com>

Add watchdog for rt2800 devices. For now it only detect hung
and print error.

[Note: I verified that printing messages from process context is
fine on MT7620 (WT3020) platform that have problem when printk
is called from interrupt context].

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c   | 56 ++++++++++++++++++++++++
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h   |  2 +
 drivers/net/wireless/ralink/rt2x00/rt2800pci.c   |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2800soc.c   |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2800usb.c   |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2x00queue.h |  6 +++
 6 files changed, 67 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 0e8e96075554..7696e3c087ef 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1215,6 +1215,60 @@ void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2800_txdone_nostatus);
 
+static int rt2800_check_hung(struct data_queue *queue)
+{
+	unsigned int cur_idx = rt2800_drv_get_dma_done(queue);
+
+	if (queue->wd_idx != cur_idx)
+		queue->wd_count = 0;
+	else
+		queue->wd_count++;
+
+	return queue->wd_count > 16;
+}
+
+void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+	bool hung_tx = false;
+	bool hung_rx = false;
+
+	if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
+		return;
+
+	queue_for_each(rt2x00dev, queue) {
+		switch (queue->qid) {
+		case QID_AC_VO:
+		case QID_AC_VI:
+		case QID_AC_BE:
+		case QID_AC_BK:
+		case QID_MGMT:
+			if (rt2x00queue_empty(queue))
+				continue;
+			hung_tx = rt2800_check_hung(queue);
+			break;
+		case QID_RX:
+			/* For station mode we should reactive at least
+			 * beacons. TODO: need to find good way detect
+			 * RX hung for AP mode.
+			 */
+			if (rt2x00dev->intf_sta_count == 0)
+				continue;
+			hung_rx = rt2800_check_hung(queue);
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (hung_tx)
+		rt2x00_warn(rt2x00dev, "Watchdog TX hung detected\n");
+
+	if (hung_rx)
+		rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n");
+}
+EXPORT_SYMBOL_GPL(rt2800_watchdog);
+
 static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
 					  unsigned int index)
 {
@@ -10214,6 +10268,8 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 		__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
 	}
 
+	rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
+
 	/*
 	 * Set the rssi offset.
 	 */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index b3e6e15d34e5..058cc61884b0 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -207,6 +207,8 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
 void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
 bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
 
+void rt2800_watchdog(struct rt2x00_dev *rt2x00dev);
+
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
 void rt2800_clear_beacon(struct queue_entry *entry);
 
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
index f22260dc2eb4..8ce6c45dbf7d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -362,6 +362,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.link_tuner		= rt2800_link_tuner,
 	.gain_calibration	= rt2800_gain_calibration,
 	.vco_calibration	= rt2800_vco_calibration,
+	.watchdog		= rt2800_watchdog,
 	.start_queue		= rt2800mmio_start_queue,
 	.kick_queue		= rt2800mmio_kick_queue,
 	.stop_queue		= rt2800mmio_stop_queue,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
index 5c4a745a7489..30e4b578ab67 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
@@ -208,6 +208,7 @@ static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
 	.link_tuner		= rt2800_link_tuner,
 	.gain_calibration	= rt2800_gain_calibration,
 	.vco_calibration	= rt2800_vco_calibration,
+	.watchdog		= rt2800_watchdog,
 	.start_queue		= rt2800mmio_start_queue,
 	.kick_queue		= rt2800mmio_kick_queue,
 	.stop_queue		= rt2800mmio_stop_queue,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
index 1ec9b1eebedb..3966f97c9e47 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
@@ -714,6 +714,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 	.link_tuner		= rt2800_link_tuner,
 	.gain_calibration	= rt2800_gain_calibration,
 	.vco_calibration	= rt2800_vco_calibration,
+	.watchdog		= rt2800_watchdog,
 	.start_queue		= rt2800usb_start_queue,
 	.kick_queue		= rt2x00usb_kick_queue,
 	.stop_queue		= rt2800usb_stop_queue,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
index a15bae29917b..32ccc819bbf0 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
@@ -449,6 +449,9 @@ enum data_queue_flags {
  * @length: Number of frames in queue.
  * @index: Index pointers to entry positions in the queue,
  *	use &enum queue_index to get a specific index field.
+ * @wd_count: watchdog counter number of times entry does change
+ *      in the queue
+ * @wd_idx: index of queue entry saved by watchdog
  * @txop: maximum burst time.
  * @aifs: The aifs value for outgoing frames (field ignored in RX queue).
  * @cw_min: The cw min value for outgoing frames (field ignored in RX queue).
@@ -476,6 +479,9 @@ struct data_queue {
 	unsigned short length;
 	unsigned short index[Q_INDEX_MAX];
 
+	unsigned short wd_count;
+	unsigned int wd_idx;
+
 	unsigned short txop;
 	unsigned short aifs;
 	unsigned short cw_min;
-- 
2.7.5


^ permalink raw reply related

* [RFC/RFT 4/7] rt2800: add pre_reset_hw callback
From: Stanislaw Gruszka @ 2019-04-29 10:54 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556535270-3551-1-git-send-email-sgruszka@redhat.com>

Add routine to cleanup interfaces data before hw reset as
ieee80211_restart_hw() will do setup interfaces again.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 19 +++++++++++++++++++
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2800pci.c |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2800soc.c |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2800usb.c |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2x00.h    |  1 +
 6 files changed, 24 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 7696e3c087ef..9a49bb44197c 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1846,6 +1846,25 @@ int rt2800_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 }
 EXPORT_SYMBOL_GPL(rt2800_sta_remove);
 
+void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+	struct data_queue *queue = rt2x00dev->bcn;
+	struct queue_entry *entry;	
+	int i, wcid;
+
+	for (wcid = WCID_START; wcid < WCID_END; wcid++) {
+		drv_data->wcid_to_sta[wcid - WCID_START] = NULL;
+		__clear_bit(wcid - WCID_START, drv_data->sta_ids);
+	}
+
+	for (i = 0; i < queue->limit; i++) {
+		entry = &queue->entries[i];
+		clear_bit(ENTRY_BCN_ASSIGNED, &entry->flags);
+	}
+}
+EXPORT_SYMBOL_GPL(rt2800_pre_reset_hw);
+
 void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
 			  const unsigned int filter_flags)
 {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index 058cc61884b0..001b46375f26 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -267,5 +267,6 @@ void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
 void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev,
 			       unsigned short *txwi_size,
 			       unsigned short *rxwi_size);
+void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev);
 
 #endif /* RT2800LIB_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
index 8ce6c45dbf7d..8836091f1205 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -379,6 +379,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.config_erp		= rt2800_config_erp,
 	.config_ant		= rt2800_config_ant,
 	.config			= rt2800_config,
+	.pre_reset_hw		= rt2800_pre_reset_hw,
 };
 
 static const struct rt2x00_ops rt2800pci_ops = {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
index 30e4b578ab67..8f8233c0b73b 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
@@ -225,6 +225,7 @@ static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
 	.config_erp		= rt2800_config_erp,
 	.config_ant		= rt2800_config_ant,
 	.config			= rt2800_config,
+	.pre_reset_hw		= rt2800_pre_reset_hw,
 };
 
 static const struct rt2x00_ops rt2800soc_ops = {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
index 3966f97c9e47..3e90e7224750 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
@@ -733,6 +733,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 	.config_erp		= rt2800_config_erp,
 	.config_ant		= rt2800_config_ant,
 	.config			= rt2800_config,
+	.pre_reset_hw		= rt2800_pre_reset_hw,
 };
 
 static void rt2800usb_queue_init(struct data_queue *queue)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index a241efa0a4f5..cdf496c55b9d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -627,6 +627,7 @@ struct rt2x00lib_ops {
 	void (*config) (struct rt2x00_dev *rt2x00dev,
 			struct rt2x00lib_conf *libconf,
 			const unsigned int changed_flags);
+	void (*pre_reset_hw) (struct rt2x00_dev *rt2x00dev);
 	int (*sta_add) (struct rt2x00_dev *rt2x00dev,
 			struct ieee80211_vif *vif,
 			struct ieee80211_sta *sta);
-- 
2.7.5


^ permalink raw reply related

* [RFC/RFT 5/7] rt2800: do not nullify initialization vector data
From: Stanislaw Gruszka @ 2019-04-29 10:54 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556535270-3551-1-git-send-email-sgruszka@redhat.com>

If we restart hw we should keep existing IV (initialization vector)
otherwise HW encryption will be broken after restart.

Also fix some coding style issues on the way.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 9a49bb44197c..4a2e15b5aba4 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1650,14 +1650,15 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
 
 	offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
 
-	memset(&iveiv_entry, 0, sizeof(iveiv_entry));
+	rt2800_register_multiread(rt2x00dev, offset,
+				  &iveiv_entry, sizeof(iveiv_entry));
 	if ((crypto->cipher == CIPHER_TKIP) ||
 	    (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
 	    (crypto->cipher == CIPHER_AES))
 		iveiv_entry.iv[3] |= 0x20;
 	iveiv_entry.iv[3] |= key->keyidx << 6;
 	rt2800_register_multiwrite(rt2x00dev, offset,
-				      &iveiv_entry, sizeof(iveiv_entry));
+				   &iveiv_entry, sizeof(iveiv_entry));
 }
 
 int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
@@ -6082,13 +6083,11 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	 * ASIC will keep garbage value after boot, clear encryption keys.
 	 */
 	for (i = 0; i < 4; i++)
-		rt2800_register_write(rt2x00dev,
-					 SHARED_KEY_MODE_ENTRY(i), 0);
+		rt2800_register_write(rt2x00dev, SHARED_KEY_MODE_ENTRY(i), 0);
 
 	for (i = 0; i < 256; i++) {
 		rt2800_config_wcid(rt2x00dev, NULL, i);
 		rt2800_delete_wcid_attr(rt2x00dev, i);
-		rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
 	}
 
 	/*
-- 
2.7.5


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox