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:

committed by
qcabuildsw

parent
d41d6d6a49
commit
b775e13093
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user