Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH 1/9] wil6210: fix spurious interrupts in 3-msi
From: Kalle Valo @ 2019-05-03  5:05 UTC (permalink / raw)
  To: Maya Erez; +Cc: Maya Erez, linux-wireless, wil6210
In-Reply-To: <1556293417-27097-2-git-send-email-merez@codeaurora.org>

Maya Erez <merez@codeaurora.org> wrote:

> Interrupt is set in ICM (ICR & ~IMV) rising trigger.
> As the driver masks the IRQ after clearing it, there can
> be a race where an additional spurious interrupt is triggered
> when the driver unmask the IRQ.
> This can happen in case HW triggers an interrupt after the clear
> and before the mask.
> 
> To prevent the second spurious interrupt the driver needs to mask the
> IRQ before reading and clearing it.
> 
> Signed-off-by: Maya Erez <merez@codeaurora.org>
> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

9 patches applied to ath-next branch of ath.git, thanks.

e10b0eddd523 wil6210: fix spurious interrupts in 3-msi
9c6465979276 wil6210: fix _desc access in __wil_tx_vring_tso
0131d1851338 wil6210: add printout of platform capabilities
a7feb56f204f wil6210: add support for multiple sections in brd file
9a874d045473 wil6210: enhancements for descriptor and status ring debugfs
ddf7afdde824 wil6210: fix overwriting max_assoc_sta module param
7441be71ba7e wil6210: fix missed MISC mbox interrupt
d6a553c0c61b wil6210: check rx_buff_mgmt before accessing it
3d0aa9198446 wil6210: remove HALP for Talyn devices

-- 
https://patchwork.kernel.org/patch/10919277/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


^ permalink raw reply

* Re: [PATCH] rsi: Properly initialize data in rsi_sdio_ta_reset
From: Kalle Valo @ 2019-05-03  4:38 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Nathan Chancellor, Amitkumar Karwar, Siva Rebbagondla,
	linux-wireless, netdev, LKML, clang-built-linux
In-Reply-To: <CAKwvOd=nvKGGW5jvN+WFUXzOm9xeiNNUD0F9--9YcpuRmnWWhA@mail.gmail.com>

Nick Desaulniers <ndesaulniers@google.com> writes:

> On Thu, May 2, 2019 at 8:16 AM Nathan Chancellor
> <natechancellor@gmail.com> wrote:
>>
>> When building with -Wuninitialized, Clang warns:
>>
>> drivers/net/wireless/rsi/rsi_91x_sdio.c:940:43: warning: variable 'data'
>> is uninitialized when used here [-Wuninitialized]
>>         put_unaligned_le32(TA_HOLD_THREAD_VALUE, data);
>>                                                  ^~~~
>> drivers/net/wireless/rsi/rsi_91x_sdio.c:930:10: note: initialize the
>> variable 'data' to silence this warning
>>         u8 *data;
>>                 ^
>>                  = NULL
>> 1 warning generated.
>>
>> Using Clang's suggestion of initializing data to NULL wouldn't work out
>> because data will be dereferenced by put_unaligned_le32. Use kzalloc to
>> properly initialize data, which matches a couple of other places in this
>> driver.
>>
>> Fixes: e5a1ecc97e5f ("rsi: add firmware loading for 9116 device")
>> Link: https://github.com/ClangBuiltLinux/linux/issues/464
>> Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
>> ---
>>  drivers/net/wireless/rsi/rsi_91x_sdio.c | 21 ++++++++++++++-------
>>  1 file changed, 14 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
>> index f9c67ed473d1..b35728564c7b 100644
>> --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
>> +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
>> @@ -929,11 +929,15 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
>>         u32 addr;
>>         u8 *data;
>>
>> +       data = kzalloc(sizeof(u32), GFP_KERNEL);
>
> Something fishy is going on here.  We allocate 4 B but declare data as
> a u8* (pointer to individual bytes)?  In general, dynamically
> allocating that few bytes is a code smell; either you meant to just
> use the stack, or this memory's lifetime extends past the lifetime of
> this stackframe, at which point you probably just meant to stack
> allocate space in a higher parent frame and pass this preallocated
> memory down to the child frame to get filled in.
>
> Reading through this code, I don't think that the memory is meant to
> outlive the stack frame.  Is there a reason why we can't just declare
> data as:
>
> u8 data [4];
>
> then use ARRAY_SIZE(data) or RSI_9116_REG_SIZE in rsi_reset_chip(),
> getting rid of the kzalloc/kfree?

I haven't checked the details but AFAIK stack variables are not supposed
to be used with DMA. So in that case I think it's ok alloc four bytes,
unless the DMA rules have changed of course. But I didn't check if rsi
is using DMA here, just a general comment.

-- 
Kalle Valo

^ permalink raw reply

* Re: [PATCH] rsi: Properly initialize data in rsi_sdio_ta_reset
From: Nathan Chancellor @ 2019-05-03  3:17 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Amitkumar Karwar, Siva Rebbagondla, Kalle Valo, linux-wireless,
	netdev, LKML, clang-built-linux
In-Reply-To: <CAKwvOd=nvKGGW5jvN+WFUXzOm9xeiNNUD0F9--9YcpuRmnWWhA@mail.gmail.com>

On Thu, May 02, 2019 at 11:18:01AM -0700, Nick Desaulniers wrote:
> On Thu, May 2, 2019 at 8:16 AM Nathan Chancellor
> <natechancellor@gmail.com> wrote:
> >
> > When building with -Wuninitialized, Clang warns:
> >
> > drivers/net/wireless/rsi/rsi_91x_sdio.c:940:43: warning: variable 'data'
> > is uninitialized when used here [-Wuninitialized]
> >         put_unaligned_le32(TA_HOLD_THREAD_VALUE, data);
> >                                                  ^~~~
> > drivers/net/wireless/rsi/rsi_91x_sdio.c:930:10: note: initialize the
> > variable 'data' to silence this warning
> >         u8 *data;
> >                 ^
> >                  = NULL
> > 1 warning generated.
> >
> > Using Clang's suggestion of initializing data to NULL wouldn't work out
> > because data will be dereferenced by put_unaligned_le32. Use kzalloc to
> > properly initialize data, which matches a couple of other places in this
> > driver.
> >
> > Fixes: e5a1ecc97e5f ("rsi: add firmware loading for 9116 device")
> > Link: https://github.com/ClangBuiltLinux/linux/issues/464
> > Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> > ---
> >  drivers/net/wireless/rsi/rsi_91x_sdio.c | 21 ++++++++++++++-------
> >  1 file changed, 14 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
> > index f9c67ed473d1..b35728564c7b 100644
> > --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
> > +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
> > @@ -929,11 +929,15 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
> >         u32 addr;
> >         u8 *data;
> >
> > +       data = kzalloc(sizeof(u32), GFP_KERNEL);
> 
> Something fishy is going on here.  We allocate 4 B but declare data as
> a u8* (pointer to individual bytes)?  In general, dynamically
> allocating that few bytes is a code smell; either you meant to just
> use the stack, or this memory's lifetime extends past the lifetime of
> this stackframe, at which point you probably just meant to stack
> allocate space in a higher parent frame and pass this preallocated
> memory down to the child frame to get filled in.
> 
> Reading through this code, I don't think that the memory is meant to
> outlive the stack frame.  Is there a reason why we can't just declare
> data as:
> 
> u8 data [4];

data was __le32 in rsi_reset_chip() before commit f700546682a6 ("rsi:
fix nommu_map_sg overflow kernel panic").

I wonder if this would be okay for this function:

-------------------------------------------------

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index f9c67ed473d1..0330c50ab99c 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -927,7 +927,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
 {
        int status;
        u32 addr;
-       u8 *data;
+       u8 data;
 
        status = rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR);
        if (status < 0) {
@@ -937,7 +937,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
        }
 
        rsi_dbg(INIT_ZONE, "%s: Bring TA out of reset\n", __func__);
-       put_unaligned_le32(TA_HOLD_THREAD_VALUE, data);
+       put_unaligned_le32(TA_HOLD_THREAD_VALUE, &data);
        addr = TA_HOLD_THREAD_REG | RSI_SD_REQUEST_MASTER;
        status = rsi_sdio_write_register_multiple(adapter, addr,
                                                  (u8 *)&data,
@@ -947,7 +947,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                return status;
        }
 
-       put_unaligned_le32(TA_SOFT_RST_CLR, data);
+       put_unaligned_le32(TA_SOFT_RST_CLR, &data);
        addr = TA_SOFT_RESET_REG | RSI_SD_REQUEST_MASTER;
        status = rsi_sdio_write_register_multiple(adapter, addr,
                                                  (u8 *)&data,
@@ -957,7 +957,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                return status;
        }
 
-       put_unaligned_le32(TA_PC_ZERO, data);
+       put_unaligned_le32(TA_PC_ZERO, &data);
        addr = TA_TH0_PC_REG | RSI_SD_REQUEST_MASTER;
        status = rsi_sdio_write_register_multiple(adapter, addr,
                                                  (u8 *)&data,
@@ -967,7 +967,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
                return -EINVAL;
        }
 
-       put_unaligned_le32(TA_RELEASE_THREAD_VALUE, data);
+       put_unaligned_le32(TA_RELEASE_THREAD_VALUE, &data);
        addr = TA_RELEASE_THREAD_REG | RSI_SD_REQUEST_MASTER;
        status = rsi_sdio_write_register_multiple(adapter, addr,
                                                  (u8 *)&data,


> 
> then use ARRAY_SIZE(data) or RSI_9116_REG_SIZE in rsi_reset_chip(),
> getting rid of the kzalloc/kfree?
> 
> (Sorry, I hate when a simple fixup becomes a "hey let's rewrite all
> this code" thus becoming "that guy.")

If we aren't actually improving the code, then why bother? :)

Thank you for the review!
Nathan

> -- 
> Thanks,
> ~Nick Desaulniers

^ permalink raw reply related

* Re: [PATCH v9 04/14] rtw88: trx files
From: Brian Norris @ 2019-05-02 18:23 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Larry Finger, Tony Chuang, linux-wireless, Johannes Berg, Pkshih,
	Andy Huang, Stanislaw Gruszka, Greg Kroah-Hartman
In-Reply-To: <87a7g6ni31.fsf@kamboji.qca.qualcomm.com>

On Wed, May 1, 2019 at 11:30 AM Kalle Valo <kvalo@codeaurora.org> wrote:
> My comment was about handling firmware commands and events as a byte
> array, not about bitfields. So that instead of accessing 'index + 1' and
> 'index + 4' you should create a proper struct for the command and access
> it using 'cmd->foo' and 'cmd->bar'. Sure, bitfields you still need to
> access using FIELD_GET() or similar but having a struct for commands is
> a lot cleaner approach. And most upstream drivers do this: ath10k,
> ath6kl, iwlwifi, p54 and whatnot.

I think I pushed Tony away from the bitfields (he was using a struct
plus some ugly bitfields / #ifdefs pre-v8), and he ended up with this
(in v8). I noted on the v8 cover letter that one can still use a
struct, but just avoid using bitfields -- so you would still have 'u8'
and '__le32' fields (or similar), and do the right le32_to_cpu()
accessors (sparse will help you) plus FIELD_GET() (for any necessary
bitfields).

Brian

^ permalink raw reply

* Re: [PATCH] rsi: Properly initialize data in rsi_sdio_ta_reset
From: Nick Desaulniers @ 2019-05-02 18:18 UTC (permalink / raw)
  To: Nathan Chancellor
  Cc: Amitkumar Karwar, Siva Rebbagondla, Kalle Valo, linux-wireless,
	netdev, LKML, clang-built-linux
In-Reply-To: <20190502151548.11143-1-natechancellor@gmail.com>

On Thu, May 2, 2019 at 8:16 AM Nathan Chancellor
<natechancellor@gmail.com> wrote:
>
> When building with -Wuninitialized, Clang warns:
>
> drivers/net/wireless/rsi/rsi_91x_sdio.c:940:43: warning: variable 'data'
> is uninitialized when used here [-Wuninitialized]
>         put_unaligned_le32(TA_HOLD_THREAD_VALUE, data);
>                                                  ^~~~
> drivers/net/wireless/rsi/rsi_91x_sdio.c:930:10: note: initialize the
> variable 'data' to silence this warning
>         u8 *data;
>                 ^
>                  = NULL
> 1 warning generated.
>
> Using Clang's suggestion of initializing data to NULL wouldn't work out
> because data will be dereferenced by put_unaligned_le32. Use kzalloc to
> properly initialize data, which matches a couple of other places in this
> driver.
>
> Fixes: e5a1ecc97e5f ("rsi: add firmware loading for 9116 device")
> Link: https://github.com/ClangBuiltLinux/linux/issues/464
> Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> ---
>  drivers/net/wireless/rsi/rsi_91x_sdio.c | 21 ++++++++++++++-------
>  1 file changed, 14 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
> index f9c67ed473d1..b35728564c7b 100644
> --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
> +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
> @@ -929,11 +929,15 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
>         u32 addr;
>         u8 *data;
>
> +       data = kzalloc(sizeof(u32), GFP_KERNEL);

Something fishy is going on here.  We allocate 4 B but declare data as
a u8* (pointer to individual bytes)?  In general, dynamically
allocating that few bytes is a code smell; either you meant to just
use the stack, or this memory's lifetime extends past the lifetime of
this stackframe, at which point you probably just meant to stack
allocate space in a higher parent frame and pass this preallocated
memory down to the child frame to get filled in.

Reading through this code, I don't think that the memory is meant to
outlive the stack frame.  Is there a reason why we can't just declare
data as:

u8 data [4];

then use ARRAY_SIZE(data) or RSI_9116_REG_SIZE in rsi_reset_chip(),
getting rid of the kzalloc/kfree?

(Sorry, I hate when a simple fixup becomes a "hey let's rewrite all
this code" thus becoming "that guy.")
-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply

* Re: [PATCH v2] rtw88: Make RA_MASK macros ULL
From: Kalle Valo @ 2019-05-02 16:26 UTC (permalink / raw)
  To: Nathan Chancellor
  Cc: Yan-Hsuan Chuang, linux-wireless, netdev, linux-kernel,
	clang-built-linux, Nick Desaulniers, Nathan Chancellor
In-Reply-To: <20190502150209.4475-1-natechancellor@gmail.com>

Nathan Chancellor <natechancellor@gmail.com> wrote:

> Clang warns about the definitions of these macros (full warnings trimmed
> for brevity):
> 
> drivers/net/wireless/realtek/rtw88/main.c:524:15: warning: signed shift
> result (0x3FF00000000) requires 43 bits to represent, but 'int' only has
> 32 bits [-Wshift-overflow]
>                         ra_mask &= RA_MASK_VHT_RATES | RA_MASK_OFDM_IN_VHT;
>                                    ^~~~~~~~~~~~~~~~~
> drivers/net/wireless/realtek/rtw88/main.c:527:15: warning: signed shift
> result (0xFF0000000) requires 37 bits to represent, but 'int' only has
> 32 bits [-Wshift-overflow]
>                         ra_mask &= RA_MASK_HT_RATES | RA_MASK_OFDM_IN_HT_5G;
>                                    ^~~~~~~~~~~~~~~~
> 
> Given that these are all used with ra_mask, which is of type u64, we can
> just declare the macros to be ULL as well.
> 
> Fixes: e3037485c68e ("rtw88: new Realtek 802.11ac driver")
> Link: https://github.com/ClangBuiltLinux/linux/issues/467
> Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>

Patch applied to wireless-drivers-next.git, thanks.

237b47efcdbc rtw88: Make RA_MASK macros ULL

-- 
https://patchwork.kernel.org/patch/10927105/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


^ permalink raw reply

* Re: [RFC 10/17] mt7615: mcu: remove skb_ret from mt7615_mcu_msg_send
From: Lorenzo Bianconi @ 2019-05-02 15:31 UTC (permalink / raw)
  To: Roy Luo
  Cc: nbd, lorenzo.bianconi, linux-wireless,
	Ryder Lee (李庚諺)
In-Reply-To: <CA+zupgzQTzQyihC_UskHD=63Ag3AnQcD4_pcas7VdaehyoCE1w@mail.gmail.com>

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

> Hi Lorenzo,
> 

Hi Roy,

> IMHO, the skb_ret parameter from mt7615_mcu_msg_send is not just used by
> patch semaphore control.
> The other cmds also got their own event response that can be interpret
> accordingly by their own caller, which can provide the status of the cmd
> (success/fail) and other information that might be helpful case by case.


Do you mean the fw does not put the status code in a 'event struct'
at the beginning of the skb data buffer? What are the cmds that do not use
that approach?

Regards,
Lorenzo

> For now, we just assume every cmd works well and do no error handling,
> which is risky.
> If we are to take FW response into consideration in the future, maybe we
> should keep this parameter.
> 
> 
> Regards,
> Cheng-Hao (Roy) Luo
> 
> 
> On Thu, May 2, 2019 at 12:08 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
> 
> > Remove skb_ret parameter from mt7615_mcu_msg_send signature since it is
> > actually used just by mt7615_mcu_patch_sem_ctrl. This is a prelimanry
> > patch to use mt76 common mcu API
> >
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > ---
> >  .../net/wireless/mediatek/mt76/mt7615/mcu.c   | 77 ++++++-------------
> >  1 file changed, 24 insertions(+), 53 deletions(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
> > b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
> > index b8d928e8949c..4d1d4c0bc2e2 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
> > @@ -116,8 +116,7 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev
> > *dev, struct sk_buff *skb,
> >  }
> >
> >  static int
> > -mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb,
> > -                   int cmd, struct sk_buff **skb_ret)
> > +mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, int cmd)
> >  {
> >         unsigned long expires = jiffies + 10 * HZ;
> >         struct mt7615_mcu_rxd *rxd;
> > @@ -142,18 +141,11 @@ mt7615_mcu_msg_send(struct mt7615_dev *dev, struct
> > sk_buff *skb,
> >                 if (seq != rxd->seq)
> >                         continue;
> >
> > -               if (skb_ret) {
> > -                       int hdr_len = sizeof(*rxd);
> > -
> > -                       if (!test_bit(MT76_STATE_MCU_RUNNING,
> > -                                     &dev->mt76.state))
> > -                               hdr_len -= 4;
> > -                       skb_pull(skb, hdr_len);
> > -                       *skb_ret = skb;
> > -               } else {
> > -                       dev_kfree_skb(skb);
> > +               if (cmd == -MCU_CMD_PATCH_SEM_CONTROL) {
> > +                       skb_pull(skb, sizeof(*rxd) - 4);
> > +                       ret = *skb->data;
> >                 }
> > -
> > +               dev_kfree_skb(skb);
> >                 break;
> >         }
> >
> > @@ -177,8 +169,7 @@ static int mt7615_mcu_init_download(struct mt7615_dev
> > *dev, u32 addr,
> >         };
> >         struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> >
> > -       return mt7615_mcu_msg_send(dev, skb,
> > -MCU_CMD_TARGET_ADDRESS_LEN_REQ,
> > -                                  NULL);
> > +       return mt7615_mcu_msg_send(dev, skb,
> > -MCU_CMD_TARGET_ADDRESS_LEN_REQ);
> >  }
> >
> >  static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void
> > *data,
> > @@ -219,43 +210,26 @@ static int mt7615_mcu_start_firmware(struct
> > mt7615_dev *dev, u32 addr,
> >         };
> >         struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> >
> > -       return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ, NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ);
> >  }
> >
> >  static int mt7615_mcu_restart(struct mt7615_dev *dev)
> >  {
> >         struct sk_buff *skb = mt7615_mcu_msg_alloc(NULL, 0);
> >
> > -       return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ,
> > NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ);
> >  }
> >
> >  static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get)
> >  {
> >         struct {
> > -               __le32 operation;
> > +               __le32 op;
> >         } req = {
> > -               .operation = cpu_to_le32(get ? PATCH_SEM_GET :
> > -                                        PATCH_SEM_RELEASE),
> > +               .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE),
> >         };
> > -       struct event {
> > -               u8 status;
> > -               u8 reserved[3];
> > -       } *resp;
> >         struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> > -       struct sk_buff *skb_ret;
> > -       int ret;
> >
> > -       ret = mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_SEM_CONTROL,
> > -                                 &skb_ret);
> > -       if (ret)
> > -               goto out;
> > -
> > -       resp = (struct event *)(skb_ret->data);
> > -       ret = resp->status;
> > -       dev_kfree_skb(skb_ret);
> > -
> > -out:
> > -       return ret;
> > +       return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_SEM_CONTROL);
> >  }
> >
> >  static int mt7615_mcu_start_patch(struct mt7615_dev *dev)
> > @@ -268,7 +242,7 @@ static int mt7615_mcu_start_patch(struct mt7615_dev
> > *dev)
> >         };
> >         struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> >
> > -       return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_FINISH_REQ,
> > NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, -MCU_CMD_PATCH_FINISH_REQ);
> >  }
> >
> >  static int mt7615_driver_own(struct mt7615_dev *dev)
> > @@ -554,8 +528,7 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev)
> >         for (off = MT_EE_NIC_CONF_0; off < __MT_EE_MAX; off++)
> >                 data[off - MT_EE_NIC_CONF_0].val = eep[off];
> >
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE,
> > -                                  NULL);
> > +       return mt7615_mcu_msg_send(dev, skb,
> > MCU_EXT_CMD_EFUSE_BUFFER_MODE);
> >  }
> >
> >  int mt7615_mcu_init_mac(struct mt7615_dev *dev)
> > @@ -570,7 +543,7 @@ int mt7615_mcu_init_mac(struct mt7615_dev *dev)
> >         };
> >         struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> >
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_MAC_INIT_CTRL,
> > NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_MAC_INIT_CTRL);
> >  }
> >
> >  int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val)
> > @@ -589,7 +562,7 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev,
> > u32 val)
> >         };
> >         struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> >
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PROTECT_CTRL,
> > NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PROTECT_CTRL);
> >  }
> >
> >  int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue,
> > @@ -627,7 +600,7 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8
> > queue,
> >         }
> >
> >         skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EDCA_UPDATE,
> > NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_EDCA_UPDATE);
> >  }
> >
> >  int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter)
> > @@ -657,7 +630,7 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev,
> > int enter)
> >         };
> >         struct sk_buff *skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> >
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL,
> > NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_PM_STATE_CTRL);
> >  }
> >
> >  static int __mt7615_mcu_set_dev_info(struct mt7615_dev *dev,
> > @@ -704,8 +677,7 @@ static int __mt7615_mcu_set_dev_info(struct mt7615_dev
> > *dev,
> >
> >         memcpy(skb_push(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr));
> >
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE,
> > -                                  NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_DEV_INFO_UPDATE);
> >  }
> >
> >  int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif
> > *vif,
> > @@ -830,8 +802,7 @@ static int __mt7615_mcu_set_bss_info(struct mt7615_dev
> > *dev,
> >                     bss_info_tag_handler[i].handler)
> >                         bss_info_tag_handler[i].handler(dev, bss_info,
> > skb);
> >
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE,
> > -                                  NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BSS_INFO_UPDATE);
> >  }
> >
> >  int mt7615_mcu_set_bss_info(struct mt7615_dev *dev,
> > @@ -914,7 +885,7 @@ __mt7615_mcu_set_wtbl(struct mt7615_dev *dev, int
> > wlan_idx,
> >         if (buf && buf_len)
> >                 memcpy(skb_put(skb, buf_len), buf, buf_len);
> >
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_WTBL_UPDATE,
> > NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_WTBL_UPDATE);
> >  }
> >
> >  static enum mt7615_cipher_type
> > @@ -1092,7 +1063,7 @@ __mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, int
> > bss_idx,
> >         if (buf && buf_len)
> >                 memcpy(skb_put(skb, buf_len), buf, buf_len);
> >
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_STA_REC_UPDATE,
> > NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_STA_REC_UPDATE);
> >  }
> >
> >  int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev,
> > @@ -1220,7 +1191,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev,
> > struct ieee80211_vif *vif,
> >
> >         skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> >
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD,
> > NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_BCN_OFFLOAD);
> >  }
> >
> >  int mt7615_mcu_set_channel(struct mt7615_dev *dev)
> > @@ -1285,12 +1256,12 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev)
> >         memset(req.txpower_sku, 0x3f, 49);
> >
> >         skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> > -       ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH,
> > NULL);
> > +       ret = mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH);
> >         if (ret)
> >                 return ret;
> >
> >         skb = mt7615_mcu_msg_alloc(&req, sizeof(req));
> > -       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_RX_PATH,
> > NULL);
> > +       return mt7615_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_RX_PATH);
> >  }
> >
> >  int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif
> > *vif,
> > --
> > 2.20.1
> >
> >

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* [PATCH] rsi: Properly initialize data in rsi_sdio_ta_reset
From: Nathan Chancellor @ 2019-05-02 15:15 UTC (permalink / raw)
  To: Amitkumar Karwar, Siva Rebbagondla, Kalle Valo
  Cc: linux-wireless, netdev, linux-kernel, clang-built-linux,
	Nick Desaulniers, Nathan Chancellor

When building with -Wuninitialized, Clang warns:

drivers/net/wireless/rsi/rsi_91x_sdio.c:940:43: warning: variable 'data'
is uninitialized when used here [-Wuninitialized]
        put_unaligned_le32(TA_HOLD_THREAD_VALUE, data);
                                                 ^~~~
drivers/net/wireless/rsi/rsi_91x_sdio.c:930:10: note: initialize the
variable 'data' to silence this warning
        u8 *data;
                ^
                 = NULL
1 warning generated.

Using Clang's suggestion of initializing data to NULL wouldn't work out
because data will be dereferenced by put_unaligned_le32. Use kzalloc to
properly initialize data, which matches a couple of other places in this
driver.

Fixes: e5a1ecc97e5f ("rsi: add firmware loading for 9116 device")
Link: https://github.com/ClangBuiltLinux/linux/issues/464
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
---
 drivers/net/wireless/rsi/rsi_91x_sdio.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index f9c67ed473d1..b35728564c7b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -929,11 +929,15 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
 	u32 addr;
 	u8 *data;
 
+	data = kzalloc(sizeof(u32), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
 	status = rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR);
 	if (status < 0) {
 		rsi_dbg(ERR_ZONE,
 			"Unable to set ms word to common reg\n");
-		return status;
+		goto err;
 	}
 
 	rsi_dbg(INIT_ZONE, "%s: Bring TA out of reset\n", __func__);
@@ -944,7 +948,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
 						  RSI_9116_REG_SIZE);
 	if (status < 0) {
 		rsi_dbg(ERR_ZONE, "Unable to hold TA threads\n");
-		return status;
+		goto err;
 	}
 
 	put_unaligned_le32(TA_SOFT_RST_CLR, data);
@@ -954,7 +958,7 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
 						  RSI_9116_REG_SIZE);
 	if (status < 0) {
 		rsi_dbg(ERR_ZONE, "Unable to get TA out of reset\n");
-		return status;
+		goto err;
 	}
 
 	put_unaligned_le32(TA_PC_ZERO, data);
@@ -964,7 +968,8 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
 						  RSI_9116_REG_SIZE);
 	if (status < 0) {
 		rsi_dbg(ERR_ZONE, "Unable to Reset TA PC value\n");
-		return -EINVAL;
+		status = -EINVAL;
+		goto err;
 	}
 
 	put_unaligned_le32(TA_RELEASE_THREAD_VALUE, data);
@@ -974,17 +979,19 @@ static int rsi_sdio_ta_reset(struct rsi_hw *adapter)
 						  RSI_9116_REG_SIZE);
 	if (status < 0) {
 		rsi_dbg(ERR_ZONE, "Unable to release TA threads\n");
-		return status;
+		goto err;
 	}
 
 	status = rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR);
 	if (status < 0) {
 		rsi_dbg(ERR_ZONE, "Unable to set ms word to common reg\n");
-		return status;
+		goto err;
 	}
 	rsi_dbg(INIT_ZONE, "***** TA Reset done *****\n");
 
-	return 0;
+err:
+	kfree(data);
+	return status;
 }
 
 static struct rsi_host_intf_ops sdio_host_intf_ops = {
-- 
2.21.0


^ permalink raw reply related

* [PATCH v2] rtw88: Make RA_MASK macros ULL
From: Nathan Chancellor @ 2019-05-02 15:02 UTC (permalink / raw)
  To: Yan-Hsuan Chuang, Kalle Valo
  Cc: linux-wireless, netdev, linux-kernel, clang-built-linux,
	Nick Desaulniers, Nathan Chancellor
In-Reply-To: <20190502150022.4182-1-natechancellor@gmail.com>

Clang warns about the definitions of these macros (full warnings trimmed
for brevity):

drivers/net/wireless/realtek/rtw88/main.c:524:15: warning: signed shift
result (0x3FF00000000) requires 43 bits to represent, but 'int' only has
32 bits [-Wshift-overflow]
                        ra_mask &= RA_MASK_VHT_RATES | RA_MASK_OFDM_IN_VHT;
                                   ^~~~~~~~~~~~~~~~~
drivers/net/wireless/realtek/rtw88/main.c:527:15: warning: signed shift
result (0xFF0000000) requires 37 bits to represent, but 'int' only has
32 bits [-Wshift-overflow]
                        ra_mask &= RA_MASK_HT_RATES | RA_MASK_OFDM_IN_HT_5G;
                                   ^~~~~~~~~~~~~~~~

Given that these are all used with ra_mask, which is of type u64, we can
just declare the macros to be ULL as well.

Fixes: e3037485c68e ("rtw88: new Realtek 802.11ac driver")
Link: https://github.com/ClangBuiltLinux/linux/issues/467
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
---

v1 -> v2:

* Fix commit message wording (made -> make)...

 drivers/net/wireless/realtek/rtw88/main.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 9893e5e297e3..a14a5f1b4b6d 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -462,15 +462,15 @@ static u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 tx_num)
 
 #define RA_MASK_CCK_RATES	0x0000f
 #define RA_MASK_OFDM_RATES	0x00ff0
-#define RA_MASK_HT_RATES_1SS	(0xff000 << 0)
-#define RA_MASK_HT_RATES_2SS	(0xff000 << 8)
-#define RA_MASK_HT_RATES_3SS	(0xff000 << 16)
+#define RA_MASK_HT_RATES_1SS	(0xff000ULL << 0)
+#define RA_MASK_HT_RATES_2SS	(0xff000ULL << 8)
+#define RA_MASK_HT_RATES_3SS	(0xff000ULL << 16)
 #define RA_MASK_HT_RATES	(RA_MASK_HT_RATES_1SS | \
 				 RA_MASK_HT_RATES_2SS | \
 				 RA_MASK_HT_RATES_3SS)
-#define RA_MASK_VHT_RATES_1SS	(0x3ff000 << 0)
-#define RA_MASK_VHT_RATES_2SS	(0x3ff000 << 10)
-#define RA_MASK_VHT_RATES_3SS	(0x3ff000 << 20)
+#define RA_MASK_VHT_RATES_1SS	(0x3ff000ULL << 0)
+#define RA_MASK_VHT_RATES_2SS	(0x3ff000ULL << 10)
+#define RA_MASK_VHT_RATES_3SS	(0x3ff000ULL << 20)
 #define RA_MASK_VHT_RATES	(RA_MASK_VHT_RATES_1SS | \
 				 RA_MASK_VHT_RATES_2SS | \
 				 RA_MASK_VHT_RATES_3SS)
-- 
2.21.0


^ permalink raw reply related

* [PATCH] rtw88: Made RA_MASK macros ULL
From: Nathan Chancellor @ 2019-05-02 15:00 UTC (permalink / raw)
  To: Yan-Hsuan Chuang, Kalle Valo
  Cc: linux-wireless, netdev, linux-kernel, clang-built-linux,
	Nick Desaulniers, Nathan Chancellor

Clang warns about the definitions of these macros (full warnings trimmed
for brevity):

drivers/net/wireless/realtek/rtw88/main.c:524:15: warning: signed shift
result (0x3FF00000000) requires 43 bits to represent, but 'int' only has
32 bits [-Wshift-overflow]
                        ra_mask &= RA_MASK_VHT_RATES | RA_MASK_OFDM_IN_VHT;
                                   ^~~~~~~~~~~~~~~~~
drivers/net/wireless/realtek/rtw88/main.c:527:15: warning: signed shift
result (0xFF0000000) requires 37 bits to represent, but 'int' only has
32 bits [-Wshift-overflow]
                        ra_mask &= RA_MASK_HT_RATES | RA_MASK_OFDM_IN_HT_5G;
                                   ^~~~~~~~~~~~~~~~

Given that these are all used with ra_mask, which is of type u64, we can
just declare the macros to be ULL as well.

Fixes: e3037485c68e ("rtw88: new Realtek 802.11ac driver")
Link: https://github.com/ClangBuiltLinux/linux/issues/467
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
---
 drivers/net/wireless/realtek/rtw88/main.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 9893e5e297e3..a14a5f1b4b6d 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -462,15 +462,15 @@ static u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 tx_num)
 
 #define RA_MASK_CCK_RATES	0x0000f
 #define RA_MASK_OFDM_RATES	0x00ff0
-#define RA_MASK_HT_RATES_1SS	(0xff000 << 0)
-#define RA_MASK_HT_RATES_2SS	(0xff000 << 8)
-#define RA_MASK_HT_RATES_3SS	(0xff000 << 16)
+#define RA_MASK_HT_RATES_1SS	(0xff000ULL << 0)
+#define RA_MASK_HT_RATES_2SS	(0xff000ULL << 8)
+#define RA_MASK_HT_RATES_3SS	(0xff000ULL << 16)
 #define RA_MASK_HT_RATES	(RA_MASK_HT_RATES_1SS | \
 				 RA_MASK_HT_RATES_2SS | \
 				 RA_MASK_HT_RATES_3SS)
-#define RA_MASK_VHT_RATES_1SS	(0x3ff000 << 0)
-#define RA_MASK_VHT_RATES_2SS	(0x3ff000 << 10)
-#define RA_MASK_VHT_RATES_3SS	(0x3ff000 << 20)
+#define RA_MASK_VHT_RATES_1SS	(0x3ff000ULL << 0)
+#define RA_MASK_VHT_RATES_2SS	(0x3ff000ULL << 10)
+#define RA_MASK_VHT_RATES_3SS	(0x3ff000ULL << 20)
 #define RA_MASK_VHT_RATES	(RA_MASK_VHT_RATES_1SS | \
 				 RA_MASK_VHT_RATES_2SS | \
 				 RA_MASK_VHT_RATES_3SS)
-- 
2.21.0


^ permalink raw reply related

* Re: [PATCH][next] rtw88: phy: mark expected switch fall-throughs
From: Kalle Valo @ 2019-05-02 14:59 UTC (permalink / raw)
  To: Gustavo A. R. Silva
  Cc: Yan-Hsuan Chuang, David S. Miller, linux-wireless, netdev,
	linux-kernel, Gustavo A. R. Silva, Kees Cook
In-Reply-To: <20190501151615.GA18557@embeddedor>

"Gustavo A. R. Silva" <gustavo@embeddedor.com> wrote:

> In preparation to enabling -Wimplicit-fallthrough, mark switch
> cases where we are expecting to fall through.
> 
> This patch fixes the following warnings:
> 
> drivers/net/wireless/realtek/rtw88/phy.c: In function ‘rtw_get_channel_group’:
> ./include/linux/compiler.h:77:22: warning: this statement may fall through [-Wimplicit-fallthrough=]
>  # define unlikely(x) __builtin_expect(!!(x), 0)
>                       ^~~~~~~~~~~~~~~~~~~~~~~~~~
> ./include/asm-generic/bug.h:125:2: note: in expansion of macro ‘unlikely’
>   unlikely(__ret_warn_on);     \
>   ^~~~~~~~
> drivers/net/wireless/realtek/rtw88/phy.c:907:3: note: in expansion of macro ‘WARN_ON’
>    WARN_ON(1);
>    ^~~~~~~
> drivers/net/wireless/realtek/rtw88/phy.c:908:2: note: here
>   case 1:
>   ^~~~
> In file included from ./include/linux/bcd.h:5,
>                  from drivers/net/wireless/realtek/rtw88/phy.c:5:
> drivers/net/wireless/realtek/rtw88/phy.c: In function ‘phy_get_2g_tx_power_index’:
> ./include/linux/compiler.h:77:22: warning: this statement may fall through [-Wimplicit-fallthrough=]
>  # define unlikely(x) __builtin_expect(!!(x), 0)
>                       ^~~~~~~~~~~~~~~~~~~~~~~~~~
> ./include/asm-generic/bug.h:125:2: note: in expansion of macro ‘unlikely’
>   unlikely(__ret_warn_on);     \
>   ^~~~~~~~
> drivers/net/wireless/realtek/rtw88/phy.c:1021:3: note: in expansion of macro ‘WARN_ON’
>    WARN_ON(1);
>    ^~~~~~~
> drivers/net/wireless/realtek/rtw88/phy.c:1022:2: note: here
>   case RTW_CHANNEL_WIDTH_20:
>   ^~~~
> 
> Warning level 3 was used: -Wimplicit-fallthrough=3
> 
> This patch is part of the ongoing efforts to enable
> -Wimplicit-fallthrough.
> 
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>

Patch applied to wireless-drivers-next.git, thanks.

aa8eaaaa123a rtw88: phy: mark expected switch fall-throughs

-- 
https://patchwork.kernel.org/patch/10925201/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


^ permalink raw reply

* Re: [PATCH][next] rtw88: fix shift of more than 32 bits of a integer
From: Kalle Valo @ 2019-05-02 14:58 UTC (permalink / raw)
  To: Colin King
  Cc: Yan-Hsuan Chuang, David S . Miller, linux-wireless, netdev,
	kernel-janitors, linux-kernel
In-Reply-To: <20190501141945.22522-1-colin.king@canonical.com>

Colin King <colin.king@canonical.com> wrote:

> From: Colin Ian King <colin.king@canonical.com>
> 
> Currently the shift of an integer value more than 32 bits can
> occur when nss is more than 32.  Fix this by making the integer
> constants unsigned long longs before shifting and bit-wise or'ing
> with the u64 ra_mask to avoid the undefined shift behaviour.
> 
> Addresses-Coverity: ("Bad shift operation")
> Fixes: e3037485c68e ("rtw88: new Realtek 802.11ac driver")
> Signed-off-by: Colin Ian King <colin.king@canonical.com>

Patch applied to wireless-drivers-next.git, thanks.

b85bd9a14c4b rtw88: fix shift of more than 32 bits of a integer

-- 
https://patchwork.kernel.org/patch/10925147/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


^ permalink raw reply

* Re: [RFC/RFT 3/7] rt2800: initial watchdog implementation
From: Kalle Valo @ 2019-05-02 14:57 UTC (permalink / raw)
  To: Stanislaw Gruszka
  Cc: linux-wireless, Tomislav Požega, Daniel Golle, Felix Fietkau,
	Mathias Kresin
In-Reply-To: <1556788021-6531-4-git-send-email-sgruszka@redhat.com>

Stanislaw Gruszka <sgruszka@redhat.com> wrote:

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

Dropped per request.

Patch set to Rejected.

-- 
https://patchwork.kernel.org/patch/10926399/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


^ permalink raw reply

* Re: carl9170 crash
From: tedheadster @ 2019-05-02 14:03 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Matthew Whitehead, Christian Lamparter, linux-wireless
In-Reply-To: <87k1fawsio.fsf@purkki.adurom.net>

Kalle,
  I just tried to bisect this and got an unexpected result: commit
4c3f49ae1306c05e91211c06feddfd0a4a57fabd "Merge branch 'for-5.1-fixes'
of git://git.kernel.org/pub/scm/linux/kernel/git/dennis/percpu".

I wanted to share this in case it is correct. I have a stronger
suspicion that the problem has a race condition and appears
intermittently, hence a peculiar bisect outcome.

I will keep debugging.

- Matthew Whitehead

^ permalink raw reply

* [PATCH] ath10k: Check tx_stats before use it
From: Yingying Tang @ 2019-05-02 13:36 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless

tx_stats will be freed and set to NULL before debugfs_sta node is
removed in station disconnetion process. So if read the debugfs_sta
node there may be NULL pointer error. Add check for tx_stats before
use it to resove this issue.

Signed-off-by: Yingying Tang <yintang@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/debugfs_sta.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
index 0f3fd65..4a8d94d 100644
--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
@@ -674,6 +674,13 @@ static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file,
 
 	mutex_lock(&ar->conf_mutex);
 
+	if (!arsta->tx_stats) {
+		ath10k_warn(ar, "failed to get tx stats");
+		mutex_unlock(&ar->conf_mutex);
+		kfree(buf);
+		return 0;
+	}
+
 	spin_lock_bh(&ar->data_lock);
 	for (k = 0; k < ATH10K_STATS_TYPE_MAX; k++) {
 		for (j = 0; j < ATH10K_COUNTER_TYPE_MAX; j++) {
-- 
1.9.1


^ permalink raw reply related

* Re: [RFC/RFT 3/7] rt2800: initial watchdog implementation
From: Stanislaw Gruszka @ 2019-05-02  9:16 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556788021-6531-4-git-send-email-sgruszka@redhat.com>

On Thu, May 02, 2019 at 11:06:56AM +0200, Stanislaw Gruszka wrote:
> 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>

Please drop this patch, it was posted accidently. 

Stanislaw


^ permalink raw reply

* [PATCH 7/7] rt2800: do not enable watchdog by default
From: Stanislaw Gruszka @ 2019-05-02  9:07 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556788021-6531-1-git-send-email-sgruszka@redhat.com>

Make watchdog disabled by default and add module parameter to enable it.

User will have to create file in /etc/modprobe.d/ with

options rt2800lib watchdog=1

to enable the watchdog or load "rt2800lib watchdog=1" module manually
before loading rt2800{soc,pci,usb} module.

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

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index a509953d7c2e..3c04e8fb65b5 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -41,6 +41,10 @@
 #include "rt2800lib.h"
 #include "rt2800.h"
 
+static bool modparam_watchdog;
+module_param_named(watchdog, modparam_watchdog, bool, S_IRUGO);
+MODULE_PARM_DESC(watchdog, "Enable watchdog to detect tx/rx hangs and reset hardware if detected");
+
 /*
  * Register access.
  * All access to the CSR registers will go through the methods
@@ -10289,8 +10293,12 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 		__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
 	}
 
-	__set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags);
-	rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
+	if (modparam_watchdog) {
+		__set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags);
+		rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
+	} else {
+		rt2x00dev->link.watchdog_disabled = true;
+	}
 
 	/*
 	 * Set the rssi offset.
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 1d7eaa9ecffb..c76d41272b03 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -337,6 +337,7 @@ struct link {
 	 */
 	struct delayed_work watchdog_work;
 	unsigned int watchdog_interval;
+	bool watchdog_disabled;
 
 	/*
 	 * 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 fcc59553918f..db4b164ac848 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
@@ -395,7 +395,7 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
 	struct link *link = &rt2x00dev->link;
 
 	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
-	    rt2x00dev->ops->lib->watchdog)
+	    rt2x00dev->ops->lib->watchdog && !link->watchdog_disabled)
 		ieee80211_queue_delayed_work(rt2x00dev->hw,
 					     &link->watchdog_work,
 					     link->watchdog_interval);
-- 
2.7.5


^ permalink raw reply related

* [PATCH 6/7] rt2x00: add restart hw
From: Stanislaw Gruszka @ 2019-05-02  9:07 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556788021-6531-1-git-send-email-sgruszka@redhat.com>

Add ieee80211_restart_hw() to watchdog and debugfs file for testing
if restart works as expected.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c   |  4 +++
 drivers/net/wireless/ralink/rt2x00/rt2x00.h      |  7 +++++
 drivers/net/wireless/ralink/rt2x00/rt2x00debug.c | 35 ++++++++++++++++++++++++
 drivers/net/wireless/ralink/rt2x00/rt2x00dev.c   | 10 +++++--
 4 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 44c1057542a2..a509953d7c2e 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1266,6 +1266,9 @@ void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
 
 	if (hung_rx)
 		rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n");
+
+	if (hung_tx || hung_rx)
+		ieee80211_restart_hw(rt2x00dev->hw);
 }
 EXPORT_SYMBOL_GPL(rt2800_watchdog);
 
@@ -10286,6 +10289,7 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 		__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
 	}
 
+	__set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags);
 	rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
 
 	/*
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index cdf496c55b9d..1d7eaa9ecffb 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -724,6 +724,7 @@ enum rt2x00_capability_flags {
 	CAPABILITY_VCO_RECALIBRATION,
 	CAPABILITY_EXTERNAL_PA_TX0,
 	CAPABILITY_EXTERNAL_PA_TX1,
+	CAPABILITY_RESTART_HW,
 };
 
 /*
@@ -1281,6 +1282,12 @@ rt2x00_has_cap_vco_recalibration(struct rt2x00_dev *rt2x00dev)
 	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION);
 }
 
+static inline bool
+rt2x00_has_cap_restart_hw(struct rt2x00_dev *rt2x00dev)
+{
+	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RESTART_HW);
+}
+
 /**
  * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
  * @entry: Pointer to &struct queue_entry
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
index 05a2e8da412c..860a19cae3e5 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
@@ -63,6 +63,7 @@ struct rt2x00debug_intf {
 	 *   - chipset file
 	 *   - device state flags file
 	 *   - device capability flags file
+	 *   - hardware restart file
 	 *   - register folder
 	 *     - csr offset/value files
 	 *     - eeprom offset/value files
@@ -79,6 +80,7 @@ struct rt2x00debug_intf {
 	struct dentry *chipset_entry;
 	struct dentry *dev_flags;
 	struct dentry *cap_flags;
+	struct dentry *restart_hw;
 	struct dentry *register_folder;
 	struct dentry *csr_off_entry;
 	struct dentry *csr_val_entry;
@@ -577,6 +579,34 @@ static const struct file_operations rt2x00debug_fop_cap_flags = {
 	.llseek		= default_llseek,
 };
 
+static ssize_t rt2x00debug_write_restart_hw(struct file *file,
+					    const char __user *buf,
+					    size_t length,
+					    loff_t *offset)
+{
+	struct rt2x00debug_intf *intf =	file->private_data;
+	struct rt2x00_dev *rt2x00dev = intf->rt2x00dev;
+	static unsigned long last_reset;
+
+	if (!rt2x00_has_cap_restart_hw(rt2x00dev))
+		return -EOPNOTSUPP;
+
+	if (time_before(jiffies, last_reset + msecs_to_jiffies(2000)))
+		return -EBUSY;
+
+	last_reset = jiffies;
+
+	ieee80211_restart_hw(rt2x00dev->hw);
+	return length;
+}
+
+static const struct file_operations rt2x00debug_restart_hw = {
+	.owner = THIS_MODULE,
+	.write = rt2x00debug_write_restart_hw,
+	.open = simple_open,
+	.llseek = generic_file_llseek,
+};
+
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
 						     struct rt2x00debug_intf
 						     *intf,
@@ -672,6 +702,10 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 					      intf->driver_folder, intf,
 					      &rt2x00debug_fop_cap_flags);
 
+	intf->restart_hw = debugfs_create_file("restart_hw", 0200,
+					       intf->driver_folder, intf,
+					       &rt2x00debug_restart_hw);
+
 	intf->register_folder =
 	    debugfs_create_dir("register", intf->driver_folder);
 
@@ -753,6 +787,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 	debugfs_remove(intf->csr_off_entry);
 	debugfs_remove(intf->register_folder);
 	debugfs_remove(intf->dev_flags);
+	debugfs_remove(intf->restart_hw);
 	debugfs_remove(intf->cap_flags);
 	debugfs_remove(intf->chipset_entry);
 	debugfs_remove(intf->driver_entry);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index 357c0941aaad..93ab4d089b21 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -1269,8 +1269,14 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
 {
 	int retval;
 
-	if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
-		return 0;
+	if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
+		/*
+		 * This is special case for ieee80211_restart_hw(), otherwise
+		 * mac80211 never call start() two times in row without stop();
+		 */
+		rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev);
+		rt2x00lib_stop(rt2x00dev);
+	}
 
 	/*
 	 * If this is the first interface which is added,
-- 
2.7.5


^ permalink raw reply related

* [PATCH 5/7] rt2800: do not nullify initialization vector data
From: Stanislaw Gruszka @ 2019-05-02  9:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556788021-6531-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 c3409578bf97..44c1057542a2 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

* [PATCH 4/7] rt2800: add pre_reset_hw callback
From: Stanislaw Gruszka @ 2019-05-02  9:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556788021-6531-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..c3409578bf97 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

* [PATCH 3/7] rt2800: initial watchdog implementation
From: Stanislaw Gruszka @ 2019-05-02  9:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556788021-6531-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 3/7] rt2800: initial watchdog implementation
From: Stanislaw Gruszka @ 2019-05-02  9:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556788021-6531-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

* [PATCH 2/7] rt2800: add helpers for reading dma done index
From: Stanislaw Gruszka @ 2019-05-02  9:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556788021-6531-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

* [PATCH 1/7] rt2x00: allow to specify watchdog interval
From: Stanislaw Gruszka @ 2019-05-02  9:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: Tomislav Požega, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1556788021-6531-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

* [PATCH 0/7] rt2800: add experimental watchdog implementation
From: Stanislaw Gruszka @ 2019-05-02  9:06 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.

RFC -> v1
 - better description for module parameter 
 - fix white space

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


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