2020-12-23 03:05:43

by Carl Huang

[permalink] [raw]
Subject: [PATCH 0/6] ath11k: support one MSI vector

This patch set is to support one MSI vector for QCA6390.

Carl Huang (6):
ath11k: get msi_data again after request_irq is called
ath11k: add ce and ext irq flag to indicate irq_handler
ath11k: use ATH11K_PCI_IRQ_DP_OFFSET for dp irqx
ath11k: refactor mulitple msi vector implementation
ath11k: supports one MSI vector
ath11k: do not restore ASPM in case of single MSI vector

drivers/net/wireless/ath/ath11k/core.h | 2 +
drivers/net/wireless/ath/ath11k/mhi.c | 13 ++-
drivers/net/wireless/ath/ath11k/pci.c | 200 +++++++++++++++++++++++++++------
drivers/net/wireless/ath/ath11k/pci.h | 8 ++
4 files changed, 189 insertions(+), 34 deletions(-)

--
2.7.4


2020-12-23 03:05:48

by Carl Huang

[permalink] [raw]
Subject: [PATCH 2/6] ath11k: add ce and ext irq flag to indicate irq_handler

This change adds two flags to indicate whether irq handler for CE
and dp can be called. This is because in one MSI vector case,
interrupt is not disabled in hif_stop and hif_irq_disable. Otherwise,
MHI interrupt is disabled too.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1

Signed-off-by: Carl Huang <[email protected]>
---
drivers/net/wireless/ath/ath11k/core.h | 2 ++
drivers/net/wireless/ath/ath11k/pci.c | 13 +++++++++++++
2 files changed, 15 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 799bf3d..3dacca5 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -741,6 +741,8 @@ struct ath11k_base {

struct completion htc_suspend;

+ bool ce_irq_enabled_flag;
+ bool ext_irq_enabled_flag;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index c1ae1df..deb2d47 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -487,6 +487,8 @@ static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab)
{
int i;

+ ab->ce_irq_enabled_flag = false;
+
for (i = 0; i < ab->hw_params.ce_count; i++) {
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue;
@@ -521,6 +523,9 @@ static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
{
struct ath11k_ce_pipe *ce_pipe = arg;

+ if (!ab->ce_irq_enabled_flag)
+ return IRQ_HANDLED;
+
ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
tasklet_schedule(&ce_pipe->intr_tq);

@@ -539,6 +544,8 @@ static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
{
int i;

+ ab->ext_irq_enabled_flag = false;
+
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i];

@@ -561,6 +568,8 @@ static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab)
{
int i;

+ ab->ext_irq_enabled_flag = true;
+
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];

@@ -613,6 +622,9 @@ static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg)
{
struct ath11k_ext_irq_grp *irq_grp = arg;

+ if (!irq_grp->ab->ext_irq_enabled_flag)
+ return IRQ_HANDLED;
+
ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);

ath11k_pci_ext_grp_disable(irq_grp);
@@ -1026,6 +1038,7 @@ static int ath11k_pci_start(struct ath11k_base *ab)
set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);

ath11k_pci_aspm_restore(ab_pci);
+ ab->ce_irq_enabled_flag = true;

ath11k_pci_ce_irqs_enable(ab);
ath11k_ce_rx_post_buf(ab);
--
2.7.4

2020-12-23 03:05:54

by Carl Huang

[permalink] [raw]
Subject: [PATCH 3/6] ath11k: use ATH11K_PCI_IRQ_DP_OFFSET for dp irqx

Like ATH11K_PCI_IRQ_CE0_OFFSET, define ATH11K_PCI_IRQ_DP_OFFSET for
dp to save the irq instead of base_vector from msi config.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1

Signed-off-by: Carl Huang <[email protected]>
---
drivers/net/wireless/ath/ath11k/pci.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index deb2d47..7ec2209 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -16,7 +16,8 @@
#define ATH11K_PCI_BAR_NUM 0
#define ATH11K_PCI_DMA_MASK 32

-#define ATH11K_PCI_IRQ_CE0_OFFSET 3
+#define ATH11K_PCI_IRQ_CE0_OFFSET 3
+#define ATH11K_PCI_IRQ_DP_OFFSET 14

#define WINDOW_ENABLE_BIT 0x40000000
#define WINDOW_REG_ADDRESS 0x310c
@@ -668,7 +669,7 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
}

irq_grp->num_irq = num_irq;
- irq_grp->irqs[0] = base_vector + i;
+ irq_grp->irqs[0] = ATH11K_PCI_IRQ_DP_OFFSET + i;

for (j = 0; j < irq_grp->num_irq; j++) {
int irq_idx = irq_grp->irqs[j];
--
2.7.4

2020-12-23 03:06:17

by Carl Huang

[permalink] [raw]
Subject: [PATCH 6/6] ath11k: do not restore ASPM in case of single MSI vector

For single MSI vector, ath11k doesn't restore ASPM as the MHI
register reading in M2 causes system hung.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1

Signed-off-by: Carl Huang <[email protected]>
---
drivers/net/wireless/ath/ath11k/pci.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index a120d7c..8c6147b 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -1119,7 +1119,11 @@ static int ath11k_pci_start(struct ath11k_base *ab)

set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);

- ath11k_pci_aspm_restore(ab_pci);
+ /* TODO: fo now don't restore ASPM in case of single MSI
+ * vector as MHI register reading in M2 causes system hang.
+ */
+ if (ab_pci->vectors_32_capability)
+ ath11k_pci_aspm_restore(ab_pci);
ab->ce_irq_enabled_flag = true;

ath11k_pci_ce_irqs_enable(ab);
--
2.7.4

2020-12-23 03:07:26

by Carl Huang

[permalink] [raw]
Subject: [PATCH 4/6] ath11k: refactor mulitple msi vector implementation

This is to prepare for one msi vector support.
Irq enable and disable functions of ce and dp are wrapped.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1

Signed-off-by: Carl Huang <[email protected]>
---
drivers/net/wireless/ath/ath11k/pci.c | 86 +++++++++++++++++++++++++++--------
drivers/net/wireless/ath/ath11k/pci.h | 8 ++++
2 files changed, 75 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 7ec2209..5fdfc72 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -406,17 +406,18 @@ int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_nam
int *num_vectors, u32 *user_base_data,
u32 *base_vector)
{
+ const struct ath11k_msi_config *msi_config = ab_pci->msi_config;
struct ath11k_base *ab = ab_pci->ab;
int idx;

- for (idx = 0; idx < msi_config.total_users; idx++) {
- if (strcmp(user_name, msi_config.users[idx].name) == 0) {
- *num_vectors = msi_config.users[idx].num_vectors;
- *user_base_data = msi_config.users[idx].base_vector
- + ab_pci->msi_ep_base_data;
- *base_vector = msi_config.users[idx].base_vector;
+ for (idx = 0; idx < msi_config->total_users; idx++) {
+ if (strcmp(user_name, msi_config->users[idx].name) == 0) {
+ *num_vectors = msi_config->users[idx].num_vectors;
+ *base_vector = msi_config->users[idx].base_vector;
+ *user_base_data = *base_vector + ab_pci->msi_ep_base_data;

- ath11k_dbg(ab, ATH11K_DBG_PCI, "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
+ ath11k_dbg(ab, ATH11K_DBG_PCI,
+ "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
user_name, *num_vectors, *user_base_data,
*base_vector);

@@ -468,7 +469,7 @@ static void ath11k_pci_free_irq(struct ath11k_base *ab)
ath11k_pci_free_ext_irq(ab);
}

-static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
+static void ath11k_pci_ce_irq_enable_multiple_msi(struct ath11k_base *ab, u16 ce_id)
{
u32 irq_idx;

@@ -476,7 +477,15 @@ static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
enable_irq(ab->irq_num[irq_idx]);
}

-static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
+static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
+{
+ struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
+
+ if (ab_pci->ce_irq_enable)
+ ab_pci->ce_irq_enable(ab, ce_id);
+}
+
+static void ath11k_pci_ce_irq_disable_multiple_msi(struct ath11k_base *ab, u16 ce_id)
{
u32 irq_idx;

@@ -484,12 +493,19 @@ static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
disable_irq_nosync(ab->irq_num[irq_idx]);
}

+static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
+{
+ struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
+
+ if (ab_pci->ce_irq_disable)
+ ab_pci->ce_irq_disable(ab, ce_id);
+}
+
static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab)
{
int i;

ab->ce_irq_enabled_flag = false;
-
for (i = 0; i < ab->hw_params.ce_count; i++) {
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue;
@@ -523,6 +539,7 @@ static void ath11k_pci_ce_tasklet(struct tasklet_struct *t)
static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
{
struct ath11k_ce_pipe *ce_pipe = arg;
+ struct ath11k_base *ab = ce_pipe->ab;

if (!ab->ce_irq_enabled_flag)
return IRQ_HANDLED;
@@ -533,7 +550,7 @@ static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
return IRQ_HANDLED;
}

-static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
+static void ath11k_pci_ext_grp_disable_multiple_msi(struct ath11k_ext_irq_grp *irq_grp)
{
int i;

@@ -541,14 +558,21 @@ static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
}

-static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
+static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
+{
+ struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab);
+
+ if (ab_pci->ext_grp_disable)
+ ab_pci->ext_grp_disable(irq_grp);
+}
+
+static void __ath11k_pci_ext_irq_disable(struct ath11k_base *ab)
{
int i;

ab->ext_irq_enabled_flag = false;
-
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
- struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i];
+ struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];

ath11k_pci_ext_grp_disable(irq_grp);

@@ -557,7 +581,7 @@ static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
}
}

-static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
+static void ath11k_pci_ext_grp_enable_multiple_msi(struct ath11k_ext_irq_grp *irq_grp)
{
int i;

@@ -565,6 +589,14 @@ static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
}

+static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
+{
+ struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab);
+
+ if (ab_pci->ext_grp_enable)
+ ab_pci->ext_grp_enable(irq_grp);
+}
+
static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab)
{
int i;
@@ -637,6 +669,7 @@ static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg)

static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
{
+ struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
int i, j, ret, num_vectors = 0;
u32 user_base_data = 0, base_vector = 0;

@@ -681,16 +714,15 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
ath11k_dbg(ab, ATH11K_DBG_PCI,
"irq:%d group:%d\n", irq, i);
ret = request_irq(irq, ath11k_pci_ext_interrupt_handler,
- IRQF_SHARED,
+ ab_pci->irq_flags,
"DP_EXT_IRQ", irq_grp);
if (ret) {
ath11k_err(ab, "failed request irq %d: %d\n",
vector, ret);
return ret;
}
-
- disable_irq_nosync(ab->irq_num[irq_idx]);
}
+ ath11k_pci_ext_grp_disable(irq_grp);
}

return 0;
@@ -698,6 +730,7 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)

static int ath11k_pci_config_irq(struct ath11k_base *ab)
{
+ struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
struct ath11k_ce_pipe *ce_pipe;
u32 msi_data_start;
u32 msi_data_count;
@@ -725,7 +758,7 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
tasklet_setup(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet);

ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
- IRQF_SHARED, irq_name[irq_idx],
+ ab_pci->irq_flags, irq_name[irq_idx],
ce_pipe);
if (ret) {
ath11k_err(ab, "failed to request irq %d: %d\n",
@@ -770,6 +803,19 @@ static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab)
}
}

+static void ath11k_pci_init_irq_handlers(struct ath11k_pci *ab_pci, bool multiple_msi)
+{
+ if (multiple_msi) {
+ ab_pci->vectors_32_capability = true;
+ ab_pci->ext_grp_enable = ath11k_pci_ext_grp_enable_multiple_msi;
+ ab_pci->ext_grp_disable = ath11k_pci_ext_grp_disable_multiple_msi;
+ ab_pci->ce_irq_enable = ath11k_pci_ce_irq_enable_multiple_msi;
+ ab_pci->ce_irq_disable = ath11k_pci_ce_irq_disable_multiple_msi;
+ ab_pci->msi_config = &msi_config;
+ ab_pci->irq_flags = IRQF_SHARED;
+ }
+}
+
static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
{
struct ath11k_base *ab = ab_pci->ab;
@@ -789,6 +835,8 @@ static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
return -EINVAL;
else
return num_vectors;
+ } else {
+ ath11k_pci_init_irq_handlers(ab_pci, true);
}

msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
diff --git a/drivers/net/wireless/ath/ath11k/pci.h b/drivers/net/wireless/ath/ath11k/pci.h
index fe44d0d..2097466 100644
--- a/drivers/net/wireless/ath/ath11k/pci.h
+++ b/drivers/net/wireless/ath/ath11k/pci.h
@@ -72,6 +72,7 @@ struct ath11k_pci {
u16 dev_id;
char amss_path[100];
u32 msi_ep_base_data;
+ bool vectors_32_capability;
struct mhi_controller *mhi_ctrl;
unsigned long mhi_state;
u32 register_window;
@@ -82,6 +83,13 @@ struct ath11k_pci {
/* enum ath11k_pci_flags */
unsigned long flags;
u16 link_ctl;
+
+ const struct ath11k_msi_config *msi_config;
+ unsigned long irq_flags;
+ void (*ext_grp_disable)(struct ath11k_ext_irq_grp *irq_grp);
+ void (*ext_grp_enable)(struct ath11k_ext_irq_grp *irq_grp);
+ void (*ce_irq_enable)(struct ath11k_base *ab, u16 ce_id);
+ void (*ce_irq_disable)(struct ath11k_base *ab, u16 ce_id);
};

static inline struct ath11k_pci *ath11k_pci_priv(struct ath11k_base *ab)
--
2.7.4

2020-12-23 03:07:29

by Carl Huang

[permalink] [raw]
Subject: [PATCH 5/6] ath11k: supports one MSI vector

Some platforms can't allocate 32 MSI vectors to QCA6390, and QCA6390
will request one MSI vector instead.

In case of one MSI vector, interrupt migration needs to be disabled.
This is because when interrupt migration happens, the msi_data may
change. However, msi_data is already programmed to rings during
initial phase and ath11k has no way to know that msi_data is changed
during run time and reprogram again.

In case of one MSI vector, MHI subsystem should not use IRQF_NO_SUSPEND
as QCA6390 doesn't set this flag too. Ath11k doesn't need to leave
IRQ enabled in suspend state.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1

Signed-off-by: Carl Huang <[email protected]>
---
drivers/net/wireless/ath/ath11k/mhi.c | 13 ++++++--
drivers/net/wireless/ath/ath11k/pci.c | 59 +++++++++++++++++++++++++++--------
2 files changed, 57 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index 09858e5..2d35309 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -152,14 +152,17 @@ static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci)
{
struct ath11k_base *ab = ab_pci->ab;
u32 user_base_data, base_vector;
+ u32 vectors_32_capability;
int ret, num_vectors, i;
int *irq;
+ unsigned int msi_data;

ret = ath11k_pci_get_user_msi_assignment(ab_pci,
"MHI", &num_vectors,
&user_base_data, &base_vector);
if (ret)
return ret;
+ vectors_32_capability = ab_pci->vectors_32_capability;

ath11k_dbg(ab, ATH11K_DBG_PCI, "Number of assigned MSI for MHI is %d, base vector is %d\n",
num_vectors, base_vector);
@@ -168,9 +171,13 @@ static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci)
if (!irq)
return -ENOMEM;

- for (i = 0; i < num_vectors; i++)
+ for (i = 0; i < num_vectors; i++) {
+ msi_data = vectors_32_capability ?
+ i + base_vector : base_vector;
+
irq[i] = ath11k_pci_get_msi_irq(ab->dev,
- base_vector + i);
+ msi_data);
+ }

ab_pci->mhi_ctrl->irq = irq;
ab_pci->mhi_ctrl->nr_irqs = num_vectors;
@@ -243,6 +250,8 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
return ret;
}

+ if (!ab_pci->vectors_32_capability)
+ mhi_ctrl->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;
mhi_ctrl->iova_start = 0;
mhi_ctrl->iova_stop = 0xffffffff;
mhi_ctrl->sbl_size = SZ_512K;
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 5fdfc72..a120d7c 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -62,6 +62,17 @@ static const struct ath11k_msi_config msi_config = {
},
};

+static const struct ath11k_msi_config msi_config_one_msi = {
+ .total_vectors = 1,
+ .total_users = 4,
+ .users = (struct ath11k_msi_user[]) {
+ { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
+ { .name = "CE", .num_vectors = 1, .base_vector = 0 },
+ { .name = "WAKE", .num_vectors = 1, .base_vector = 0 },
+ { .name = "DP", .num_vectors = 1, .base_vector = 0 },
+ },
+};
+
static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
"bhi",
"mhi-er0",
@@ -530,10 +541,11 @@ static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab)
static void ath11k_pci_ce_tasklet(struct tasklet_struct *t)
{
struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
+ int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;

ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);

- ath11k_pci_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
+ enable_irq(ce_pipe->ab->irq_num[irq_idx]);
}

static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
@@ -541,10 +553,13 @@ static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
struct ath11k_ce_pipe *ce_pipe = arg;
struct ath11k_base *ab = ce_pipe->ab;

+ int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
+
if (!ab->ce_irq_enabled_flag)
return IRQ_HANDLED;

- ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
+ disable_irq_nosync(ab->irq_num[irq_idx]);
+
tasklet_schedule(&ce_pipe->intr_tq);

return IRQ_HANDLED;
@@ -638,11 +653,13 @@ static int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget)
napi);
struct ath11k_base *ab = irq_grp->ab;
int work_done;
+ int i;

work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
if (work_done < budget) {
napi_complete_done(napi, work_done);
- ath11k_pci_ext_grp_enable(irq_grp);
+ for (i = 0; i < irq_grp->num_irq; i++)
+ enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
}

if (work_done > budget)
@@ -654,13 +671,15 @@ static int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget)
static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg)
{
struct ath11k_ext_irq_grp *irq_grp = arg;
+ int i;

if (!irq_grp->ab->ext_irq_enabled_flag)
return IRQ_HANDLED;

ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);

- ath11k_pci_ext_grp_disable(irq_grp);
+ for (i = 0; i < irq_grp->num_irq; i++)
+ disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);

napi_schedule(&irq_grp->napi);

@@ -747,6 +766,7 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
/* Configure CE irqs */
for (i = 0; i < ab->hw_params.ce_count; i++) {
msi_data = (i % msi_data_count) + msi_irq_start;
+
irq = ath11k_pci_get_msi_irq(ab->dev, msi_data);
ce_pipe = &ab->ce.ce_pipe[i];

@@ -813,6 +833,14 @@ static void ath11k_pci_init_irq_handlers(struct ath11k_pci *ab_pci, bool multipl
ab_pci->ce_irq_disable = ath11k_pci_ce_irq_disable_multiple_msi;
ab_pci->msi_config = &msi_config;
ab_pci->irq_flags = IRQF_SHARED;
+ } else {
+ ab_pci->vectors_32_capability = false;
+ ab_pci->ext_grp_enable = NULL;
+ ab_pci->ext_grp_disable = NULL;
+ ab_pci->ce_irq_enable = NULL;
+ ab_pci->ce_irq_disable = NULL;
+ ab_pci->msi_config = &msi_config_one_msi;
+ ab_pci->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;
}
}

@@ -827,16 +855,20 @@ static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
msi_config.total_vectors,
msi_config.total_vectors,
PCI_IRQ_MSI);
- if (num_vectors != msi_config.total_vectors) {
- ath11k_err(ab, "failed to get %d MSI vectors, only %d available",
- msi_config.total_vectors, num_vectors);
-
- if (num_vectors >= 0)
- return -EINVAL;
- else
- return num_vectors;
- } else {
+
+ if (num_vectors == msi_config.total_vectors) {
ath11k_pci_init_irq_handlers(ab_pci, true);
+ } else {
+ num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
+ 1,
+ 1,
+ PCI_IRQ_MSI);
+ if (num_vectors < 0) {
+ ret = -EINVAL;
+ goto reset_msi_config;
+ }
+ ath11k_pci_init_irq_handlers(ab_pci, false);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "request MSI one vector\n");
}

msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
@@ -857,6 +889,7 @@ static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
free_msi_vector:
pci_free_irq_vectors(ab_pci->pdev);

+reset_msi_config:
return ret;
}

--
2.7.4

2021-02-11 07:11:57

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 0/6] ath11k: support one MSI vector

Carl Huang <[email protected]> writes:

> This patch set is to support one MSI vector for QCA6390.
>
> Carl Huang (6):
> ath11k: get msi_data again after request_irq is called
> ath11k: add ce and ext irq flag to indicate irq_handler
> ath11k: use ATH11K_PCI_IRQ_DP_OFFSET for dp irqx
> ath11k: refactor mulitple msi vector implementation
> ath11k: supports one MSI vector
> ath11k: do not restore ASPM in case of single MSI vector

I did some cleanup and before submitting v2 I noticed the patchset (both
v1 and v2) is crashing during suspend on my Dell XPS 13 9310. We are
investigating the reason for that and will submit v2 once those are
fixed.

--
https://patchwork.kernel.org/project/linux-wireless/list/

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

2021-10-22 08:05:38

by Janusz Dziedzic

[permalink] [raw]
Subject: Re: [PATCH 0/6] ath11k: support one MSI vector

czw., 11 lut 2021 o 08:10 Kalle Valo <[email protected]> napisał(a):
>
> Carl Huang <[email protected]> writes:
>
> > This patch set is to support one MSI vector for QCA6390.
> >
> > Carl Huang (6):
> > ath11k: get msi_data again after request_irq is called
> > ath11k: add ce and ext irq flag to indicate irq_handler
> > ath11k: use ATH11K_PCI_IRQ_DP_OFFSET for dp irqx
> > ath11k: refactor mulitple msi vector implementation
> > ath11k: supports one MSI vector
> > ath11k: do not restore ASPM in case of single MSI vector
>
> I did some cleanup and before submitting v2 I noticed the patchset (both
> v1 and v2) is crashing during suspend on my Dell XPS 13 9310. We are
> investigating the reason for that and will submit v2 once those are
> fixed.
>
Hello Kalle,

What is status for this series?
I am using ath11k in my banana-pi-r64 (backports-5.15-rc6) board and hit:
[ 162.392043] ath11k_pci 0000:01:00.0: failed to get 32 MSI vectors,
only -28 available
[ 162.399927] ath11k_pci 0000:01:00.0: failed to enable msi: -28
[ 162.405778] ath11k_pci 0000:01:00.0: disabling bus mastering
[ 162.411481] ath11k_pci: probe of 0000:01:00.0 failed with error -28

I suspect this series should fix my issue?

BR
Janusz

> --
> https://patchwork.kernel.org/project/linux-wireless/list/
>
> https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches



--
Janusz Dziedzic

2021-11-15 10:43:56

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 0/6] ath11k: support one MSI vector

Janusz Dziedzic <[email protected]> writes:

> czw., 11 lut 2021 o 08:10 Kalle Valo <[email protected]> napisał(a):
>>
>> Carl Huang <[email protected]> writes:
>>
>> > This patch set is to support one MSI vector for QCA6390.
>> >
>> > Carl Huang (6):
>> > ath11k: get msi_data again after request_irq is called
>> > ath11k: add ce and ext irq flag to indicate irq_handler
>> > ath11k: use ATH11K_PCI_IRQ_DP_OFFSET for dp irqx
>> > ath11k: refactor mulitple msi vector implementation
>> > ath11k: supports one MSI vector
>> > ath11k: do not restore ASPM in case of single MSI vector
>>
>> I did some cleanup and before submitting v2 I noticed the patchset (both
>> v1 and v2) is crashing during suspend on my Dell XPS 13 9310. We are
>> investigating the reason for that and will submit v2 once those are
>> fixed.
>>
> Hello Kalle,
>
> What is status for this series?

There's now a new version available:

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

If you can, please do test the version in the master-pending branch
(commit 9a914cfdbfd69):

https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/log/?h=master-pending

> I am using ath11k in my banana-pi-r64 (backports-5.15-rc6) board and hit:
> [ 162.392043] ath11k_pci 0000:01:00.0: failed to get 32 MSI vectors,
> only -28 available
> [ 162.399927] ath11k_pci 0000:01:00.0: failed to enable msi: -28
> [ 162.405778] ath11k_pci 0000:01:00.0: disabling bus mastering
> [ 162.411481] ath11k_pci: probe of 0000:01:00.0 failed with error -28
>
> I suspect this series should fix my issue?

Most likely this should fix it. You could also try changing your BIOS
settings to get more MSI vectors, IIRC enabling VT-d help on NUC boards
at least.

--
https://patchwork.kernel.org/project/linux-wireless/list/

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