The purpose of the series is to get comments and reviews so we can merge
and test the series in downstream kernel.
The latest Realtek vendor driver and its Windows driver implements a
feature called "dynamic ASPM" which can improve performance on it's
ethernet NICs.
Heiner Kallweit pointed out the potential root cause can be that the
buffer is to small for its ASPM exit latency.
So bring the dynamic ASPM to r8169 so we can have both nice performance
and powersaving at the same time.
For the slow/fast alternating traffic pattern, we'll need some real
world test to know if we need to lower the dynamic ASPM interval.
v4:
https://lore.kernel.org/netdev/20210827171452.217123-1-kai.heng.feng@canonical.com/
v3:
https://lore.kernel.org/netdev/20210819054542.608745-1-kai.heng.feng@canonical.com/
v2:
https://lore.kernel.org/netdev/20210812155341.817031-1-kai.heng.feng@canonical.com/
v1:
https://lore.kernel.org/netdev/20210803152823.515849-1-kai.heng.feng@canonical.com/
Kai-Heng Feng (3):
PCI/ASPM: Introduce a new helper to report ASPM capability
r8169: Use PCIe ASPM status for NIC ASPM enablement
r8169: Implement dynamic ASPM mechanism
drivers/net/ethernet/realtek/r8169_main.c | 69 ++++++++++++++++++++---
drivers/pci/pcie/aspm.c | 11 ++++
include/linux/pci.h | 2 +
3 files changed, 73 insertions(+), 9 deletions(-)
--
2.32.0
Introduce a new helper, pcie_aspm_capable(), to report ASPM capability.
The user will be introduced by next patch.
Signed-off-by: Kai-Heng Feng <redacted>
---
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(+)
@@ -1631,6 +1631,7 @@ int pci_disable_link_state_locked(struct pci_dev *pdev, int state);voidpcie_no_aspm(void);boolpcie_aspm_support_enabled(void);boolpcie_aspm_enabled(structpci_dev*pdev);+boolpcie_aspm_capable(structpci_dev*pdev);#elsestaticinlineintpci_disable_link_state(structpci_dev*pdev,intstate){return0;}
@@ -1639,6 +1640,7 @@ static inline int pci_disable_link_state_locked(struct pci_dev *pdev, int state)staticinlinevoidpcie_no_aspm(void){}staticinlineboolpcie_aspm_support_enabled(void){returnfalse;}staticinlineboolpcie_aspm_enabled(structpci_dev*pdev){returnfalse;}+staticinlineboolpcie_aspm_capable(structpci_dev*pdev){returnfalse;}#endif#ifdef CONFIG_PCIEAER
Because ASPM control may not be granted by BIOS while ASPM is enabled,
and ASPM can be enabled via sysfs, so use pcie_aspm_enabled() directly
to check current ASPM enable status.
Signed-off-by: Kai-Heng Feng <redacted>
---
v5:
- New patch.
drivers/net/ethernet/realtek/r8169_main.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
@@ -2664,8 +2663,13 @@ static void rtl_enable_exit_l1(struct rtl8169_private *tp)staticvoidrtl_hw_aspm_clkreq_enable(structrtl8169_private*tp,boolenable){-/* Don't enable ASPM in the chip if OS can't control ASPM */-if(enable&&tp->aspm_manageable){+structpci_dev*pdev=tp->pci_dev;++/* Don't enable ASPM in the chip if PCIe ASPM isn't enabled */+if(!pcie_aspm_enabled(pdev)&&enable)+return;++if(enable){RTL_W8(tp,Config5,RTL_R8(tp,Config5)|ASPM_en);RTL_W8(tp,Config2,RTL_R8(tp,Config2)|ClkReqEn);}else{
@@ -5272,8 +5276,7 @@ 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*problemsaswellasfullsystemhangsforsomePCIedevicesusers.*/-rc=pci_disable_link_state(pdev,PCIE_LINK_STATE_L1);-tp->aspm_manageable=!rc;+pci_disable_link_state(pdev,PCIE_LINK_STATE_L1);/* enable device (incl. PCI PM wakeup and hotplug setup) */rc=pcim_enable_device(pdev);
r8169 NICs on some platforms have abysmal speed when ASPM is enabled.
Same issue can be observed with older vendor drivers.
The issue is however solved by the latest vendor driver. There's a new
mechanism, which disables r8169's internal ASPM when the NIC traffic has
more than 10 packets, and vice versa. The possible reason for this is
likely because the buffer on the chip is too small for its ASPM exit
latency.
Realtek confirmed that all their PCIe LAN NICs, r8106, r8168 and r8125
use dynamic ASPM under Windows. So implement the same mechanism here to
resolve the issue.
Also introduce a lock to prevent race on accessing config registers.
Signed-off-by: Kai-Heng Feng <redacted>
---
v5:
- Split out aspm_manageable replacement as another patch.
- Introduce a lock for lock_config_regs() and unlock_config_regs().
v4:
- Squash two patches
- Remove aspm_manageable and use pcie_aspm_capable()
pcie_aspm_enabled() accordingly
v3:
- Use msecs_to_jiffies() for delay time
- Use atomic_t instead of mutex for bh
- Mention the buffer size and ASPM exit latency in commit message
v2:
- Use delayed_work instead of timer_list to avoid interrupt context
- Use mutex to serialize packet counter read/write
- Wording change
drivers/net/ethernet/realtek/r8169_main.c | 58 +++++++++++++++++++++--
1 file changed, 53 insertions(+), 5 deletions(-)
On Thu, Sep 16, 2021 at 11:44:16PM +0800, Kai-Heng Feng wrote:
quoted hunk
Because ASPM control may not be granted by BIOS while ASPM is enabled,
and ASPM can be enabled via sysfs, so use pcie_aspm_enabled() directly
to check current ASPM enable status.
Signed-off-by: Kai-Heng Feng <redacted>
---
v5:
- New patch.
drivers/net/ethernet/realtek/r8169_main.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
@@ -2664,8 +2663,13 @@ static void rtl_enable_exit_l1(struct rtl8169_private *tp)staticvoidrtl_hw_aspm_clkreq_enable(structrtl8169_private*tp,boolenable){-/* Don't enable ASPM in the chip if OS can't control ASPM */-if(enable&&tp->aspm_manageable){+structpci_dev*pdev=tp->pci_dev;++/* Don't enable ASPM in the chip if PCIe ASPM isn't enabled */+if(!pcie_aspm_enabled(pdev)&&enable)+return;
@@ -5272,8 +5276,7 @@ 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. */- rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);- tp->aspm_manageable = !rc;+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L1); /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pcim_enable_device(pdev);
On Thu, Sep 16, 2021 at 11:44:17PM +0800, Kai-Heng Feng wrote:
r8169 NICs on some platforms have abysmal speed when ASPM is enabled.
Same issue can be observed with older vendor drivers.
The issue is however solved by the latest vendor driver. There's a new
mechanism, which disables r8169's internal ASPM when the NIC traffic has
more than 10 packets, and vice versa.
Obviously this is a *rate*, not an absolute number. I think you mean
something like "10 packets in 1000ms".
The possible reason for this is
likely because the buffer on the chip is too small for its ASPM exit
latency.
Realtek confirmed that all their PCIe LAN NICs, r8106, r8168 and r8125
use dynamic ASPM under Windows. So implement the same mechanism here to
resolve the issue.
Also introduce a lock to prevent race on accessing config registers.
On Fri, Sep 17, 2021 at 1:07 AM Bjorn Helgaas [off-list ref] wrote:
On Thu, Sep 16, 2021 at 11:44:16PM +0800, Kai-Heng Feng wrote:
quoted
Because ASPM control may not be granted by BIOS while ASPM is enabled,
and ASPM can be enabled via sysfs, so use pcie_aspm_enabled() directly
to check current ASPM enable status.
Signed-off-by: Kai-Heng Feng <redacted>
---
v5:
- New patch.
drivers/net/ethernet/realtek/r8169_main.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
@@ -2664,8 +2663,13 @@ static void rtl_enable_exit_l1(struct rtl8169_private *tp)staticvoidrtl_hw_aspm_clkreq_enable(structrtl8169_private*tp,boolenable){-/* Don't enable ASPM in the chip if OS can't control ASPM */-if(enable&&tp->aspm_manageable){+structpci_dev*pdev=tp->pci_dev;++/* Don't enable ASPM in the chip if PCIe ASPM isn't enabled */+if(!pcie_aspm_enabled(pdev)&&enable)+return;
@@ -5272,8 +5276,7 @@ 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. */- rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);- tp->aspm_manageable = !rc;+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L1); /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pcim_enable_device(pdev);--
On Fri, Sep 17, 2021 at 1:12 AM Bjorn Helgaas [off-list ref] wrote:
On Thu, Sep 16, 2021 at 11:44:17PM +0800, Kai-Heng Feng wrote:
quoted
r8169 NICs on some platforms have abysmal speed when ASPM is enabled.
Same issue can be observed with older vendor drivers.
The issue is however solved by the latest vendor driver. There's a new
mechanism, which disables r8169's internal ASPM when the NIC traffic has
more than 10 packets, and vice versa.
Obviously this is a *rate*, not an absolute number. I think you mean
something like "10 packets in 1000ms".
Will amend this in next iteration.
quoted
The possible reason for this is
likely because the buffer on the chip is too small for its ASPM exit
latency.
Realtek confirmed that all their PCIe LAN NICs, r8106, r8168 and r8125
use dynamic ASPM under Windows. So implement the same mechanism here to
resolve the issue.
Also introduce a lock to prevent race on accessing config registers.
On Fri, Sep 17, 2021 at 12:09:08PM +0800, Kai-Heng Feng wrote:
On Fri, Sep 17, 2021 at 1:07 AM Bjorn Helgaas [off-list ref] wrote:
quoted
On Thu, Sep 16, 2021 at 11:44:16PM +0800, Kai-Heng Feng wrote:
quoted
Because ASPM control may not be granted by BIOS while ASPM is enabled,
and ASPM can be enabled via sysfs, so use pcie_aspm_enabled() directly
to check current ASPM enable status.
Signed-off-by: Kai-Heng Feng <redacted>
---
v5:
- New patch.
drivers/net/ethernet/realtek/r8169_main.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
@@ -2664,8 +2663,13 @@ static void rtl_enable_exit_l1(struct rtl8169_private *tp)staticvoidrtl_hw_aspm_clkreq_enable(structrtl8169_private*tp,boolenable){-/* Don't enable ASPM in the chip if OS can't control ASPM */-if(enable&&tp->aspm_manageable){+structpci_dev*pdev=tp->pci_dev;++/* Don't enable ASPM in the chip if PCIe ASPM isn't enabled */+if(!pcie_aspm_enabled(pdev)&&enable)+return;
So it's still better to fold this patch into next one? So the periodic
delayed_work can toggle ASPM accordingly.
No, my point is that the user can enable/disable ASPM via sysfs, and
the driver will not know anything about it. There's no callback that
tells the driver when this happens.
My question is whether this code works when that happens. I doubt it
works, because if ASPM is not enabled at this moment, you return
without doing enabling ASPM in the chip below.
If the user subsequently enables ASPM via sysfs, the chip setup below
will not be done.
If there's chip-specific setup to make ASPM work, I think the
chip-specific part needs to be done unconditionally.
@@ -5272,8 +5276,7 @@ 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. */- rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);- tp->aspm_manageable = !rc;+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L1); /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pcim_enable_device(pdev);--
On Thu, Sep 16, 2021 at 11:44:14PM +0800, Kai-Heng Feng wrote:
The purpose of the series is to get comments and reviews so we can merge
and test the series in downstream kernel.
The latest Realtek vendor driver and its Windows driver implements a
feature called "dynamic ASPM" which can improve performance on it's
ethernet NICs.
Heiner Kallweit pointed out the potential root cause can be that the
buffer is too small for its ASPM exit latency.
I looked at the lspci data in your bugzilla
(https://bugzilla.kernel.org/show_bug.cgi?id=214307).
L1.2 is enabled, which requires the Latency Tolerance Reporting
capability, which helps determine when the Link will be put in L1.2.
IIUC, these are analogous to the DevCap "Acceptable Latency" values.
Zero latency values indicate the device will be impacted by any delay
(PCIe r5.0, sec 6.18).
Linux does not currently program those values, so the values there
must have been set by the BIOS. On the working AMD system, they're
set to 1048576ns, while on the broken Intel system, they're set to
3145728ns.
I don't really understand how these values should be computed, and I
think they depend on some electrical characteristics of the Link, so
I'm not sure it's *necessarily* a problem that they are different.
But a 3X difference does seem pretty large.
So I'm curious whether this is related to the problem. Here are some
things we could try on the broken Intel system:
- What happens if you disable ASPM L1.2 using
/sys/devices/pci*/.../link/l1_2_aspm?
- If that doesn't work, what happens if you also disable PCI-PM L1.2
using /sys/devices/pci*/.../link/l1_2_pcipm?
- If either of the above makes things work, then at least we know
the problem is sensitive to L1.2.
- Then what happens if you use setpci to set the LTR Latency
registers to 0, then re-enable ASPM L1.2 and PCI-PM L1.2? This
should mean the Realtek device wants the best possible service and
the Link probably won't spend much time in L1.2.
- What happens if you set the LTR Latency registers to 0x1001
(should be the same as on the AMD system)?
On Sat, Sep 18, 2021 at 6:09 AM Bjorn Helgaas [off-list ref] wrote:
On Thu, Sep 16, 2021 at 11:44:14PM +0800, Kai-Heng Feng wrote:
quoted
The purpose of the series is to get comments and reviews so we can merge
and test the series in downstream kernel.
The latest Realtek vendor driver and its Windows driver implements a
feature called "dynamic ASPM" which can improve performance on it's
ethernet NICs.
Heiner Kallweit pointed out the potential root cause can be that the
buffer is too small for its ASPM exit latency.
I looked at the lspci data in your bugzilla
(https://bugzilla.kernel.org/show_bug.cgi?id=214307).
L1.2 is enabled, which requires the Latency Tolerance Reporting
capability, which helps determine when the Link will be put in L1.2.
IIUC, these are analogous to the DevCap "Acceptable Latency" values.
Zero latency values indicate the device will be impacted by any delay
(PCIe r5.0, sec 6.18).
Linux does not currently program those values, so the values there
must have been set by the BIOS. On the working AMD system, they're
set to 1048576ns, while on the broken Intel system, they're set to
3145728ns.
I don't really understand how these values should be computed, and I
think they depend on some electrical characteristics of the Link, so
I'm not sure it's *necessarily* a problem that they are different.
But a 3X difference does seem pretty large.
So I'm curious whether this is related to the problem. Here are some
things we could try on the broken Intel system:
Original network speed, tested via iperf3:
TX: ~255 Mbps
RX: ~490 Mbps
- What happens if you disable ASPM L1.2 using
/sys/devices/pci*/.../link/l1_2_aspm?
TX: ~670 Mbps
RX: ~670 Mbps
- If that doesn't work, what happens if you also disable PCI-PM L1.2
using /sys/devices/pci*/.../link/l1_2_pcipm?
Same as only disables l1_2_aspm.
- If either of the above makes things work, then at least we know
the problem is sensitive to L1.2.
Right now the downstream kernel disables ASPM L1.2 as workaround.
- Then what happens if you use setpci to set the LTR Latency
registers to 0, then re-enable ASPM L1.2 and PCI-PM L1.2? This
should mean the Realtek device wants the best possible service and
the Link probably won't spend much time in L1.2.
# setpci -s 01:00.0 ECAP_LTR+4.w=0x0
# setpci -s 01:00.0 ECAP_LTR+6.w=0x0
Then re-enable ASPM L1.2, the issue persists - the network speed is
still very slow.
- What happens if you set the LTR Latency registers to 0x1001
(should be the same as on the AMD system)?
On Fri, Sep 17, 2021 at 11:26 PM Bjorn Helgaas [off-list ref] wrote:
On Fri, Sep 17, 2021 at 12:09:08PM +0800, Kai-Heng Feng wrote:
quoted
On Fri, Sep 17, 2021 at 1:07 AM Bjorn Helgaas [off-list ref] wrote:
quoted
On Thu, Sep 16, 2021 at 11:44:16PM +0800, Kai-Heng Feng wrote:
quoted
Because ASPM control may not be granted by BIOS while ASPM is enabled,
and ASPM can be enabled via sysfs, so use pcie_aspm_enabled() directly
to check current ASPM enable status.
Signed-off-by: Kai-Heng Feng <redacted>
---
v5:
- New patch.
drivers/net/ethernet/realtek/r8169_main.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
@@ -2664,8 +2663,13 @@ static void rtl_enable_exit_l1(struct rtl8169_private *tp)staticvoidrtl_hw_aspm_clkreq_enable(structrtl8169_private*tp,boolenable){-/* Don't enable ASPM in the chip if OS can't control ASPM */-if(enable&&tp->aspm_manageable){+structpci_dev*pdev=tp->pci_dev;++/* Don't enable ASPM in the chip if PCIe ASPM isn't enabled */+if(!pcie_aspm_enabled(pdev)&&enable)+return;
So it's still better to fold this patch into next one? So the periodic
delayed_work can toggle ASPM accordingly.
No, my point is that the user can enable/disable ASPM via sysfs, and
the driver will not know anything about it. There's no callback that
tells the driver when this happens.
My question is whether this code works when that happens. I doubt it
works, because if ASPM is not enabled at this moment, you return
without doing enabling ASPM in the chip below.
If the user subsequently enables ASPM via sysfs, the chip setup below
will not be done.
If there's chip-specific setup to make ASPM work, I think the
chip-specific part needs to be done unconditionally.
So it's either adding a callback to notify driver about ASPM change,
or doing chip-specific ASPM unconditionally.
Which one do you prefer?
Kai-Heng
@@ -5272,8 +5276,7 @@ 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. */- rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);- tp->aspm_manageable = !rc;+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L1); /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pcim_enable_device(pdev);--
On Fri, Oct 01, 2021 at 12:17:26PM +0800, Kai-Heng Feng wrote:
On Sat, Sep 18, 2021 at 6:09 AM Bjorn Helgaas [off-list ref] wrote:
quoted
On Thu, Sep 16, 2021 at 11:44:14PM +0800, Kai-Heng Feng wrote:
quoted
The purpose of the series is to get comments and reviews so we can merge
and test the series in downstream kernel.
The latest Realtek vendor driver and its Windows driver implements a
feature called "dynamic ASPM" which can improve performance on it's
ethernet NICs.
Heiner Kallweit pointed out the potential root cause can be that the
buffer is too small for its ASPM exit latency.
I looked at the lspci data in your bugzilla
(https://bugzilla.kernel.org/show_bug.cgi?id=214307).
L1.2 is enabled, which requires the Latency Tolerance Reporting
capability, which helps determine when the Link will be put in L1.2.
IIUC, these are analogous to the DevCap "Acceptable Latency" values.
Zero latency values indicate the device will be impacted by any delay
(PCIe r5.0, sec 6.18).
Linux does not currently program those values, so the values there
must have been set by the BIOS. On the working AMD system, they're
set to 1048576ns, while on the broken Intel system, they're set to
3145728ns.
I don't really understand how these values should be computed, and I
think they depend on some electrical characteristics of the Link, so
I'm not sure it's *necessarily* a problem that they are different.
But a 3X difference does seem pretty large.
So I'm curious whether this is related to the problem. Here are some
things we could try on the broken Intel system:
Original network speed, tested via iperf3:
TX: ~255 Mbps
RX: ~490 Mbps
quoted
- What happens if you disable ASPM L1.2 using
/sys/devices/pci*/.../link/l1_2_aspm?
TX: ~670 Mbps
RX: ~670 Mbps
quoted
- If that doesn't work, what happens if you also disable PCI-PM L1.2
using /sys/devices/pci*/.../link/l1_2_pcipm?
Same as only disables l1_2_aspm.
quoted
- If either of the above makes things work, then at least we know
the problem is sensitive to L1.2.
Right now the downstream kernel disables ASPM L1.2 as workaround.
quoted
- Then what happens if you use setpci to set the LTR Latency
registers to 0, then re-enable ASPM L1.2 and PCI-PM L1.2? This
should mean the Realtek device wants the best possible service and
the Link probably won't spend much time in L1.2.
# setpci -s 01:00.0 ECAP_LTR+4.w=0x0
# setpci -s 01:00.0 ECAP_LTR+6.w=0x0
Then re-enable ASPM L1.2, the issue persists - the network speed is
still very slow.
quoted
- What happens if you set the LTR Latency registers to 0x1001
(should be the same as on the AMD system)?
Same slow speed here.
Thanks a lot for indulging my curiosity and testing this. So I guess
you confirmed that specifically ASPM L1.2 is the issue, which makes
sense given the current downstream kernel workaround.
On Fri, Oct 01, 2021 at 12:17:26PM +0800, Kai-Heng Feng wrote:
On Sat, Sep 18, 2021 at 6:09 AM Bjorn Helgaas [off-list ref] wrote:
quoted
On Thu, Sep 16, 2021 at 11:44:14PM +0800, Kai-Heng Feng wrote:
quoted
The purpose of the series is to get comments and reviews so we can merge
and test the series in downstream kernel.
The latest Realtek vendor driver and its Windows driver implements a
feature called "dynamic ASPM" which can improve performance on it's
ethernet NICs.
Heiner Kallweit pointed out the potential root cause can be that the
buffer is too small for its ASPM exit latency.
I looked at the lspci data in your bugzilla
(https://bugzilla.kernel.org/show_bug.cgi?id=214307).
L1.2 is enabled, which requires the Latency Tolerance Reporting
capability, which helps determine when the Link will be put in L1.2.
IIUC, these are analogous to the DevCap "Acceptable Latency" values.
Zero latency values indicate the device will be impacted by any delay
(PCIe r5.0, sec 6.18).
Linux does not currently program those values, so the values there
must have been set by the BIOS. On the working AMD system, they're
set to 1048576ns, while on the broken Intel system, they're set to
3145728ns.
I don't really understand how these values should be computed, and I
think they depend on some electrical characteristics of the Link, so
I'm not sure it's *necessarily* a problem that they are different.
But a 3X difference does seem pretty large.
So I'm curious whether this is related to the problem. Here are some
things we could try on the broken Intel system:
Original network speed, tested via iperf3:
TX: ~255 Mbps
RX: ~490 Mbps
quoted
- What happens if you disable ASPM L1.2 using
/sys/devices/pci*/.../link/l1_2_aspm?