Search Linux Wireless

Re: [PATCH v4 3/8] rtw88: add napi support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Jan 15, 2021 at 1:26 AM Ping-Ke Shih <pkshih@xxxxxxxxxxx> wrote:
> --- a/drivers/net/wireless/realtek/rtw88/pci.c
> +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> @@ -935,16 +935,49 @@ static void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
>         ring->r.rp = cur_rp;
>  }
>
> -static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
> +static void rtw_pci_rx_isr(struct rtw_dev *rtwdev)
> +{
> +       struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> +       struct napi_struct *napi = &rtwpci->napi;
> +
> +       napi_schedule(napi);

I don't claim to be all that familiar with NAPI, but my understanding
is that you are scheduling a NAPI poll, but immediately after you
return here, you're re-enabling your RX interrupt. That doesn't sound
like how NAPI is supposed to work -- you're supposed to wait to
re-enable your interrupt until you're done with your polling function.
Ref: https://wiki.linuxfoundation.org/networking/napi

> +}
...
> +static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
>                            u8 hw_queue)
...

Are you sure you don't want any locking in rtw_pci_rx_napi()?
Previously, you held irq_lock for the entirety of rtw_pci_rx_isr(),
but now all the RX work is being deferred to a NAPI context, without
any additional lock. IIUC, that means you can be both handling RX and
other ISR operations at the same time. Is that intentional?

> +static int rtw_pci_napi_poll(struct napi_struct *napi, int budget)
> +{
> +       struct rtw_pci *rtwpci = container_of(napi, struct rtw_pci, napi);
> +       struct rtw_dev *rtwdev = container_of((void *)rtwpci, struct rtw_dev,
> +                                             priv);
> +       int work_done = 0;
> +
> +       while (work_done < budget) {
> +               u32 work_done_once;
> +
> +               work_done_once = rtw_pci_rx_napi(rtwdev, rtwpci,
> +                                                RTW_RX_QUEUE_MPDU);
> +               if (work_done_once == 0)
> +                       break;
> +               work_done += work_done_once;
> +       }
> +       if (work_done < budget) {
> +               napi_complete_done(napi, work_done);
> +               /* When ISR happens during polling and before napi_complete
> +                * while no further data is received. Data on the dma_ring will
> +                * not be processed immediately. Check whether dma ring is
> +                * empty and perform napi_schedule accordingly.
> +                */
> +               if (rtw_pci_get_hw_rx_ring_nr(rtwdev, rtwpci, NULL, NULL))
> +                       napi_schedule(napi);
> +       }
> +
> +       return work_done;
> +}
> +
> +static void rtw_pci_napi_init(struct rtw_dev *rtwdev)
> +{
> +       struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> +
> +       init_dummy_netdev(&rtwpci->netdev);
> +       netif_napi_add(&rtwpci->netdev, &rtwpci->napi, rtw_pci_napi_poll,
> +                      RTW_NAPI_WEIGHT_NUM);
> +       napi_enable(&rtwpci->napi);
> +}
...
> @@ -1547,6 +1624,8 @@ int rtw_pci_probe(struct pci_dev *pdev,
>                 goto err_destroy_pci;
>         }
>
> +       rtw_pci_napi_init(rtwdev);

You're initializing NAPI after you've already established your ISR,
and your ISR might start scheduling NAPI. Even if that's unlikely
(because you haven't initiated any RX traffic yet), it seems like an
ordering problem -- shouldn't you initialize the NAPI device, then set
up the ISR, and only then call napi_enable()?

Brian

> +
>         return 0;
>
>  err_destroy_pci:



[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux