qcacmn: Enable msi support for ext_group ring groupings

assign msi vectors to srng rings based on the ext_group they will be
serviced in.

provide support for ext_groups in hif_pci.

Change-Id: If313fdb43b939871c0d73dea9a05f757427b5b16
CRs-Fixed: 2051911
このコミットが含まれているのは:
Houston Hoffman
2017-05-21 23:27:50 -07:00
committed by snandini
コミット 648a918927
14個のファイルの変更553行の追加186行の削除

ファイルの表示

@@ -585,9 +585,6 @@ static void ce_srng_msi_ring_params_setup(struct hif_softc *scn, uint32_t ce_id,
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;
@@ -595,19 +592,18 @@ static void ce_srng_msi_ring_params_setup(struct hif_softc *scn, uint32_t ce_id,
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,
HIF_DBG("%s: ce_id %d, msi_addr %p, msi_data %d", __func__, ce_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,
struct CE_ring_state *src_ring)
struct CE_ring_state *src_ring,
struct CE_attr *attr)
{
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_vaddr = src_ring->base_addr_owner_space;
ring_params.num_entries = src_ring->nentries;
@@ -617,14 +613,13 @@ static void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id,
* A valid default value caused continuous interrupts to
* fire with MSI enabled. Need to revisit usage of the timer
*/
ring_params.intr_timer_thres_us = 0;
ring_params.intr_batch_cntr_thres_entries = 1;
/* TODO
* ring_params.msi_addr = XXX;
* ring_params.msi_data = XXX;
* ring_params.flags = XXX;
*/
if (!(CE_ATTR_DISABLE_INTR & attr->flags)) {
ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
ring_params.intr_timer_thres_us = 0;
ring_params.intr_batch_cntr_thres_entries = 1;
}
src_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_SRC, ce_id, 0,
&ring_params);
@@ -635,25 +630,31 @@ static void ce_srng_dest_ring_setup(struct hif_softc *scn, uint32_t ce_id,
struct CE_attr *attr)
{
struct hal_srng_params ring_params = {0};
bool status_ring_timer_thresh_work_arround = true;
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_vaddr = dest_ring->base_addr_owner_space;
ring_params.num_entries = dest_ring->nentries;
ring_params.low_threshold = dest_ring->nentries - 1;
ring_params.flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE;
ring_params.intr_timer_thres_us = 1024;
ring_params.intr_batch_cntr_thres_entries = 0;
ring_params.max_buffer_length = attr->src_sz_max;
/* TODO
* ring_params.msi_addr = XXX;
* ring_params.msi_data = XXX;
* ring_params.flags = XXX;
*/
if (!(CE_ATTR_DISABLE_INTR & attr->flags)) {
ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
if (status_ring_timer_thresh_work_arround) {
/* hw bug work arround*/
ring_params.low_threshold = dest_ring->nentries - 1;
ring_params.intr_timer_thres_us = 1024;
ring_params.intr_batch_cntr_thres_entries = 0;
ring_params.flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE;
} else {
/* normal behavior for future chips */
ring_params.low_threshold = dest_ring->nentries >> 3;
ring_params.intr_timer_thres_us = 100000;
ring_params.intr_batch_cntr_thres_entries = 0;
ring_params.flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE;
}
}
/*Dest ring is also source ring*/
dest_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_DST, ce_id, 0,
@@ -661,7 +662,8 @@ static void ce_srng_dest_ring_setup(struct hif_softc *scn, uint32_t ce_id,
}
static void ce_srng_status_ring_setup(struct hif_softc *scn, uint32_t ce_id,
struct CE_ring_state *status_ring)
struct CE_ring_state *status_ring,
struct CE_attr *attr)
{
struct hal_srng_params ring_params = {0};
@@ -672,14 +674,11 @@ static void ce_srng_status_ring_setup(struct hif_softc *scn, uint32_t ce_id,
ring_params.ring_base_paddr = status_ring->base_addr_CE_space;
ring_params.ring_base_vaddr = status_ring->base_addr_owner_space;
ring_params.num_entries = status_ring->nentries;
ring_params.intr_timer_thres_us = 0;
ring_params.intr_batch_cntr_thres_entries = 1;
/* TODO
* ring_params.msi_addr = XXX;
* ring_params.msi_data = XXX;
* ring_params.flags = XXX;
*/
if (!(CE_ATTR_DISABLE_INTR & attr->flags)) {
ring_params.intr_timer_thres_us = 0x1000;
ring_params.intr_batch_cntr_thres_entries = 0x1;
}
status_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_DST_STATUS,
ce_id, 0, &ring_params);
@@ -691,13 +690,13 @@ static void ce_ring_setup_srng(struct hif_softc *scn, uint8_t ring_type,
{
switch (ring_type) {
case CE_RING_SRC:
ce_srng_src_ring_setup(scn, ce_id, ring);
ce_srng_src_ring_setup(scn, ce_id, ring, attr);
break;
case CE_RING_DEST:
ce_srng_dest_ring_setup(scn, ce_id, ring, attr);
break;
case CE_RING_STATUS:
ce_srng_status_ring_setup(scn, ce_id, ring);
ce_srng_status_ring_setup(scn, ce_id, ring, attr);
break;
default:
qdf_assert(0);

ファイルの表示

@@ -398,6 +398,7 @@ irqreturn_t ce_dispatch_interrupt(int ce_id,
__func__, tasklet_entry->ce_id, CE_COUNT_MAX);
return IRQ_NONE;
}
hif_irq_disable(scn, ce_id);
hif_record_ce_desc_event(scn, ce_id, HIF_IRQ_EVENT, NULL, NULL, 0);
hif_ce_increment_interrupt_count(hif_ce_state, ce_id);

ファイルの表示

@@ -83,6 +83,7 @@ QDF_STATUS hif_initialize_pci_ops(struct hif_softc *hif_sc)
&hif_pci_enable_power_management;
bus_ops->hif_disable_power_management =
&hif_pci_disable_power_management;
bus_ops->hif_grp_irq_configure = &hif_pci_configure_grp_irq;
bus_ops->hif_display_stats =
&hif_pci_display_stats;
bus_ops->hif_clear_stats =

ファイルの表示

@@ -26,6 +26,8 @@
*/
#ifndef _PCI_API_H_
#define _PCI_API_H_
struct hif_exec_context;
QDF_STATUS hif_pci_open(struct hif_softc *hif_ctx,
enum qdf_bus_type bus_type);
void hif_pci_close(struct hif_softc *hif_ctx);
@@ -52,6 +54,8 @@ int hif_pci_dump_registers(struct hif_softc *scn);
void hif_pci_enable_power_management(struct hif_softc *hif_ctx,
bool is_packet_log_enabled);
void hif_pci_disable_power_management(struct hif_softc *hif_ctx);
int hif_pci_configure_grp_irq(struct hif_softc *scn,
struct hif_exec_context *exec);
void hif_pci_display_stats(struct hif_softc *hif_ctx);
void hif_pci_clear_stats(struct hif_softc *hif_ctx);
int hif_pci_legacy_map_ce_to_irq(struct hif_softc *scn, int ce_id);

ファイルの表示

@@ -299,7 +299,6 @@ irqreturn_t hif_ext_group_interrupt_handler(int irq, void *context)
struct hif_exec_context *hif_ext_group = context;
struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif);
hif_ext_group->irq_disable(hif_ext_group);
qdf_atomic_inc(&scn->active_grp_tasklet_cnt);

ファイルの表示

@@ -54,6 +54,7 @@
#include "if_pci_internal.h"
#include "ce_tasklet.h"
#include "targaddrs.h"
#include "hif_exec.h"
#include "pci_api.h"
#include "ahb_api.h"
@@ -2592,6 +2593,25 @@ static int hif_ce_srng_msi_free_irq(struct hif_softc *scn)
return ret;
}
static void hif_pci_deconfigure_grp_irq(struct hif_softc *scn)
{
int i, j, irq;
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
struct hif_exec_context *hif_ext_group;
for (i = 0; i < hif_state->hif_num_extgroup; i++) {
hif_ext_group = hif_state->hif_ext_group[i];
if (hif_ext_group->irq_requested) {
hif_ext_group->irq_requested = false;
for (j = 0; j < hif_ext_group->numirq; j++) {
irq = hif_ext_group->os_irq[j];
free_irq(irq, hif_ext_group);
}
hif_ext_group->numirq = 0;
}
}
}
/**
* hif_nointrs(): disable IRQ
*
@@ -2612,6 +2632,8 @@ void hif_pci_nointrs(struct hif_softc *scn)
if (scn->request_irq_done == false)
return;
hif_pci_deconfigure_grp_irq(scn);
ret = hif_ce_srng_msi_free_irq(scn);
if (ret != 0 && sc->num_msi_intrs > 0) {
/* MSI interrupt(s) */
@@ -3623,11 +3645,14 @@ static int hif_ce_msi_configure_irq(struct hif_softc *scn)
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)",
HIF_DBG("%s: (ce_id %d, msi_data %d, irq %d tasklet %p)",
__func__, ce_id, msi_data, irq,
&ce_sc->tasklets[ce_id]);
/* implies the ce is also initialized */
if (!ce_sc->tasklets[ce_id].inited)
continue;
pci_sc->ce_msi_irq_num[ce_id] = irq;
ret = request_irq(irq, hif_ce_interrupt_handler,
IRQF_SHARED,
@@ -3652,6 +3677,53 @@ free_irq:
return ret;
}
static void hif_exec_grp_irq_disable(struct hif_exec_context *hif_ext_group)
{
int i;
for (i = 0; i < hif_ext_group->numirq; i++)
disable_irq_nosync(hif_ext_group->os_irq[i]);
}
static void hif_exec_grp_irq_enable(struct hif_exec_context *hif_ext_group)
{
int i;
for (i = 0; i < hif_ext_group->numirq; i++)
enable_irq(hif_ext_group->os_irq[i]);
}
int hif_pci_configure_grp_irq(struct hif_softc *scn,
struct hif_exec_context *hif_ext_group)
{
int ret = 0;
int irq = 0;
int j;
hif_ext_group->irq_enable = &hif_exec_grp_irq_enable;
hif_ext_group->irq_disable = &hif_exec_grp_irq_disable;
hif_ext_group->work_complete = &hif_dummy_grp_done;
for (j = 0; j < hif_ext_group->numirq; j++) {
irq = hif_ext_group->irq[j];
HIF_DBG("%s: request_irq = %d for grp %d",
__func__, irq, hif_ext_group->grp_id);
ret = request_irq(irq,
hif_ext_group_interrupt_handler,
IRQF_SHARED, "wlan_EXT_GRP",
hif_ext_group);
if (ret) {
HIF_ERROR("%s: request_irq failed ret = %d",
__func__, ret);
return -EFAULT;
}
hif_ext_group->os_irq[j] = irq;
}
hif_ext_group->irq_requested = true;
return 0;
}
/**
* hif_configure_irq() - configure interrupt