2023-11-24 08:47:46

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 00/10] wifi: rtlwifi: PCI related fixes & cleanups

The rtlwifi driver has code fragments that are using old interface or
custom code to access PCIe capabilities which is buggy and messy.

First two patches are fixes to problems related to ASPM and LNKCTL
register RMW operations. The rest of the patches cleanup PCIe
capability related code.

Additional note: This series provides only a stop-gap solution to the
RMW concurrency issue, the overall plan is to migrate all ASPM related
handling into the ASPM service driver in order for it to accurately
track ASPM state [1].

[1] https://lore.kernel.org/linux-pci/[email protected]/

v2:
- Remove upstream bridge ASPM code which has never functioned
- Convert more bits to pci_regs.h
- Ensure _rtl_pci_switch_clk_req() only changes CLKREQ_EN
- wifi: prefix to all patches
- Add 2 more cleanup patches for unused stuff

Ilpo Järvinen (10):
wifi: rtlwifi: Remove bogus and dangerous ASPM disable/enable code
wifi: rtlwifi: Convert LNKCTL change to PCIe cap RMW accessors
wifi: rtlwifi: Convert to use PCIe capability accessors
wifi: rtlwifi: rtl8821ae: Remove unnecessary PME_Status bit set
wifi: rtlwifi: rtl8821ae: Reverse PM Capability exists check
wifi: rtlwifi: rtl8821ae: Use pci_find_capability()
wifi: rtlwifi: rtl8821ae: Add pdev into
_rtl8821ae_clear_pci_pme_status()
wifi: rtlwifi: rtl8821ae: Access full PMCS reg and use pci_regs.h
wifi: rtlwifi: Remove unused PCI related defines and struct
wifi: rtlwifi: Remove bridge vendor/device ids

drivers/net/wireless/realtek/rtlwifi/pci.c | 98 +++++--------------
drivers/net/wireless/realtek/rtlwifi/pci.h | 24 -----
.../wireless/realtek/rtlwifi/rtl8821ae/hw.c | 76 ++++----------
3 files changed, 43 insertions(+), 155 deletions(-)

--
2.30.2



2023-11-24 08:47:56

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 01/10] wifi: rtlwifi: Remove bogus and dangerous ASPM disable/enable code

Ever since introduction in the commit 0c8173385e54 ("rtl8192ce: Add new
driver") the rtlwifi code has, according to comments, attempted to
disable/enable ASPM of the upstream bridge by writing into its LNKCTL
register. However, the code has never been correct because it performs
the writes to the device instead of the upstream bridge.

Worse yet, the offset where the PCIe capabilities reside is derived
from the offset of the upstream bridge. As a result, the write will use
an offset on the device that does not relate to the LNKCTL register
making the ASPM disable/enable code outright dangerous.

Because of those problems, there is no indication that the driver needs
disable/enable ASPM on the upstream bridge. As the Capabilities offset
is not correctly calculated for the write to target device's LNKCTL
register, the code is not disabling/enabling device's ASPM either.
Therefore, just remove the upstream bridge related ASPM disable/enable
code entirely.

The upstream bridge related ASPM code was the only user of the struct
mp_adapter members num4bytes, pcibridge_pciehdr_offset, and
pcibridge_linkctrlreg so those are removed as well.

Note: This change does not remove the code related to changing the
device's ASPM on purpose (which is independent of this flawed code
related to upstream bridge's ASPM).

Suggested-by: Bjorn Helgaas <[email protected]>
Fixes: 0c8173385e54 ("rtl8192ce: Add new driver")
Fixes: 886e14b65a8f ("rtlwifi: Eliminate raw reads and writes from PCIe portion")
Cc: [email protected]
Signed-off-by: Ilpo Järvinen <[email protected]>
---
drivers/net/wireless/realtek/rtlwifi/pci.c | 58 +---------------------
drivers/net/wireless/realtek/rtlwifi/pci.h | 5 --
2 files changed, 1 insertion(+), 62 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 9886e719739b..206eca310cd7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -192,11 +192,8 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
- u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
/*Retrieve original configuration settings. */
u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg;
- u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter.
- pcibridge_linkctrlreg;
u16 aspmlevel = 0;
u8 tmp_u1b = 0;

@@ -221,16 +218,8 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
/*Set corresponding value. */
aspmlevel |= BIT(0) | BIT(1);
linkctrl_reg &= ~aspmlevel;
- pcibridge_linkctrlreg &= ~(BIT(0) | BIT(1));

_rtl_pci_platform_switch_device_pci_aspm(hw, linkctrl_reg);
- udelay(50);
-
- /*4 Disable Pci Bridge ASPM */
- pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
- pcibridge_linkctrlreg);
-
- udelay(50);
}

/*Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for
@@ -245,9 +234,7 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
- u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
u16 aspmlevel;
- u8 u_pcibridge_aspmsetting;
u8 u_device_aspmsetting;

if (!ppsc->support_aspm)
@@ -259,25 +246,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
return;
}

- /*4 Enable Pci Bridge ASPM */
-
- u_pcibridge_aspmsetting =
- pcipriv->ndis_adapter.pcibridge_linkctrlreg |
- rtlpci->const_hostpci_aspm_setting;
-
- if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL)
- u_pcibridge_aspmsetting &= ~BIT(0);
-
- pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
- u_pcibridge_aspmsetting);
-
- rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
- "PlatformEnableASPM(): Write reg[%x] = %x\n",
- (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10),
- u_pcibridge_aspmsetting);
-
- udelay(50);
-
/*Get ASPM level (with/without Clock Req) */
aspmlevel = rtlpci->const_devicepci_aspm_setting;
u_device_aspmsetting = pcipriv->ndis_adapter.linkctrl_reg;
@@ -358,22 +326,6 @@ static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw,
return tpriv != NULL;
}

-static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)
-{
- struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
- struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
- u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset;
- u8 linkctrl_reg;
- u8 num4bbytes;
-
- num4bbytes = (capabilityoffset + 0x10) / 4;
-
- /*Read Link Control Register */
- pci_read_config_byte(rtlpci->pdev, (num4bbytes << 2), &linkctrl_reg);
-
- pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg;
-}
-
static void rtl_pci_parse_configuration(struct pci_dev *pdev,
struct ieee80211_hw *hw)
{
@@ -2028,12 +1980,6 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
PCI_SLOT(bridge_pdev->devfn);
pcipriv->ndis_adapter.pcibridge_funcnum =
PCI_FUNC(bridge_pdev->devfn);
- pcipriv->ndis_adapter.pcibridge_pciehdr_offset =
- pci_pcie_cap(bridge_pdev);
- pcipriv->ndis_adapter.num4bytes =
- (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4;
-
- rtl_pci_get_linkcontrol_field(hw);

if (pcipriv->ndis_adapter.pcibridge_vendor ==
PCI_BRIDGE_VENDOR_AMD) {
@@ -2050,13 +1996,11 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
pdev->vendor, pcipriv->ndis_adapter.linkctrl_reg);

rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
- "pci_bridge busnumber:devnumber:funcnumber:vendor:pcie_cap:link_ctl_reg:amd %d:%d:%d:%x:%x:%x:%x\n",
+ "pci_bridge busnumber:devnumber:funcnumber:vendor:amd %d:%d:%d:%x:%x\n",
pcipriv->ndis_adapter.pcibridge_busnum,
pcipriv->ndis_adapter.pcibridge_devnum,
pcipriv->ndis_adapter.pcibridge_funcnum,
pcibridge_vendors[pcipriv->ndis_adapter.pcibridge_vendor],
- pcipriv->ndis_adapter.pcibridge_pciehdr_offset,
- pcipriv->ndis_adapter.pcibridge_linkctrlreg,
pcipriv->ndis_adapter.amd_l1_patch);

rtl_pci_parse_configuration(pdev, hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h
index 866861626a0a..d6307197dfea 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.h
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.h
@@ -236,11 +236,6 @@ struct mp_adapter {
u16 pcibridge_vendorid;
u16 pcibridge_deviceid;

- u8 num4bytes;
-
- u8 pcibridge_pciehdr_offset;
- u8 pcibridge_linkctrlreg;
-
bool amd_l1_patch;
};

--
2.30.2


2023-11-24 08:48:12

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 03/10] wifi: rtlwifi: Convert to use PCIe capability accessors

The rtlwifi driver accesses PCIe capabilities through custom config
offsets. Convert the accesses to use the normal PCIe capability
accessors.

Signed-off-by: Ilpo Järvinen <[email protected]>
---
drivers/net/wireless/realtek/rtlwifi/pci.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index b118df035243..a29d7df6fff5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -64,7 +64,7 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
- u8 init_aspm;
+ u16 init_aspm;

ppsc->reg_rfps_level = 0;
ppsc->support_aspm = false;
@@ -151,9 +151,10 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)
/* toshiba aspm issue, toshiba will set aspm selfly
* so we should not set aspm in driver
*/
- pci_read_config_byte(rtlpci->pdev, 0x80, &init_aspm);
+ pcie_capability_read_word(rtlpci->pdev, PCI_EXP_LNKCTL, &init_aspm);
if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8192SE &&
- init_aspm == 0x43)
+ ((u8)init_aspm) == (PCI_EXP_LNKCTL_ASPM_L0S |
+ PCI_EXP_LNKCTL_ASPM_L1 | PCI_EXP_LNKCTL_CCC))
ppsc->support_aspm = false;
}

@@ -203,7 +204,7 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
/*Retrieve original configuration settings. */
u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg;
u16 aspmlevel = 0;
- u8 tmp_u1b = 0;
+ u16 tmp_u1b = 0;

if (!ppsc->support_aspm)
return;
@@ -221,10 +222,10 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
}

/*for promising device will in L0 state after an I/O. */
- pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b);
+ pcie_capability_read_word(rtlpci->pdev, PCI_EXP_LNKCTL, &tmp_u1b);

/*Set corresponding value. */
- aspmlevel |= BIT(0) | BIT(1);
+ aspmlevel |= PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1;
linkctrl_reg &= ~aspmlevel;

_rtl_pci_platform_switch_device_pci_aspm(hw, linkctrl_reg);
@@ -351,9 +352,8 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,
rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "Link Control Register =%x\n",
pcipriv->ndis_adapter.linkctrl_reg);

- pci_read_config_byte(pdev, 0x98, &tmp);
- tmp |= BIT(4);
- pci_write_config_byte(pdev, 0x98, tmp);
+ pcie_capability_set_word(pdev, PCI_EXP_DEVCTL2,
+ PCI_EXP_DEVCTL2_COMP_TMOUT_DIS);

tmp = 0x17;
pci_write_config_byte(pdev, 0x70f, tmp);
--
2.30.2


2023-11-24 08:48:12

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 02/10] wifi: rtlwifi: Convert LNKCTL change to PCIe cap RMW accessors

The rtlwifi driver comes with custom code to write into PCIe Link
Control register. RMW access for the Link Control register requires
locking that is already provided by the standard PCIe capability
accessors.

Convert the custom RMW code writing into LNKCTL register to standard
RMW capability accessors. The accesses are changed to cover the full
LNKCTL register instead of touching just a single byte of the register.

Fixes: 0c8173385e54 ("rtl8192ce: Add new driver")
Cc: [email protected]
Signed-off-by: Ilpo Järvinen <[email protected]>
---
drivers/net/wireless/realtek/rtlwifi/pci.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 206eca310cd7..b118df035243 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -164,21 +164,29 @@ static bool _rtl_pci_platform_switch_device_pci_aspm(
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));

+ value &= PCI_EXP_LNKCTL_ASPMC;
+
if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)
- value |= 0x40;
+ value |= PCI_EXP_LNKCTL_CCC;

- pci_write_config_byte(rtlpci->pdev, 0x80, value);
+ pcie_capability_clear_and_set_word(rtlpci->pdev, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_ASPMC | value,
+ value);

return false;
}

-/*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/
-static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value)
+/* @value is PCI_EXP_LNKCTL_CLKREQ_EN or 0 to enable/disable clk request. */
+static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u16 value)
{
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));

- pci_write_config_byte(rtlpci->pdev, 0x81, value);
+ value &= PCI_EXP_LNKCTL_CLKREQ_EN;
+
+ pcie_capability_clear_and_set_word(rtlpci->pdev, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_CLKREQ_EN,
+ value);

if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE)
udelay(100);
@@ -259,7 +267,8 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)

if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) {
_rtl_pci_switch_clk_req(hw, (ppsc->reg_rfps_level &
- RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0);
+ RT_RF_OFF_LEVL_CLK_REQ) ?
+ PCI_EXP_LNKCTL_CLKREQ_EN : 0);
RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ);
}
udelay(100);
--
2.30.2


2023-11-24 08:48:17

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 04/10] wifi: rtlwifi: rtl8821ae: Remove unnecessary PME_Status bit set

BIT(7) (PME_Status) is first checked and then set unnecessarily. Remove
the unnecessary setting for the bit that is already on and adjust the
comment related to it.

Signed-off-by: Ilpo Järvinen <[email protected]>
---
drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index 1633328bc3d1..6ae37d61a2a2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -2312,9 +2312,7 @@ static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw)
pci_read_config_byte(rtlpci->pdev, cap_pointer + 5, &pmcs_reg);

if (pmcs_reg & BIT(7)) {
- /* PME event occured, clear the PM_Status by write 1 */
- pmcs_reg = pmcs_reg | BIT(7);
-
+ /* Clear PME_Status with write */
pci_write_config_byte(rtlpci->pdev, cap_pointer + 5,
pmcs_reg);
/* Read it back to check */
--
2.30.2


2023-11-24 08:48:26

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 05/10] wifi: rtlwifi: rtl8821ae: Reverse PM Capability exists check

Check if PM Capability does not exists and return early which follows
the usual error handling pattern.

Signed-off-by: Ilpo Järvinen <[email protected]>
---
.../wireless/realtek/rtlwifi/rtl8821ae/hw.c | 45 ++++++++++---------
1 file changed, 23 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index 6ae37d61a2a2..53cfeed0b030 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -2305,30 +2305,31 @@ static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw)
}
} while (cnt++ < 200);

- if (cap_id == 0x01) {
- /* Get the PM CSR (Control/Status Register),
- * The PME_Status is located at PM Capatibility offset 5, bit 7
- */
- pci_read_config_byte(rtlpci->pdev, cap_pointer + 5, &pmcs_reg);
-
- if (pmcs_reg & BIT(7)) {
- /* Clear PME_Status with write */
- pci_write_config_byte(rtlpci->pdev, cap_pointer + 5,
- pmcs_reg);
- /* Read it back to check */
- pci_read_config_byte(rtlpci->pdev, cap_pointer + 5,
- &pmcs_reg);
- rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
- "Clear PME status 0x%2x to 0x%2x\n",
- cap_pointer + 5, pmcs_reg);
- } else {
- rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
- "PME status(0x%2x) = 0x%2x\n",
- cap_pointer + 5, pmcs_reg);
- }
- } else {
+ if (cap_id != 0x01) {
rtl_dbg(rtlpriv, COMP_INIT, DBG_WARNING,
"Cannot find PME Capability\n");
+ return;
+ }
+
+ /* Get the PM CSR (Control/Status Register),
+ * The PME_Status is located at PM Capatibility offset 5, bit 7
+ */
+ pci_read_config_byte(rtlpci->pdev, cap_pointer + 5, &pmcs_reg);
+
+ if (pmcs_reg & BIT(7)) {
+ /* Clear PME_Status with write */
+ pci_write_config_byte(rtlpci->pdev, cap_pointer + 5,
+ pmcs_reg);
+ /* Read it back to check */
+ pci_read_config_byte(rtlpci->pdev, cap_pointer + 5,
+ &pmcs_reg);
+ rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+ "Clear PME status 0x%2x to 0x%2x\n",
+ cap_pointer + 5, pmcs_reg);
+ } else {
+ rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+ "PME status(0x%2x) = 0x%2x\n",
+ cap_pointer + 5, pmcs_reg);
}
}

--
2.30.2


2023-11-24 08:48:34

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 06/10] wifi: rtlwifi: rtl8821ae: Use pci_find_capability()

Instead of open coding the capability structure search, find the PM
Capability using pci_find_capability().

While at it, rename the generic 'cap_pointer' to 'pm_cap' which makes
the intent of the code more obvious.

Signed-off-by: Ilpo Järvinen <[email protected]>
---
.../wireless/realtek/rtlwifi/rtl8821ae/hw.c | 49 +++----------------
1 file changed, 8 insertions(+), 41 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index 53cfeed0b030..7877509c34c7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -2270,42 +2270,11 @@ static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- u16 cap_hdr;
- u8 cap_pointer;
- u8 cap_id = 0xff;
u8 pmcs_reg;
- u8 cnt = 0;
+ u8 pm_cap;

- /* Get the Capability pointer first,
- * the Capability Pointer is located at
- * offset 0x34 from the Function Header */
-
- pci_read_config_byte(rtlpci->pdev, 0x34, &cap_pointer);
- rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
- "PCI configuration 0x34 = 0x%2x\n", cap_pointer);
-
- do {
- pci_read_config_word(rtlpci->pdev, cap_pointer, &cap_hdr);
- cap_id = cap_hdr & 0xFF;
-
- rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
- "in pci configuration, cap_pointer%x = %x\n",
- cap_pointer, cap_id);
-
- if (cap_id == 0x01) {
- break;
- } else {
- /* point to next Capability */
- cap_pointer = (cap_hdr >> 8) & 0xFF;
- /* 0: end of pci capability, 0xff: invalid value */
- if (cap_pointer == 0x00 || cap_pointer == 0xff) {
- cap_id = 0xff;
- break;
- }
- }
- } while (cnt++ < 200);
-
- if (cap_id != 0x01) {
+ pm_cap = pci_find_capability(rtlpci->pdev, PCI_CAP_ID_PM);
+ if (!pm_cap) {
rtl_dbg(rtlpriv, COMP_INIT, DBG_WARNING,
"Cannot find PME Capability\n");
return;
@@ -2314,22 +2283,20 @@ static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw)
/* Get the PM CSR (Control/Status Register),
* The PME_Status is located at PM Capatibility offset 5, bit 7
*/
- pci_read_config_byte(rtlpci->pdev, cap_pointer + 5, &pmcs_reg);
+ pci_read_config_byte(rtlpci->pdev, pm_cap + 5, &pmcs_reg);

if (pmcs_reg & BIT(7)) {
/* Clear PME_Status with write */
- pci_write_config_byte(rtlpci->pdev, cap_pointer + 5,
- pmcs_reg);
+ pci_write_config_byte(rtlpci->pdev, pm_cap + 5, pmcs_reg);
/* Read it back to check */
- pci_read_config_byte(rtlpci->pdev, cap_pointer + 5,
- &pmcs_reg);
+ pci_read_config_byte(rtlpci->pdev, pm_cap + 5, &pmcs_reg);
rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
"Clear PME status 0x%2x to 0x%2x\n",
- cap_pointer + 5, pmcs_reg);
+ pm_cap + 5, pmcs_reg);
} else {
rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
"PME status(0x%2x) = 0x%2x\n",
- cap_pointer + 5, pmcs_reg);
+ pm_cap + 5, pmcs_reg);
}
}

--
2.30.2


2023-11-24 08:48:41

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 07/10] wifi: rtlwifi: rtl8821ae: Add pdev into _rtl8821ae_clear_pci_pme_status()

Add local variable pdev to shorten rtlpci->pdev.

Signed-off-by: Ilpo Järvinen <[email protected]>
---
drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index 7877509c34c7..7cc648d49f2d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -2270,10 +2270,11 @@ static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ struct pci_dev *pdev = rtlpci->pdev;
u8 pmcs_reg;
u8 pm_cap;

- pm_cap = pci_find_capability(rtlpci->pdev, PCI_CAP_ID_PM);
+ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
if (!pm_cap) {
rtl_dbg(rtlpriv, COMP_INIT, DBG_WARNING,
"Cannot find PME Capability\n");
@@ -2283,13 +2284,13 @@ static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw)
/* Get the PM CSR (Control/Status Register),
* The PME_Status is located at PM Capatibility offset 5, bit 7
*/
- pci_read_config_byte(rtlpci->pdev, pm_cap + 5, &pmcs_reg);
+ pci_read_config_byte(pdev, pm_cap + 5, &pmcs_reg);

if (pmcs_reg & BIT(7)) {
/* Clear PME_Status with write */
- pci_write_config_byte(rtlpci->pdev, pm_cap + 5, pmcs_reg);
+ pci_write_config_byte(pdev, pm_cap + 5, pmcs_reg);
/* Read it back to check */
- pci_read_config_byte(rtlpci->pdev, pm_cap + 5, &pmcs_reg);
+ pci_read_config_byte(pdev, pm_cap + 5, &pmcs_reg);
rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
"Clear PME status 0x%2x to 0x%2x\n",
pm_cap + 5, pmcs_reg);
--
2.30.2


2023-11-24 08:48:51

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 08/10] wifi: rtlwifi: rtl8821ae: Access full PMCS reg and use pci_regs.h

_rtl8821ae_clear_pci_pme_status() accesses the upper byte of the Power
Management Control/Status register (PMCS) with literal 5 offset.

Access the entire PMCS register using defines from pci_regs.h to
improve code readability.

While at it, remove the obvious comment and tweak debug prints
slightly to not sound misleading.

Signed-off-by: Ilpo Järvinen <[email protected]>
---
.../wireless/realtek/rtlwifi/rtl8821ae/hw.c | 21 +++++++------------
1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index 7cc648d49f2d..f4b232f038a9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -2271,7 +2271,7 @@ static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct pci_dev *pdev = rtlpci->pdev;
- u8 pmcs_reg;
+ u16 pmcs_reg;
u8 pm_cap;

pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
@@ -2281,23 +2281,16 @@ static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw)
return;
}

- /* Get the PM CSR (Control/Status Register),
- * The PME_Status is located at PM Capatibility offset 5, bit 7
- */
- pci_read_config_byte(pdev, pm_cap + 5, &pmcs_reg);
-
- if (pmcs_reg & BIT(7)) {
+ pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pmcs_reg);
+ if (pmcs_reg & PCI_PM_CTRL_PME_STATUS) {
/* Clear PME_Status with write */
- pci_write_config_byte(pdev, pm_cap + 5, pmcs_reg);
- /* Read it back to check */
- pci_read_config_byte(pdev, pm_cap + 5, &pmcs_reg);
+ pci_write_config_word(pdev, pm_cap + PCI_PM_CTRL, pmcs_reg);
+ pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pmcs_reg);
rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
- "Clear PME status 0x%2x to 0x%2x\n",
- pm_cap + 5, pmcs_reg);
+ "Cleared PME status, PMCS reg = 0x%4x\n", pmcs_reg);
} else {
rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
- "PME status(0x%2x) = 0x%2x\n",
- pm_cap + 5, pmcs_reg);
+ "PMCS reg = 0x%4x\n", pmcs_reg);
}
}

--
2.30.2


2023-11-24 08:48:57

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 09/10] wifi: rtlwifi: Remove unused PCI related defines and struct

The rtlwifi driver comes with a number of PCI related defines that are
unused and many would be provided by PCI core anyway if they'd be
needed again.

Similarly, the struct rtl_pci_capabilities_header is unused and no
driver should come up their own way to access PCI Capabilities anyway.

Remove the unused/duplicated PCI related defines and struct.

Signed-off-by: Ilpo Järvinen <[email protected]>
---
drivers/net/wireless/realtek/rtlwifi/pci.h | 17 -----------------
1 file changed, 17 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h
index d6307197dfea..8bb35506ab1e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.h
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.h
@@ -44,18 +44,6 @@
#define ATI_DEVICE_ID 0x7914
#define AMD_VENDOR_ID 0x1022

-#define PCI_MAX_BRIDGE_NUMBER 255
-#define PCI_MAX_DEVICES 32
-#define PCI_MAX_FUNCTION 8
-
-#define PCI_CONF_ADDRESS 0x0CF8 /*PCI Configuration Space Address */
-#define PCI_CONF_DATA 0x0CFC /*PCI Configuration Space Data */
-
-#define PCI_CLASS_BRIDGE_DEV 0x06
-#define PCI_SUBCLASS_BR_PCI_TO_PCI 0x04
-#define PCI_CAPABILITY_ID_PCI_EXPRESS 0x10
-#define PCI_CAP_ID_EXP 0x10
-
#define U1DONTCARE 0xFF
#define U2DONTCARE 0xFFFF
#define U4DONTCARE 0xFFFFFFFF
@@ -113,11 +101,6 @@ enum pci_bridge_vendor {
PCI_BRIDGE_VENDOR_MAX,
};

-struct rtl_pci_capabilities_header {
- u8 capability_id;
- u8 next;
-};
-
/* In new TRX flow, Buffer_desc is new concept
* But TX wifi info == TX descriptor in old flow
* RX wifi info == RX descriptor in old flow
--
2.30.2


2023-11-24 08:49:05

by Ilpo Järvinen

[permalink] [raw]
Subject: [PATCH v2 10/10] wifi: rtlwifi: Remove bridge vendor/device ids

Neither vendorid nor deviceid in the struct mp_adapter is used so
remove them.

Signed-off-by: Ilpo Järvinen <[email protected]>
---
drivers/net/wireless/realtek/rtlwifi/pci.c | 1 -
drivers/net/wireless/realtek/rtlwifi/pci.h | 2 --
2 files changed, 3 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index a29d7df6fff5..aa00ee971bc3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -1969,7 +1969,6 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
*/
if (bridge_pdev) {
/*find bridge info if available */
- pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor;
for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) {
if (bridge_pdev->vendor == pcibridge_vendors[tmp]) {
pcipriv->ndis_adapter.pcibridge_vendor = tmp;
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h
index 8bb35506ab1e..616e5ba30d74 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.h
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.h
@@ -216,8 +216,6 @@ struct mp_adapter {
u8 pcibridge_funcnum;

u8 pcibridge_vendor;
- u16 pcibridge_vendorid;
- u16 pcibridge_deviceid;

bool amd_l1_patch;
};
--
2.30.2


2023-12-01 12:41:57

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 01/10] wifi: rtlwifi: Remove bogus and dangerous ASPM disable/enable code

Ilpo Järvinen <[email protected]> wrote:

> Ever since introduction in the commit 0c8173385e54 ("rtl8192ce: Add new
> driver") the rtlwifi code has, according to comments, attempted to
> disable/enable ASPM of the upstream bridge by writing into its LNKCTL
> register. However, the code has never been correct because it performs
> the writes to the device instead of the upstream bridge.
>
> Worse yet, the offset where the PCIe capabilities reside is derived
> from the offset of the upstream bridge. As a result, the write will use
> an offset on the device that does not relate to the LNKCTL register
> making the ASPM disable/enable code outright dangerous.
>
> Because of those problems, there is no indication that the driver needs
> disable/enable ASPM on the upstream bridge. As the Capabilities offset
> is not correctly calculated for the write to target device's LNKCTL
> register, the code is not disabling/enabling device's ASPM either.
> Therefore, just remove the upstream bridge related ASPM disable/enable
> code entirely.
>
> The upstream bridge related ASPM code was the only user of the struct
> mp_adapter members num4bytes, pcibridge_pciehdr_offset, and
> pcibridge_linkctrlreg so those are removed as well.
>
> Note: This change does not remove the code related to changing the
> device's ASPM on purpose (which is independent of this flawed code
> related to upstream bridge's ASPM).
>
> Suggested-by: Bjorn Helgaas <[email protected]>
> Fixes: 0c8173385e54 ("rtl8192ce: Add new driver")
> Fixes: 886e14b65a8f ("rtlwifi: Eliminate raw reads and writes from PCIe portion")
> Cc: [email protected]
> Signed-off-by: Ilpo Järvinen <[email protected]>

10 patches applied to wireless-next.git, thanks.

b3943b3c2971 wifi: rtlwifi: Remove bogus and dangerous ASPM disable/enable code
5894d0089cbc wifi: rtlwifi: Convert LNKCTL change to PCIe cap RMW accessors
a4fcac11a25a wifi: rtlwifi: Convert to use PCIe capability accessors
6e071ae899f1 wifi: rtlwifi: rtl8821ae: Remove unnecessary PME_Status bit set
760bfed91201 wifi: rtlwifi: rtl8821ae: Reverse PM Capability exists check
9dcc75e0b7d0 wifi: rtlwifi: rtl8821ae: Use pci_find_capability()
7bd350d2ac91 wifi: rtlwifi: rtl8821ae: Add pdev into _rtl8821ae_clear_pci_pme_status()
05b311a3f915 wifi: rtlwifi: rtl8821ae: Access full PMCS reg and use pci_regs.h
217fbc032eaa wifi: rtlwifi: Remove unused PCI related defines and struct
874a0eda000d wifi: rtlwifi: Remove bridge vendor/device ids

--
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches