qcacmn: Add top-level interrupt handling support for DP

Add support for initialization of Lithium Datapath interrupts
and top-level interrupt handler for Datapath interrupts

CRs-Fixed: 1073253
Change-Id: I690d914221cf8a6d2ffdeb25785b1d534f56dfe7
This commit is contained in:
Vijay Pamidipati
2016-10-19 21:19:52 +05:30
committed by qcabuildsw
parent d41d6d6a49
commit b775e13093

View File

@@ -154,6 +154,15 @@ void *dp_soc_attach_wifi3(void *osif_soc, void *hif_handle,
goto fail1;
}
soc->wlan_cfg_ctx = wlan_cfg_soc_attach();
if (!soc->wlan_cfg_ctx) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: wlan_cfg_soc_attach failed\n", __func__);
goto fail2;
}
#ifdef notyet
if (wdi_event_attach(soc)) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
@@ -162,18 +171,224 @@ void *dp_soc_attach_wifi3(void *osif_soc, void *hif_handle,
}
#endif
if (dp_soc_interrupt_attach(soc) != QDF_STATUS_SUCCESS) {
goto fail2;
}
return (void *)soc;
#ifdef notyet
fail2:
htt_soc_detach(soc->htt_handle);
#endif
fail1:
qdf_mem_free(soc);
fail0:
return NULL;
}
/*
* dp_service_srngs() - Top level interrupt handler for DP Ring interrupts
* @dp_ctx: DP SOC handle
* @budget: Number of frames/descriptors that can be processed in one shot
*
* Return: remaining budget/quota for the soc device
*/
uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
{
struct dp_intr *int_ctx = (struct dp_intr *)dp_ctx;
struct dp_soc *soc = int_ctx->soc;
int ring = 0;
uint32_t work_done = 0;
uint32_t budget = dp_budget;
uint8_t tx_mask = int_ctx->tx_ring_mask;
uint8_t rx_mask = int_ctx->rx_ring_mask;
/* Process Tx completion interrupts first to return back buffers */
if (tx_mask) {
for (ring = 0; ring < soc->num_tcl_data_rings; ring++) {
if (tx_mask & (1 << ring)) {
work_done =
dp_tx_comp_handler(soc, ring, budget);
budget -= work_done;
if (budget <= 0)
goto budget_done;
}
}
}
/* Process Rx interrupts */
if (rx_mask) {
for (ring = 0; ring < soc->num_reo_dest_rings; ring++) {
if (rx_mask & (1 << ring)) {
work_done =
dp_rx_process(soc,
soc->reo_dest_ring[ring].hal_srng,
budget);
budget -= work_done;
if (budget <= 0)
goto budget_done;
}
}
}
budget_done:
return dp_budget - budget;
}
/* dp_interrupt_timer()- timer poll for interrupts
*
* @arg: SoC Handle
*
* Return:
*
*/
#ifdef DP_INTR_POLL_BASED
void dp_interrupt_timer(void *arg)
{
struct dp_soc *soc = (struct dp_soc *) arg;
int i;
for (i = 0 ; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++)
dp_service_srngs(&soc->intr_ctx[i], 0xffff);
qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS);
}
/*
* dp_soc_interrupt_attach() - Register handlers for DP interrupts
* @txrx_soc: DP SOC handle
*
* Host driver will register for “DP_NUM_INTERRUPT_CONTEXTS” number of NAPI
* contexts. Each NAPI context will have a tx_ring_mask , rx_ring_mask ,and
* rx_monitor_ring mask to indicate the rings that are processed by the handler.
*
* Return: 0 for success. nonzero for failure.
*/
QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc)
{
struct dp_soc *soc = (struct dp_soc *)txrx_soc;
int i;
for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) {
soc->intr_ctx[i].tx_ring_mask = 0xF;
soc->intr_ctx[i].rx_ring_mask = 0xF;
soc->intr_ctx[i].rx_mon_ring_mask = 0xF;
soc->intr_ctx[i].soc = soc;
}
qdf_timer_init(soc->osdev, &soc->int_timer,
dp_interrupt_timer, (void *)soc,
QDF_TIMER_TYPE_WAKE_APPS);
qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS);
return QDF_STATUS_SUCCESS;
}
/*
* dp_soc_interrupt_detach() - Deregister any allocations done for interrupts
* @txrx_soc: DP SOC handle
*
* Return: void
*/
void dp_soc_interrupt_detach(void *txrx_soc)
{
struct dp_soc *soc = (struct dp_soc *)txrx_soc;
qdf_timer_stop(&soc->int_timer);
qdf_timer_detach(&soc->int_timer);
}
#else
/*
* dp_soc_interrupt_attach() - Register handlers for DP interrupts
* @txrx_soc: DP SOC handle
*
* Host driver will register for “DP_NUM_INTERRUPT_CONTEXTS” number of NAPI
* contexts. Each NAPI context will have a tx_ring_mask , rx_ring_mask ,and
* rx_monitor_ring mask to indicate the rings that are processed by the handler.
*
* Return: 0 for success. nonzero for failure.
*/
QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc)
{
struct dp_soc *soc = (struct dp_soc *)txrx_soc;
int i = 0;
int num_irq = 0;
for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) {
int tx_mask =
wlan_cfg_get_tx_ring_mask(soc->wlan_cfg_ctx, i);
int rx_mask =
wlan_cfg_get_rx_ring_mask(soc->wlan_cfg_ctx, i);
int rx_mon_mask =
wlan_cfg_get_rx_mon_ring_mask(soc->wlan_cfg_ctx, i);
soc->intr_ctx[i].tx_ring_mask = tx_mask;
soc->intr_ctx[i].rx_ring_mask = rx_mask;
soc->intr_ctx[i].rx_mon_ring_mask = rx_mon_mask;
soc->intr_ctx[i].soc = soc;
num_irq = 0;
int j = 0;
int ret = 0;
/* Map of IRQ ids registered with one interrupt context */
int irq_id_map[HIF_MAX_GRP_IRQ];
for (j = 0; j < HIF_MAX_GRP_IRQ; j++) {
if (tx_mask & (1 << j)) {
irq_id_map[num_irq++] =
(wbm2host_tx_completions_ring1 - j);
}
if (rx_mask & (1 << j)) {
irq_id_map[num_irq++] =
(reo2host_destination_ring1 - j);
}
if (rx_mon_mask & (1 << j)) {
irq_id_map[num_irq++] =
(rxdma2host_monitor_destination_mac1
- j);
}
}
ret = hif_register_ext_group_int_handler(soc->hif_handle,
num_irq, irq_id_map,
dp_service_srngs,
&soc->intr_ctx[i]);
if (ret) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: failed, ret = %d", __func__, ret);
return QDF_STATUS_E_FAILURE;
}
}
return QDF_STATUS_SUCCESS;
}
/*
* dp_soc_interrupt_detach() - Deregister any allocations done for interrupts
* @txrx_soc: DP SOC handle
*
* Return: void
*/
void dp_soc_interrupt_detach(void *txrx_soc)
{
struct dp_soc *soc = (struct dp_soc *)txrx_soc;
soc->intr_ctx[i].tx_ring_mask = 0;
soc->intr_ctx[i].rx_ring_mask = 0;
soc->intr_ctx[i].rx_mon_ring_mask = 0;
}
#endif
#define AVG_MAX_MPDUS_PER_TID 128
#define AVG_TIDS_PER_CLIENT 2
#define AVG_FLOWS_PER_TID 2
@@ -704,6 +919,8 @@ void *dp_pdev_attach_wifi3(void *txrx_soc, void *ctrl_pdev,
if (!pdev->wlan_cfg_ctx) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: pdev cfg_attach failed\n", __func__);
qdf_mem_free(pdev);
goto fail0;
}
@@ -718,7 +935,7 @@ void *dp_pdev_attach_wifi3(void *txrx_soc, void *ctrl_pdev,
if (dp_soc_cmn_setup(soc)) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: dp_soc_cmn_setup failed\n", __func__);
goto fail0;
goto fail1;
}
/* Setup per PDEV TCL rings if configured */
@@ -728,14 +945,14 @@ void *dp_pdev_attach_wifi3(void *txrx_soc, void *ctrl_pdev,
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: dp_srng_setup failed for tcl_data_ring\n",
__func__);
goto fail0;
goto fail1;
}
if (dp_srng_setup(soc, &soc->tx_comp_ring[pdev_id],
WBM2SW_RELEASE, pdev_id, pdev_id, TCL_DATA_RING_SIZE)) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: dp_srng_setup failed for tx_comp_ring\n",
__func__);
goto fail0;
goto fail1;
}
soc->num_tcl_data_rings++;
}
@@ -744,7 +961,7 @@ void *dp_pdev_attach_wifi3(void *txrx_soc, void *ctrl_pdev,
if (dp_tx_pdev_attach(pdev)) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: dp_tx_pdev_attach failed\n", __func__);
goto fail0;
goto fail1;
}
/* Setup per PDEV REO rings if configured */
@@ -754,7 +971,7 @@ void *dp_pdev_attach_wifi3(void *txrx_soc, void *ctrl_pdev,
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: dp_srng_setup failed for reo_dest_ring\n",
__func__);
goto fail0;
goto fail1;
}
soc->num_reo_dest_rings++;
@@ -764,14 +981,14 @@ void *dp_pdev_attach_wifi3(void *txrx_soc, void *ctrl_pdev,
RXDMA_BUF_RING_SIZE)) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: dp_srng_setup failed rx refill ring\n", __func__);
goto fail0;
goto fail1;
}
#ifdef QCA_HOST2FW_RXBUF_RING
if (dp_srng_setup(soc, &pdev->rx_mac_buf_ring, RXDMA_BUF, 1, pdev_id,
RXDMA_BUF_RING_SIZE)) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: dp_srng_setup failed rx mac ring\n", __func__);
goto fail0;
goto fail1;
}
#endif
/* TODO: RXDMA destination ring is not planned to be used currently.
@@ -782,7 +999,7 @@ void *dp_pdev_attach_wifi3(void *txrx_soc, void *ctrl_pdev,
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: dp_srng_setup failed for rxdma_mon_buf_ring\n",
__func__);
goto fail0;
goto fail1;
}
if (dp_srng_setup(soc, &pdev->rxdma_mon_dst_ring, RXDMA_MONITOR_DST, 0,
@@ -790,7 +1007,7 @@ void *dp_pdev_attach_wifi3(void *txrx_soc, void *ctrl_pdev,
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: dp_srng_setup failed for rxdma_mon_dst_ring\n",
__func__);
goto fail0;
goto fail1;
}
@@ -800,14 +1017,16 @@ void *dp_pdev_attach_wifi3(void *txrx_soc, void *ctrl_pdev,
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: dp_srng_setup failed for rxdma_mon_status_ring\n",
__func__);
goto fail0;
goto fail1;
}
return (void *)pdev;
fail0:
fail1:
dp_pdev_detach_wifi3((void *)pdev, 0);
fail0:
return NULL;
}