diff mbox series

[rtw-next,v1,06/13] wifi: rtw89: Disable some power saving for USB

Message ID c64fe6a4-b48c-4a80-9d6c-5c90fb7f7bbd@gmail.com
State New
Headers show
Series wifi: rtw89: Add support for USB devices | expand

Commit Message

Bitterblue Smith May 4, 2025, 8:51 p.m. UTC
Disable rtw89_ps_power_mode_change() and rtw89_mac_send_rpwm() for
USB because they are called in atomic context and accessing hardware
registers results in "scheduling while atomic" errors.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/mac.c | 3 +++
 drivers/net/wireless/realtek/rtw89/ps.c  | 3 +++
 2 files changed, 6 insertions(+)

Comments

Ping-Ke Shih May 13, 2025, 3:27 a.m. UTC | #1
Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Disable rtw89_ps_power_mode_change() and rtw89_mac_send_rpwm() for
> USB because they are called in atomic context and accessing hardware
> registers results in "scheduling while atomic" errors.

I feel rtw89_ps_power_mode_change() should be not in atomic context.
Please check this. 

> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> ---
>  drivers/net/wireless/realtek/rtw89/mac.c | 3 +++
>  drivers/net/wireless/realtek/rtw89/ps.c  | 3 +++
>  2 files changed, 6 insertions(+)
> 
> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
> index a316864ad137..1a03355b340f 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac.c
> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
> @@ -1338,6 +1338,9 @@ static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
>  {
>         u16 request;
> 
> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)

I think SDIO devices have the same problems as USB, so I prefer to return
if "!= PCIE".

> +               return;
> +
>         spin_lock_bh(&rtwdev->rpwm_lock);
> 
>         request = rtw89_read16(rtwdev, R_AX_RPWM);
> diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
> index ac46a7baa00d..edff9f8e1016 100644
> --- a/drivers/net/wireless/realtek/rtw89/ps.c
> +++ b/drivers/net/wireless/realtek/rtw89/ps.c
> @@ -56,6 +56,9 @@ static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
> 
>  static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
>  {
> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
> +               return;
> +
>         if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) &&
>             !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags))
>                 rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
> --
> 2.49.0
Bitterblue Smith May 25, 2025, 9:57 p.m. UTC | #2
On 13/05/2025 06:27, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> Disable rtw89_ps_power_mode_change() and rtw89_mac_send_rpwm() for
>> USB because they are called in atomic context and accessing hardware
>> registers results in "scheduling while atomic" errors.
> 
> I feel rtw89_ps_power_mode_change() should be not in atomic context.
> Please check this. 
> 

I think you're right, only rtw89_mac_send_rpwm() is called in atomic
context. rtw89_ps_power_mode_change() is disabled for other reasons:

1) It calls rtw89_mac_power_mode_change(), which prints errors when
rtw89_mac_send_rpwm() is disabled.

2) With RTL8852CU it calls rtw89_ps_power_mode_change_with_hci()
which calls napi_schedule(). That results in dereferencing a null
pointer.

>>
>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>> ---
>>  drivers/net/wireless/realtek/rtw89/mac.c | 3 +++
>>  drivers/net/wireless/realtek/rtw89/ps.c  | 3 +++
>>  2 files changed, 6 insertions(+)
>>
>> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
>> index a316864ad137..1a03355b340f 100644
>> --- a/drivers/net/wireless/realtek/rtw89/mac.c
>> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
>> @@ -1338,6 +1338,9 @@ static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
>>  {
>>         u16 request;
>>
>> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
> 
> I think SDIO devices have the same problems as USB, so I prefer to return
> if "!= PCIE".
> 
>> +               return;
>> +
>>         spin_lock_bh(&rtwdev->rpwm_lock);
>>
>>         request = rtw89_read16(rtwdev, R_AX_RPWM);
>> diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
>> index ac46a7baa00d..edff9f8e1016 100644
>> --- a/drivers/net/wireless/realtek/rtw89/ps.c
>> +++ b/drivers/net/wireless/realtek/rtw89/ps.c
>> @@ -56,6 +56,9 @@ static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
>>
>>  static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
>>  {
>> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
>> +               return;
>> +
>>         if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) &&
>>             !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags))
>>                 rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
>> --
>> 2.49.0
>
Ping-Ke Shih May 26, 2025, 2:36 a.m. UTC | #3
Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> On 13/05/2025 06:27, Ping-Ke Shih wrote:
> > Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> >> Disable rtw89_ps_power_mode_change() and rtw89_mac_send_rpwm() for
> >> USB because they are called in atomic context and accessing hardware
> >> registers results in "scheduling while atomic" errors.
> >
> > I feel rtw89_ps_power_mode_change() should be not in atomic context.
> > Please check this.
> >
> 
> I think you're right, only rtw89_mac_send_rpwm() is called in atomic
> context. rtw89_ps_power_mode_change() is disabled for other reasons:

The rtw89_ps_power_mode_change() is to enter deep power save mode, which
can save more power save but need to leave the mode before you are going
to do IO/TX/RX. That means if you totally disable it, code flow would
be simpler, but power consumption would be higher. Since this is the
first patches to enable USB, I suggest you can disable it totally for
now, and add it later. 

> 
> 1) It calls rtw89_mac_power_mode_change(), which prints errors when
> rtw89_mac_send_rpwm() is disabled.
> 
> 2) With RTL8852CU it calls rtw89_ps_power_mode_change_with_hci()
> which calls napi_schedule(). That results in dereferencing a null
> pointer.

I see. Your implementation doesn't use NAPI for USB devices. 

The rtw89_ps_power_mode_change_with_hci() is to switch IO address for
PCI devices in deep power save mode, and USB devices don't need this.
I think we can run this only if HCI is PCI.
diff mbox series

Patch

diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index a316864ad137..1a03355b340f 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1338,6 +1338,9 @@  static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
 {
 	u16 request;
 
+	if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
+		return;
+
 	spin_lock_bh(&rtwdev->rpwm_lock);
 
 	request = rtw89_read16(rtwdev, R_AX_RPWM);
diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
index ac46a7baa00d..edff9f8e1016 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.c
+++ b/drivers/net/wireless/realtek/rtw89/ps.c
@@ -56,6 +56,9 @@  static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
 
 static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
 {
+	if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
+		return;
+
 	if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) &&
 	    !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags))
 		rtw89_ps_power_mode_change_with_hci(rtwdev, enter);