diff mbox series

wifi: rtw88/usb: stop rx work before potential power off

Message ID 20240603145535.1858856-1-marcin.slusarz@gmail.com (mailing list archive)
State Changes Requested
Delegated to: Ping-Ke Shih
Headers show
Series wifi: rtw88/usb: stop rx work before potential power off | expand

Commit Message

Marcin Ślusarz June 3, 2024, 2:55 p.m. UTC
From: Marcin Ślusarz <mslusarz@renau.com>

Avoids WARN_ON(!local->started) in ieee80211_rx_list, after
the patch that disables power management of 8821CU.

Signed-off-by: Marcin Ślusarz <mslusarz@renau.com>
---
 drivers/net/wireless/realtek/rtw88/hci.h  | 12 +++++++
 drivers/net/wireless/realtek/rtw88/main.c |  7 +++-
 drivers/net/wireless/realtek/rtw88/pci.c  |  6 ++++
 drivers/net/wireless/realtek/rtw88/sdio.c |  6 ++++
 drivers/net/wireless/realtek/rtw88/usb.c  | 40 +++++++++++++++--------
 drivers/net/wireless/realtek/rtw88/usb.h  |  1 +
 6 files changed, 58 insertions(+), 14 deletions(-)

Comments

Ping-Ke Shih June 4, 2024, 12:57 a.m. UTC | #1
Marcin Ślusarz <marcin.slusarz@gmail.com> wrote:
> From: Marcin Ślusarz <mslusarz@renau.com>
> 
> Avoids WARN_ON(!local->started) in ieee80211_rx_list, after
> the patch that disables power management of 8821CU.

Please describe how/what you do in this patch. 

> 
> Signed-off-by: Marcin Ślusarz <mslusarz@renau.com>
> ---
>  drivers/net/wireless/realtek/rtw88/hci.h  | 12 +++++++
>  drivers/net/wireless/realtek/rtw88/main.c |  7 +++-
>  drivers/net/wireless/realtek/rtw88/pci.c  |  6 ++++
>  drivers/net/wireless/realtek/rtw88/sdio.c |  6 ++++
>  drivers/net/wireless/realtek/rtw88/usb.c  | 40 +++++++++++++++--------
>  drivers/net/wireless/realtek/rtw88/usb.h  |  1 +
>  6 files changed, 58 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h
> index 830d7532f2a3..d1b38b34fdd0 100644
> --- a/drivers/net/wireless/realtek/rtw88/hci.h
> +++ b/drivers/net/wireless/realtek/rtw88/hci.h
> @@ -18,6 +18,8 @@ struct rtw_hci_ops {
>         void (*deep_ps)(struct rtw_dev *rtwdev, bool enter);
>         void (*link_ps)(struct rtw_dev *rtwdev, bool enter);
>         void (*interface_cfg)(struct rtw_dev *rtwdev);
> +       void (*stop_rx)(struct rtw_dev *rtwdev);
> +       void (*start_rx)(struct rtw_dev *rtwdev);
> 
>         int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
>         int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
> @@ -57,6 +59,16 @@ static inline void rtw_hci_stop(struct rtw_dev *rtwdev)
>         rtwdev->hci.ops->stop(rtwdev);
>  }
> 
> +static inline void rtw_hci_start_rx(struct rtw_dev *rtwdev)
> +{

For PCI/SDIO nop, I would like to give them NULL, so here can be

if (rtwdev->hci.ops->start_rx)
	rtwdev->hci.ops->start_rx(rtwdev);

> +       rtwdev->hci.ops->start_rx(rtwdev);
> +}
> +
> +static inline void rtw_hci_stop_rx(struct rtw_dev *rtwdev)
> +{
> +       rtwdev->hci.ops->stop_rx(rtwdev);
> +}
> +
>  static inline void rtw_hci_deep_ps(struct rtw_dev *rtwdev, bool enter)
>  {
>         rtwdev->hci.ops->deep_ps(rtwdev, enter);
> diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
> index a48e919adddb..bb0122d19416 100644
> --- a/drivers/net/wireless/realtek/rtw88/main.c
> +++ b/drivers/net/wireless/realtek/rtw88/main.c
> @@ -1357,7 +1357,7 @@ static int rtw_power_on(struct rtw_dev *rtwdev)
>         int ret;
> 
>         if (rtwdev->always_power_on && test_bit(RTW_FLAG_POWERON, rtwdev->flags))
> -               return 0;
> +               goto success;

rtw_hci_start_rx(rtwdev) is only needed by this case, so 

if (rtwdev->always_power_on && test_bit(RTW_FLAG_POWERON, rtwdev->flags)) {
	rtw_hci_start_rx(rtwdev);
	return 0;
}

> 
>         ret = rtw_hci_setup(rtwdev);
>         if (ret) {
> @@ -1407,6 +1407,9 @@ static int rtw_power_on(struct rtw_dev *rtwdev)
>         rtw_coex_power_on_setting(rtwdev);
>         rtw_coex_init_hw_config(rtwdev, wifi_only);
> 
> +success:
> +       rtw_hci_start_rx(rtwdev);
> +
>         return 0;
> 
>  err_off:
> @@ -1509,6 +1512,8 @@ int rtw_core_start(struct rtw_dev *rtwdev)
> 
>  static void rtw_power_off(struct rtw_dev *rtwdev)
>  {
> +       rtw_hci_stop_rx(rtwdev);
> +

Similarly here can be

if (rtwdev->always_power_on) {
	rtw_hci_stop_rx(rtwdev);
	return;
}


>         if (rtwdev->always_power_on)
>                 return;
> 
> diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
> index 7a093f3d5f74..0a3ec94f6ab2 100644
> --- a/drivers/net/wireless/realtek/rtw88/pci.c
> +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> @@ -1590,6 +1590,10 @@ static void rtw_pci_destroy(struct rtw_dev *rtwdev, struct pci_dev *pdev)
>         rtw_pci_io_unmapping(rtwdev, pdev);
>  }
> 
> +static void rtw_pci_nop(struct rtw_dev *rtwdev)
> +{
> +}
> +
>  static struct rtw_hci_ops rtw_pci_ops = {
>         .tx_write = rtw_pci_tx_write,
>         .tx_kick_off = rtw_pci_tx_kick_off,
> @@ -1600,6 +1604,8 @@ static struct rtw_hci_ops rtw_pci_ops = {
>         .deep_ps = rtw_pci_deep_ps,
>         .link_ps = rtw_pci_link_ps,
>         .interface_cfg = rtw_pci_interface_cfg,
> +       .stop_rx = rtw_pci_nop,
> +       .start_rx = rtw_pci_nop,
> 
>         .read8 = rtw_pci_read8,
>         .read16 = rtw_pci_read16,
> diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
> index 0cae5746f540..4a7923851c81 100644
> --- a/drivers/net/wireless/realtek/rtw88/sdio.c
> +++ b/drivers/net/wireless/realtek/rtw88/sdio.c
> @@ -1147,6 +1147,10 @@ static void rtw_sdio_declaim(struct rtw_dev *rtwdev,
>         sdio_release_host(sdio_func);
>  }
> 
> +static void rtw_sdio_nop(struct rtw_dev *rtwdev)
> +{
> +}
> +
>  static struct rtw_hci_ops rtw_sdio_ops = {
>         .tx_write = rtw_sdio_tx_write,
>         .tx_kick_off = rtw_sdio_tx_kick_off,
> @@ -1156,6 +1160,8 @@ static struct rtw_hci_ops rtw_sdio_ops = {
>         .deep_ps = rtw_sdio_deep_ps,
>         .link_ps = rtw_sdio_link_ps,
>         .interface_cfg = rtw_sdio_interface_cfg,
> +       .stop_rx = rtw_sdio_nop,
> +       .start_rx = rtw_sdio_nop,
> 
>         .read8 = rtw_sdio_read8,
>         .read16 = rtw_sdio_read16,
> diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
> index e1b66f339cca..d5cf3eb51c8a 100644
> --- a/drivers/net/wireless/realtek/rtw88/usb.c
> +++ b/drivers/net/wireless/realtek/rtw88/usb.c
> @@ -716,6 +716,30 @@ static void rtw_usb_interface_cfg(struct rtw_dev *rtwdev)
>         /* empty function for rtw_hci_ops */
>  }
> 
> +static void rtw_usb_stop_rx(struct rtw_dev *rtwdev)
> +{
> +       struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);

Do we really need a ' rtwusb->rx_enabled' to maintain symmetric calling of 
start/stop_rx? If yes, here should add

	if (!rtwusb->rx_enabled)
		return;

But, I don't like that flag if it isn't strongly required. 

> +       rtw_usb_cancel_rx_bufs(rtwusb);
> +       rtwusb->rx_enabled = false;
> +}
> +
> +static void rtw_usb_start_rx(struct rtw_dev *rtwdev)
> +{
> +       struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
> +       int i;
> +
> +       if (rtwusb->rx_enabled)
> +               return;
> +
> +       for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
> +               struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
> +
> +               rtw_usb_rx_resubmit(rtwusb, rxcb);
> +       }
> +
> +       rtwusb->rx_enabled = true;
> +}
> +
>  static struct rtw_hci_ops rtw_usb_ops = {
>         .tx_write = rtw_usb_tx_write,
>         .tx_kick_off = rtw_usb_tx_kick_off,
> @@ -725,6 +749,8 @@ static struct rtw_hci_ops rtw_usb_ops = {
>         .deep_ps = rtw_usb_deep_ps,
>         .link_ps = rtw_usb_link_ps,
>         .interface_cfg = rtw_usb_interface_cfg,
> +       .stop_rx = rtw_usb_stop_rx,
> +       .start_rx = rtw_usb_start_rx,
> 
>         .write8  = rtw_usb_write8,
>         .write16 = rtw_usb_write16,
> @@ -754,18 +780,6 @@ static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
>         return 0;
>  }
> 
> -static void rtw_usb_setup_rx(struct rtw_dev *rtwdev)
> -{
> -       struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
> -       int i;
> -
> -       for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
> -               struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
> -
> -               rtw_usb_rx_resubmit(rtwusb, rxcb);
> -       }
> -}
> -
>  static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)
>  {
>         struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
> @@ -903,7 +917,7 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
>                 goto err_destroy_rxwq;
>         }
> 
> -       rtw_usb_setup_rx(rtwdev);
> +       rtw_usb_start_rx(rtwdev);
> 
>         return 0;
> 
> diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h
> index 86697a5c0103..a6b004d4f74e 100644
> --- a/drivers/net/wireless/realtek/rtw88/usb.h
> +++ b/drivers/net/wireless/realtek/rtw88/usb.h
> @@ -82,6 +82,7 @@ struct rtw_usb {
>         struct rx_usb_ctrl_block rx_cb[RTW_USB_RXCB_NUM];
>         struct sk_buff_head rx_queue;
>         struct work_struct rx_work;
> +       bool rx_enabled;
>  };
> 
>  static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb)
> --
> 2.25.1
>
Marcin Ślusarz June 14, 2024, 11:35 a.m. UTC | #2
wt., 4 cze 2024 o 02:57 Ping-Ke Shih <pkshih@realtek.com> napisał(a):
>
> Marcin Ślusarz <marcin.slusarz@gmail.com> wrote:
> > From: Marcin Ślusarz <mslusarz@renau.com>
> >
> > Avoids WARN_ON(!local->started) in ieee80211_rx_list, after
> > the patch that disables power management of 8821CU.
>
> Please describe how/what you do in this patch.
>
> >
> > Signed-off-by: Marcin Ślusarz <mslusarz@renau.com>
> > ---
> >  drivers/net/wireless/realtek/rtw88/hci.h  | 12 +++++++
> >  drivers/net/wireless/realtek/rtw88/main.c |  7 +++-
> >  drivers/net/wireless/realtek/rtw88/pci.c  |  6 ++++
> >  drivers/net/wireless/realtek/rtw88/sdio.c |  6 ++++
> >  drivers/net/wireless/realtek/rtw88/usb.c  | 40 +++++++++++++++--------
> >  drivers/net/wireless/realtek/rtw88/usb.h  |  1 +
> >  6 files changed, 58 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h
> > index 830d7532f2a3..d1b38b34fdd0 100644
> > --- a/drivers/net/wireless/realtek/rtw88/hci.h
> > +++ b/drivers/net/wireless/realtek/rtw88/hci.h
> > @@ -18,6 +18,8 @@ struct rtw_hci_ops {
> >         void (*deep_ps)(struct rtw_dev *rtwdev, bool enter);
> >         void (*link_ps)(struct rtw_dev *rtwdev, bool enter);
> >         void (*interface_cfg)(struct rtw_dev *rtwdev);
> > +       void (*stop_rx)(struct rtw_dev *rtwdev);
> > +       void (*start_rx)(struct rtw_dev *rtwdev);
> >
> >         int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
> >         int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
> > @@ -57,6 +59,16 @@ static inline void rtw_hci_stop(struct rtw_dev *rtwdev)
> >         rtwdev->hci.ops->stop(rtwdev);
> >  }
> >
> > +static inline void rtw_hci_start_rx(struct rtw_dev *rtwdev)
> > +{
>
> For PCI/SDIO nop, I would like to give them NULL, so here can be
>
> if (rtwdev->hci.ops->start_rx)
>         rtwdev->hci.ops->start_rx(rtwdev);

Sure

>
> > +       rtwdev->hci.ops->start_rx(rtwdev);
> > +}
> > +
> > +static inline void rtw_hci_stop_rx(struct rtw_dev *rtwdev)
> > +{
> > +       rtwdev->hci.ops->stop_rx(rtwdev);
> > +}
> > +
> >  static inline void rtw_hci_deep_ps(struct rtw_dev *rtwdev, bool enter)
> >  {
> >         rtwdev->hci.ops->deep_ps(rtwdev, enter);
> > diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
> > index a48e919adddb..bb0122d19416 100644
> > --- a/drivers/net/wireless/realtek/rtw88/main.c
> > +++ b/drivers/net/wireless/realtek/rtw88/main.c
> > @@ -1357,7 +1357,7 @@ static int rtw_power_on(struct rtw_dev *rtwdev)
> >         int ret;
> >
> >         if (rtwdev->always_power_on && test_bit(RTW_FLAG_POWERON, rtwdev->flags))
> > -               return 0;
> > +               goto success;
>
> rtw_hci_start_rx(rtwdev) is only needed by this case, so
>
> if (rtwdev->always_power_on && test_bit(RTW_FLAG_POWERON, rtwdev->flags)) {
>         rtw_hci_start_rx(rtwdev);
>         return 0;
> }

Yes, strictly speaking, it's needed only in the always_power_on case,
but doing that in the common code path ensures that it's tested and
still works.

>
> >
> >         ret = rtw_hci_setup(rtwdev);
> >         if (ret) {
> > @@ -1407,6 +1407,9 @@ static int rtw_power_on(struct rtw_dev *rtwdev)
> >         rtw_coex_power_on_setting(rtwdev);
> >         rtw_coex_init_hw_config(rtwdev, wifi_only);
> >
> > +success:
> > +       rtw_hci_start_rx(rtwdev);
> > +
> >         return 0;
> >
> >  err_off:
> > @@ -1509,6 +1512,8 @@ int rtw_core_start(struct rtw_dev *rtwdev)
> >
> >  static void rtw_power_off(struct rtw_dev *rtwdev)
> >  {
> > +       rtw_hci_stop_rx(rtwdev);
> > +
>
> Similarly here can be
>
> if (rtwdev->always_power_on) {
>         rtw_hci_stop_rx(rtwdev);
>         return;
> }

Ditto

>
>
> >         if (rtwdev->always_power_on)
> >                 return;
> >
> > diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
> > index 7a093f3d5f74..0a3ec94f6ab2 100644
> > --- a/drivers/net/wireless/realtek/rtw88/pci.c
> > +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> > @@ -1590,6 +1590,10 @@ static void rtw_pci_destroy(struct rtw_dev *rtwdev, struct pci_dev *pdev)
> >         rtw_pci_io_unmapping(rtwdev, pdev);
> >  }
> >
> > +static void rtw_pci_nop(struct rtw_dev *rtwdev)
> > +{
> > +}
> > +
> >  static struct rtw_hci_ops rtw_pci_ops = {
> >         .tx_write = rtw_pci_tx_write,
> >         .tx_kick_off = rtw_pci_tx_kick_off,
> > @@ -1600,6 +1604,8 @@ static struct rtw_hci_ops rtw_pci_ops = {
> >         .deep_ps = rtw_pci_deep_ps,
> >         .link_ps = rtw_pci_link_ps,
> >         .interface_cfg = rtw_pci_interface_cfg,
> > +       .stop_rx = rtw_pci_nop,
> > +       .start_rx = rtw_pci_nop,
> >
> >         .read8 = rtw_pci_read8,
> >         .read16 = rtw_pci_read16,
> > diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
> > index 0cae5746f540..4a7923851c81 100644
> > --- a/drivers/net/wireless/realtek/rtw88/sdio.c
> > +++ b/drivers/net/wireless/realtek/rtw88/sdio.c
> > @@ -1147,6 +1147,10 @@ static void rtw_sdio_declaim(struct rtw_dev *rtwdev,
> >         sdio_release_host(sdio_func);
> >  }
> >
> > +static void rtw_sdio_nop(struct rtw_dev *rtwdev)
> > +{
> > +}
> > +
> >  static struct rtw_hci_ops rtw_sdio_ops = {
> >         .tx_write = rtw_sdio_tx_write,
> >         .tx_kick_off = rtw_sdio_tx_kick_off,
> > @@ -1156,6 +1160,8 @@ static struct rtw_hci_ops rtw_sdio_ops = {
> >         .deep_ps = rtw_sdio_deep_ps,
> >         .link_ps = rtw_sdio_link_ps,
> >         .interface_cfg = rtw_sdio_interface_cfg,
> > +       .stop_rx = rtw_sdio_nop,
> > +       .start_rx = rtw_sdio_nop,
> >
> >         .read8 = rtw_sdio_read8,
> >         .read16 = rtw_sdio_read16,
> > diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
> > index e1b66f339cca..d5cf3eb51c8a 100644
> > --- a/drivers/net/wireless/realtek/rtw88/usb.c
> > +++ b/drivers/net/wireless/realtek/rtw88/usb.c
> > @@ -716,6 +716,30 @@ static void rtw_usb_interface_cfg(struct rtw_dev *rtwdev)
> >         /* empty function for rtw_hci_ops */
> >  }
> >
> > +static void rtw_usb_stop_rx(struct rtw_dev *rtwdev)
> > +{
> > +       struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
>
> Do we really need a ' rtwusb->rx_enabled' to maintain symmetric calling of
> start/stop_rx? If yes, here should add
>
>         if (!rtwusb->rx_enabled)
>                 return;

Sure

> But, I don't like that flag if it isn't strongly required.

It's required because start_rx is called twice initially - from
rtw_usb_probe and rtw_core_start (via rtw_power_on).

>
> > +       rtw_usb_cancel_rx_bufs(rtwusb);
> > +       rtwusb->rx_enabled = false;
> > +}
> > +
> > +static void rtw_usb_start_rx(struct rtw_dev *rtwdev)
> > +{
> > +       struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
> > +       int i;
> > +
> > +       if (rtwusb->rx_enabled)
> > +               return;
> > +
> > +       for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
> > +               struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
> > +
> > +               rtw_usb_rx_resubmit(rtwusb, rxcb);
> > +       }
> > +
> > +       rtwusb->rx_enabled = true;
> > +}
> > +
> >  static struct rtw_hci_ops rtw_usb_ops = {
> >         .tx_write = rtw_usb_tx_write,
> >         .tx_kick_off = rtw_usb_tx_kick_off,
> > @@ -725,6 +749,8 @@ static struct rtw_hci_ops rtw_usb_ops = {
> >         .deep_ps = rtw_usb_deep_ps,
> >         .link_ps = rtw_usb_link_ps,
> >         .interface_cfg = rtw_usb_interface_cfg,
> > +       .stop_rx = rtw_usb_stop_rx,
> > +       .start_rx = rtw_usb_start_rx,
> >
> >         .write8  = rtw_usb_write8,
> >         .write16 = rtw_usb_write16,
> > @@ -754,18 +780,6 @@ static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
> >         return 0;
> >  }
> >
> > -static void rtw_usb_setup_rx(struct rtw_dev *rtwdev)
> > -{
> > -       struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
> > -       int i;
> > -
> > -       for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
> > -               struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
> > -
> > -               rtw_usb_rx_resubmit(rtwusb, rxcb);
> > -       }
> > -}
> > -
> >  static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)
> >  {
> >         struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
> > @@ -903,7 +917,7 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
> >                 goto err_destroy_rxwq;
> >         }
> >
> > -       rtw_usb_setup_rx(rtwdev);
> > +       rtw_usb_start_rx(rtwdev);
> >
> >         return 0;
> >
> > diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h
> > index 86697a5c0103..a6b004d4f74e 100644
> > --- a/drivers/net/wireless/realtek/rtw88/usb.h
> > +++ b/drivers/net/wireless/realtek/rtw88/usb.h
> > @@ -82,6 +82,7 @@ struct rtw_usb {
> >         struct rx_usb_ctrl_block rx_cb[RTW_USB_RXCB_NUM];
> >         struct sk_buff_head rx_queue;
> >         struct work_struct rx_work;
> > +       bool rx_enabled;
> >  };
> >
> >  static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb)
> > --
> > 2.25.1
> >
>
Ping-Ke Shih June 17, 2024, 1:47 a.m. UTC | #3
Marcin Ślusarz <marcin.slusarz@gmail.com> wrote:
> wt., 4 cze 2024 o 02:57 Ping-Ke Shih <pkshih@realtek.com> napisał(a):
> >
> > Marcin Ślusarz <marcin.slusarz@gmail.com> wrote:
> > > --- a/drivers/net/wireless/realtek/rtw88/main.c
> > > +++ b/drivers/net/wireless/realtek/rtw88/main.c
> > > @@ -1357,7 +1357,7 @@ static int rtw_power_on(struct rtw_dev *rtwdev)
> > >         int ret;
> > >
> > >         if (rtwdev->always_power_on && test_bit(RTW_FLAG_POWERON, rtwdev->flags))
> > > -               return 0;
> > > +               goto success;
> >
> > rtw_hci_start_rx(rtwdev) is only needed by this case, so
> >
> > if (rtwdev->always_power_on && test_bit(RTW_FLAG_POWERON, rtwdev->flags)) {
> >         rtw_hci_start_rx(rtwdev);
> >         return 0;
> > }
> 
> Yes, strictly speaking, it's needed only in the always_power_on case,
> but doing that in the common code path ensures that it's tested and
> still works.

For the non- always_power_on case, it calls rtw_hci_start()/rtw_hci_stop() already
so I don't think we should call these duplicates.
diff mbox series

Patch

diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h
index 830d7532f2a3..d1b38b34fdd0 100644
--- a/drivers/net/wireless/realtek/rtw88/hci.h
+++ b/drivers/net/wireless/realtek/rtw88/hci.h
@@ -18,6 +18,8 @@  struct rtw_hci_ops {
 	void (*deep_ps)(struct rtw_dev *rtwdev, bool enter);
 	void (*link_ps)(struct rtw_dev *rtwdev, bool enter);
 	void (*interface_cfg)(struct rtw_dev *rtwdev);
+	void (*stop_rx)(struct rtw_dev *rtwdev);
+	void (*start_rx)(struct rtw_dev *rtwdev);
 
 	int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
 	int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
@@ -57,6 +59,16 @@  static inline void rtw_hci_stop(struct rtw_dev *rtwdev)
 	rtwdev->hci.ops->stop(rtwdev);
 }
 
+static inline void rtw_hci_start_rx(struct rtw_dev *rtwdev)
+{
+	rtwdev->hci.ops->start_rx(rtwdev);
+}
+
+static inline void rtw_hci_stop_rx(struct rtw_dev *rtwdev)
+{
+	rtwdev->hci.ops->stop_rx(rtwdev);
+}
+
 static inline void rtw_hci_deep_ps(struct rtw_dev *rtwdev, bool enter)
 {
 	rtwdev->hci.ops->deep_ps(rtwdev, enter);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index a48e919adddb..bb0122d19416 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -1357,7 +1357,7 @@  static int rtw_power_on(struct rtw_dev *rtwdev)
 	int ret;
 
 	if (rtwdev->always_power_on && test_bit(RTW_FLAG_POWERON, rtwdev->flags))
-		return 0;
+		goto success;
 
 	ret = rtw_hci_setup(rtwdev);
 	if (ret) {
@@ -1407,6 +1407,9 @@  static int rtw_power_on(struct rtw_dev *rtwdev)
 	rtw_coex_power_on_setting(rtwdev);
 	rtw_coex_init_hw_config(rtwdev, wifi_only);
 
+success:
+	rtw_hci_start_rx(rtwdev);
+
 	return 0;
 
 err_off:
@@ -1509,6 +1512,8 @@  int rtw_core_start(struct rtw_dev *rtwdev)
 
 static void rtw_power_off(struct rtw_dev *rtwdev)
 {
+	rtw_hci_stop_rx(rtwdev);
+
 	if (rtwdev->always_power_on)
 		return;
 
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index 7a093f3d5f74..0a3ec94f6ab2 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -1590,6 +1590,10 @@  static void rtw_pci_destroy(struct rtw_dev *rtwdev, struct pci_dev *pdev)
 	rtw_pci_io_unmapping(rtwdev, pdev);
 }
 
+static void rtw_pci_nop(struct rtw_dev *rtwdev)
+{
+}
+
 static struct rtw_hci_ops rtw_pci_ops = {
 	.tx_write = rtw_pci_tx_write,
 	.tx_kick_off = rtw_pci_tx_kick_off,
@@ -1600,6 +1604,8 @@  static struct rtw_hci_ops rtw_pci_ops = {
 	.deep_ps = rtw_pci_deep_ps,
 	.link_ps = rtw_pci_link_ps,
 	.interface_cfg = rtw_pci_interface_cfg,
+	.stop_rx = rtw_pci_nop,
+	.start_rx = rtw_pci_nop,
 
 	.read8 = rtw_pci_read8,
 	.read16 = rtw_pci_read16,
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 0cae5746f540..4a7923851c81 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -1147,6 +1147,10 @@  static void rtw_sdio_declaim(struct rtw_dev *rtwdev,
 	sdio_release_host(sdio_func);
 }
 
+static void rtw_sdio_nop(struct rtw_dev *rtwdev)
+{
+}
+
 static struct rtw_hci_ops rtw_sdio_ops = {
 	.tx_write = rtw_sdio_tx_write,
 	.tx_kick_off = rtw_sdio_tx_kick_off,
@@ -1156,6 +1160,8 @@  static struct rtw_hci_ops rtw_sdio_ops = {
 	.deep_ps = rtw_sdio_deep_ps,
 	.link_ps = rtw_sdio_link_ps,
 	.interface_cfg = rtw_sdio_interface_cfg,
+	.stop_rx = rtw_sdio_nop,
+	.start_rx = rtw_sdio_nop,
 
 	.read8 = rtw_sdio_read8,
 	.read16 = rtw_sdio_read16,
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index e1b66f339cca..d5cf3eb51c8a 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -716,6 +716,30 @@  static void rtw_usb_interface_cfg(struct rtw_dev *rtwdev)
 	/* empty function for rtw_hci_ops */
 }
 
+static void rtw_usb_stop_rx(struct rtw_dev *rtwdev)
+{
+	struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+	rtw_usb_cancel_rx_bufs(rtwusb);
+	rtwusb->rx_enabled = false;
+}
+
+static void rtw_usb_start_rx(struct rtw_dev *rtwdev)
+{
+	struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+	int i;
+
+	if (rtwusb->rx_enabled)
+		return;
+
+	for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
+		struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
+
+		rtw_usb_rx_resubmit(rtwusb, rxcb);
+	}
+
+	rtwusb->rx_enabled = true;
+}
+
 static struct rtw_hci_ops rtw_usb_ops = {
 	.tx_write = rtw_usb_tx_write,
 	.tx_kick_off = rtw_usb_tx_kick_off,
@@ -725,6 +749,8 @@  static struct rtw_hci_ops rtw_usb_ops = {
 	.deep_ps = rtw_usb_deep_ps,
 	.link_ps = rtw_usb_link_ps,
 	.interface_cfg = rtw_usb_interface_cfg,
+	.stop_rx = rtw_usb_stop_rx,
+	.start_rx = rtw_usb_start_rx,
 
 	.write8  = rtw_usb_write8,
 	.write16 = rtw_usb_write16,
@@ -754,18 +780,6 @@  static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
 	return 0;
 }
 
-static void rtw_usb_setup_rx(struct rtw_dev *rtwdev)
-{
-	struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
-	int i;
-
-	for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
-		struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
-
-		rtw_usb_rx_resubmit(rtwusb, rxcb);
-	}
-}
-
 static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)
 {
 	struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
@@ -903,7 +917,7 @@  int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 		goto err_destroy_rxwq;
 	}
 
-	rtw_usb_setup_rx(rtwdev);
+	rtw_usb_start_rx(rtwdev);
 
 	return 0;
 
diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h
index 86697a5c0103..a6b004d4f74e 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.h
+++ b/drivers/net/wireless/realtek/rtw88/usb.h
@@ -82,6 +82,7 @@  struct rtw_usb {
 	struct rx_usb_ctrl_block rx_cb[RTW_USB_RXCB_NUM];
 	struct sk_buff_head rx_queue;
 	struct work_struct rx_work;
+	bool rx_enabled;
 };
 
 static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb)