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:

committed by
Madan Koyyalamudi

parent
2359af8cea
commit
718d6aeece
@@ -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);
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user