2024-05-23 11:21:51

by Mingyen Hsieh

[permalink] [raw]
Subject: [PATCH v2] wifi: mt76: mt792x: fix scheduler interference in drv own process

From: Michael Lo <[email protected]>

Add some time to wait for LP engine to complete its operation
before polling pmctrl register.

Signed-off-by: Michael Lo <[email protected]>
Signed-off-by: Ming Yen Hsieh <[email protected]>
---
v2: change funcion and variable naming.
---

drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
.../net/wireless/mediatek/mt76/mt7921/pci.c | 3 +++
.../net/wireless/mediatek/mt76/mt7925/pci.c | 3 +++
drivers/net/wireless/mediatek/mt76/mt792x.h | 1 +
.../net/wireless/mediatek/mt76/mt792x_core.c | 4 ++++
drivers/net/wireless/mediatek/mt76/pci.c | 23 +++++++++++++++++++
6 files changed, 35 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 11b9f22ca7f3..4168104fa141 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -1081,6 +1081,7 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,

void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs);
void mt76_pci_disable_aspm(struct pci_dev *pdev);
+bool mt76_pci_aspm_supported(struct pci_dev *pdev);

static inline u16 mt76_chip(struct mt76_dev *dev)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index f768e9389ac6..ca54ae7deb54 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -339,6 +339,9 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
bus_ops->rmw = mt7921_rmw;
dev->mt76.bus = bus_ops;

+ if (!mt7921_disable_aspm && mt76_pci_aspm_supported(pdev))
+ dev->aspm_supported = true;
+
ret = mt792xe_mcu_fw_pmctrl(dev);
if (ret)
goto err_free_dev;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index 07b74d492ce1..2449b3e6c396 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -373,6 +373,9 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
bus_ops->rmw = mt7925_rmw;
dev->mt76.bus = bus_ops;

+ if (!mt7925_disable_aspm && mt76_pci_aspm_supported(pdev))
+ dev->aspm_supported = true;
+
ret = __mt792x_mcu_fw_pmctrl(dev);
if (ret)
goto err_free_dev;
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 20578497a405..c2c42e5d650a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -190,6 +190,7 @@ struct mt792x_dev {
bool fw_assert:1;
bool has_eht:1;
bool regd_in_progress:1;
+ bool aspm_supported:1;
wait_queue_head_t wait;

struct work_struct init_work;
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
index a405af8d9052..588b24edfdd9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
@@ -766,6 +766,10 @@ int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev)

for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) {
mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN);
+
+ if (dev->aspm_supported)
+ usleep_range(2000, 3000);
+
if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL,
PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1))
break;
diff --git a/drivers/net/wireless/mediatek/mt76/pci.c b/drivers/net/wireless/mediatek/mt76/pci.c
index 4c1c159fbb62..b5031ca7f73f 100644
--- a/drivers/net/wireless/mediatek/mt76/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/pci.c
@@ -45,3 +45,26 @@ void mt76_pci_disable_aspm(struct pci_dev *pdev)
aspm_conf);
}
EXPORT_SYMBOL_GPL(mt76_pci_disable_aspm);
+
+bool mt76_pci_aspm_supported(struct pci_dev *pdev)
+{
+ struct pci_dev *parent = pdev->bus->self;
+ u16 aspm_conf, parent_aspm_conf = 0;
+ bool result = true;
+
+ pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &aspm_conf);
+ aspm_conf &= PCI_EXP_LNKCTL_ASPMC;
+ if (parent) {
+ pcie_capability_read_word(parent, PCI_EXP_LNKCTL,
+ &parent_aspm_conf);
+ parent_aspm_conf &= PCI_EXP_LNKCTL_ASPMC;
+ }
+
+ if (!aspm_conf && (!parent || !parent_aspm_conf)) {
+ /* aspm already disabled */
+ result = false;
+ }
+
+ return result;
+}
+EXPORT_SYMBOL_GPL(mt76_pci_aspm_supported);
--
2.18.0



2024-06-04 23:12:15

by Sean Wang

[permalink] [raw]
Subject: Re: [PATCH v2] wifi: mt76: mt792x: fix scheduler interference in drv own process

Hi,

On Thu, May 23, 2024 at 4:21 AM Mingyen Hsieh
<[email protected]> wrote:
>
> From: Michael Lo <[email protected]>
>
> Add some time to wait for LP engine to complete its operation
> before polling pmctrl register.
>
> Signed-off-by: Michael Lo <[email protected]>
> Signed-off-by: Ming Yen Hsieh <[email protected]>

The new patch is an improvement over v1 as it avoids unnecessary
waiting in specific cases, such as when users are forced to disable
ASPM or when the host doesn't support ASPM as I suggested in v1. Thus,

Acked-by: Sean Wang <[email protected]>

> ---
> v2: change funcion and variable naming.
> ---
>
> drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
> .../net/wireless/mediatek/mt76/mt7921/pci.c | 3 +++
> .../net/wireless/mediatek/mt76/mt7925/pci.c | 3 +++
> drivers/net/wireless/mediatek/mt76/mt792x.h | 1 +
> .../net/wireless/mediatek/mt76/mt792x_core.c | 4 ++++
> drivers/net/wireless/mediatek/mt76/pci.c | 23 +++++++++++++++++++
> 6 files changed, 35 insertions(+)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 11b9f22ca7f3..4168104fa141 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -1081,6 +1081,7 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
>
> void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs);
> void mt76_pci_disable_aspm(struct pci_dev *pdev);
> +bool mt76_pci_aspm_supported(struct pci_dev *pdev);
>
> static inline u16 mt76_chip(struct mt76_dev *dev)
> {
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> index f768e9389ac6..ca54ae7deb54 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> @@ -339,6 +339,9 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
> bus_ops->rmw = mt7921_rmw;
> dev->mt76.bus = bus_ops;
>
> + if (!mt7921_disable_aspm && mt76_pci_aspm_supported(pdev))
> + dev->aspm_supported = true;
> +
> ret = mt792xe_mcu_fw_pmctrl(dev);
> if (ret)
> goto err_free_dev;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
> index 07b74d492ce1..2449b3e6c396 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
> @@ -373,6 +373,9 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
> bus_ops->rmw = mt7925_rmw;
> dev->mt76.bus = bus_ops;
>
> + if (!mt7925_disable_aspm && mt76_pci_aspm_supported(pdev))
> + dev->aspm_supported = true;
> +
> ret = __mt792x_mcu_fw_pmctrl(dev);
> if (ret)
> goto err_free_dev;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
> index 20578497a405..c2c42e5d650a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt792x.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
> @@ -190,6 +190,7 @@ struct mt792x_dev {
> bool fw_assert:1;
> bool has_eht:1;
> bool regd_in_progress:1;
> + bool aspm_supported:1;
> wait_queue_head_t wait;
>
> struct work_struct init_work;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
> index a405af8d9052..588b24edfdd9 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
> @@ -766,6 +766,10 @@ int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev)
>
> for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) {
> mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN);
> +
> + if (dev->aspm_supported)
> + usleep_range(2000, 3000);
> +
> if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL,
> PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1))
> break;
> diff --git a/drivers/net/wireless/mediatek/mt76/pci.c b/drivers/net/wireless/mediatek/mt76/pci.c
> index 4c1c159fbb62..b5031ca7f73f 100644
> --- a/drivers/net/wireless/mediatek/mt76/pci.c
> +++ b/drivers/net/wireless/mediatek/mt76/pci.c
> @@ -45,3 +45,26 @@ void mt76_pci_disable_aspm(struct pci_dev *pdev)
> aspm_conf);
> }
> EXPORT_SYMBOL_GPL(mt76_pci_disable_aspm);
> +
> +bool mt76_pci_aspm_supported(struct pci_dev *pdev)
> +{
> + struct pci_dev *parent = pdev->bus->self;
> + u16 aspm_conf, parent_aspm_conf = 0;
> + bool result = true;
> +
> + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &aspm_conf);
> + aspm_conf &= PCI_EXP_LNKCTL_ASPMC;
> + if (parent) {
> + pcie_capability_read_word(parent, PCI_EXP_LNKCTL,
> + &parent_aspm_conf);
> + parent_aspm_conf &= PCI_EXP_LNKCTL_ASPMC;
> + }
> +
> + if (!aspm_conf && (!parent || !parent_aspm_conf)) {
> + /* aspm already disabled */
> + result = false;
> + }
> +
> + return result;
> +}
> +EXPORT_SYMBOL_GPL(mt76_pci_aspm_supported);
> --
> 2.18.0
>
>