qcacmn: Add configurable option for MSI interrupts

Provide multiple combinations to configure the msi interrupts
of DP and CE based on the number of MSIs available in the platform.
Number of MSIs used for CE and DP can be changed by modifying the
MSI assignment table in platform driver. Best possible mask for that
MSI is automatically chosen based on predetermined settings.

Change-Id: I02b44fb033631d69d97f2d8d2d3f698541d37aad
This commit is contained in:
Nandha Kishore Easwaran
2021-03-03 12:38:42 +05:30
committed by Madan Koyyalamudi
parent 2359af8cea
commit 718d6aeece
7 changed files with 987 additions and 292 deletions

View File

@@ -103,6 +103,195 @@ static void hif_target_access_log_dump(void)
}
#endif
/*
* This structure contains the interrupt index for each Copy engine
* for various number of MSIs available in the system.
*/
static struct ce_int_assignment ce_int_context[NUM_CE_CONTEXT] = {
/* Default configuration */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(3),
CE_INTERRUPT_IDX(4),
CE_INTERRUPT_IDX(5),
CE_INTERRUPT_IDX(6),
CE_INTERRUPT_IDX(7),
CE_INTERRUPT_IDX(8),
CE_INTERRUPT_IDX(9),
CE_INTERRUPT_IDX(10),
CE_INTERRUPT_IDX(11),
} },
/* Interrupt assignment for 1 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
} },
/* Interrupt assignment for 2 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
} },
/* Interrupt assignment for 3 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
} },
/* Interrupt assignment for 4 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(3),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0)
} },
/* Interrupt assignment for 5 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(3),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(4),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0)
} },
/* Interrupt assignment for 6 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(3),
CE_INTERRUPT_IDX(4),
CE_INTERRUPT_IDX(5),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0)
} },
/* Interrupt assignment for 7 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(3),
CE_INTERRUPT_IDX(4),
CE_INTERRUPT_IDX(5),
CE_INTERRUPT_IDX(6),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0)
} },
/* Interrupt assignment for 8 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(3),
CE_INTERRUPT_IDX(4),
CE_INTERRUPT_IDX(5),
CE_INTERRUPT_IDX(6),
CE_INTERRUPT_IDX(7),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0)
} },
/* Interrupt assignment for 9 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(3),
CE_INTERRUPT_IDX(4),
CE_INTERRUPT_IDX(5),
CE_INTERRUPT_IDX(6),
CE_INTERRUPT_IDX(7),
CE_INTERRUPT_IDX(8),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0)
} },
/* Interrupt assignment for 10 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(3),
CE_INTERRUPT_IDX(4),
CE_INTERRUPT_IDX(5),
CE_INTERRUPT_IDX(6),
CE_INTERRUPT_IDX(7),
CE_INTERRUPT_IDX(8),
CE_INTERRUPT_IDX(9),
CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(0)
} },
/* Interrupt assignment for 11 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(3),
CE_INTERRUPT_IDX(4),
CE_INTERRUPT_IDX(5),
CE_INTERRUPT_IDX(6),
CE_INTERRUPT_IDX(7),
CE_INTERRUPT_IDX(8),
CE_INTERRUPT_IDX(9),
CE_INTERRUPT_IDX(10),
CE_INTERRUPT_IDX(0)
} },
/* Interrupt assignment for 12 MSI combination */
{{ CE_INTERRUPT_IDX(0),
CE_INTERRUPT_IDX(1),
CE_INTERRUPT_IDX(2),
CE_INTERRUPT_IDX(3),
CE_INTERRUPT_IDX(4),
CE_INTERRUPT_IDX(5),
CE_INTERRUPT_IDX(6),
CE_INTERRUPT_IDX(7),
CE_INTERRUPT_IDX(8),
CE_INTERRUPT_IDX(9),
CE_INTERRUPT_IDX(10),
CE_INTERRUPT_IDX(11)
} },
};
void hif_trigger_dump(struct hif_opaque_softc *hif_ctx,
uint8_t cmd_id, bool start)
@@ -3376,11 +3565,20 @@ void hif_ce_prepare_config(struct hif_softc *scn)
struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_hdl);
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
int ret;
int msi_data_count = 0;
int msi_data_start = 0;
int msi_irq_start = 0;
hif_ce_service_init();
hif_state->ce_services = ce_services_attach(scn);
ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
&msi_data_count, &msi_data_start,
&msi_irq_start);
scn->ce_count = HOST_CE_COUNT;
scn->int_assignment = &ce_int_context[msi_data_count];
/* if epping is enabled we need to use the epping configuration. */
if (QDF_IS_EPPING_ENABLED(mode)) {
hif_ce_prepare_epping_config(scn, hif_state);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -719,6 +719,7 @@ static void ce_srng_msi_ring_params_setup(struct hif_softc *scn, uint32_t ce_id,
uint32_t msi_data_count;
uint32_t msi_irq_start;
int ret;
int irq_id;
ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
&msi_data_count, &msi_data_start,
@@ -728,15 +729,16 @@ static void ce_srng_msi_ring_params_setup(struct hif_softc *scn, uint32_t ce_id,
if (ret)
return;
irq_id = scn->int_assignment->msi_idx[ce_id];
pld_get_msi_address(scn->qdf_dev->dev, &addr_low, &addr_high);
ring_params->msi_addr = addr_low;
ring_params->msi_addr |= (qdf_dma_addr_t)(((uint64_t)addr_high) << 32);
ring_params->msi_data = (ce_id % msi_data_count) + msi_data_start;
ring_params->msi_data = irq_id + msi_data_start;
ring_params->flags |= HAL_SRNG_MSI_INTR;
hif_debug("ce_id %d, msi_addr %pK, msi_data %d", ce_id,
(void *)ring_params->msi_addr, ring_params->msi_data);
hif_debug("ce_id %d irq_id %d, msi_addr %pK, msi_data %d", ce_id,
irq_id, (void *)ring_params->msi_addr, ring_params->msi_data);
}
static void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id,

View File

@@ -143,6 +143,16 @@
#define HIF_GET_SOFTC(scn) ((struct hif_softc *)scn)
#define GET_HIF_OPAQUE_HDL(scn) ((struct hif_opaque_softc *)scn)
#define NUM_CE_AVAILABLE 12
/* Add 1 here to store default configuration in index 0 */
#define NUM_CE_CONTEXT (NUM_CE_AVAILABLE + 1)
#define CE_INTERRUPT_IDX(x) x
struct ce_int_assignment {
uint8_t msi_idx[NUM_CE_AVAILABLE];
};
struct hif_ce_stats {
int hif_pipe_no_resrc_count;
int ce_ring_delta_fail_count;
@@ -220,6 +230,7 @@ struct hif_softc {
uint32_t ce_irq_summary;
/* No of copy engines supported */
unsigned int ce_count;
struct ce_int_assignment *int_assignment;
atomic_t active_tasklet_cnt;
atomic_t active_grp_tasklet_cnt;
atomic_t link_suspended;

View File

@@ -2058,7 +2058,7 @@ end:
static int hif_ce_srng_msi_free_irq(struct hif_softc *scn)
{
int ret;
int ce_id, irq;
int ce_id, irq, irq_id;
uint32_t msi_data_start;
uint32_t msi_data_count;
uint32_t msi_irq_start;
@@ -2083,13 +2083,14 @@ static int hif_ce_srng_msi_free_irq(struct hif_softc *scn)
if (!ce_sc->tasklets[ce_id].inited)
continue;
msi_data = (ce_id % msi_data_count) + msi_irq_start;
irq_id = scn->int_assignment->msi_idx[ce_id];
msi_data = irq_id + msi_irq_start;
irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
hif_pci_ce_irq_remove_affinity_hint(irq);
hif_debug("%s: (ce_id %d, msi_data %d, irq %d)", __func__,
ce_id, msi_data, irq);
hif_debug("%s: (ce_id %d, irq_id %d, msi_data %d, irq %d)",
__func__, irq_id, ce_id, msi_data, irq);
pfrm_free_irq(scn->qdf_dev->dev, irq, &ce_sc->tasklets[ce_id]);
}
@@ -2875,6 +2876,7 @@ int hif_ce_msi_configure_irq_by_ceid(struct hif_softc *scn, int ce_id)
uint32_t msi_data_start;
uint32_t msi_data_count;
unsigned int msi_data;
int irq_id;
uint32_t msi_irq_start;
struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn);
struct hif_pci_softc *pci_sc = HIF_GET_PCI_SOFTC(scn);
@@ -2888,15 +2890,21 @@ int hif_ce_msi_configure_irq_by_ceid(struct hif_softc *scn, int ce_id)
&msi_data_count, &msi_data_start,
&msi_irq_start);
if (ret) {
hif_err("Failed to get CE msi config");
return -EINVAL;
}
irq_id = scn->int_assignment->msi_idx[ce_id];
/* needs to match the ce_id -> irq data mapping
* used in the srng parameter configuration
*/
pci_slot = hif_get_pci_slot(scn);
msi_data = (ce_id % msi_data_count) + msi_irq_start;
msi_data = irq_id + msi_irq_start;
irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
hif_debug("%s: (ce_id %d, msi_data %d, irq %d tasklet %pK)",
__func__, ce_id, msi_data, irq,
&ce_sc->tasklets[ce_id]);
hif_debug("%s: (ce_id %d, irq_id %d, msi_data %d, irq %d tasklet %pK)",
__func__, ce_id, irq_id, msi_data, irq,
&ce_sc->tasklets[ce_id]);
/* implies the ce is also initialized */
if (!ce_sc->tasklets[ce_id].inited)