qcacmn: Use pld msi allocation for CE

Use the msi vectors allocated by the platform driver
for the copy engine interrupts.

Change-Id: I3fa96daa3222524ffe31659c12b3c0f5a2725e18
CRs-Fixed: 1093364
This commit is contained in:
Houston Hoffman
2016-09-16 14:01:13 -07:00
committed by qcabuildsw
parent 9e2bb31af7
commit 15010778ea
3 changed files with 165 additions and 2 deletions

View File

@@ -28,6 +28,7 @@
#include "hif_main.h" #include "hif_main.h"
#include "hif_debug.h" #include "hif_debug.h"
#include "hal_api.h" #include "hal_api.h"
#include "pld_common.h"
/* /*
* Support for Copy Engine hardware, which is mainly used for * Support for Copy Engine hardware, which is mainly used for
@@ -584,11 +585,47 @@ uint32_t ce_get_desc_size_srng(uint8_t ring_type)
return 0; return 0;
} }
static void ce_srng_msi_ring_params_setup(struct hif_softc *scn, uint32_t ce_id,
struct hal_srng_params *ring_params)
{
uint32_t addr_low;
uint32_t addr_high;
uint32_t msi_data_start;
uint32_t msi_data_count;
uint32_t msi_irq_start;
int ret;
ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
&msi_data_count, &msi_data_start,
&msi_irq_start);
/* msi config not found */
if (ret)
return;
HIF_INFO("%s: ce_id %d, msi_start: %d, msi_count %d", __func__, ce_id,
msi_data_start, msi_data_count);
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->flags |= HAL_SRNG_MSI_INTR;
HIF_INFO("%s: ce_id %d, msi_addr %p, msi_data %d", __func__, ce_id,
(void *)ring_params->msi_addr, ring_params->msi_data);
}
void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id, void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id,
struct CE_ring_state *src_ring) struct CE_ring_state *src_ring)
{ {
struct hal_srng_params ring_params = {0}; struct hal_srng_params ring_params = {0};
HIF_INFO("%s: ce_id %d", __func__, ce_id);
ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
ring_params.ring_base_paddr = src_ring->base_addr_CE_space; ring_params.ring_base_paddr = src_ring->base_addr_CE_space;
ring_params.ring_base_vaddr = src_ring->base_addr_owner_space; ring_params.ring_base_vaddr = src_ring->base_addr_owner_space;
ring_params.num_entries = src_ring->nentries; ring_params.num_entries = src_ring->nentries;
@@ -617,6 +654,10 @@ void ce_srng_dest_ring_setup(struct hif_softc *scn, uint32_t ce_id,
{ {
struct hal_srng_params ring_params = {0}; struct hal_srng_params ring_params = {0};
HIF_INFO("%s: ce_id %d", __func__, ce_id);
ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
ring_params.ring_base_paddr = dest_ring->base_addr_CE_space; ring_params.ring_base_paddr = dest_ring->base_addr_CE_space;
ring_params.ring_base_vaddr = dest_ring->base_addr_owner_space; ring_params.ring_base_vaddr = dest_ring->base_addr_owner_space;
ring_params.num_entries = dest_ring->nentries; ring_params.num_entries = dest_ring->nentries;
@@ -640,6 +681,10 @@ void ce_srng_status_ring_setup(struct hif_softc *scn, uint32_t ce_id,
{ {
struct hal_srng_params ring_params = {0}; struct hal_srng_params ring_params = {0};
HIF_INFO("%s: ce_id %d", __func__, ce_id);
ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
ring_params.ring_base_paddr = status_ring->base_addr_CE_space; ring_params.ring_base_paddr = status_ring->base_addr_CE_space;
ring_params.ring_base_vaddr = status_ring->base_addr_owner_space; ring_params.ring_base_vaddr = status_ring->base_addr_owner_space;
ring_params.num_entries = status_ring->nentries; ring_params.num_entries = status_ring->nentries;

View File

@@ -2546,6 +2546,38 @@ end:
return ret; return ret;
} }
static int hif_ce_srng_msi_free_irq(struct hif_softc *scn)
{
int ret;
int ce_id, irq;
uint32_t msi_data_start;
uint32_t msi_data_count;
uint32_t msi_irq_start;
struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn);
ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
&msi_data_count, &msi_data_start,
&msi_irq_start);
if (ret)
return ret;
/* needs to match the ce_id -> irq data mapping
* used in the srng parameter configuration
*/
for (ce_id = 0; ce_id < scn->ce_count; ce_id++) {
unsigned int msi_data;
msi_data = (ce_id % msi_data_count) + msi_irq_start;
irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
HIF_INFO("%s: (ce_id %d, msi_data %d, irq %d)", __func__,
ce_id, msi_data, irq);
free_irq(irq, &ce_sc->tasklets[ce_id]);
}
return ret;
}
/** /**
* hif_nointrs(): disable IRQ * hif_nointrs(): disable IRQ
* *
@@ -2557,13 +2589,15 @@ end:
*/ */
void hif_pci_nointrs(struct hif_softc *scn) void hif_pci_nointrs(struct hif_softc *scn)
{ {
int i; int i, ret;
struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn); struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
if (scn->request_irq_done == false) if (scn->request_irq_done == false)
return; return;
if (sc->num_msi_intrs > 0) {
ret = hif_ce_srng_msi_free_irq(scn);
if (ret != 0 && sc->num_msi_intrs > 0) {
/* MSI interrupt(s) */ /* MSI interrupt(s) */
for (i = 0; i < sc->num_msi_intrs; i++) { for (i = 0; i < sc->num_msi_intrs; i++) {
free_irq(sc->irq + i, sc); free_irq(sc->irq + i, sc);
@@ -3510,6 +3544,63 @@ int hif_ahb_configure_irq(struct hif_pci_softc *sc)
} }
#endif #endif
irqreturn_t hif_ce_interrupt_handler(int irq, void *context)
{
struct ce_tasklet_entry *tasklet_entry = context;
return ce_dispatch_interrupt(tasklet_entry->ce_id, tasklet_entry);
}
extern const char *ce_name[];
static int hif_ce_srng_msi_request_irq(struct hif_softc *scn)
{
int ret;
int ce_id, irq;
uint32_t msi_data_start;
uint32_t msi_data_count;
uint32_t msi_irq_start;
struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn);
ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
&msi_data_count, &msi_data_start,
&msi_irq_start);
if (ret)
return ret;
/* needs to match the ce_id -> irq data mapping
* used in the srng parameter configuration
*/
for (ce_id = 0; ce_id < scn->ce_count; ce_id++) {
unsigned int msi_data = (ce_id % msi_data_count) +
msi_irq_start;
irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
HIF_INFO("%s: (ce_id %d, msi_data %d, irq %d tasklet %p)",
__func__, ce_id, msi_data, irq,
&ce_sc->tasklets[ce_id]);
ret = request_irq(irq, hif_ce_interrupt_handler,
IRQF_SHARED,
ce_name[ce_id],
&ce_sc->tasklets[ce_id]);
if (ret)
goto free_irq;
}
return ret;
free_irq:
/* the request_irq for the last ce_id failed so skip it. */
while (ce_id > 0 && ce_id < scn->ce_count) {
unsigned int msi_data;
ce_id--;
msi_data = (ce_id % msi_data_count) + msi_data_start;
irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
free_irq(irq, &ce_sc->tasklets[ce_id]);
}
return ret;
}
/** /**
* hif_configure_irq() - configure interrupt * hif_configure_irq() - configure interrupt
* *
@@ -3529,6 +3620,11 @@ int hif_configure_irq(struct hif_softc *scn)
hif_init_reschedule_tasklet_work(sc); hif_init_reschedule_tasklet_work(sc);
ret = hif_ce_srng_msi_request_irq(scn);
if (ret == 0) {
goto end;
}
if (ENABLE_MSI) { if (ENABLE_MSI) {
ret = hif_configure_msi(sc); ret = hif_configure_msi(sc);
if (ret == 0) if (ret == 0)

View File

@@ -176,6 +176,28 @@ static inline void pld_intr_notify_q6(struct device *dev)
{ {
return; return;
} }
static inline int pld_get_user_msi_assignment(struct device *dev,
char *user_name, int *num_vectors,
uint32_t *user_base_data, uint32_t *base_vector)
{
return -EINVAL;
}
/* should not be called if pld_get_user_msi_assignment returns error */
static inline int pld_get_msi_irq(struct device *dev, unsigned int vector)
{
return -EINVAL;
}
/* should not be called if pld_get_user_msi_assignment returns error */
static inline void pld_get_msi_address(struct device *dev,
uint32_t *msi_addr_low,
uint32_t *msi_addr_high)
{
return;
}
static inline int pld_ce_request_irq(struct device *dev, unsigned int ce_id, static inline int pld_ce_request_irq(struct device *dev, unsigned int ce_id,
irqreturn_t (*handler)(int, void *), irqreturn_t (*handler)(int, void *),
unsigned long flags, const char *name, unsigned long flags, const char *name,