* [PATCH RFT] ath11k: pci: support platforms with one MSI vector
@ 2020-11-11 18:58 ` Kalle Valo
0 siblings, 0 replies; 7+ messages in thread
From: Kalle Valo @ 2020-11-11 18:58 UTC (permalink / raw)
To: ath11k; +Cc: linux-wireless
From: Carl Huang <cjhuang@codeaurora.org>
Dell XPS 13 9310 has only one MSI vector available for QCA6390 device and ath11k fails with:
ath11k_pci 0000:56:00.0: failed to get 32 MSI vectors, only -28 available
ath11k_pci 0000:56:00.0: failed to enable msi: -28
ath11k_pci: probe of 0000:56:00.0 failed with error -28
This is a proof of concept patch for getting ath11k to work with QCA6390 using
only one MSI vector, not the final solution. Testing feedback more than
welcome. The patch applies to v5.10-rc2.
The idea here is to add a flag to indicate whether this ISR can be called
or not as all the ISR handlers are registered with IRQF_SHARED when ath11k can
only request 1 vector. This needs to be refined later.
In some scenarios, kernel crashed when the interrupt migration happens, so add
IRQF_NOBALANCING.
Also add debug messages to ath11k_qmi_respond_fw_mem_request() for helping to
debug mysterious firmware initialisation timeouts:
ath11k_pci 0000:05:00.0: qmi failed memory request, err = -110
ath11k_pci 0000:05:00.0: qmi failed to respond fw mem req:-110
If that happens, one way to workaround the problem is to revert this commit:
7fef431be9c9 mm/page_alloc: place pages to tail in __free_pages_core()
Link: https://lore.kernel.org/linux-pci/87mtzxkus5.fsf@nanos.tec.linutronix.de/
Link: http://lists.infradead.org/pipermail/ath11k/2020-November/000550.html
Signed-off-by: Carl Huang <cjhuang@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/bus/mhi/core/init.c | 4 +-
drivers/net/wireless/ath/ath11k/ce.c | 6 +-
drivers/net/wireless/ath/ath11k/core.h | 1 +
drivers/net/wireless/ath/ath11k/dp.c | 8 +-
drivers/net/wireless/ath/ath11k/hif.h | 1 +
drivers/net/wireless/ath/ath11k/mhi.c | 11 +-
drivers/net/wireless/ath/ath11k/pci.c | 178 +++++++++++++++++++++++++++------
drivers/net/wireless/ath/ath11k/pci.h | 1 +
drivers/net/wireless/ath/ath11k/qmi.c | 4 +
9 files changed, 174 insertions(+), 40 deletions(-)
diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index 0ffdebde8265..d182ffdbaf64 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -153,7 +153,7 @@ int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl)
/* Setup BHI_INTVEC IRQ */
ret = request_threaded_irq(mhi_cntrl->irq[0], mhi_intvec_handler,
mhi_intvec_threaded_handler,
- IRQF_SHARED | IRQF_NO_SUSPEND,
+ IRQF_SHARED | IRQF_NOBALANCING,
"bhi", mhi_cntrl);
if (ret)
return ret;
@@ -171,7 +171,7 @@ int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl)
ret = request_irq(mhi_cntrl->irq[mhi_event->irq],
mhi_irq_handler,
- IRQF_SHARED | IRQF_NO_SUSPEND,
+ IRQF_SHARED | IRQF_NOBALANCING,
"mhi", mhi_event);
if (ret) {
dev_err(dev, "Error requesting irq:%d for ev:%d\n",
diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c
index 9d730f8ac816..46c717a344c3 100644
--- a/drivers/net/wireless/ath/ath11k/ce.c
+++ b/drivers/net/wireless/ath/ath11k/ce.c
@@ -459,20 +459,22 @@ static void ath11k_ce_srng_msi_ring_params_setup(struct ath11k_base *ab, u32 ce_
u32 msi_irq_start;
u32 addr_lo;
u32 addr_hi;
+ u32 vectors_32_capability;
int ret;
ret = ath11k_get_user_msi_vector(ab, "CE",
&msi_data_count, &msi_data_start,
&msi_irq_start);
-
if (ret)
return;
+ vectors_32_capability = ab->hif.ops->is_32_vecs_support(ab);
ath11k_get_msi_address(ab, &addr_lo, &addr_hi);
ring_params->msi_addr = addr_lo;
ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32);
- ring_params->msi_data = (ce_id % msi_data_count) + msi_data_start;
+ ring_params->msi_data = vectors_32_capability ?
+ (ce_id % msi_data_count) + msi_data_start : msi_data_start;
ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;
}
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 18b97420f0d8..0de6b2cd8c75 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -683,6 +683,7 @@ struct ath11k_base {
bool wmi_ready;
u32 wlan_init_status;
int irq_num[ATH11K_IRQ_NUM_MAX];
+ int irq_enable_flag[ATH11K_IRQ_NUM_MAX];
struct ath11k_ext_irq_grp ext_irq_grp[ATH11K_EXT_IRQ_GRP_NUM_MAX];
struct napi_struct *napi;
struct ath11k_targ_cap target_caps;
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index 59dd185a0cfc..b7288dc47199 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -180,13 +180,15 @@ static void ath11k_dp_srng_msi_setup(struct ath11k_base *ab,
{
int msi_group_number, msi_data_count;
u32 msi_data_start, msi_irq_start, addr_lo, addr_hi;
- int ret;
+ u32 vectors_32_capability;
+ int ret = -EINVAL;
ret = ath11k_get_user_msi_vector(ab, "DP",
&msi_data_count, &msi_data_start,
&msi_irq_start);
if (ret)
return;
+ vectors_32_capability = ab->hif.ops->is_32_vecs_support(ab);
msi_group_number = ath11k_dp_srng_calculate_msi_group(ab, type,
ring_num);
@@ -209,8 +211,8 @@ static void ath11k_dp_srng_msi_setup(struct ath11k_base *ab,
ring_params->msi_addr = addr_lo;
ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32);
- ring_params->msi_data = (msi_group_number % msi_data_count)
- + msi_data_start;
+ ring_params->msi_data = vectors_32_capability ?
+ (msi_group_number % msi_data_count) + msi_data_start : msi_data_start;
ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;
}
diff --git a/drivers/net/wireless/ath/ath11k/hif.h b/drivers/net/wireless/ath/ath11k/hif.h
index dbe5568916e8..b6bde194a390 100644
--- a/drivers/net/wireless/ath/ath11k/hif.h
+++ b/drivers/net/wireless/ath/ath11k/hif.h
@@ -24,6 +24,7 @@ struct ath11k_hif_ops {
u32 *base_vector);
void (*get_msi_address)(struct ath11k_base *ab, u32 *msi_addr_lo,
u32 *msi_addr_hi);
+ int (*is_32_vecs_support)(struct ath11k_base *ab);
};
static inline int ath11k_hif_start(struct ath11k_base *sc)
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index aded9a719d51..80d7dd18034d 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -156,14 +156,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);
@@ -172,9 +175,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;
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index d7eb6b7160bb..a7a98bdc0c5f 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -17,6 +17,7 @@
#define ATH11K_PCI_DMA_MASK 32
#define ATH11K_PCI_IRQ_CE0_OFFSET 3
+#define ATH11K_PCI_IRQ_DP_OFFSET 14
#define WINDOW_ENABLE_BIT 0x40000000
#define WINDOW_REG_ADDRESS 0x310c
@@ -265,12 +266,17 @@ static void ath11k_pci_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
u32 *msi_addr_hi)
{
struct pci_dev *pci_dev = to_pci_dev(ab->dev);
+ u16 is_64bits;
pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,
msi_addr_lo);
+ pci_read_config_word(pci_dev, pci_dev->msi_cap + PCI_MSI_FLAGS, &is_64bits);
- pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
- msi_addr_hi);
+ if (is_64bits & PCI_MSI_FLAGS_64BIT)
+ pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
+ msi_addr_hi);
+ else
+ *msi_addr_hi = 0;
}
int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name,
@@ -278,14 +284,15 @@ int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_nam
u32 *base_vector)
{
struct ath11k_base *ab = ab_pci->ab;
+ u32 msi_32_cap = ab_pci->vectors_32_capability;
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;
+ *base_vector = msi_32_cap ?
+ msi_config.users[idx].base_vector : 0;
+ *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",
user_name, *num_vectors, *user_base_data,
@@ -339,20 +346,38 @@ static void ath11k_pci_free_irq(struct ath11k_base *ab)
ath11k_pci_free_ext_irq(ab);
}
+static void ath11k_pci_set_irq_enable_flag(struct ath11k_base *ab, u32 irq_idx, int flag)
+{
+ ab->irq_enable_flag[irq_idx] = flag;
+}
+
static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
{
u32 irq_idx;
+ u32 vecs_32_cap;
- irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
- enable_irq(ab->irq_num[irq_idx]);
+ vecs_32_cap = ath11k_pci_priv(ab)->vectors_32_capability;
+ irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
+
+ if (vecs_32_cap)
+ enable_irq(ab->irq_num[irq_idx]);
+
+ ath11k_pci_set_irq_enable_flag(ab, irq_idx, 1);
}
static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
{
u32 irq_idx;
+ u32 vecs_32_cap;
+ vecs_32_cap = ath11k_pci_priv(ab)->vectors_32_capability;
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
- disable_irq_nosync(ab->irq_num[irq_idx]);
+
+ /* Cannot disable the irq when using one msi interrupt */
+ if (vecs_32_cap)
+ disable_irq_nosync(ab->irq_num[irq_idx]);
+
+ ath11k_pci_set_irq_enable_flag(ab, irq_idx, 0);
}
static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab)
@@ -382,18 +407,28 @@ static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab)
static void ath11k_pci_ce_tasklet(unsigned long data)
{
+
struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data;
+ 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)
{
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;
+
+ disable_irq_nosync(ab->irq_num[irq_idx]);
+
+ if (!ab->irq_enable_flag[irq_idx]) {
+ enable_irq(ab->irq_num[irq_idx]);
+ return IRQ_HANDLED;
+ }
- ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
tasklet_schedule(&ce_pipe->intr_tq);
return IRQ_HANDLED;
@@ -402,9 +437,16 @@ static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
{
int i;
+ u32 vecs_32_cap;
- for (i = 0; i < irq_grp->num_irq; i++)
- disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
+ vecs_32_cap = ath11k_pci_priv(irq_grp->ab)->vectors_32_capability;
+
+ for (i = 0; i < irq_grp->num_irq; i++) {
+ if (vecs_32_cap)
+ disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
+
+ ath11k_pci_set_irq_enable_flag(irq_grp->ab, irq_grp->irqs[i], 0);
+ }
}
static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
@@ -424,9 +466,15 @@ 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)
{
int i;
+ u32 vecs_32_cap;
- for (i = 0; i < irq_grp->num_irq; i++)
- enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
+ vecs_32_cap = ath11k_pci_priv(irq_grp->ab)->vectors_32_capability;
+
+ for (i = 0; i < irq_grp->num_irq; i++) {
+ if (vecs_32_cap)
+ enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
+ ath11k_pci_set_irq_enable_flag(irq_grp->ab, irq_grp->irqs[i], 1);
+ }
}
static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab)
@@ -468,11 +516,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)
@@ -484,10 +534,16 @@ 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;
- ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);
+ for (i = 0; i < irq_grp->num_irq; i++)
+ disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
- ath11k_pci_ext_grp_disable(irq_grp);
+ if (!irq_grp->ab->irq_enable_flag[irq_grp->irqs[0]]) {
+ for (i = 0; i < irq_grp->num_irq; i++)
+ enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
+ return IRQ_HANDLED;
+ }
napi_schedule(&irq_grp->napi);
@@ -498,6 +554,7 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
{
int i, j, ret, num_vectors = 0;
u32 user_base_data = 0, base_vector = 0;
+ u32 vecs_32_cap;
ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP",
&num_vectors,
@@ -506,6 +563,8 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
if (ret < 0)
return ret;
+ vecs_32_cap = ath11k_pci_priv(ab)->vectors_32_capability;
+
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
u32 num_irq = 0;
@@ -528,11 +587,12 @@ 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];
- int vector = (i % num_vectors) + base_vector;
+ int vector = vecs_32_cap ?
+ (i % num_vectors) + base_vector : base_vector;
int irq = ath11k_pci_get_msi_irq(ab->dev, vector);
ab->irq_num[irq_idx] = irq;
@@ -540,7 +600,7 @@ 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,
+ IRQF_SHARED | IRQF_NOBALANCING,
"DP_EXT_IRQ", irq_grp);
if (ret) {
ath11k_err(ab, "failed request irq %d: %d\n",
@@ -548,7 +608,11 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
return ret;
}
- disable_irq_nosync(ab->irq_num[irq_idx]);
+ /* balance irq_enable */
+ if (vecs_32_cap)
+ disable_irq_nosync(ab->irq_num[irq_idx]);
+
+ ath11k_pci_set_irq_enable_flag(ab, irq_idx, 0);
}
}
@@ -561,6 +625,7 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
u32 msi_data_start;
u32 msi_data_count;
u32 msi_irq_start;
+ u32 vecs_32_cap;
unsigned int msi_data;
int irq, i, ret, irq_idx;
@@ -570,9 +635,13 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
if (ret)
return ret;
+ vecs_32_cap = ath11k_pci_priv(ab)->vectors_32_capability;
+
/* Configure CE irqs */
for (i = 0; i < ab->hw_params.ce_count; i++) {
- msi_data = (i % msi_data_count) + msi_irq_start;
+ msi_data = vecs_32_cap ?
+ (i % msi_data_count) + msi_irq_start : msi_irq_start;
+
irq = ath11k_pci_get_msi_irq(ab->dev, msi_data);
ce_pipe = &ab->ce.ce_pipe[i];
@@ -585,7 +654,7 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
(unsigned long)ce_pipe);
ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
- IRQF_SHARED, irq_name[irq_idx],
+ IRQF_SHARED | IRQF_NOBALANCING, irq_name[irq_idx],
ce_pipe);
if (ret) {
ath11k_err(ab, "failed to request irq %d: %d\n",
@@ -641,14 +710,19 @@ 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;
+
+ if (num_vectors == msi_config.total_vectors) {
+ ab_pci->vectors_32_capability = 1;
+ } else {
+ ab_pci->vectors_32_capability = 0;
+ num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
+ 1,
+ 1,
+ PCI_IRQ_MSI);
+ if (num_vectors < 0) {
+ ret = -EINVAL;
+ goto reset_msi_config;
+ }
}
msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
@@ -658,6 +732,8 @@ static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
goto free_msi_vector;
}
+ ath11k_info(ab, "MSI vectors: %d", num_vectors);
+
ab_pci->msi_ep_base_data = msi_desc->msg.data;
ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab_pci->msi_ep_base_data);
@@ -667,6 +743,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;
}
@@ -675,6 +752,32 @@ static void ath11k_pci_disable_msi(struct ath11k_pci *ab_pci)
pci_free_irq_vectors(ab_pci->pdev);
}
+static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci)
+{
+ struct msi_desc *msi_desc;
+ int ret;
+
+ msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
+
+ if (!msi_desc) {
+ ath11k_err(ab_pci->ab, "msi_desc is NULL!\n");
+ ret = -EINVAL;
+ goto free_msi_vector;
+ }
+
+ ab_pci->msi_ep_base_data = msi_desc->msg.data;
+
+ ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "msi base data is %d\n",
+ ab_pci->msi_ep_base_data);
+
+ return 0;
+
+ free_msi_vector:
+ pci_free_irq_vectors(ab_pci->pdev);
+
+ return ret;
+}
+
static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
{
struct ath11k_base *ab = ab_pci->ab;
@@ -862,6 +965,11 @@ static int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id
return 0;
}
+static int ath11k_pci_is_32_vectors_support(struct ath11k_base *ab)
+{
+ return ath11k_pci_priv(ab)->vectors_32_capability;
+}
+
static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
.start = ath11k_pci_start,
.stop = ath11k_pci_stop,
@@ -874,6 +982,7 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
.get_msi_address = ath11k_pci_get_msi_address,
.get_user_msi_vector = ath11k_get_user_msi_assignment,
.map_service_to_pipe = ath11k_pci_map_service_to_pipe,
+ .is_32_vecs_support = ath11k_pci_is_32_vectors_support,
};
static int ath11k_pci_probe(struct pci_dev *pdev,
@@ -972,6 +1081,13 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
goto err_ce_free;
}
+ /* Get the correct msi_data after request_irq() to avoid spurious interrupt */
+ ret = ath11k_pci_config_msi_data(ab_pci);
+ if (ret) {
+ ath11k_err(ab, "failed to config msi_data: %d\n", ret);
+ goto err_ce_free;
+ }
+
ret = ath11k_core_init(ab);
if (ret) {
ath11k_err(ab, "failed to init core: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath11k/pci.h b/drivers/net/wireless/ath/ath11k/pci.h
index 43562f774a37..e165e8f0029f 100644
--- a/drivers/net/wireless/ath/ath11k/pci.h
+++ b/drivers/net/wireless/ath/ath11k/pci.h
@@ -46,6 +46,7 @@ struct ath11k_pci {
u16 dev_id;
char amss_path[100];
u32 msi_ep_base_data;
+ u32 vectors_32_capability;
struct mhi_controller *mhi_ctrl;
unsigned long mhi_state;
u32 register_window;
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index c2b165158225..5ac7e2685518 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -1675,6 +1675,10 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr;
req->mem_seg[i].size = ab->qmi.target_mem[i].size;
req->mem_seg[i].type = ab->qmi.target_mem[i].type;
+ ath11k_info(ab, "req mem_seg[%d] 0x%llx %u %u\n", i,
+ ab->qmi.target_mem[i].paddr,
+ ab->qmi.target_mem[i].size,
+ ab->qmi.target_mem[i].type);
}
}
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH RFT] ath11k: pci: support platforms with one MSI vector
@ 2020-11-11 18:58 ` Kalle Valo
0 siblings, 0 replies; 7+ messages in thread
From: Kalle Valo @ 2020-11-11 18:58 UTC (permalink / raw)
To: ath11k; +Cc: linux-wireless
From: Carl Huang <cjhuang@codeaurora.org>
Dell XPS 13 9310 has only one MSI vector available for QCA6390 device and ath11k fails with:
ath11k_pci 0000:56:00.0: failed to get 32 MSI vectors, only -28 available
ath11k_pci 0000:56:00.0: failed to enable msi: -28
ath11k_pci: probe of 0000:56:00.0 failed with error -28
This is a proof of concept patch for getting ath11k to work with QCA6390 using
only one MSI vector, not the final solution. Testing feedback more than
welcome. The patch applies to v5.10-rc2.
The idea here is to add a flag to indicate whether this ISR can be called
or not as all the ISR handlers are registered with IRQF_SHARED when ath11k can
only request 1 vector. This needs to be refined later.
In some scenarios, kernel crashed when the interrupt migration happens, so add
IRQF_NOBALANCING.
Also add debug messages to ath11k_qmi_respond_fw_mem_request() for helping to
debug mysterious firmware initialisation timeouts:
ath11k_pci 0000:05:00.0: qmi failed memory request, err = -110
ath11k_pci 0000:05:00.0: qmi failed to respond fw mem req:-110
If that happens, one way to workaround the problem is to revert this commit:
7fef431be9c9 mm/page_alloc: place pages to tail in __free_pages_core()
Link: https://lore.kernel.org/linux-pci/87mtzxkus5.fsf@nanos.tec.linutronix.de/
Link: http://lists.infradead.org/pipermail/ath11k/2020-November/000550.html
Signed-off-by: Carl Huang <cjhuang@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
drivers/bus/mhi/core/init.c | 4 +-
drivers/net/wireless/ath/ath11k/ce.c | 6 +-
drivers/net/wireless/ath/ath11k/core.h | 1 +
drivers/net/wireless/ath/ath11k/dp.c | 8 +-
drivers/net/wireless/ath/ath11k/hif.h | 1 +
drivers/net/wireless/ath/ath11k/mhi.c | 11 +-
drivers/net/wireless/ath/ath11k/pci.c | 178 +++++++++++++++++++++++++++------
drivers/net/wireless/ath/ath11k/pci.h | 1 +
drivers/net/wireless/ath/ath11k/qmi.c | 4 +
9 files changed, 174 insertions(+), 40 deletions(-)
diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index 0ffdebde8265..d182ffdbaf64 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -153,7 +153,7 @@ int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl)
/* Setup BHI_INTVEC IRQ */
ret = request_threaded_irq(mhi_cntrl->irq[0], mhi_intvec_handler,
mhi_intvec_threaded_handler,
- IRQF_SHARED | IRQF_NO_SUSPEND,
+ IRQF_SHARED | IRQF_NOBALANCING,
"bhi", mhi_cntrl);
if (ret)
return ret;
@@ -171,7 +171,7 @@ int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl)
ret = request_irq(mhi_cntrl->irq[mhi_event->irq],
mhi_irq_handler,
- IRQF_SHARED | IRQF_NO_SUSPEND,
+ IRQF_SHARED | IRQF_NOBALANCING,
"mhi", mhi_event);
if (ret) {
dev_err(dev, "Error requesting irq:%d for ev:%d\n",
diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c
index 9d730f8ac816..46c717a344c3 100644
--- a/drivers/net/wireless/ath/ath11k/ce.c
+++ b/drivers/net/wireless/ath/ath11k/ce.c
@@ -459,20 +459,22 @@ static void ath11k_ce_srng_msi_ring_params_setup(struct ath11k_base *ab, u32 ce_
u32 msi_irq_start;
u32 addr_lo;
u32 addr_hi;
+ u32 vectors_32_capability;
int ret;
ret = ath11k_get_user_msi_vector(ab, "CE",
&msi_data_count, &msi_data_start,
&msi_irq_start);
-
if (ret)
return;
+ vectors_32_capability = ab->hif.ops->is_32_vecs_support(ab);
ath11k_get_msi_address(ab, &addr_lo, &addr_hi);
ring_params->msi_addr = addr_lo;
ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32);
- ring_params->msi_data = (ce_id % msi_data_count) + msi_data_start;
+ ring_params->msi_data = vectors_32_capability ?
+ (ce_id % msi_data_count) + msi_data_start : msi_data_start;
ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;
}
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 18b97420f0d8..0de6b2cd8c75 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -683,6 +683,7 @@ struct ath11k_base {
bool wmi_ready;
u32 wlan_init_status;
int irq_num[ATH11K_IRQ_NUM_MAX];
+ int irq_enable_flag[ATH11K_IRQ_NUM_MAX];
struct ath11k_ext_irq_grp ext_irq_grp[ATH11K_EXT_IRQ_GRP_NUM_MAX];
struct napi_struct *napi;
struct ath11k_targ_cap target_caps;
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index 59dd185a0cfc..b7288dc47199 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -180,13 +180,15 @@ static void ath11k_dp_srng_msi_setup(struct ath11k_base *ab,
{
int msi_group_number, msi_data_count;
u32 msi_data_start, msi_irq_start, addr_lo, addr_hi;
- int ret;
+ u32 vectors_32_capability;
+ int ret = -EINVAL;
ret = ath11k_get_user_msi_vector(ab, "DP",
&msi_data_count, &msi_data_start,
&msi_irq_start);
if (ret)
return;
+ vectors_32_capability = ab->hif.ops->is_32_vecs_support(ab);
msi_group_number = ath11k_dp_srng_calculate_msi_group(ab, type,
ring_num);
@@ -209,8 +211,8 @@ static void ath11k_dp_srng_msi_setup(struct ath11k_base *ab,
ring_params->msi_addr = addr_lo;
ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32);
- ring_params->msi_data = (msi_group_number % msi_data_count)
- + msi_data_start;
+ ring_params->msi_data = vectors_32_capability ?
+ (msi_group_number % msi_data_count) + msi_data_start : msi_data_start;
ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;
}
diff --git a/drivers/net/wireless/ath/ath11k/hif.h b/drivers/net/wireless/ath/ath11k/hif.h
index dbe5568916e8..b6bde194a390 100644
--- a/drivers/net/wireless/ath/ath11k/hif.h
+++ b/drivers/net/wireless/ath/ath11k/hif.h
@@ -24,6 +24,7 @@ struct ath11k_hif_ops {
u32 *base_vector);
void (*get_msi_address)(struct ath11k_base *ab, u32 *msi_addr_lo,
u32 *msi_addr_hi);
+ int (*is_32_vecs_support)(struct ath11k_base *ab);
};
static inline int ath11k_hif_start(struct ath11k_base *sc)
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index aded9a719d51..80d7dd18034d 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -156,14 +156,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);
@@ -172,9 +175,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;
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index d7eb6b7160bb..a7a98bdc0c5f 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -17,6 +17,7 @@
#define ATH11K_PCI_DMA_MASK 32
#define ATH11K_PCI_IRQ_CE0_OFFSET 3
+#define ATH11K_PCI_IRQ_DP_OFFSET 14
#define WINDOW_ENABLE_BIT 0x40000000
#define WINDOW_REG_ADDRESS 0x310c
@@ -265,12 +266,17 @@ static void ath11k_pci_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
u32 *msi_addr_hi)
{
struct pci_dev *pci_dev = to_pci_dev(ab->dev);
+ u16 is_64bits;
pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,
msi_addr_lo);
+ pci_read_config_word(pci_dev, pci_dev->msi_cap + PCI_MSI_FLAGS, &is_64bits);
- pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
- msi_addr_hi);
+ if (is_64bits & PCI_MSI_FLAGS_64BIT)
+ pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
+ msi_addr_hi);
+ else
+ *msi_addr_hi = 0;
}
int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name,
@@ -278,14 +284,15 @@ int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_nam
u32 *base_vector)
{
struct ath11k_base *ab = ab_pci->ab;
+ u32 msi_32_cap = ab_pci->vectors_32_capability;
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;
+ *base_vector = msi_32_cap ?
+ msi_config.users[idx].base_vector : 0;
+ *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",
user_name, *num_vectors, *user_base_data,
@@ -339,20 +346,38 @@ static void ath11k_pci_free_irq(struct ath11k_base *ab)
ath11k_pci_free_ext_irq(ab);
}
+static void ath11k_pci_set_irq_enable_flag(struct ath11k_base *ab, u32 irq_idx, int flag)
+{
+ ab->irq_enable_flag[irq_idx] = flag;
+}
+
static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
{
u32 irq_idx;
+ u32 vecs_32_cap;
- irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
- enable_irq(ab->irq_num[irq_idx]);
+ vecs_32_cap = ath11k_pci_priv(ab)->vectors_32_capability;
+ irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
+
+ if (vecs_32_cap)
+ enable_irq(ab->irq_num[irq_idx]);
+
+ ath11k_pci_set_irq_enable_flag(ab, irq_idx, 1);
}
static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
{
u32 irq_idx;
+ u32 vecs_32_cap;
+ vecs_32_cap = ath11k_pci_priv(ab)->vectors_32_capability;
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
- disable_irq_nosync(ab->irq_num[irq_idx]);
+
+ /* Cannot disable the irq when using one msi interrupt */
+ if (vecs_32_cap)
+ disable_irq_nosync(ab->irq_num[irq_idx]);
+
+ ath11k_pci_set_irq_enable_flag(ab, irq_idx, 0);
}
static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab)
@@ -382,18 +407,28 @@ static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab)
static void ath11k_pci_ce_tasklet(unsigned long data)
{
+
struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data;
+ 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)
{
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;
+
+ disable_irq_nosync(ab->irq_num[irq_idx]);
+
+ if (!ab->irq_enable_flag[irq_idx]) {
+ enable_irq(ab->irq_num[irq_idx]);
+ return IRQ_HANDLED;
+ }
- ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
tasklet_schedule(&ce_pipe->intr_tq);
return IRQ_HANDLED;
@@ -402,9 +437,16 @@ static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
{
int i;
+ u32 vecs_32_cap;
- for (i = 0; i < irq_grp->num_irq; i++)
- disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
+ vecs_32_cap = ath11k_pci_priv(irq_grp->ab)->vectors_32_capability;
+
+ for (i = 0; i < irq_grp->num_irq; i++) {
+ if (vecs_32_cap)
+ disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
+
+ ath11k_pci_set_irq_enable_flag(irq_grp->ab, irq_grp->irqs[i], 0);
+ }
}
static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
@@ -424,9 +466,15 @@ 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)
{
int i;
+ u32 vecs_32_cap;
- for (i = 0; i < irq_grp->num_irq; i++)
- enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
+ vecs_32_cap = ath11k_pci_priv(irq_grp->ab)->vectors_32_capability;
+
+ for (i = 0; i < irq_grp->num_irq; i++) {
+ if (vecs_32_cap)
+ enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
+ ath11k_pci_set_irq_enable_flag(irq_grp->ab, irq_grp->irqs[i], 1);
+ }
}
static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab)
@@ -468,11 +516,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)
@@ -484,10 +534,16 @@ 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;
- ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);
+ for (i = 0; i < irq_grp->num_irq; i++)
+ disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
- ath11k_pci_ext_grp_disable(irq_grp);
+ if (!irq_grp->ab->irq_enable_flag[irq_grp->irqs[0]]) {
+ for (i = 0; i < irq_grp->num_irq; i++)
+ enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
+ return IRQ_HANDLED;
+ }
napi_schedule(&irq_grp->napi);
@@ -498,6 +554,7 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
{
int i, j, ret, num_vectors = 0;
u32 user_base_data = 0, base_vector = 0;
+ u32 vecs_32_cap;
ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP",
&num_vectors,
@@ -506,6 +563,8 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
if (ret < 0)
return ret;
+ vecs_32_cap = ath11k_pci_priv(ab)->vectors_32_capability;
+
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
u32 num_irq = 0;
@@ -528,11 +587,12 @@ 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];
- int vector = (i % num_vectors) + base_vector;
+ int vector = vecs_32_cap ?
+ (i % num_vectors) + base_vector : base_vector;
int irq = ath11k_pci_get_msi_irq(ab->dev, vector);
ab->irq_num[irq_idx] = irq;
@@ -540,7 +600,7 @@ 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,
+ IRQF_SHARED | IRQF_NOBALANCING,
"DP_EXT_IRQ", irq_grp);
if (ret) {
ath11k_err(ab, "failed request irq %d: %d\n",
@@ -548,7 +608,11 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
return ret;
}
- disable_irq_nosync(ab->irq_num[irq_idx]);
+ /* balance irq_enable */
+ if (vecs_32_cap)
+ disable_irq_nosync(ab->irq_num[irq_idx]);
+
+ ath11k_pci_set_irq_enable_flag(ab, irq_idx, 0);
}
}
@@ -561,6 +625,7 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
u32 msi_data_start;
u32 msi_data_count;
u32 msi_irq_start;
+ u32 vecs_32_cap;
unsigned int msi_data;
int irq, i, ret, irq_idx;
@@ -570,9 +635,13 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
if (ret)
return ret;
+ vecs_32_cap = ath11k_pci_priv(ab)->vectors_32_capability;
+
/* Configure CE irqs */
for (i = 0; i < ab->hw_params.ce_count; i++) {
- msi_data = (i % msi_data_count) + msi_irq_start;
+ msi_data = vecs_32_cap ?
+ (i % msi_data_count) + msi_irq_start : msi_irq_start;
+
irq = ath11k_pci_get_msi_irq(ab->dev, msi_data);
ce_pipe = &ab->ce.ce_pipe[i];
@@ -585,7 +654,7 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
(unsigned long)ce_pipe);
ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
- IRQF_SHARED, irq_name[irq_idx],
+ IRQF_SHARED | IRQF_NOBALANCING, irq_name[irq_idx],
ce_pipe);
if (ret) {
ath11k_err(ab, "failed to request irq %d: %d\n",
@@ -641,14 +710,19 @@ 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;
+
+ if (num_vectors == msi_config.total_vectors) {
+ ab_pci->vectors_32_capability = 1;
+ } else {
+ ab_pci->vectors_32_capability = 0;
+ num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
+ 1,
+ 1,
+ PCI_IRQ_MSI);
+ if (num_vectors < 0) {
+ ret = -EINVAL;
+ goto reset_msi_config;
+ }
}
msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
@@ -658,6 +732,8 @@ static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
goto free_msi_vector;
}
+ ath11k_info(ab, "MSI vectors: %d", num_vectors);
+
ab_pci->msi_ep_base_data = msi_desc->msg.data;
ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab_pci->msi_ep_base_data);
@@ -667,6 +743,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;
}
@@ -675,6 +752,32 @@ static void ath11k_pci_disable_msi(struct ath11k_pci *ab_pci)
pci_free_irq_vectors(ab_pci->pdev);
}
+static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci)
+{
+ struct msi_desc *msi_desc;
+ int ret;
+
+ msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
+
+ if (!msi_desc) {
+ ath11k_err(ab_pci->ab, "msi_desc is NULL!\n");
+ ret = -EINVAL;
+ goto free_msi_vector;
+ }
+
+ ab_pci->msi_ep_base_data = msi_desc->msg.data;
+
+ ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "msi base data is %d\n",
+ ab_pci->msi_ep_base_data);
+
+ return 0;
+
+ free_msi_vector:
+ pci_free_irq_vectors(ab_pci->pdev);
+
+ return ret;
+}
+
static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
{
struct ath11k_base *ab = ab_pci->ab;
@@ -862,6 +965,11 @@ static int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id
return 0;
}
+static int ath11k_pci_is_32_vectors_support(struct ath11k_base *ab)
+{
+ return ath11k_pci_priv(ab)->vectors_32_capability;
+}
+
static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
.start = ath11k_pci_start,
.stop = ath11k_pci_stop,
@@ -874,6 +982,7 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
.get_msi_address = ath11k_pci_get_msi_address,
.get_user_msi_vector = ath11k_get_user_msi_assignment,
.map_service_to_pipe = ath11k_pci_map_service_to_pipe,
+ .is_32_vecs_support = ath11k_pci_is_32_vectors_support,
};
static int ath11k_pci_probe(struct pci_dev *pdev,
@@ -972,6 +1081,13 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
goto err_ce_free;
}
+ /* Get the correct msi_data after request_irq() to avoid spurious interrupt */
+ ret = ath11k_pci_config_msi_data(ab_pci);
+ if (ret) {
+ ath11k_err(ab, "failed to config msi_data: %d\n", ret);
+ goto err_ce_free;
+ }
+
ret = ath11k_core_init(ab);
if (ret) {
ath11k_err(ab, "failed to init core: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath11k/pci.h b/drivers/net/wireless/ath/ath11k/pci.h
index 43562f774a37..e165e8f0029f 100644
--- a/drivers/net/wireless/ath/ath11k/pci.h
+++ b/drivers/net/wireless/ath/ath11k/pci.h
@@ -46,6 +46,7 @@ struct ath11k_pci {
u16 dev_id;
char amss_path[100];
u32 msi_ep_base_data;
+ u32 vectors_32_capability;
struct mhi_controller *mhi_ctrl;
unsigned long mhi_state;
u32 register_window;
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index c2b165158225..5ac7e2685518 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -1675,6 +1675,10 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr;
req->mem_seg[i].size = ab->qmi.target_mem[i].size;
req->mem_seg[i].type = ab->qmi.target_mem[i].type;
+ ath11k_info(ab, "req mem_seg[%d] 0x%llx %u %u\n", i,
+ ab->qmi.target_mem[i].paddr,
+ ab->qmi.target_mem[i].size,
+ ab->qmi.target_mem[i].type);
}
}
--
2.7.4
--
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH RFT] ath11k: pci: support platforms with one MSI vector
2020-11-11 18:58 ` Kalle Valo
(?)
@ 2020-11-12 6:46 ` kernel test robot
-1 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2020-11-12 6:46 UTC (permalink / raw)
To: Kalle Valo, ath11k; +Cc: kbuild-all, linux-wireless
[-- Attachment #1: Type: text/plain, Size: 6098 bytes --]
Hi Kalle,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on linus/master]
[also build test WARNING on v5.10-rc3 next-20201111]
[cannot apply to ath6kl/ath-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Kalle-Valo/ath11k-pci-support-platforms-with-one-MSI-vector/20201112-030041
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git eccc876724927ff3b9ff91f36f7b6b159e948f0c
config: m68k-allmodconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/e2c4c01cee2e8ce50345b8f70f192921a4875e18
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Kalle-Valo/ath11k-pci-support-platforms-with-one-MSI-vector/20201112-030041
git checkout e2c4c01cee2e8ce50345b8f70f192921a4875e18
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=m68k
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
In file included from include/linux/kernel.h:11,
from include/linux/list.h:9,
from include/linux/mutex.h:15,
from drivers/net/wireless/ath/ath11k/qmi.h:9,
from drivers/net/wireless/ath/ath11k/qmi.c:8:
include/linux/scatterlist.h: In function 'sg_set_buf':
arch/m68k/include/asm/page_mm.h:169:49: warning: ordered comparison of pointer with null pointer [-Wextra]
169 | #define virt_addr_valid(kaddr) ((void *)(kaddr) >= (void *)PAGE_OFFSET && (void *)(kaddr) < high_memory)
| ^~
include/linux/compiler.h:78:42: note: in definition of macro 'unlikely'
78 | # define unlikely(x) __builtin_expect(!!(x), 0)
| ^
include/linux/scatterlist.h:143:2: note: in expansion of macro 'BUG_ON'
143 | BUG_ON(!virt_addr_valid(buf));
| ^~~~~~
include/linux/scatterlist.h:143:10: note: in expansion of macro 'virt_addr_valid'
143 | BUG_ON(!virt_addr_valid(buf));
| ^~~~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/qmi.c: In function 'ath11k_qmi_respond_fw_mem_request':
>> drivers/net/wireless/ath/ath11k/qmi.c:1678:42: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 4 has type 'dma_addr_t' {aka 'unsigned int'} [-Wformat=]
1678 | ath11k_info(ab, "req mem_seg[%d] 0x%llx %u %u\n", i,
| ~~~^
| |
| long long unsigned int
| %x
1679 | ab->qmi.target_mem[i].paddr,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| dma_addr_t {aka unsigned int}
vim +1678 drivers/net/wireless/ath/ath11k/qmi.c
1648
1649 static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
1650 {
1651 struct qmi_wlanfw_respond_mem_req_msg_v01 *req;
1652 struct qmi_wlanfw_respond_mem_resp_msg_v01 resp;
1653 struct qmi_txn txn = {};
1654 int ret = 0, i;
1655
1656 req = kzalloc(sizeof(*req), GFP_KERNEL);
1657 if (!req)
1658 return -ENOMEM;
1659
1660 memset(&resp, 0, sizeof(resp));
1661
1662 /* For QCA6390 by default FW requests a block of ~4M contiguous
1663 * DMA memory, it's hard to allocate from OS. So host returns
1664 * failure to FW and FW will then request mulitple blocks of small
1665 * chunk size memory.
1666 */
1667 if (!ab->bus_params.fixed_mem_region && ab->qmi.mem_seg_count <= 2) {
1668 ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n",
1669 ab->qmi.mem_seg_count);
1670 memset(req, 0, sizeof(*req));
1671 } else {
1672 req->mem_seg_len = ab->qmi.mem_seg_count;
1673
1674 for (i = 0; i < req->mem_seg_len ; i++) {
1675 req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr;
1676 req->mem_seg[i].size = ab->qmi.target_mem[i].size;
1677 req->mem_seg[i].type = ab->qmi.target_mem[i].type;
> 1678 ath11k_info(ab, "req mem_seg[%d] 0x%llx %u %u\n", i,
1679 ab->qmi.target_mem[i].paddr,
1680 ab->qmi.target_mem[i].size,
1681 ab->qmi.target_mem[i].type);
1682 }
1683 }
1684
1685 ret = qmi_txn_init(&ab->qmi.handle, &txn,
1686 qmi_wlanfw_respond_mem_resp_msg_v01_ei, &resp);
1687 if (ret < 0)
1688 goto out;
1689
1690 ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
1691 QMI_WLANFW_RESPOND_MEM_REQ_V01,
1692 QMI_WLANFW_RESPOND_MEM_REQ_MSG_V01_MAX_LEN,
1693 qmi_wlanfw_respond_mem_req_msg_v01_ei, req);
1694 if (ret < 0) {
1695 ath11k_warn(ab, "qmi failed to respond memory request, err = %d\n",
1696 ret);
1697 goto out;
1698 }
1699
1700 ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
1701 if (ret < 0) {
1702 ath11k_warn(ab, "qmi failed memory request, err = %d\n", ret);
1703 goto out;
1704 }
1705
1706 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
1707 ath11k_warn(ab, "Respond mem req failed, result: %d, err: %d\n",
1708 resp.resp.result, resp.resp.error);
1709 ret = -EINVAL;
1710 goto out;
1711 }
1712 out:
1713 kfree(req);
1714 return ret;
1715 }
1716
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 58831 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH RFT] ath11k: pci: support platforms with one MSI vector
@ 2020-11-12 6:46 ` kernel test robot
0 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2020-11-12 6:46 UTC (permalink / raw)
To: Kalle Valo, ath11k; +Cc: linux-wireless, kbuild-all
[-- Attachment #1: Type: text/plain, Size: 6098 bytes --]
Hi Kalle,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on linus/master]
[also build test WARNING on v5.10-rc3 next-20201111]
[cannot apply to ath6kl/ath-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Kalle-Valo/ath11k-pci-support-platforms-with-one-MSI-vector/20201112-030041
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git eccc876724927ff3b9ff91f36f7b6b159e948f0c
config: m68k-allmodconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/e2c4c01cee2e8ce50345b8f70f192921a4875e18
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Kalle-Valo/ath11k-pci-support-platforms-with-one-MSI-vector/20201112-030041
git checkout e2c4c01cee2e8ce50345b8f70f192921a4875e18
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=m68k
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
In file included from include/linux/kernel.h:11,
from include/linux/list.h:9,
from include/linux/mutex.h:15,
from drivers/net/wireless/ath/ath11k/qmi.h:9,
from drivers/net/wireless/ath/ath11k/qmi.c:8:
include/linux/scatterlist.h: In function 'sg_set_buf':
arch/m68k/include/asm/page_mm.h:169:49: warning: ordered comparison of pointer with null pointer [-Wextra]
169 | #define virt_addr_valid(kaddr) ((void *)(kaddr) >= (void *)PAGE_OFFSET && (void *)(kaddr) < high_memory)
| ^~
include/linux/compiler.h:78:42: note: in definition of macro 'unlikely'
78 | # define unlikely(x) __builtin_expect(!!(x), 0)
| ^
include/linux/scatterlist.h:143:2: note: in expansion of macro 'BUG_ON'
143 | BUG_ON(!virt_addr_valid(buf));
| ^~~~~~
include/linux/scatterlist.h:143:10: note: in expansion of macro 'virt_addr_valid'
143 | BUG_ON(!virt_addr_valid(buf));
| ^~~~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/qmi.c: In function 'ath11k_qmi_respond_fw_mem_request':
>> drivers/net/wireless/ath/ath11k/qmi.c:1678:42: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 4 has type 'dma_addr_t' {aka 'unsigned int'} [-Wformat=]
1678 | ath11k_info(ab, "req mem_seg[%d] 0x%llx %u %u\n", i,
| ~~~^
| |
| long long unsigned int
| %x
1679 | ab->qmi.target_mem[i].paddr,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| dma_addr_t {aka unsigned int}
vim +1678 drivers/net/wireless/ath/ath11k/qmi.c
1648
1649 static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
1650 {
1651 struct qmi_wlanfw_respond_mem_req_msg_v01 *req;
1652 struct qmi_wlanfw_respond_mem_resp_msg_v01 resp;
1653 struct qmi_txn txn = {};
1654 int ret = 0, i;
1655
1656 req = kzalloc(sizeof(*req), GFP_KERNEL);
1657 if (!req)
1658 return -ENOMEM;
1659
1660 memset(&resp, 0, sizeof(resp));
1661
1662 /* For QCA6390 by default FW requests a block of ~4M contiguous
1663 * DMA memory, it's hard to allocate from OS. So host returns
1664 * failure to FW and FW will then request mulitple blocks of small
1665 * chunk size memory.
1666 */
1667 if (!ab->bus_params.fixed_mem_region && ab->qmi.mem_seg_count <= 2) {
1668 ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n",
1669 ab->qmi.mem_seg_count);
1670 memset(req, 0, sizeof(*req));
1671 } else {
1672 req->mem_seg_len = ab->qmi.mem_seg_count;
1673
1674 for (i = 0; i < req->mem_seg_len ; i++) {
1675 req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr;
1676 req->mem_seg[i].size = ab->qmi.target_mem[i].size;
1677 req->mem_seg[i].type = ab->qmi.target_mem[i].type;
> 1678 ath11k_info(ab, "req mem_seg[%d] 0x%llx %u %u\n", i,
1679 ab->qmi.target_mem[i].paddr,
1680 ab->qmi.target_mem[i].size,
1681 ab->qmi.target_mem[i].type);
1682 }
1683 }
1684
1685 ret = qmi_txn_init(&ab->qmi.handle, &txn,
1686 qmi_wlanfw_respond_mem_resp_msg_v01_ei, &resp);
1687 if (ret < 0)
1688 goto out;
1689
1690 ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
1691 QMI_WLANFW_RESPOND_MEM_REQ_V01,
1692 QMI_WLANFW_RESPOND_MEM_REQ_MSG_V01_MAX_LEN,
1693 qmi_wlanfw_respond_mem_req_msg_v01_ei, req);
1694 if (ret < 0) {
1695 ath11k_warn(ab, "qmi failed to respond memory request, err = %d\n",
1696 ret);
1697 goto out;
1698 }
1699
1700 ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
1701 if (ret < 0) {
1702 ath11k_warn(ab, "qmi failed memory request, err = %d\n", ret);
1703 goto out;
1704 }
1705
1706 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
1707 ath11k_warn(ab, "Respond mem req failed, result: %d, err: %d\n",
1708 resp.resp.result, resp.resp.error);
1709 ret = -EINVAL;
1710 goto out;
1711 }
1712 out:
1713 kfree(req);
1714 return ret;
1715 }
1716
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 58831 bytes --]
[-- Attachment #3: Type: text/plain, Size: 102 bytes --]
--
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH RFT] ath11k: pci: support platforms with one MSI vector
@ 2020-11-12 6:46 ` kernel test robot
0 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2020-11-12 6:46 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 6233 bytes --]
Hi Kalle,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on linus/master]
[also build test WARNING on v5.10-rc3 next-20201111]
[cannot apply to ath6kl/ath-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Kalle-Valo/ath11k-pci-support-platforms-with-one-MSI-vector/20201112-030041
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git eccc876724927ff3b9ff91f36f7b6b159e948f0c
config: m68k-allmodconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/e2c4c01cee2e8ce50345b8f70f192921a4875e18
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Kalle-Valo/ath11k-pci-support-platforms-with-one-MSI-vector/20201112-030041
git checkout e2c4c01cee2e8ce50345b8f70f192921a4875e18
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=m68k
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
In file included from include/linux/kernel.h:11,
from include/linux/list.h:9,
from include/linux/mutex.h:15,
from drivers/net/wireless/ath/ath11k/qmi.h:9,
from drivers/net/wireless/ath/ath11k/qmi.c:8:
include/linux/scatterlist.h: In function 'sg_set_buf':
arch/m68k/include/asm/page_mm.h:169:49: warning: ordered comparison of pointer with null pointer [-Wextra]
169 | #define virt_addr_valid(kaddr) ((void *)(kaddr) >= (void *)PAGE_OFFSET && (void *)(kaddr) < high_memory)
| ^~
include/linux/compiler.h:78:42: note: in definition of macro 'unlikely'
78 | # define unlikely(x) __builtin_expect(!!(x), 0)
| ^
include/linux/scatterlist.h:143:2: note: in expansion of macro 'BUG_ON'
143 | BUG_ON(!virt_addr_valid(buf));
| ^~~~~~
include/linux/scatterlist.h:143:10: note: in expansion of macro 'virt_addr_valid'
143 | BUG_ON(!virt_addr_valid(buf));
| ^~~~~~~~~~~~~~~
drivers/net/wireless/ath/ath11k/qmi.c: In function 'ath11k_qmi_respond_fw_mem_request':
>> drivers/net/wireless/ath/ath11k/qmi.c:1678:42: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 4 has type 'dma_addr_t' {aka 'unsigned int'} [-Wformat=]
1678 | ath11k_info(ab, "req mem_seg[%d] 0x%llx %u %u\n", i,
| ~~~^
| |
| long long unsigned int
| %x
1679 | ab->qmi.target_mem[i].paddr,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| dma_addr_t {aka unsigned int}
vim +1678 drivers/net/wireless/ath/ath11k/qmi.c
1648
1649 static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
1650 {
1651 struct qmi_wlanfw_respond_mem_req_msg_v01 *req;
1652 struct qmi_wlanfw_respond_mem_resp_msg_v01 resp;
1653 struct qmi_txn txn = {};
1654 int ret = 0, i;
1655
1656 req = kzalloc(sizeof(*req), GFP_KERNEL);
1657 if (!req)
1658 return -ENOMEM;
1659
1660 memset(&resp, 0, sizeof(resp));
1661
1662 /* For QCA6390 by default FW requests a block of ~4M contiguous
1663 * DMA memory, it's hard to allocate from OS. So host returns
1664 * failure to FW and FW will then request mulitple blocks of small
1665 * chunk size memory.
1666 */
1667 if (!ab->bus_params.fixed_mem_region && ab->qmi.mem_seg_count <= 2) {
1668 ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n",
1669 ab->qmi.mem_seg_count);
1670 memset(req, 0, sizeof(*req));
1671 } else {
1672 req->mem_seg_len = ab->qmi.mem_seg_count;
1673
1674 for (i = 0; i < req->mem_seg_len ; i++) {
1675 req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr;
1676 req->mem_seg[i].size = ab->qmi.target_mem[i].size;
1677 req->mem_seg[i].type = ab->qmi.target_mem[i].type;
> 1678 ath11k_info(ab, "req mem_seg[%d] 0x%llx %u %u\n", i,
1679 ab->qmi.target_mem[i].paddr,
1680 ab->qmi.target_mem[i].size,
1681 ab->qmi.target_mem[i].type);
1682 }
1683 }
1684
1685 ret = qmi_txn_init(&ab->qmi.handle, &txn,
1686 qmi_wlanfw_respond_mem_resp_msg_v01_ei, &resp);
1687 if (ret < 0)
1688 goto out;
1689
1690 ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
1691 QMI_WLANFW_RESPOND_MEM_REQ_V01,
1692 QMI_WLANFW_RESPOND_MEM_REQ_MSG_V01_MAX_LEN,
1693 qmi_wlanfw_respond_mem_req_msg_v01_ei, req);
1694 if (ret < 0) {
1695 ath11k_warn(ab, "qmi failed to respond memory request, err = %d\n",
1696 ret);
1697 goto out;
1698 }
1699
1700 ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
1701 if (ret < 0) {
1702 ath11k_warn(ab, "qmi failed memory request, err = %d\n", ret);
1703 goto out;
1704 }
1705
1706 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
1707 ath11k_warn(ab, "Respond mem req failed, result: %d, err: %d\n",
1708 resp.resp.result, resp.resp.error);
1709 ret = -EINVAL;
1710 goto out;
1711 }
1712 out:
1713 kfree(req);
1714 return ret;
1715 }
1716
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 58831 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH RFT] ath11k: pci: support platforms with one MSI vector
2021-10-22 23:16 Rama McIntosh
@ 2021-11-24 9:32 ` Kalle Valo
0 siblings, 0 replies; 7+ messages in thread
From: Kalle Valo @ 2021-11-24 9:32 UTC (permalink / raw)
To: Rama McIntosh; +Cc: ath11k, rama
Rama McIntosh <face00@gmail.com> writes:
> Hi Kalle and Carl,
>
> Nice, I missed this patch. While my hardware supports multi-vector
> msi and the driver works great on fedora (dell 9700), I run Qubes-os
> and qemu hw/xen currently only supports a single msi vector. I've
> been looking into fixing qemu to support multi-vector msi...but don't
> have a lot of free time and am still learning how pci and qemu all
> work (should be doable, qemu supports multi vector for msix, just not
> msi).
>
> I applied this patch to the latest Qubes-os 4.1 alpha (kernel
> 5.10.71). Now instead of the msi initialization error (-28), I
> get a page fault and kernel panic in my sys-net vm. I tried
> permissive mode and no-strict-rest mode too, same effect (i.e 'qvm-pci
> attach sys-net-clone-1 dom0:05_00.0 --persistent -o permissive=true
> -o no-strict-reset=true'). However, I'm excited and I will see if I
> can fix this patch to work with xen as soon as I have some time off
> work.
1 MSI vector support is applied now:
https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/commit/?h=ath-next&id=ac6e73483f7b
The plan is is that it will be in v5.17.
--
https://patchwork.kernel.org/project/linux-wireless/list/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
--
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH RFT] ath11k: pci: support platforms with one MSI vector
@ 2021-10-22 23:16 Rama McIntosh
2021-11-24 9:32 ` Kalle Valo
0 siblings, 1 reply; 7+ messages in thread
From: Rama McIntosh @ 2021-10-22 23:16 UTC (permalink / raw)
To: ath11k
Hi Kalle and Carl,
Nice, I missed this patch. While my hardware supports multi-vector
msi and the driver works great on fedora (dell 9700), I run Qubes-os
and qemu hw/xen currently only supports a single msi vector. I've
been looking into fixing qemu to support multi-vector msi...but don't
have a lot of free time and am still learning how pci and qemu all
work (should be doable, qemu supports multi vector for msix, just not
msi).
I applied this patch to the latest Qubes-os 4.1 alpha (kernel
5.10.71). Now instead of the msi initialization error (-28), I
get a page fault and kernel panic in my sys-net vm. I tried
permissive mode and no-strict-rest mode too, same effect (i.e 'qvm-pci
attach sys-net-clone-1 dom0:05_00.0 --persistent -o permissive=true
-o no-strict-reset=true'). However, I'm excited and I will see if I
can fix this patch to work with xen as soon as I have some time off
work. Here is the details:
[2021-10-22 12:46:11] [ 2.920848] ath11k_pci 0000:00:06.0: link
down error during global reset
[2021-10-22 12:46:11] [ 2.941848] ath11k_pci 0000:00:06.0: link
down error during global reset
[2021-10-22 12:46:11] [ 2.972047] mhi 0000:00:06.0: Requested to power ON
[2021-10-22 12:46:11] [ 2.975416] BUG: unable to handle page fault
for address: ffff9a46c070001f
[2021-10-22 12:46:11] [ 2.975417] #PF: supervisor write access in kernel mode
[2021-10-22 12:46:11] [ 2.975418] #PF: error_code(0x0002) - not-present page
[2021-10-22 12:46:11] [ 2.975419] PGD 1000067 P4D 1000067 PUD 0
[2021-10-22 12:46:11] [ 2.975421] Oops: 0002 [#1] SMP PTI
[2021-10-22 12:46:11] [ 2.975422] CPU: 0 PID: 314 Comm:
systemd-udevd Not tainted 5.10.71-2.fc32.qubes.x86_64 #1
[2021-10-22 12:46:11] [ 2.975423] Hardware name: Xen HVM domU, BIOS
4.14.3 10/09/2021
[2021-10-22 12:46:11] [ 2.975426] RIP:
0010:ath11k_mhi_op_write_reg+0x5/0x10 [ath11k_pci]
[2021-10-22 12:46:11] [ 2.975427] Code: 00 00 00 00 00 0f 1f 44 00
00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 8b 06 89 02 31 c0
c3 0f 1f 40 00 0f 1f 44 00 00 <89> 16 c3 0f 1f 84 00 00 00 00 00 48 83
ef 01 b8 ff ff ff ff 48 c1
[2021-10-22 12:46:11] [ 2.975428] RSP: 0018:ffff9a45c0283b10 EFLAGS: 00010082
[2021-10-22 12:46:11] [ 2.975429] RAX: ffffffffc0a09040 RBX:
0000000000000000 RCX: 0000000000000000
[2021-10-22 12:46:11] [ 2.975429] RDX: 0000000000000000 RSI:
ffff9a46c070001f RDI: ffff8d6682d92800
[2021-10-22 12:46:11] [ 2.975430] RBP: ffff8d668fe40000 R08:
0000000000000020 R09: ffffffff8c944708
[2021-10-22 12:46:11] [ 2.975430] R10: 0000000000000000 R11:
0000000000000000 R12: 0000000000000000
[2021-10-22 12:46:11] [ 2.975431] R13: ffff8d6682d91c28 R14:
ffff8d6682d92920 R15: ffff8d6682d92800
[2021-10-22 12:46:11] [ 2.975432] FS: 0000792a78e7db40(0000)
GS:ffff8d66bd400000(0000) knlGS:0000000000000000
[2021-10-22 12:46:11] [ 2.975433] CS: 0010 DS: 0000 ES: 0000 CR0:
0000000080050033
[2021-10-22 12:46:11] [ 2.975433] CR2: ffff9a46c070001f CR3:
000000000b520002 CR4: 00000000007706f0
[2021-10-22 12:46:11] [ 2.975435] PKRU: 55555554
[2021-10-22 12:46:11] [ 2.975436] Call Trace:
[2021-10-22 12:46:11] [ 2.975440] mhi_async_power_up+0x1b7/0x401 [mhi]
[2021-10-22 12:46:11] [ 2.975442] ? mhi_init_dev_ctxt+0x262/0x430 [mhi]
[2021-10-22 12:46:11] [ 2.975447] ath11k_mhi_start+0x6d/0x120 [ath11k_pci]
[2021-10-22 12:46:11] [ 2.975449] ath11k_pci_power_up+0x3c/0x70 [ath11k_pci]
[2021-10-22 12:46:11] [ 2.975455] ath11k_core_soc_create+0x36/0xa0 [ath11k]
[2021-10-22 12:46:11] [ 2.975458] ath11k_core_init+0x12/0x40 [ath11k]
[2021-10-22 12:46:11] [ 2.975461] ? irq_get_irq_data+0xa/0x20
[2021-10-22 12:46:11] [ 2.975463] ath11k_pci_probe+0x2ad/0x318 [ath11k_pci]
[2021-10-22 12:46:11] [ 2.975466] local_pci_probe+0x42/0x80
[2021-10-22 12:46:11] [ 2.975820] ? _cond_resched+0x16/0x40
[2021-10-22 12:46:11] [ 2.975822] pci_call_probe+0x51/0xf0
[2021-10-22 12:46:11] [ 2.975823] pci_device_probe+0xa5/0xe0
[2021-10-22 12:46:11] [ 2.975826] really_probe+0x222/0x480
[2021-10-22 12:46:11] [ 2.975828] driver_probe_device+0xe1/0x150
[2021-10-22 12:46:11] [ 2.975829] device_driver_attach+0xa1/0xb0
[2021-10-22 12:46:11] [ 2.975831] __driver_attach+0x8a/0x150
[2021-10-22 12:46:11] [ 2.975832] ? device_driver_attach+0xb0/0xb0
[2021-10-22 12:46:11] [ 2.975833] ? device_driver_attach+0xb0/0xb0
[2021-10-22 12:46:11] [ 2.975835] bus_for_each_dev+0x89/0xd0
[2021-10-22 12:46:11] [ 2.975836] bus_add_driver+0x12b/0x1e0
[2021-10-22 12:46:11] [ 2.975838] driver_register+0x8f/0xe0
[2021-10-22 12:46:11] [ 2.975840] ?
ath11k_get_user_msi_assignment+0x20/0x20 [ath11k_pci]
[2021-10-22 12:46:11] [ 2.975841] ath11k_pci_init+0x21/0x40 [ath11k_pci]
[2021-10-22 12:46:11] [ 2.975843] do_one_initcall+0x57/0x200
[2021-10-22 12:46:11] [ 2.975846] do_init_module+0x5c/0x260
[2021-10-22 12:46:11] [ 2.975847] __do_sys_finit_module+0xb1/0x110
[2021-10-22 12:46:11] [ 2.975849] do_syscall_64+0x33/0x40
[2021-10-22 12:46:11] [ 2.975851] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[2021-10-22 12:46:11] [ 2.975853] RIP: 0033:0x792a79ac2e0d
[2021-10-22 12:46:11] [ 2.975855] Code: c8 0c 00 0f 05 eb a9 66 0f
1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2
4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 3b
80 0c 00 f7 d8 64 89 01 48
[2021-10-22 12:46:11] [ 2.975855] RSP: 002b:00007ffc4ae4dc18
EFLAGS: 00000246 ORIG_RAX: 0000000000000139
[2021-10-22 12:46:11] [ 2.975856] RAX: ffffffffffffffda RBX:
00005e699a802970 RCX: 0000792a79ac2e0d
[2021-10-22 12:46:11] [ 2.975857] RDX: 0000000000000000 RSI:
0000792a79c1c32c RDI: 0000000000000013
[2021-10-22 12:46:11] [ 2.975857] R[2021-10-22 12:46:11] BP:
0000000000020000 R08: 0000000000000000 R09: 0000000000000000
[2021-10-22 12:46:11] [ 2.975858] R10: 0000000000000013 R11:
0000000000000246 R12: 0000792a79c1c32c
[2021-10-22 12:46:11] [ 2.975858] R13: 00005e699a7d2380 R14:
0000000000000007 R15: 00005e699a8dbf70
[2021-10-22 12:46:11] [ 2.975859] Modules linked in: iptable_nat
nf_nat nf_conntrack qrtr nf_defrag_ipv6 ns nf_defrag_ipv4
ath11k_pci(+) mhi intel_cstate(-) ath11k qmi_helpers mac80211
drm_vram_helper drm_ttm_helper ttm drm_kms_helper pcspkr cfg80211
ehci_pci rfkill serio_raw libarc4 ehci_hcd ata_generic cec i2c_piix4
pata_acpi floppy xen_scsiback target_core_mod xen_netback xen_privcmd
xen_gntdev xen_gntalloc xen_blkback xen_evtchn drm fuse bpf_preload
ip_tables overlay xen_blkfront
[2021-10-22 12:46:11] [ 2.975879] CR2: ffff9a46c070001f
[2021-10-22 12:46:11] [ 2.975882] ---[ end trace 7cec67ab6b3c652d ]---
[2021-10-22 12:46:11] [ 2.975884] RIP:
0010:ath11k_mhi_op_write_reg+0x5/0x10 [ath11k_pci]
[2021-10-22 12:46:11] [ 2.975884] Code: 00 00 00 00 00 0f 1f 44 00
00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 8b 06 89 02 31 c0
c3 0f 1f 40 00 0f 1f 44 00 00 <89> 16 c3 0f 1f 84 00 00 00 00 00 48 83
ef 01 b8 ff ff ff ff 48 c1
[2021-10-22 12:46:11] [ 2.975885] RSP: 0018:ffff9a45c0283b10 EFLAGS: 00010082
[2021-10-22 12:46:11] [ 2.975886] RAX: ffffffffc0a09040 RBX:
0000000000000000 RCX: 0000000000000000
[2021-10-22 12:46:11] [ 2.975886] RDX: 0000000000000000 RSI:
ffff9a46c070001f RDI: ffff8d6682d92800
[2021-10-22 12:46:11] [ 2.975887] RBP: ffff8d668fe40000 R08:
0000000000000020 R09: ffffffff8c944708
[2021-10-22 12:46:11] [ 2.975887] R10: 0000000000000000 R11:
0000000000000000 R12: 0000000000000000
[2021-10-22 12:46:11] [ 2.975888] R13: ffff8d6682d91c28 R14:
ffff8d6682d92920 R15: ffff8d6682d92800
[2021-10-22 12:46:11] [ 2.975889] FS: 0000792a78e7db40(0000)
GS:ffff8d66bd400000(0000) knlGS:0000000000000000
[2021-10-22 12:46:11] [ 2.975889] CS: 0010 DS: 0000 ES: 0000 CR0:
0000000080050033
[2021-10-22 12:46:11] [ 2.975890] CR2: ffff9a46c070001f CR3:
000000000b520002 CR4: 00000000007706f0
[2021-10-22 12:46:11] [ 2.975890] PKRU: 55555554
[2021-10-22 12:46:11] [ 2.975891] Kernel panic - not syncing: Fatal exception
[2021-10-22 12:46:11] [ 2.975948] Kernel Offset: 0xa000000 from
0xffffffff81000000 (relocation range:
0xffffffff80000000-0xffffffffbfffffff)
--
http://myutil.com
--
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-11-24 9:32 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-11 18:58 [PATCH RFT] ath11k: pci: support platforms with one MSI vector Kalle Valo
2020-11-11 18:58 ` Kalle Valo
2020-11-12 6:46 ` kernel test robot
2020-11-12 6:46 ` kernel test robot
2020-11-12 6:46 ` kernel test robot
2021-10-22 23:16 Rama McIntosh
2021-11-24 9:32 ` Kalle Valo
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.