2023-02-21 02:39:47

by Kai-Heng Feng

[permalink] [raw]
Subject: [PATCH v8 RESEND 0/6] r8169: Enable ASPM for recent 1.0/2.5Gbps Realtek NICs

The series is to enable ASPM on more r8169 supported devices, if
available.

The latest Realtek vendor driver and its Windows driver implements a
feature called "dynamic ASPM" which can improve performance on it's
ethernet NICs.

We have "dynamic ASPM" mechanism in Ubuntu 22.04 LTS kernel for quite a
while, and AFAIK it hasn't introduced any regression so far.

A very similar issue was observed on Realtek wireless NIC, and it was
resolved by disabling ASPM during NAPI poll. So in v8, we use the same
approach, which is more straightforward, instead of toggling ASPM based
on packet count.

v7:
https://lore.kernel.org/netdev/[email protected]/

v6:
https://lore.kernel.org/netdev/[email protected]/

v5:
https://lore.kernel.org/netdev/[email protected]/

v4:
https://lore.kernel.org/netdev/[email protected]/

v3:
https://lore.kernel.org/netdev/[email protected]/

v2:
https://lore.kernel.org/netdev/[email protected]/

v1:
https://lore.kernel.org/netdev/[email protected]/

Kai-Heng Feng (6):
r8169: Disable ASPM L1.1 on 8168h
Revert "PCI/ASPM: Unexport pcie_aspm_support_enabled()"
PCI/ASPM: Add pcie_aspm_capable() helper
r8169: Consider chip-specific ASPM can be enabled on more cases
r8169: Use mutex to guard config register locking
r8169: Disable ASPM while doing NAPI poll

drivers/net/ethernet/realtek/r8169_main.c | 48 ++++++++++++++++++-----
drivers/pci/pcie/aspm.c | 12 ++++++
include/linux/pci.h | 2 +
3 files changed, 53 insertions(+), 9 deletions(-)

--
2.34.1



2023-02-21 02:40:07

by Kai-Heng Feng

[permalink] [raw]
Subject: [PATCH v8 RESEND 1/6] r8169: Disable ASPM L1.1 on 8168h

ASPM L1/L1.1 gets enabled based on [0], but ASPM L1.1 was actually
disabled too [1].

So also disable L1.1 for better compatibility.

[0] https://bugs.launchpad.net/bugs/1942830
[1] https://git.launchpad.net/~canonical-kernel/ubuntu/+source/linux-oem/+git/focal/commit/?id=c9b3736de48fd419d6699045d59a0dd1041da014

Signed-off-by: Kai-Heng Feng <[email protected]>
---
v8:
- New patch.

drivers/net/ethernet/realtek/r8169_main.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)


diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 45147a1016bec..1c949822661ae 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -5224,13 +5224,13 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)

/* Disable ASPM L1 as that cause random device stop working
* problems as well as full system hangs for some PCIe devices users.
- * Chips from RTL8168h partially have issues with L1.2, but seem
- * to work fine with L1 and L1.1.
+ * Chips from RTL8168h partially have issues with L1.1 and L1.2, but
+ * seem to work fine with L1.
*/
if (rtl_aspm_is_safe(tp))
rc = 0;
else if (tp->mac_version >= RTL_GIGA_MAC_VER_46)
- rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2);
+ rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2);
else
rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
tp->aspm_manageable = !rc;
--
2.34.1


2023-02-21 02:40:10

by Kai-Heng Feng

[permalink] [raw]
Subject: [PATCH v8 RESEND 2/6] Revert "PCI/ASPM: Unexport pcie_aspm_support_enabled()"

This reverts commit ba13d4575da5e656a3cbc18583e0da5c5d865417.

This will be used by module once again.

Signed-off-by: Kai-Heng Feng <[email protected]>
---
v8:
- New patch.

drivers/pci/pcie/aspm.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 4b4184563a927..692d6953f0970 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -1372,3 +1372,4 @@ bool pcie_aspm_support_enabled(void)
{
return aspm_support_enabled;
}
+EXPORT_SYMBOL(pcie_aspm_support_enabled);
--
2.34.1


2023-02-21 02:40:22

by Kai-Heng Feng

[permalink] [raw]
Subject: [PATCH v8 RESEND 3/6] PCI/ASPM: Add pcie_aspm_capable() helper

Introduce a new helper, pcie_aspm_capable(), to report ASPM capability.

The user will be introduced by next patch.

Acked-by: Bjorn Helgaas <[email protected]>
Suggested-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Kai-Heng Feng <[email protected]>
---
v8:
- No change.

v7:
- Change subject.

v6:
- No change.

v5:
- No change.

v4:
- Report aspm_capable instead.

v3:
- This is a new patch

drivers/pci/pcie/aspm.c | 11 +++++++++++
include/linux/pci.h | 2 ++
2 files changed, 13 insertions(+)

diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 692d6953f0970..d96bf0a362aa2 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -1199,6 +1199,17 @@ bool pcie_aspm_enabled(struct pci_dev *pdev)
}
EXPORT_SYMBOL_GPL(pcie_aspm_enabled);

+bool pcie_aspm_capable(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link = pcie_aspm_get_link(pdev);
+
+ if (!link)
+ return false;
+
+ return link->aspm_capable;
+}
+EXPORT_SYMBOL_GPL(pcie_aspm_capable);
+
static ssize_t aspm_attr_show_common(struct device *dev,
struct device_attribute *attr,
char *buf, u8 state)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index adffd65e84b4e..fd56872883e14 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1692,6 +1692,7 @@ int pci_disable_link_state_locked(struct pci_dev *pdev, int state);
void pcie_no_aspm(void);
bool pcie_aspm_support_enabled(void);
bool pcie_aspm_enabled(struct pci_dev *pdev);
+bool pcie_aspm_capable(struct pci_dev *pdev);
#else
static inline int pci_disable_link_state(struct pci_dev *pdev, int state)
{ return 0; }
@@ -1700,6 +1701,7 @@ static inline int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
static inline void pcie_no_aspm(void) { }
static inline bool pcie_aspm_support_enabled(void) { return false; }
static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }
+static inline bool pcie_aspm_capable(struct pci_dev *pdev) { return false; }
#endif

#ifdef CONFIG_PCIEAER
--
2.34.1


2023-02-21 02:40:26

by Kai-Heng Feng

[permalink] [raw]
Subject: [PATCH v8 RESEND 4/6] r8169: Consider chip-specific ASPM can be enabled on more cases

To really enable ASPM on r8169 NICs, both standard PCIe ASPM and
chip-specific ASPM have to be enabled at the same time.

Before enabling ASPM at chip side, make sure the following conditions
are met:
1) Use pcie_aspm_support_enabled() to check if ASPM is disabled by
kernel parameter.
2) Use pcie_aspm_capable() to see if the device is capable to perform
PCIe ASPM.
3) Check the return value of pci_disable_link_state(). If it's -EPERM,
it means BIOS doesn't grant ASPM control to OS, and device should use
the ASPM setting as is

Consider ASPM is manageable when those conditions are met.

While at it, disable ASPM at chip-side for TX timeout reset, since
pci_disable_link_state() doesn't have any effect when OS isn't granted
with ASPM control.

Signed-off-by: Kai-Heng Feng <[email protected]>
---
v8:
- Enable chip-side ASPM only when PCIe ASPM is already available.
- Wording.

v7:
- No change.

v6:
- Unconditionally enable chip-specific ASPM.

v5:
- New patch.

drivers/net/ethernet/realtek/r8169_main.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 1c949822661ae..e40498dd08d17 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -2675,8 +2675,11 @@ static void rtl_disable_exit_l1(struct rtl8169_private *tp)

static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
{
- /* Don't enable ASPM in the chip if OS can't control ASPM */
- if (enable && tp->aspm_manageable) {
+ /* Skip if PCIe ASPM isn't possible */
+ if (!tp->aspm_manageable)
+ return;
+
+ if (enable) {
RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en);
RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn);

@@ -4545,8 +4548,13 @@ static void rtl_task(struct work_struct *work)
/* ASPM compatibility issues are a typical reason for tx timeouts */
ret = pci_disable_link_state(tp->pci_dev, PCIE_LINK_STATE_L1 |
PCIE_LINK_STATE_L0S);
+
+ /* OS may not be granted to control PCIe ASPM, prevent the driver from using it */
+ tp->aspm_manageable = 0;
+
if (!ret)
netdev_warn_once(tp->dev, "ASPM disabled on Tx timeout\n");
+
goto reset;
}

@@ -5227,13 +5235,19 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
* Chips from RTL8168h partially have issues with L1.1 and L1.2, but
* seem to work fine with L1.
*/
- if (rtl_aspm_is_safe(tp))
+ if (!pcie_aspm_support_enabled() || !pcie_aspm_capable(pdev))
+ rc = -EINVAL;
+ else if (rtl_aspm_is_safe(tp))
rc = 0;
else if (tp->mac_version >= RTL_GIGA_MAC_VER_46)
rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2);
else
rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
- tp->aspm_manageable = !rc;
+
+ /* -EPERM means BIOS doesn't grant OS ASPM control, ASPM should be use
+ * as is. Honor it.
+ */
+ tp->aspm_manageable = (rc == -EPERM) ? 1 : !rc;

tp->dash_type = rtl_check_dash(tp);

--
2.34.1


2023-02-21 02:40:44

by Kai-Heng Feng

[permalink] [raw]
Subject: [PATCH v8 RESEND 5/6] r8169: Use mutex to guard config register locking

Right now r8169 doesn't have parallel access to its config register, but
the next patch makes the driver access config register at anytime.

So add a mutex to protect the config register from any potential race.

Signed-off-by: Kai-Heng Feng <[email protected]>
---
v8:
- Swap the place when using the mutex. Protect when config register is
unlocked.

v7:
- This is a new patch.

drivers/net/ethernet/realtek/r8169_main.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index e40498dd08d17..897f90b48bba6 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -613,6 +613,8 @@ struct rtl8169_private {
struct work_struct work;
} wk;

+ struct mutex config_lock;
+
unsigned supports_gmii:1;
unsigned aspm_manageable:1;
dma_addr_t counters_phys_addr;
@@ -662,10 +664,12 @@ static inline struct device *tp_to_dev(struct rtl8169_private *tp)
static void rtl_lock_config_regs(struct rtl8169_private *tp)
{
RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+ mutex_unlock(&tp->config_lock);
}

static void rtl_unlock_config_regs(struct rtl8169_private *tp)
{
+ mutex_lock(&tp->config_lock);
RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
}

@@ -5217,6 +5221,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
}

+ mutex_init(&tp->config_lock);
+
tp->mmio_addr = pcim_iomap_table(pdev)[region];

xid = (RTL_R32(tp, TxConfig) >> 20) & 0xfcf;
--
2.34.1


2023-02-21 02:40:57

by Kai-Heng Feng

[permalink] [raw]
Subject: [PATCH v8 RESEND 6/6] r8169: Disable ASPM while doing NAPI poll

NAPI poll of Realtek NICs don't seem to perform well ASPM is enabled.
The vendor driver uses a mechanism called "dynamic ASPM" to toggle ASPM
based on the packet number in given time period.

Instead of implementing "dynamic ASPM", use a more straightforward way
by disabling ASPM during NAPI poll, as a similar approach was
implemented to solve slow performance on Realtek wireless NIC, see
commit 24f5e38a13b5 ("rtw88: Disable PCIe ASPM while doing NAPI poll on
8821CE").

Since NAPI poll should be handled as fast as possible, also remove the
delay in rtl_hw_aspm_clkreq_enable() which was added by commit
94235460f9ea ("r8169: Align ASPM/CLKREQ setting function with vendor
driver").

Signed-off-by: Kai-Heng Feng <[email protected]>
---
v8:
- New patch.

drivers/net/ethernet/realtek/r8169_main.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 897f90b48bba6..4d4a802346ae3 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -2711,8 +2711,6 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
}
-
- udelay(10);
}

static void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat,
@@ -4577,6 +4575,12 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
struct net_device *dev = tp->dev;
int work_done;

+ if (tp->aspm_manageable) {
+ rtl_unlock_config_regs(tp);
+ rtl_hw_aspm_clkreq_enable(tp, false);
+ rtl_lock_config_regs(tp);
+ }
+
rtl_tx(dev, tp, budget);

work_done = rtl_rx(dev, tp, budget);
@@ -4584,6 +4588,12 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
if (work_done < budget && napi_complete_done(napi, work_done))
rtl_irq_enable(tp);

+ if (tp->aspm_manageable) {
+ rtl_unlock_config_regs(tp);
+ rtl_hw_aspm_clkreq_enable(tp, true);
+ rtl_lock_config_regs(tp);
+ }
+
return work_done;
}

--
2.34.1


2023-02-21 11:09:11

by Heiner Kallweit

[permalink] [raw]
Subject: Re: [PATCH v8 RESEND 0/6] r8169: Enable ASPM for recent 1.0/2.5Gbps Realtek NICs

On 21.02.2023 03:38, Kai-Heng Feng wrote:
> The series is to enable ASPM on more r8169 supported devices, if
> available.
>
> The latest Realtek vendor driver and its Windows driver implements a
> feature called "dynamic ASPM" which can improve performance on it's
> ethernet NICs.
>
> We have "dynamic ASPM" mechanism in Ubuntu 22.04 LTS kernel for quite a
> while, and AFAIK it hasn't introduced any regression so far.
>
> A very similar issue was observed on Realtek wireless NIC, and it was
> resolved by disabling ASPM during NAPI poll. So in v8, we use the same
> approach, which is more straightforward, instead of toggling ASPM based
> on packet count.
>
> v7:
> https://lore.kernel.org/netdev/[email protected]/
>
> v6:
> https://lore.kernel.org/netdev/[email protected]/
>
> v5:
> https://lore.kernel.org/netdev/[email protected]/
>
> v4:
> https://lore.kernel.org/netdev/[email protected]/
>
> v3:
> https://lore.kernel.org/netdev/[email protected]/
>
> v2:
> https://lore.kernel.org/netdev/[email protected]/
>
> v1:
> https://lore.kernel.org/netdev/[email protected]/
>
> Kai-Heng Feng (6):
> r8169: Disable ASPM L1.1 on 8168h
> Revert "PCI/ASPM: Unexport pcie_aspm_support_enabled()"
> PCI/ASPM: Add pcie_aspm_capable() helper
> r8169: Consider chip-specific ASPM can be enabled on more cases
> r8169: Use mutex to guard config register locking
> r8169: Disable ASPM while doing NAPI poll
>
> drivers/net/ethernet/realtek/r8169_main.c | 48 ++++++++++++++++++-----
> drivers/pci/pcie/aspm.c | 12 ++++++
> include/linux/pci.h | 2 +
> 3 files changed, 53 insertions(+), 9 deletions(-)
>

Note that net-next is closed during merge window.
Formal aspect: Your patches miss the net/net-next annotation.
The title of the series may be an old one. Actually most ASPM
states are enabled, you add to disable ASPM temporarily.

2023-02-21 11:09:15

by Heiner Kallweit

[permalink] [raw]
Subject: Re: [PATCH v8 RESEND 1/6] r8169: Disable ASPM L1.1 on 8168h

On 21.02.2023 03:38, Kai-Heng Feng wrote:
> ASPM L1/L1.1 gets enabled based on [0], but ASPM L1.1 was actually
> disabled too [1].
>
> So also disable L1.1 for better compatibility.
>
> [0] https://bugs.launchpad.net/bugs/1942830
> [1] https://git.launchpad.net/~canonical-kernel/ubuntu/+source/linux-oem/+git/focal/commit/?id=c9b3736de48fd419d6699045d59a0dd1041da014
>
These references are about problems with L1.2 (which is disabled
per default in mainline). They don't allow any statement about whether
L1.1 is problematic too (and under which circumstances).
At least on my system with RTL8168h there's no problem with L1.1
when running iperf.

> Signed-off-by: Kai-Heng Feng <[email protected]>
> ---
> v8:
> - New patch.
>
> drivers/net/ethernet/realtek/r8169_main.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
>
> diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
> index 45147a1016bec..1c949822661ae 100644
> --- a/drivers/net/ethernet/realtek/r8169_main.c
> +++ b/drivers/net/ethernet/realtek/r8169_main.c
> @@ -5224,13 +5224,13 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>
> /* Disable ASPM L1 as that cause random device stop working
> * problems as well as full system hangs for some PCIe devices users.
> - * Chips from RTL8168h partially have issues with L1.2, but seem
> - * to work fine with L1 and L1.1.
> + * Chips from RTL8168h partially have issues with L1.1 and L1.2, but
> + * seem to work fine with L1.
> */
> if (rtl_aspm_is_safe(tp))
> rc = 0;
> else if (tp->mac_version >= RTL_GIGA_MAC_VER_46)
> - rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2);
> + rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2);
> else
> rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
> tp->aspm_manageable = !rc;


2023-02-21 11:09:19

by Heiner Kallweit

[permalink] [raw]
Subject: Re: [PATCH v8 RESEND 6/6] r8169: Disable ASPM while doing NAPI poll

On 21.02.2023 03:38, Kai-Heng Feng wrote:
> NAPI poll of Realtek NICs don't seem to perform well ASPM is enabled.
> The vendor driver uses a mechanism called "dynamic ASPM" to toggle ASPM
> based on the packet number in given time period.
>
> Instead of implementing "dynamic ASPM", use a more straightforward way
> by disabling ASPM during NAPI poll, as a similar approach was
> implemented to solve slow performance on Realtek wireless NIC, see
> commit 24f5e38a13b5 ("rtw88: Disable PCIe ASPM while doing NAPI poll on
> 8821CE").
>
> Since NAPI poll should be handled as fast as possible, also remove the
> delay in rtl_hw_aspm_clkreq_enable() which was added by commit
> 94235460f9ea ("r8169: Align ASPM/CLKREQ setting function with vendor
> driver").
>
> Signed-off-by: Kai-Heng Feng <[email protected]>
> ---
> v8:
> - New patch.
>
> drivers/net/ethernet/realtek/r8169_main.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
> index 897f90b48bba6..4d4a802346ae3 100644
> --- a/drivers/net/ethernet/realtek/r8169_main.c
> +++ b/drivers/net/ethernet/realtek/r8169_main.c
> @@ -2711,8 +2711,6 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
> RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
> RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
> }
> -
> - udelay(10);
> }
>
> static void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat,
> @@ -4577,6 +4575,12 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
> struct net_device *dev = tp->dev;
> int work_done;
>
> + if (tp->aspm_manageable) {
> + rtl_unlock_config_regs(tp);

NAPI poll runs in softirq context (except for threaded NAPI).
Therefore you should use a spinlock instead of a mutex.

> + rtl_hw_aspm_clkreq_enable(tp, false);
> + rtl_lock_config_regs(tp);
> + }
> +
> rtl_tx(dev, tp, budget);
>
> work_done = rtl_rx(dev, tp, budget);
> @@ -4584,6 +4588,12 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
> if (work_done < budget && napi_complete_done(napi, work_done))
> rtl_irq_enable(tp);
>
> + if (tp->aspm_manageable) {
> + rtl_unlock_config_regs(tp);
> + rtl_hw_aspm_clkreq_enable(tp, true);
> + rtl_lock_config_regs(tp);

Why not moving lock/unlock into rtl_hw_aspm_clkreq_enable()?

> + }
> +
> return work_done;
> }
>


2023-02-22 12:58:51

by Kai-Heng Feng

[permalink] [raw]
Subject: Re: [PATCH v8 RESEND 0/6] r8169: Enable ASPM for recent 1.0/2.5Gbps Realtek NICs

On Tue, Feb 21, 2023 at 7:09 PM Heiner Kallweit <[email protected]> wrote:
>
> On 21.02.2023 03:38, Kai-Heng Feng wrote:
> > The series is to enable ASPM on more r8169 supported devices, if
> > available.
> >
> > The latest Realtek vendor driver and its Windows driver implements a
> > feature called "dynamic ASPM" which can improve performance on it's
> > ethernet NICs.
> >
> > We have "dynamic ASPM" mechanism in Ubuntu 22.04 LTS kernel for quite a
> > while, and AFAIK it hasn't introduced any regression so far.
> >
> > A very similar issue was observed on Realtek wireless NIC, and it was
> > resolved by disabling ASPM during NAPI poll. So in v8, we use the same
> > approach, which is more straightforward, instead of toggling ASPM based
> > on packet count.
> >
> > v7:
> > https://lore.kernel.org/netdev/[email protected]/
> >
> > v6:
> > https://lore.kernel.org/netdev/[email protected]/
> >
> > v5:
> > https://lore.kernel.org/netdev/[email protected]/
> >
> > v4:
> > https://lore.kernel.org/netdev/[email protected]/
> >
> > v3:
> > https://lore.kernel.org/netdev/[email protected]/
> >
> > v2:
> > https://lore.kernel.org/netdev/[email protected]/
> >
> > v1:
> > https://lore.kernel.org/netdev/[email protected]/
> >
> > Kai-Heng Feng (6):
> > r8169: Disable ASPM L1.1 on 8168h
> > Revert "PCI/ASPM: Unexport pcie_aspm_support_enabled()"
> > PCI/ASPM: Add pcie_aspm_capable() helper
> > r8169: Consider chip-specific ASPM can be enabled on more cases
> > r8169: Use mutex to guard config register locking
> > r8169: Disable ASPM while doing NAPI poll
> >
> > drivers/net/ethernet/realtek/r8169_main.c | 48 ++++++++++++++++++-----
> > drivers/pci/pcie/aspm.c | 12 ++++++
> > include/linux/pci.h | 2 +
> > 3 files changed, 53 insertions(+), 9 deletions(-)
> >
>
> Note that net-next is closed during merge window.
> Formal aspect: Your patches miss the net/net-next annotation.

Will do in next revision.

> The title of the series may be an old one. Actually most ASPM
> states are enabled, you add to disable ASPM temporarily.

Right.
Most hardwares I have access to don't grant OS ASPM control, so
tp->aspm_manageable is not enabled.
Will make it more clearer.

Kai-Heng

2023-02-22 13:01:05

by Kai-Heng Feng

[permalink] [raw]
Subject: Re: [PATCH v8 RESEND 1/6] r8169: Disable ASPM L1.1 on 8168h

On Tue, Feb 21, 2023 at 7:09 PM Heiner Kallweit <[email protected]> wrote:
>
> On 21.02.2023 03:38, Kai-Heng Feng wrote:
> > ASPM L1/L1.1 gets enabled based on [0], but ASPM L1.1 was actually
> > disabled too [1].
> >
> > So also disable L1.1 for better compatibility.
> >
> > [0] https://bugs.launchpad.net/bugs/1942830
> > [1] https://git.launchpad.net/~canonical-kernel/ubuntu/+source/linux-oem/+git/focal/commit/?id=c9b3736de48fd419d6699045d59a0dd1041da014
> >
> These references are about problems with L1.2 (which is disabled
> per default in mainline). They don't allow any statement about whether
> L1.1 is problematic too (and under which circumstances).
> At least on my system with RTL8168h there's no problem with L1.1
> when running iperf.

There are some systems have performance issue with L1.1 too.
But since the series will disable chip-side ASPM during NAPI poll,
maybe we can keep both L1.1 and L1.2 enabled?

Kai-Heng

>
> > Signed-off-by: Kai-Heng Feng <[email protected]>
> > ---
> > v8:
> > - New patch.
> >
> > drivers/net/ethernet/realtek/r8169_main.c | 6 +++---
> > 1 file changed, 3 insertions(+), 3 deletions(-)
> >
> >
> > diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
> > index 45147a1016bec..1c949822661ae 100644
> > --- a/drivers/net/ethernet/realtek/r8169_main.c
> > +++ b/drivers/net/ethernet/realtek/r8169_main.c
> > @@ -5224,13 +5224,13 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
> >
> > /* Disable ASPM L1 as that cause random device stop working
> > * problems as well as full system hangs for some PCIe devices users.
> > - * Chips from RTL8168h partially have issues with L1.2, but seem
> > - * to work fine with L1 and L1.1.
> > + * Chips from RTL8168h partially have issues with L1.1 and L1.2, but
> > + * seem to work fine with L1.
> > */
> > if (rtl_aspm_is_safe(tp))
> > rc = 0;
> > else if (tp->mac_version >= RTL_GIGA_MAC_VER_46)
> > - rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2);
> > + rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2);
> > else
> > rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
> > tp->aspm_manageable = !rc;
>

2023-02-22 13:03:24

by Kai-Heng Feng

[permalink] [raw]
Subject: Re: [PATCH v8 RESEND 6/6] r8169: Disable ASPM while doing NAPI poll

On Tue, Feb 21, 2023 at 7:09 PM Heiner Kallweit <[email protected]> wrote:
>
> On 21.02.2023 03:38, Kai-Heng Feng wrote:
> > NAPI poll of Realtek NICs don't seem to perform well ASPM is enabled.
> > The vendor driver uses a mechanism called "dynamic ASPM" to toggle ASPM
> > based on the packet number in given time period.
> >
> > Instead of implementing "dynamic ASPM", use a more straightforward way
> > by disabling ASPM during NAPI poll, as a similar approach was
> > implemented to solve slow performance on Realtek wireless NIC, see
> > commit 24f5e38a13b5 ("rtw88: Disable PCIe ASPM while doing NAPI poll on
> > 8821CE").
> >
> > Since NAPI poll should be handled as fast as possible, also remove the
> > delay in rtl_hw_aspm_clkreq_enable() which was added by commit
> > 94235460f9ea ("r8169: Align ASPM/CLKREQ setting function with vendor
> > driver").
> >
> > Signed-off-by: Kai-Heng Feng <[email protected]>
> > ---
> > v8:
> > - New patch.
> >
> > drivers/net/ethernet/realtek/r8169_main.c | 14 ++++++++++++--
> > 1 file changed, 12 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
> > index 897f90b48bba6..4d4a802346ae3 100644
> > --- a/drivers/net/ethernet/realtek/r8169_main.c
> > +++ b/drivers/net/ethernet/realtek/r8169_main.c
> > @@ -2711,8 +2711,6 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
> > RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
> > RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
> > }
> > -
> > - udelay(10);
> > }
> >
> > static void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat,
> > @@ -4577,6 +4575,12 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
> > struct net_device *dev = tp->dev;
> > int work_done;
> >
> > + if (tp->aspm_manageable) {
> > + rtl_unlock_config_regs(tp);
>
> NAPI poll runs in softirq context (except for threaded NAPI).
> Therefore you should use a spinlock instead of a mutex.

You are right. Will change it in next revision.

>
> > + rtl_hw_aspm_clkreq_enable(tp, false);
> > + rtl_lock_config_regs(tp);
> > + }
> > +
> > rtl_tx(dev, tp, budget);
> >
> > work_done = rtl_rx(dev, tp, budget);
> > @@ -4584,6 +4588,12 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
> > if (work_done < budget && napi_complete_done(napi, work_done))
> > rtl_irq_enable(tp);
> >
> > + if (tp->aspm_manageable) {
> > + rtl_unlock_config_regs(tp);
> > + rtl_hw_aspm_clkreq_enable(tp, true);
> > + rtl_lock_config_regs(tp);
>
> Why not moving lock/unlock into rtl_hw_aspm_clkreq_enable()?

Because where it gets called at other places don't need the lock.
But yes this will make it easier to read, will do in next revision.

Kai-Heng

>
> > + }
> > +
> > return work_done;
> > }
> >
>

2023-02-24 03:39:19

by Kai-Heng Feng

[permalink] [raw]
Subject: Re: [PATCH v8 RESEND 6/6] r8169: Disable ASPM while doing NAPI poll

On Wed, Feb 22, 2023 at 9:03 PM Kai-Heng Feng
<[email protected]> wrote:
>
> On Tue, Feb 21, 2023 at 7:09 PM Heiner Kallweit <[email protected]> wrote:
> >
> > On 21.02.2023 03:38, Kai-Heng Feng wrote:
> > > NAPI poll of Realtek NICs don't seem to perform well ASPM is enabled.
> > > The vendor driver uses a mechanism called "dynamic ASPM" to toggle ASPM
> > > based on the packet number in given time period.
> > >
> > > Instead of implementing "dynamic ASPM", use a more straightforward way
> > > by disabling ASPM during NAPI poll, as a similar approach was
> > > implemented to solve slow performance on Realtek wireless NIC, see
> > > commit 24f5e38a13b5 ("rtw88: Disable PCIe ASPM while doing NAPI poll on
> > > 8821CE").
> > >
> > > Since NAPI poll should be handled as fast as possible, also remove the
> > > delay in rtl_hw_aspm_clkreq_enable() which was added by commit
> > > 94235460f9ea ("r8169: Align ASPM/CLKREQ setting function with vendor
> > > driver").
> > >
> > > Signed-off-by: Kai-Heng Feng <[email protected]>
> > > ---
> > > v8:
> > > - New patch.
> > >
> > > drivers/net/ethernet/realtek/r8169_main.c | 14 ++++++++++++--
> > > 1 file changed, 12 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
> > > index 897f90b48bba6..4d4a802346ae3 100644
> > > --- a/drivers/net/ethernet/realtek/r8169_main.c
> > > +++ b/drivers/net/ethernet/realtek/r8169_main.c
> > > @@ -2711,8 +2711,6 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
> > > RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
> > > RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
> > > }
> > > -
> > > - udelay(10);
> > > }
> > >
> > > static void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat,
> > > @@ -4577,6 +4575,12 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
> > > struct net_device *dev = tp->dev;
> > > int work_done;
> > >
> > > + if (tp->aspm_manageable) {
> > > + rtl_unlock_config_regs(tp);
> >
> > NAPI poll runs in softirq context (except for threaded NAPI).
> > Therefore you should use a spinlock instead of a mutex.
>
> You are right. Will change it in next revision.
>
> >
> > > + rtl_hw_aspm_clkreq_enable(tp, false);
> > > + rtl_lock_config_regs(tp);
> > > + }
> > > +
> > > rtl_tx(dev, tp, budget);
> > >
> > > work_done = rtl_rx(dev, tp, budget);
> > > @@ -4584,6 +4588,12 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
> > > if (work_done < budget && napi_complete_done(napi, work_done))
> > > rtl_irq_enable(tp);
> > >
> > > + if (tp->aspm_manageable) {
> > > + rtl_unlock_config_regs(tp);
> > > + rtl_hw_aspm_clkreq_enable(tp, true);
> > > + rtl_lock_config_regs(tp);
> >
> > Why not moving lock/unlock into rtl_hw_aspm_clkreq_enable()?
>
> Because where it gets called at other places don't need the lock.
> But yes this will make it easier to read, will do in next revision.

We can't do that because it creates deadlock:
rtl_hw_start()
rtl_unlock_config_regs()
rtl_hw_start_8168()
rtl_hw_config()
rtl_hw_start_8168h_1()
rtl_hw_aspm_clkreq_enable()

Kai-Heng

>
> Kai-Heng
>
> >
> > > + }
> > > +
> > > return work_done;
> > > }
> > >
> >