@@ -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);
@@ -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)
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 <cjhuang@codeaurora.org> --- drivers/net/wireless/ath/ath11k/pci.c | 86 +++++++++++++++++++++++++++-------- drivers/net/wireless/ath/ath11k/pci.h | 8 ++++ 2 files changed, 75 insertions(+), 19 deletions(-)