Skip to content
Permalink
Browse files
ath11k: pci: support platforms with one MSI vector
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:

7fef431 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>
  • Loading branch information
Carl Huang authored and intel-lab-lkp committed Nov 11, 2020
1 parent eccc876 commit e2c4c01cee2e8ce50345b8f70f192921a4875e18
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 40 deletions.
@@ -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",
@@ -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;
}

@@ -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;
@@ -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;
}

@@ -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)
@@ -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;

0 comments on commit e2c4c01

Please sign in to comment.