qcacmn: Restrict RX softirq poll times
The following changes are made -Yield dp_rx_process if poll time exceeds -Yield dp_tx_comp_handler if poll time exceeds -Interrupt statistics to track various interrupt contexts and corresponding interrupt masks -Add poll times histogram buckets to NAPI stats Change-Id: I8c7a6bbbb97c7b3dd1dde6ac3a97113c433086a2 CRs-Fixed: 2423879
This commit is contained in:
@@ -204,6 +204,7 @@ enum htt_cmn_dbg_stats_type {
|
|||||||
* @TXRX_SOC_CFG_PARAMS: Print soc cfg params info
|
* @TXRX_SOC_CFG_PARAMS: Print soc cfg params info
|
||||||
* @TXRX_PDEV_CFG_PARAMS: Print pdev cfg params info
|
* @TXRX_PDEV_CFG_PARAMS: Print pdev cfg params info
|
||||||
* @TXRX_NAPI_STATS: Print NAPI scheduling statistics
|
* @TXRX_NAPI_STATS: Print NAPI scheduling statistics
|
||||||
|
* @TXRX_SOC_INTERRUPT_STATS: Print soc interrupt stats
|
||||||
*/
|
*/
|
||||||
enum cdp_host_txrx_stats {
|
enum cdp_host_txrx_stats {
|
||||||
TXRX_HOST_STATS_INVALID = -1,
|
TXRX_HOST_STATS_INVALID = -1,
|
||||||
@@ -219,6 +220,7 @@ enum cdp_host_txrx_stats {
|
|||||||
TXRX_SOC_CFG_PARAMS = 9,
|
TXRX_SOC_CFG_PARAMS = 9,
|
||||||
TXRX_PDEV_CFG_PARAMS = 10,
|
TXRX_PDEV_CFG_PARAMS = 10,
|
||||||
TXRX_NAPI_STATS = 11,
|
TXRX_NAPI_STATS = 11,
|
||||||
|
TXRX_SOC_INTERRUPT_STATS = 12,
|
||||||
TXRX_HOST_STATS_MAX,
|
TXRX_HOST_STATS_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1042,6 +1044,7 @@ typedef void (*data_stall_detect_cb)(struct data_stall_event_info *);
|
|||||||
* @CDP_TXRX_STATS_28: Host Peer entry stats
|
* @CDP_TXRX_STATS_28: Host Peer entry stats
|
||||||
* @CDP_TXRX_STATS_29: Host Soc config params info
|
* @CDP_TXRX_STATS_29: Host Soc config params info
|
||||||
* @CDP_TXRX_STATS_30: Host Pdev config params info
|
* @CDP_TXRX_STATS_30: Host Pdev config params info
|
||||||
|
* @CDP_TXRX_STATS_31: Host DP Interrupt Stats
|
||||||
*/
|
*/
|
||||||
enum cdp_stats {
|
enum cdp_stats {
|
||||||
CDP_TXRX_STATS_0 = 0,
|
CDP_TXRX_STATS_0 = 0,
|
||||||
@@ -1075,6 +1078,7 @@ enum cdp_stats {
|
|||||||
CDP_TXRX_STATS_28,
|
CDP_TXRX_STATS_28,
|
||||||
CDP_TXRX_STATS_29,
|
CDP_TXRX_STATS_29,
|
||||||
CDP_TXRX_STATS_30,
|
CDP_TXRX_STATS_30,
|
||||||
|
CDP_TXRX_STATS_31,
|
||||||
CDP_TXRX_STATS_HTT_MAX = 256,
|
CDP_TXRX_STATS_HTT_MAX = 256,
|
||||||
CDP_TXRX_MAX_STATS = 265,
|
CDP_TXRX_MAX_STATS = 265,
|
||||||
};
|
};
|
||||||
@@ -1536,6 +1540,9 @@ struct cdp_rx_indication_msdu {
|
|||||||
* @tx_flow_stop_queue_threshold: Value to Pause tx queues
|
* @tx_flow_stop_queue_threshold: Value to Pause tx queues
|
||||||
* @tx_flow_start_queue_offset: Available Tx descriptors to unpause
|
* @tx_flow_start_queue_offset: Available Tx descriptors to unpause
|
||||||
* tx queue
|
* tx queue
|
||||||
|
* @tx_comp_loop_pkt_limit: Max # of packets to be processed in 1 tx comp loop
|
||||||
|
* @rx_reap_loop_pkt_limit: Max # of packets to be processed in 1 rx reap loop
|
||||||
|
* @rx_hp_oos_update_limit: Max # of HP OOS (out of sync) updates
|
||||||
*/
|
*/
|
||||||
struct cdp_config_params {
|
struct cdp_config_params {
|
||||||
unsigned int tso_enable:1;
|
unsigned int tso_enable:1;
|
||||||
@@ -1548,6 +1555,9 @@ struct cdp_config_params {
|
|||||||
/* Set when QCA_LL_TX_FLOW_CONTROL_V2 is enabled */
|
/* Set when QCA_LL_TX_FLOW_CONTROL_V2 is enabled */
|
||||||
uint8_t tx_flow_stop_queue_threshold;
|
uint8_t tx_flow_stop_queue_threshold;
|
||||||
uint8_t tx_flow_start_queue_offset;
|
uint8_t tx_flow_start_queue_offset;
|
||||||
|
uint32_t tx_comp_loop_pkt_limit;
|
||||||
|
uint32_t rx_reap_loop_pkt_limit;
|
||||||
|
uint32_t rx_hp_oos_update_limit;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -816,7 +816,14 @@ extern QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc,
|
|||||||
void (*callback_fn), void *data);
|
void (*callback_fn), void *data);
|
||||||
|
|
||||||
extern void dp_reo_cmdlist_destroy(struct dp_soc *soc);
|
extern void dp_reo_cmdlist_destroy(struct dp_soc *soc);
|
||||||
extern void dp_reo_status_ring_handler(struct dp_soc *soc);
|
|
||||||
|
/**
|
||||||
|
* dp_reo_status_ring_handler - Handler for REO Status ring
|
||||||
|
* @soc: DP Soc handle
|
||||||
|
*
|
||||||
|
* Returns: Number of descriptors reaped
|
||||||
|
*/
|
||||||
|
uint32_t dp_reo_status_ring_handler(struct dp_soc *soc);
|
||||||
void dp_aggregate_vdev_stats(struct dp_vdev *vdev,
|
void dp_aggregate_vdev_stats(struct dp_vdev *vdev,
|
||||||
struct cdp_vdev_stats *vdev_stats);
|
struct cdp_vdev_stats *vdev_stats);
|
||||||
void dp_rx_tid_stats_cb(struct dp_soc *soc, void *cb_ctxt,
|
void dp_rx_tid_stats_cb(struct dp_soc *soc, void *cb_ctxt,
|
||||||
|
@@ -285,6 +285,7 @@ const int dp_stats_mapping_table[][STATS_TYPE_MAX] = {
|
|||||||
{TXRX_FW_STATS_INVALID, TXRX_REO_QUEUE_STATS},
|
{TXRX_FW_STATS_INVALID, TXRX_REO_QUEUE_STATS},
|
||||||
{TXRX_FW_STATS_INVALID, TXRX_SOC_CFG_PARAMS},
|
{TXRX_FW_STATS_INVALID, TXRX_SOC_CFG_PARAMS},
|
||||||
{TXRX_FW_STATS_INVALID, TXRX_PDEV_CFG_PARAMS},
|
{TXRX_FW_STATS_INVALID, TXRX_PDEV_CFG_PARAMS},
|
||||||
|
{TXRX_FW_STATS_INVALID, TXRX_SOC_INTERRUPT_STATS},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* MCL specific functions */
|
/* MCL specific functions */
|
||||||
@@ -1273,6 +1274,7 @@ void *hif_get_hal_handle(void *hif_handle);
|
|||||||
static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
|
static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
|
||||||
{
|
{
|
||||||
struct dp_intr *int_ctx = (struct dp_intr *)dp_ctx;
|
struct dp_intr *int_ctx = (struct dp_intr *)dp_ctx;
|
||||||
|
struct dp_intr_stats *intr_stats = &int_ctx->intr_stats;
|
||||||
struct dp_soc *soc = int_ctx->soc;
|
struct dp_soc *soc = int_ctx->soc;
|
||||||
int ring = 0;
|
int ring = 0;
|
||||||
uint32_t work_done = 0;
|
uint32_t work_done = 0;
|
||||||
@@ -1286,15 +1288,27 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
|
|||||||
struct dp_pdev *pdev = NULL;
|
struct dp_pdev *pdev = NULL;
|
||||||
int mac_id;
|
int mac_id;
|
||||||
|
|
||||||
|
dp_verbose_debug("tx %x rx %x rx_err %x rx_wbm_rel %x reo_status %x rx_mon_ring %x host2rxdma %x rxdma2host %x\n",
|
||||||
|
tx_mask, rx_mask, rx_err_mask, rx_wbm_rel_mask,
|
||||||
|
reo_status_mask,
|
||||||
|
int_ctx->rx_mon_ring_mask,
|
||||||
|
int_ctx->host2rxdma_ring_mask,
|
||||||
|
int_ctx->rxdma2host_ring_mask);
|
||||||
|
|
||||||
/* Process Tx completion interrupts first to return back buffers */
|
/* Process Tx completion interrupts first to return back buffers */
|
||||||
while (tx_mask) {
|
while (tx_mask) {
|
||||||
if (tx_mask & 0x1) {
|
if (tx_mask & 0x1) {
|
||||||
work_done = dp_tx_comp_handler(soc,
|
work_done = dp_tx_comp_handler(int_ctx,
|
||||||
soc->tx_comp_ring[ring].hal_srng,
|
soc,
|
||||||
remaining_quota);
|
soc->tx_comp_ring[ring].hal_srng,
|
||||||
|
remaining_quota);
|
||||||
|
|
||||||
dp_verbose_debug("tx mask 0x%x ring %d, budget %d, work_done %d",
|
if (work_done) {
|
||||||
tx_mask, ring, budget, work_done);
|
intr_stats->num_tx_ring_masks[ring]++;
|
||||||
|
dp_verbose_debug("tx mask 0x%x ring %d, budget %d, work_done %d",
|
||||||
|
tx_mask, ring, budget,
|
||||||
|
work_done);
|
||||||
|
}
|
||||||
|
|
||||||
budget -= work_done;
|
budget -= work_done;
|
||||||
if (budget <= 0)
|
if (budget <= 0)
|
||||||
@@ -1306,15 +1320,17 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
|
|||||||
ring++;
|
ring++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Process REO Exception ring interrupt */
|
/* Process REO Exception ring interrupt */
|
||||||
if (rx_err_mask) {
|
if (rx_err_mask) {
|
||||||
work_done = dp_rx_err_process(soc,
|
work_done = dp_rx_err_process(soc,
|
||||||
soc->reo_exception_ring.hal_srng,
|
soc->reo_exception_ring.hal_srng,
|
||||||
remaining_quota);
|
remaining_quota);
|
||||||
|
|
||||||
dp_verbose_debug("REO Exception Ring: work_done %d budget %d",
|
if (work_done) {
|
||||||
work_done, budget);
|
intr_stats->num_rx_err_ring_masks++;
|
||||||
|
dp_verbose_debug("REO Exception Ring: work_done %d budget %d",
|
||||||
|
work_done, budget);
|
||||||
|
}
|
||||||
|
|
||||||
budget -= work_done;
|
budget -= work_done;
|
||||||
if (budget <= 0) {
|
if (budget <= 0) {
|
||||||
@@ -1328,8 +1344,11 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
|
|||||||
work_done = dp_rx_wbm_err_process(soc,
|
work_done = dp_rx_wbm_err_process(soc,
|
||||||
soc->rx_rel_ring.hal_srng, remaining_quota);
|
soc->rx_rel_ring.hal_srng, remaining_quota);
|
||||||
|
|
||||||
dp_verbose_debug("WBM Release Ring: work_done %d budget %d",
|
if (work_done) {
|
||||||
work_done, budget);
|
intr_stats->num_rx_wbm_rel_ring_masks++;
|
||||||
|
dp_verbose_debug("WBM Release Ring: work_done %d budget %d",
|
||||||
|
work_done, budget);
|
||||||
|
}
|
||||||
|
|
||||||
budget -= work_done;
|
budget -= work_done;
|
||||||
if (budget <= 0) {
|
if (budget <= 0) {
|
||||||
@@ -1341,16 +1360,17 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
|
|||||||
/* Process Rx interrupts */
|
/* Process Rx interrupts */
|
||||||
if (rx_mask) {
|
if (rx_mask) {
|
||||||
for (ring = 0; ring < soc->num_reo_dest_rings; ring++) {
|
for (ring = 0; ring < soc->num_reo_dest_rings; ring++) {
|
||||||
if (rx_mask & (1 << ring)) {
|
if (!(rx_mask & (1 << ring)))
|
||||||
work_done = dp_rx_process(int_ctx,
|
continue;
|
||||||
soc->reo_dest_ring[ring].hal_srng,
|
work_done = dp_rx_process(int_ctx,
|
||||||
ring,
|
soc->reo_dest_ring[ring].hal_srng,
|
||||||
remaining_quota);
|
ring,
|
||||||
|
remaining_quota);
|
||||||
|
if (work_done) {
|
||||||
|
intr_stats->num_rx_ring_masks[ring]++;
|
||||||
dp_verbose_debug("rx mask 0x%x ring %d, work_done %d budget %d",
|
dp_verbose_debug("rx mask 0x%x ring %d, work_done %d budget %d",
|
||||||
rx_mask, ring,
|
rx_mask, ring,
|
||||||
work_done, budget);
|
work_done, budget);
|
||||||
|
|
||||||
budget -= work_done;
|
budget -= work_done;
|
||||||
if (budget <= 0)
|
if (budget <= 0)
|
||||||
goto budget_done;
|
goto budget_done;
|
||||||
@@ -1359,8 +1379,10 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reo_status_mask)
|
if (reo_status_mask) {
|
||||||
dp_reo_status_ring_handler(soc);
|
if (dp_reo_status_ring_handler(soc))
|
||||||
|
int_ctx->intr_stats.num_reo_status_ring_masks++;
|
||||||
|
}
|
||||||
|
|
||||||
/* Process LMAC interrupts */
|
/* Process LMAC interrupts */
|
||||||
for (ring = 0 ; ring < MAX_PDEV_CNT; ring++) {
|
for (ring = 0 ; ring < MAX_PDEV_CNT; ring++) {
|
||||||
@@ -1372,7 +1394,9 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
|
|||||||
pdev->pdev_id);
|
pdev->pdev_id);
|
||||||
if (int_ctx->rx_mon_ring_mask & (1 << mac_for_pdev)) {
|
if (int_ctx->rx_mon_ring_mask & (1 << mac_for_pdev)) {
|
||||||
work_done = dp_mon_process(soc, mac_for_pdev,
|
work_done = dp_mon_process(soc, mac_for_pdev,
|
||||||
remaining_quota);
|
remaining_quota);
|
||||||
|
if (work_done)
|
||||||
|
intr_stats->num_rx_mon_ring_masks++;
|
||||||
budget -= work_done;
|
budget -= work_done;
|
||||||
if (budget <= 0)
|
if (budget <= 0)
|
||||||
goto budget_done;
|
goto budget_done;
|
||||||
@@ -1382,8 +1406,10 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
|
|||||||
if (int_ctx->rxdma2host_ring_mask &
|
if (int_ctx->rxdma2host_ring_mask &
|
||||||
(1 << mac_for_pdev)) {
|
(1 << mac_for_pdev)) {
|
||||||
work_done = dp_rxdma_err_process(soc,
|
work_done = dp_rxdma_err_process(soc,
|
||||||
mac_for_pdev,
|
mac_for_pdev,
|
||||||
remaining_quota);
|
remaining_quota);
|
||||||
|
if (work_done)
|
||||||
|
intr_stats->num_rxdma2host_ring_masks++;
|
||||||
budget -= work_done;
|
budget -= work_done;
|
||||||
if (budget <= 0)
|
if (budget <= 0)
|
||||||
goto budget_done;
|
goto budget_done;
|
||||||
@@ -1397,17 +1423,19 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
|
|||||||
struct dp_srng *rx_refill_buf_ring =
|
struct dp_srng *rx_refill_buf_ring =
|
||||||
&pdev->rx_refill_buf_ring;
|
&pdev->rx_refill_buf_ring;
|
||||||
|
|
||||||
|
intr_stats->num_host2rxdma_ring_masks++;
|
||||||
DP_STATS_INC(pdev, replenish.low_thresh_intrs,
|
DP_STATS_INC(pdev, replenish.low_thresh_intrs,
|
||||||
1);
|
1);
|
||||||
dp_rx_buffers_replenish(soc, mac_for_pdev,
|
dp_rx_buffers_replenish(soc, mac_for_pdev,
|
||||||
rx_refill_buf_ring,
|
rx_refill_buf_ring,
|
||||||
&soc->rx_desc_buf[mac_for_pdev], 0,
|
&soc->rx_desc_buf[mac_for_pdev],
|
||||||
&desc_list, &tail);
|
0, &desc_list, &tail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qdf_lro_flush(int_ctx->lro_ctx);
|
qdf_lro_flush(int_ctx->lro_ctx);
|
||||||
|
intr_stats->num_masks++;
|
||||||
|
|
||||||
budget_done:
|
budget_done:
|
||||||
return dp_budget - budget;
|
return dp_budget - budget;
|
||||||
@@ -6920,7 +6948,44 @@ dp_print_soc_tx_stats(struct dp_soc *soc)
|
|||||||
soc->stats.tx.tcl_ring_full[2]);
|
soc->stats.tx.tcl_ring_full[2]);
|
||||||
DP_PRINT_STATS("Tx invalid completion release = %d",
|
DP_PRINT_STATS("Tx invalid completion release = %d",
|
||||||
soc->stats.tx.invalid_release_source);
|
soc->stats.tx.invalid_release_source);
|
||||||
|
DP_PRINT_STATS("Tx comp loop pkt limit hit = %d",
|
||||||
|
soc->stats.tx.tx_comp_loop_pkt_limit_hit);
|
||||||
|
DP_PRINT_STATS("Tx comp HP out of sync2 = %d",
|
||||||
|
soc->stats.tx.hp_oos2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dp_print_soc_interrupt_stats() - Print interrupt stats for the soc
|
||||||
|
* @soc: dp_soc handle
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void dp_print_soc_interrupt_stats(struct dp_soc *soc)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
struct dp_intr_stats *intr_stats;
|
||||||
|
|
||||||
|
DP_PRINT_STATS("INT: Total |txComps|reo[0] |reo[1] |reo[2] |reo[3] |mon |rx_err | wbm |reo_sta|rxdm2hst|hst2rxdm|");
|
||||||
|
for (i = 0; i < WLAN_CFG_INT_NUM_CONTEXTS; i++) {
|
||||||
|
intr_stats = &soc->intr_ctx[i].intr_stats;
|
||||||
|
DP_PRINT_STATS("%3u[%d]: %7u %7u %7u %7u %7u %7u %7u %7u %7u %7u %8u %8u",
|
||||||
|
i,
|
||||||
|
hif_get_int_ctx_irq_num(soc->hif_handle, i),
|
||||||
|
intr_stats->num_masks,
|
||||||
|
intr_stats->num_tx_ring_masks[0],
|
||||||
|
intr_stats->num_rx_ring_masks[0],
|
||||||
|
intr_stats->num_rx_ring_masks[1],
|
||||||
|
intr_stats->num_rx_ring_masks[2],
|
||||||
|
intr_stats->num_rx_ring_masks[3],
|
||||||
|
intr_stats->num_rx_mon_ring_masks,
|
||||||
|
intr_stats->num_rx_err_ring_masks,
|
||||||
|
intr_stats->num_rx_wbm_rel_ring_masks,
|
||||||
|
intr_stats->num_reo_status_ring_masks,
|
||||||
|
intr_stats->num_rxdma2host_ring_masks,
|
||||||
|
intr_stats->num_host2rxdma_ring_masks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dp_print_soc_rx_stats: Print SOC level Rx stats
|
* dp_print_soc_rx_stats: Print SOC level Rx stats
|
||||||
* @soc: DP_SOC Handle
|
* @soc: DP_SOC Handle
|
||||||
@@ -6962,7 +7027,11 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
|
|||||||
DP_PRINT_STATS("RX frags: %d", soc->stats.rx.rx_frags);
|
DP_PRINT_STATS("RX frags: %d", soc->stats.rx.rx_frags);
|
||||||
DP_PRINT_STATS("RX frag wait: %d", soc->stats.rx.rx_frag_wait);
|
DP_PRINT_STATS("RX frag wait: %d", soc->stats.rx.rx_frag_wait);
|
||||||
DP_PRINT_STATS("RX frag err: %d", soc->stats.rx.rx_frag_err);
|
DP_PRINT_STATS("RX frag err: %d", soc->stats.rx.rx_frag_err);
|
||||||
DP_PRINT_STATS("RX HP out_of_sync: %d", soc->stats.rx.hp_oos);
|
|
||||||
|
DP_PRINT_STATS("RX HP out_of_sync: %d %d", soc->stats.rx.hp_oos,
|
||||||
|
soc->stats.rx.hp_oos2);
|
||||||
|
DP_PRINT_STATS("RX Reap Loop Pkt Limit Hit: %d",
|
||||||
|
soc->stats.rx.reap_loop_pkt_limit_hit);
|
||||||
DP_PRINT_STATS("RX DESC invalid magic: %u",
|
DP_PRINT_STATS("RX DESC invalid magic: %u",
|
||||||
soc->stats.rx.err.rx_desc_invalid_magic);
|
soc->stats.rx.err.rx_desc_invalid_magic);
|
||||||
DP_PRINT_STATS("RX DUP DESC: %d",
|
DP_PRINT_STATS("RX DUP DESC: %d",
|
||||||
@@ -7211,6 +7280,8 @@ dp_print_host_stats(struct cdp_vdev *vdev_handle,
|
|||||||
break;
|
break;
|
||||||
case TXRX_NAPI_STATS:
|
case TXRX_NAPI_STATS:
|
||||||
dp_print_napi_stats(pdev->soc);
|
dp_print_napi_stats(pdev->soc);
|
||||||
|
case TXRX_SOC_INTERRUPT_STATS:
|
||||||
|
dp_print_soc_interrupt_stats(pdev->soc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dp_info("Wrong Input For TxRx Host Stats");
|
dp_info("Wrong Input For TxRx Host Stats");
|
||||||
@@ -8148,6 +8219,7 @@ static QDF_STATUS dp_txrx_dump_stats(void *psoc, uint16_t value,
|
|||||||
switch (value) {
|
switch (value) {
|
||||||
case CDP_TXRX_PATH_STATS:
|
case CDP_TXRX_PATH_STATS:
|
||||||
dp_txrx_path_stats(soc);
|
dp_txrx_path_stats(soc);
|
||||||
|
dp_print_soc_interrupt_stats(soc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CDP_RX_RING_STATS:
|
case CDP_RX_RING_STATS:
|
||||||
@@ -8205,6 +8277,50 @@ void dp_update_flow_control_parameters(struct dp_soc *soc,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
|
||||||
|
/* Max packet limit for TX Comp packet loop (dp_tx_comp_handler) */
|
||||||
|
#define DP_TX_COMP_LOOP_PKT_LIMIT_MAX 1024
|
||||||
|
|
||||||
|
/* Max packet limit for RX REAP Loop (dp_rx_process) */
|
||||||
|
#define DP_RX_REAP_LOOP_PKT_LIMIT_MAX 1024
|
||||||
|
|
||||||
|
static
|
||||||
|
void dp_update_rx_soft_irq_limit_params(struct dp_soc *soc,
|
||||||
|
struct cdp_config_params *params)
|
||||||
|
{
|
||||||
|
soc->wlan_cfg_ctx->tx_comp_loop_pkt_limit =
|
||||||
|
params->tx_comp_loop_pkt_limit;
|
||||||
|
|
||||||
|
if (params->tx_comp_loop_pkt_limit < DP_TX_COMP_LOOP_PKT_LIMIT_MAX)
|
||||||
|
soc->wlan_cfg_ctx->tx_comp_enable_eol_data_check = true;
|
||||||
|
else
|
||||||
|
soc->wlan_cfg_ctx->tx_comp_enable_eol_data_check = false;
|
||||||
|
|
||||||
|
soc->wlan_cfg_ctx->rx_reap_loop_pkt_limit =
|
||||||
|
params->rx_reap_loop_pkt_limit;
|
||||||
|
|
||||||
|
if (params->rx_reap_loop_pkt_limit < DP_RX_REAP_LOOP_PKT_LIMIT_MAX)
|
||||||
|
soc->wlan_cfg_ctx->rx_enable_eol_data_check = true;
|
||||||
|
else
|
||||||
|
soc->wlan_cfg_ctx->rx_enable_eol_data_check = false;
|
||||||
|
|
||||||
|
soc->wlan_cfg_ctx->rx_hp_oos_update_limit =
|
||||||
|
params->rx_hp_oos_update_limit;
|
||||||
|
|
||||||
|
dp_info("tx_comp_loop_pkt_limit %u tx_comp_enable_eol_data_check %u rx_reap_loop_pkt_limit %u rx_enable_eol_data_check %u rx_hp_oos_update_limit %u",
|
||||||
|
soc->wlan_cfg_ctx->tx_comp_loop_pkt_limit,
|
||||||
|
soc->wlan_cfg_ctx->tx_comp_enable_eol_data_check,
|
||||||
|
soc->wlan_cfg_ctx->rx_reap_loop_pkt_limit,
|
||||||
|
soc->wlan_cfg_ctx->rx_enable_eol_data_check,
|
||||||
|
soc->wlan_cfg_ctx->rx_hp_oos_update_limit);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline
|
||||||
|
void dp_update_rx_soft_irq_limit_params(struct dp_soc *soc,
|
||||||
|
struct cdp_config_params *params)
|
||||||
|
{ }
|
||||||
|
#endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dp_update_config_parameters() - API to store datapath
|
* dp_update_config_parameters() - API to store datapath
|
||||||
* config parameters
|
* config parameters
|
||||||
@@ -8234,6 +8350,7 @@ QDF_STATUS dp_update_config_parameters(struct cdp_soc *psoc,
|
|||||||
soc->wlan_cfg_ctx->ipa_enabled = params->ipa_enable;
|
soc->wlan_cfg_ctx->ipa_enabled = params->ipa_enable;
|
||||||
soc->wlan_cfg_ctx->gro_enabled = params->gro_enable;
|
soc->wlan_cfg_ctx->gro_enabled = params->gro_enable;
|
||||||
|
|
||||||
|
dp_update_rx_soft_irq_limit_params(soc, params);
|
||||||
dp_update_flow_control_parameters(soc, params);
|
dp_update_flow_control_parameters(soc, params);
|
||||||
|
|
||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -85,22 +85,24 @@ QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc, enum hal_reo_cmd_type type,
|
|||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dp_reo_status_ring_handler(struct dp_soc *soc)
|
uint32_t dp_reo_status_ring_handler(struct dp_soc *soc)
|
||||||
{
|
{
|
||||||
uint32_t *reo_desc;
|
uint32_t *reo_desc;
|
||||||
struct dp_reo_cmd_info *reo_cmd = NULL;
|
struct dp_reo_cmd_info *reo_cmd = NULL;
|
||||||
union hal_reo_status reo_status;
|
union hal_reo_status reo_status;
|
||||||
int num;
|
int num;
|
||||||
|
int processed_count = 0;
|
||||||
|
|
||||||
if (hal_srng_access_start(soc->hal_soc,
|
if (hal_srng_access_start(soc->hal_soc,
|
||||||
soc->reo_status_ring.hal_srng)) {
|
soc->reo_status_ring.hal_srng)) {
|
||||||
return;
|
return processed_count;
|
||||||
}
|
}
|
||||||
reo_desc = hal_srng_dst_get_next(soc->hal_soc,
|
reo_desc = hal_srng_dst_get_next(soc->hal_soc,
|
||||||
soc->reo_status_ring.hal_srng);
|
soc->reo_status_ring.hal_srng);
|
||||||
|
|
||||||
while (reo_desc) {
|
while (reo_desc) {
|
||||||
uint16_t tlv = HAL_GET_TLV(reo_desc);
|
uint16_t tlv = HAL_GET_TLV(reo_desc);
|
||||||
|
processed_count++;
|
||||||
|
|
||||||
switch (tlv) {
|
switch (tlv) {
|
||||||
case HAL_REO_QUEUE_STATS_STATUS_TLV:
|
case HAL_REO_QUEUE_STATS_STATUS_TLV:
|
||||||
@@ -173,6 +175,7 @@ next:
|
|||||||
} /* while */
|
} /* while */
|
||||||
|
|
||||||
hal_srng_access_end(soc->hal_soc, soc->reo_status_ring.hal_srng);
|
hal_srng_access_end(soc->hal_soc, soc->reo_status_ring.hal_srng);
|
||||||
|
return processed_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1619,6 +1619,57 @@ static inline void dp_rx_desc_nbuf_sanity_check(void *ring_desc,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
|
||||||
|
static inline
|
||||||
|
bool dp_rx_reap_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped)
|
||||||
|
{
|
||||||
|
bool limit_hit = false;
|
||||||
|
struct wlan_cfg_dp_soc_ctxt *cfg = soc->wlan_cfg_ctx;
|
||||||
|
|
||||||
|
limit_hit =
|
||||||
|
(num_reaped >= cfg->rx_reap_loop_pkt_limit) ? true : false;
|
||||||
|
|
||||||
|
if (limit_hit)
|
||||||
|
DP_STATS_INC(soc, rx.reap_loop_pkt_limit_hit, 1)
|
||||||
|
|
||||||
|
return limit_hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
bool dp_rx_hp_oos_update_limit_hit(struct dp_soc *soc, int hp_oos_updates)
|
||||||
|
{
|
||||||
|
bool limit_hit = false;
|
||||||
|
struct wlan_cfg_dp_soc_ctxt *cfg = soc->wlan_cfg_ctx;
|
||||||
|
|
||||||
|
limit_hit =
|
||||||
|
(hp_oos_updates >= cfg->rx_hp_oos_update_limit) ? true : false;
|
||||||
|
return limit_hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool dp_rx_enable_eol_data_check(struct dp_soc *soc)
|
||||||
|
{
|
||||||
|
return soc->wlan_cfg_ctx->rx_enable_eol_data_check;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static inline
|
||||||
|
bool dp_rx_reap_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
bool dp_rx_hp_oos_update_limit_hit(struct dp_soc *soc, int hp_oos_updates)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool dp_rx_enable_eol_data_check(struct dp_soc *soc)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */
|
||||||
/**
|
/**
|
||||||
* dp_rx_process() - Brain of the Rx processing functionality
|
* dp_rx_process() - Brain of the Rx processing functionality
|
||||||
* Called from the bottom half (tasklet/NET_RX_SOFTIRQ)
|
* Called from the bottom half (tasklet/NET_RX_SOFTIRQ)
|
||||||
@@ -1639,21 +1690,21 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring,
|
|||||||
void *ring_desc;
|
void *ring_desc;
|
||||||
struct dp_rx_desc *rx_desc = NULL;
|
struct dp_rx_desc *rx_desc = NULL;
|
||||||
qdf_nbuf_t nbuf, next;
|
qdf_nbuf_t nbuf, next;
|
||||||
union dp_rx_desc_list_elem_t *head[MAX_PDEV_CNT] = { NULL };
|
union dp_rx_desc_list_elem_t *head[MAX_PDEV_CNT];
|
||||||
union dp_rx_desc_list_elem_t *tail[MAX_PDEV_CNT] = { NULL };
|
union dp_rx_desc_list_elem_t *tail[MAX_PDEV_CNT];
|
||||||
uint32_t rx_bufs_used = 0, rx_buf_cookie;
|
uint32_t rx_bufs_used = 0, rx_buf_cookie;
|
||||||
uint32_t l2_hdr_offset = 0;
|
uint32_t l2_hdr_offset = 0;
|
||||||
uint16_t msdu_len = 0;
|
uint16_t msdu_len = 0;
|
||||||
uint16_t peer_id;
|
uint16_t peer_id;
|
||||||
struct dp_peer *peer = NULL;
|
struct dp_peer *peer;
|
||||||
struct dp_vdev *vdev = NULL;
|
struct dp_vdev *vdev;
|
||||||
uint32_t pkt_len = 0;
|
uint32_t pkt_len = 0;
|
||||||
struct hal_rx_mpdu_desc_info mpdu_desc_info = { 0 };
|
struct hal_rx_mpdu_desc_info mpdu_desc_info;
|
||||||
struct hal_rx_msdu_desc_info msdu_desc_info = { 0 };
|
struct hal_rx_msdu_desc_info msdu_desc_info;
|
||||||
enum hal_reo_error_status error;
|
enum hal_reo_error_status error;
|
||||||
uint32_t peer_mdata;
|
uint32_t peer_mdata;
|
||||||
uint8_t *rx_tlv_hdr;
|
uint8_t *rx_tlv_hdr;
|
||||||
uint32_t rx_bufs_reaped[MAX_PDEV_CNT] = { 0 };
|
uint32_t rx_bufs_reaped[MAX_PDEV_CNT];
|
||||||
uint8_t mac_id = 0;
|
uint8_t mac_id = 0;
|
||||||
struct dp_pdev *pdev;
|
struct dp_pdev *pdev;
|
||||||
struct dp_pdev *rx_pdev;
|
struct dp_pdev *rx_pdev;
|
||||||
@@ -1662,24 +1713,41 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring,
|
|||||||
struct dp_soc *soc = int_ctx->soc;
|
struct dp_soc *soc = int_ctx->soc;
|
||||||
uint8_t ring_id = 0;
|
uint8_t ring_id = 0;
|
||||||
uint8_t core_id = 0;
|
uint8_t core_id = 0;
|
||||||
qdf_nbuf_t nbuf_head = NULL;
|
|
||||||
qdf_nbuf_t nbuf_tail = NULL;
|
|
||||||
qdf_nbuf_t deliver_list_head = NULL;
|
|
||||||
qdf_nbuf_t deliver_list_tail = NULL;
|
|
||||||
int32_t tid = 0;
|
|
||||||
uint32_t dst_num_valid = 0;
|
|
||||||
struct cdp_tid_rx_stats *tid_stats;
|
struct cdp_tid_rx_stats *tid_stats;
|
||||||
|
qdf_nbuf_t nbuf_head;
|
||||||
|
qdf_nbuf_t nbuf_tail;
|
||||||
|
qdf_nbuf_t deliver_list_head;
|
||||||
|
qdf_nbuf_t deliver_list_tail;
|
||||||
|
uint32_t num_rx_bufs_reaped = 0;
|
||||||
|
uint32_t intr_id;
|
||||||
|
struct hif_opaque_softc *scn;
|
||||||
|
uint32_t hp_oos_updates = 0;
|
||||||
|
int32_t tid = 0;
|
||||||
DP_HIST_INIT();
|
DP_HIST_INIT();
|
||||||
/* Debug -- Remove later */
|
|
||||||
qdf_assert(soc && hal_ring);
|
|
||||||
|
|
||||||
|
qdf_assert_always(soc && hal_ring);
|
||||||
hal_soc = soc->hal_soc;
|
hal_soc = soc->hal_soc;
|
||||||
|
qdf_assert_always(hal_soc);
|
||||||
/* Debug -- Remove later */
|
|
||||||
qdf_assert(hal_soc);
|
|
||||||
|
|
||||||
hif_pm_runtime_mark_last_busy(soc->osdev->dev);
|
hif_pm_runtime_mark_last_busy(soc->osdev->dev);
|
||||||
|
scn = soc->hif_handle;
|
||||||
|
intr_id = int_ctx->dp_intr_id;
|
||||||
|
|
||||||
|
more_data:
|
||||||
|
/* reset local variables here to be re-used in the function */
|
||||||
|
nbuf_head = NULL;
|
||||||
|
nbuf_tail = NULL;
|
||||||
|
deliver_list_head = NULL;
|
||||||
|
deliver_list_tail = NULL;
|
||||||
|
peer = NULL;
|
||||||
|
vdev = NULL;
|
||||||
|
num_rx_bufs_reaped = 0;
|
||||||
|
|
||||||
|
qdf_mem_zero(rx_bufs_reaped, sizeof(rx_bufs_reaped));
|
||||||
|
qdf_mem_zero(&mpdu_desc_info, sizeof(mpdu_desc_info));
|
||||||
|
qdf_mem_zero(&msdu_desc_info, sizeof(msdu_desc_info));
|
||||||
|
qdf_mem_zero(head, sizeof(head));
|
||||||
|
qdf_mem_zero(tail, sizeof(tail));
|
||||||
|
|
||||||
if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_ring))) {
|
if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_ring))) {
|
||||||
|
|
||||||
@@ -1699,6 +1767,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring,
|
|||||||
* them in per vdev queue.
|
* them in per vdev queue.
|
||||||
* Process the received pkts in a different per vdev loop.
|
* Process the received pkts in a different per vdev loop.
|
||||||
*/
|
*/
|
||||||
|
hp_oos_updates = 0;
|
||||||
while (qdf_likely(quota)) {
|
while (qdf_likely(quota)) {
|
||||||
ring_desc = hal_srng_dst_get_next(hal_soc, hal_ring);
|
ring_desc = hal_srng_dst_get_next(hal_soc, hal_ring);
|
||||||
|
|
||||||
@@ -1716,10 +1785,12 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring,
|
|||||||
* complete mpdu in one reap.
|
* complete mpdu in one reap.
|
||||||
*/
|
*/
|
||||||
if (qdf_unlikely(!ring_desc)) {
|
if (qdf_unlikely(!ring_desc)) {
|
||||||
dst_num_valid = hal_srng_dst_num_valid(hal_soc,
|
if (dp_rx_hp_oos_update_limit_hit(soc,
|
||||||
hal_ring,
|
hp_oos_updates)) {
|
||||||
true);
|
break;
|
||||||
if (dst_num_valid) {
|
}
|
||||||
|
hp_oos_updates++;
|
||||||
|
if (hal_srng_dst_peek_sync(hal_soc, hal_ring)) {
|
||||||
DP_STATS_INC(soc, rx.hp_oos, 1);
|
DP_STATS_INC(soc, rx.hp_oos, 1);
|
||||||
hal_srng_access_end_unlocked(hal_soc,
|
hal_srng_access_end_unlocked(hal_soc,
|
||||||
hal_ring);
|
hal_ring);
|
||||||
@@ -1834,6 +1905,10 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring,
|
|||||||
dp_rx_add_to_free_desc_list(&head[rx_desc->pool_id],
|
dp_rx_add_to_free_desc_list(&head[rx_desc->pool_id],
|
||||||
&tail[rx_desc->pool_id],
|
&tail[rx_desc->pool_id],
|
||||||
rx_desc);
|
rx_desc);
|
||||||
|
|
||||||
|
num_rx_bufs_reaped++;
|
||||||
|
if (dp_rx_reap_loop_pkt_limit_hit(soc, num_rx_bufs_reaped))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
hal_srng_access_end(hal_soc, hal_ring);
|
hal_srng_access_end(hal_soc, hal_ring);
|
||||||
@@ -1858,6 +1933,7 @@ done:
|
|||||||
&head[mac_id], &tail[mac_id]);
|
&head[mac_id], &tail[mac_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dp_verbose_debug("replenished %u\n", rx_bufs_reaped[0]);
|
||||||
/* Peer can be NULL is case of LFR */
|
/* Peer can be NULL is case of LFR */
|
||||||
if (qdf_likely(peer))
|
if (qdf_likely(peer))
|
||||||
vdev = NULL;
|
vdev = NULL;
|
||||||
@@ -2069,16 +2145,6 @@ done:
|
|||||||
dp_rx_fill_mesh_stats(vdev, nbuf, rx_tlv_hdr, peer);
|
dp_rx_fill_mesh_stats(vdev, nbuf, rx_tlv_hdr, peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef QCA_WIFI_NAPIER_EMULATION_DBG /* Debug code, remove later */
|
|
||||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
|
||||||
"p_id %d msdu_len %d hdr_off %d",
|
|
||||||
peer_id, msdu_len, l2_hdr_offset);
|
|
||||||
|
|
||||||
print_hex_dump(KERN_ERR,
|
|
||||||
"\t Pkt Data:", DUMP_PREFIX_NONE, 32, 4,
|
|
||||||
qdf_nbuf_data(nbuf), 128, false);
|
|
||||||
#endif /* NAPIER_EMULATION */
|
|
||||||
|
|
||||||
if (qdf_likely(vdev->rx_decap_type ==
|
if (qdf_likely(vdev->rx_decap_type ==
|
||||||
htt_cmn_pkt_type_ethernet) &&
|
htt_cmn_pkt_type_ethernet) &&
|
||||||
qdf_likely(!vdev->mesh_vdev)) {
|
qdf_likely(!vdev->mesh_vdev)) {
|
||||||
@@ -2133,13 +2199,21 @@ done:
|
|||||||
dp_peer_unref_del_find_by_id(peer);
|
dp_peer_unref_del_find_by_id(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update histogram statistics by looping through pdev's */
|
|
||||||
DP_RX_HIST_STATS_PER_PDEV();
|
|
||||||
|
|
||||||
if (deliver_list_head)
|
if (deliver_list_head)
|
||||||
dp_rx_deliver_to_stack(vdev, peer, deliver_list_head,
|
dp_rx_deliver_to_stack(vdev, peer, deliver_list_head,
|
||||||
deliver_list_tail);
|
deliver_list_tail);
|
||||||
|
|
||||||
|
if (dp_rx_enable_eol_data_check(soc)) {
|
||||||
|
if (quota &&
|
||||||
|
hal_srng_dst_peek_sync_locked(soc, hal_ring)) {
|
||||||
|
DP_STATS_INC(soc, rx.hp_oos2, 1);
|
||||||
|
if (!hif_exec_should_yield(scn, intr_id))
|
||||||
|
goto more_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Update histogram statistics by looping through pdev's */
|
||||||
|
DP_RX_HIST_STATS_PER_PDEV();
|
||||||
|
|
||||||
return rx_bufs_used; /* Assume no scale factor for now */
|
return rx_bufs_used; /* Assume no scale factor for now */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3205,7 +3205,6 @@ dp_tx_comp_process_desc_list(struct dp_soc *soc,
|
|||||||
struct dp_peer *peer;
|
struct dp_peer *peer;
|
||||||
qdf_nbuf_t netbuf;
|
qdf_nbuf_t netbuf;
|
||||||
|
|
||||||
DP_HIST_INIT();
|
|
||||||
desc = comp_head;
|
desc = comp_head;
|
||||||
|
|
||||||
while (desc) {
|
while (desc) {
|
||||||
@@ -3223,15 +3222,12 @@ dp_tx_comp_process_desc_list(struct dp_soc *soc,
|
|||||||
if (peer)
|
if (peer)
|
||||||
dp_peer_unref_del_find_by_id(peer);
|
dp_peer_unref_del_find_by_id(peer);
|
||||||
|
|
||||||
DP_HIST_PACKET_COUNT_INC(desc->pdev->pdev_id);
|
|
||||||
|
|
||||||
next = desc->next;
|
next = desc->next;
|
||||||
|
|
||||||
dp_tx_desc_release(desc, desc->pool_id);
|
dp_tx_desc_release(desc, desc->pool_id);
|
||||||
desc = next;
|
desc = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
DP_TX_HIST_STATS_PER_PDEV();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3342,19 +3338,41 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
|
||||||
* dp_tx_comp_handler() - Tx completion handler
|
static inline
|
||||||
* @soc: core txrx main context
|
bool dp_tx_comp_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped)
|
||||||
* @ring_id: completion ring id
|
{
|
||||||
* @quota: No. of packets/descriptors that can be serviced in one loop
|
bool limit_hit = false;
|
||||||
*
|
struct wlan_cfg_dp_soc_ctxt *cfg = soc->wlan_cfg_ctx;
|
||||||
* This function will collect hardware release ring element contents and
|
|
||||||
* handle descriptor contents. Based on contents, free packet or handle error
|
limit_hit =
|
||||||
* conditions
|
(num_reaped >= cfg->tx_comp_loop_pkt_limit) ? true : false;
|
||||||
*
|
|
||||||
* Return: none
|
if (limit_hit)
|
||||||
*/
|
DP_STATS_INC(soc, tx.tx_comp_loop_pkt_limit_hit, 1);
|
||||||
uint32_t dp_tx_comp_handler(struct dp_soc *soc, void *hal_srng, uint32_t quota)
|
|
||||||
|
return limit_hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool dp_tx_comp_enable_eol_data_check(struct dp_soc *soc)
|
||||||
|
{
|
||||||
|
return soc->wlan_cfg_ctx->tx_comp_enable_eol_data_check;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline
|
||||||
|
bool dp_tx_comp_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool dp_tx_comp_enable_eol_data_check(struct dp_soc *soc)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc,
|
||||||
|
void *hal_srng, uint32_t quota)
|
||||||
{
|
{
|
||||||
void *tx_comp_hal_desc;
|
void *tx_comp_hal_desc;
|
||||||
uint8_t buffer_src;
|
uint8_t buffer_src;
|
||||||
@@ -3363,9 +3381,16 @@ uint32_t dp_tx_comp_handler(struct dp_soc *soc, void *hal_srng, uint32_t quota)
|
|||||||
struct dp_tx_desc_s *tx_desc = NULL;
|
struct dp_tx_desc_s *tx_desc = NULL;
|
||||||
struct dp_tx_desc_s *head_desc = NULL;
|
struct dp_tx_desc_s *head_desc = NULL;
|
||||||
struct dp_tx_desc_s *tail_desc = NULL;
|
struct dp_tx_desc_s *tail_desc = NULL;
|
||||||
uint32_t num_processed;
|
uint32_t num_processed = 0;
|
||||||
uint32_t count;
|
uint32_t count = 0;
|
||||||
|
bool force_break = false;
|
||||||
|
|
||||||
|
DP_HIST_INIT();
|
||||||
|
|
||||||
|
more_data:
|
||||||
|
/* Re-initialize local variables to be re-used */
|
||||||
|
head_desc = NULL;
|
||||||
|
tail_desc = NULL;
|
||||||
if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) {
|
if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) {
|
||||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||||
"%s %d : HAL RING Access Failed -- %pK",
|
"%s %d : HAL RING Access Failed -- %pK",
|
||||||
@@ -3373,9 +3398,6 @@ uint32_t dp_tx_comp_handler(struct dp_soc *soc, void *hal_srng, uint32_t quota)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_processed = 0;
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
/* Find head descriptor from completion ring */
|
/* Find head descriptor from completion ring */
|
||||||
while (qdf_likely(tx_comp_hal_desc =
|
while (qdf_likely(tx_comp_hal_desc =
|
||||||
hal_srng_dst_get_next(soc->hal_soc, hal_srng))) {
|
hal_srng_dst_get_next(soc->hal_soc, hal_srng))) {
|
||||||
@@ -3466,6 +3488,8 @@ uint32_t dp_tx_comp_handler(struct dp_soc *soc, void *hal_srng, uint32_t quota)
|
|||||||
tx_desc->next = NULL;
|
tx_desc->next = NULL;
|
||||||
tail_desc = tx_desc;
|
tail_desc = tx_desc;
|
||||||
|
|
||||||
|
DP_HIST_PACKET_COUNT_INC(tx_desc->pdev->pdev_id);
|
||||||
|
|
||||||
/* Collect hw completion contents */
|
/* Collect hw completion contents */
|
||||||
hal_tx_comp_desc_sync(tx_comp_hal_desc,
|
hal_tx_comp_desc_sync(tx_comp_hal_desc,
|
||||||
&tx_desc->comp, 1);
|
&tx_desc->comp, 1);
|
||||||
@@ -3478,10 +3502,15 @@ uint32_t dp_tx_comp_handler(struct dp_soc *soc, void *hal_srng, uint32_t quota)
|
|||||||
* Processed packet count is more than given quota
|
* Processed packet count is more than given quota
|
||||||
* stop to processing
|
* stop to processing
|
||||||
*/
|
*/
|
||||||
if ((num_processed >= quota))
|
if (num_processed >= quota) {
|
||||||
|
force_break = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
if (dp_tx_comp_loop_pkt_limit_hit(soc, count))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
hal_srng_access_end(soc->hal_soc, hal_srng);
|
hal_srng_access_end(soc->hal_soc, hal_srng);
|
||||||
@@ -3490,6 +3519,17 @@ uint32_t dp_tx_comp_handler(struct dp_soc *soc, void *hal_srng, uint32_t quota)
|
|||||||
if (head_desc)
|
if (head_desc)
|
||||||
dp_tx_comp_process_desc_list(soc, head_desc);
|
dp_tx_comp_process_desc_list(soc, head_desc);
|
||||||
|
|
||||||
|
if (dp_tx_comp_enable_eol_data_check(soc)) {
|
||||||
|
if (!force_break &&
|
||||||
|
hal_srng_dst_peek_sync_locked(soc, hal_srng)) {
|
||||||
|
DP_STATS_INC(soc, tx.hp_oos2, 1);
|
||||||
|
if (!hif_exec_should_yield(soc->hif_handle,
|
||||||
|
int_ctx->dp_intr_id))
|
||||||
|
goto more_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DP_TX_HIST_STATS_PER_PDEV();
|
||||||
|
|
||||||
return num_processed;
|
return num_processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -177,7 +177,21 @@ qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle,
|
|||||||
enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list);
|
enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t dp_tx_comp_handler(struct dp_soc *soc, void *hal_srng, uint32_t quota);
|
/**
|
||||||
|
* dp_tx_comp_handler() - Tx completion handler
|
||||||
|
* @int_ctx: pointer to DP interrupt context
|
||||||
|
* @soc: core txrx main context
|
||||||
|
* @ring_id: completion ring id
|
||||||
|
* @quota: No. of packets/descriptors that can be serviced in one loop
|
||||||
|
*
|
||||||
|
* This function will collect hardware release ring element contents and
|
||||||
|
* handle descriptor contents. Based on contents, free packet or handle error
|
||||||
|
* conditions
|
||||||
|
*
|
||||||
|
* Return: Number of TX completions processed
|
||||||
|
*/
|
||||||
|
uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc,
|
||||||
|
void *hal_srng, uint32_t quota);
|
||||||
|
|
||||||
QDF_STATUS
|
QDF_STATUS
|
||||||
dp_tx_prepare_send_me(struct dp_vdev *vdev, qdf_nbuf_t nbuf);
|
dp_tx_prepare_send_me(struct dp_vdev *vdev, qdf_nbuf_t nbuf);
|
||||||
|
@@ -576,6 +576,34 @@ struct dp_rx_tid {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct dp_intr_stats - DP Interrupt Stats for an interrupt context
|
||||||
|
* @num_tx_ring_masks: interrupts with tx_ring_mask set
|
||||||
|
* @num_rx_ring_masks: interrupts with rx_ring_mask set
|
||||||
|
* @num_rx_mon_ring_masks: interrupts with rx_mon_ring_mask set
|
||||||
|
* @num_rx_err_ring_masks: interrupts with rx_err_ring_mask set
|
||||||
|
* @num_rx_wbm_rel_ring_masks: interrupts with rx_wbm_rel_ring_mask set
|
||||||
|
* @num_reo_status_ring_masks: interrupts with reo_status_ring_mask set
|
||||||
|
* @num_rxdma2host_ring_masks: interrupts with rxdma2host_ring_mask set
|
||||||
|
* @num_host2rxdma_ring_masks: interrupts with host2rxdma_ring_mask set
|
||||||
|
* @num_host2rxdma_ring_masks: interrupts with host2rxdma_ring_mask set
|
||||||
|
* @num_masks: total number of times the interrupt was received
|
||||||
|
*
|
||||||
|
* Counter for individual masks are incremented only if there are any packets
|
||||||
|
* on that ring.
|
||||||
|
*/
|
||||||
|
struct dp_intr_stats {
|
||||||
|
uint32_t num_tx_ring_masks[MAX_TCL_DATA_RINGS];
|
||||||
|
uint32_t num_rx_ring_masks[MAX_REO_DEST_RINGS];
|
||||||
|
uint32_t num_rx_mon_ring_masks;
|
||||||
|
uint32_t num_rx_err_ring_masks;
|
||||||
|
uint32_t num_rx_wbm_rel_ring_masks;
|
||||||
|
uint32_t num_reo_status_ring_masks;
|
||||||
|
uint32_t num_rxdma2host_ring_masks;
|
||||||
|
uint32_t num_host2rxdma_ring_masks;
|
||||||
|
uint32_t num_masks;
|
||||||
|
};
|
||||||
|
|
||||||
/* per interrupt context */
|
/* per interrupt context */
|
||||||
struct dp_intr {
|
struct dp_intr {
|
||||||
uint8_t tx_ring_mask; /* WBM Tx completion rings (0-2)
|
uint8_t tx_ring_mask; /* WBM Tx completion rings (0-2)
|
||||||
@@ -594,6 +622,9 @@ struct dp_intr {
|
|||||||
to get DMA ring handles */
|
to get DMA ring handles */
|
||||||
qdf_lro_ctx_t lro_ctx;
|
qdf_lro_ctx_t lro_ctx;
|
||||||
uint8_t dp_intr_id;
|
uint8_t dp_intr_id;
|
||||||
|
|
||||||
|
/* Interrupt Stats for individual masks */
|
||||||
|
struct dp_intr_stats intr_stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define REO_DESC_FREELIST_SIZE 64
|
#define REO_DESC_FREELIST_SIZE 64
|
||||||
@@ -624,6 +655,10 @@ struct dp_soc_stats {
|
|||||||
uint32_t dropped_fw_removed;
|
uint32_t dropped_fw_removed;
|
||||||
/* tx completion release_src != TQM or FW */
|
/* tx completion release_src != TQM or FW */
|
||||||
uint32_t invalid_release_source;
|
uint32_t invalid_release_source;
|
||||||
|
/* TX Comp loop packet limit hit */
|
||||||
|
uint32_t tx_comp_loop_pkt_limit_hit;
|
||||||
|
/* Head pointer Out of sync at the end of dp_tx_comp_handler */
|
||||||
|
uint32_t hp_oos2;
|
||||||
} tx;
|
} tx;
|
||||||
|
|
||||||
/* SOC level RX stats */
|
/* SOC level RX stats */
|
||||||
@@ -639,8 +674,13 @@ struct dp_soc_stats {
|
|||||||
uint32_t rx_frag_err;
|
uint32_t rx_frag_err;
|
||||||
/* No of reinjected packets */
|
/* No of reinjected packets */
|
||||||
uint32_t reo_reinject;
|
uint32_t reo_reinject;
|
||||||
/* Head pointer Out of sync */
|
|
||||||
|
/* Reap loop packet limit hit */
|
||||||
|
uint32_t reap_loop_pkt_limit_hit;
|
||||||
|
/* Head pointer Out of sync during reap loop*/
|
||||||
uint32_t hp_oos;
|
uint32_t hp_oos;
|
||||||
|
/* Head pointer Out of sync at the end of dp_rx_process */
|
||||||
|
uint32_t hp_oos2;
|
||||||
struct {
|
struct {
|
||||||
/* Invalid RBM error count */
|
/* Invalid RBM error count */
|
||||||
uint32_t invalid_rbm;
|
uint32_t invalid_rbm;
|
||||||
|
@@ -628,26 +628,79 @@ static inline void *hal_srng_dst_get_next_hp(void *hal_soc, void *hal_ring)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hal_srng_dst_peek - Get next entry from a ring without moving tail pointer.
|
* hal_srng_dst_peek - Check if there are any entries in the ring (peek)
|
||||||
* hal_srng_dst_get_next should be called subsequently to move the tail pointer
|
|
||||||
* TODO: See if we need an optimized version of get_next that doesn't check for
|
|
||||||
* loop_cnt
|
|
||||||
*
|
|
||||||
* @hal_soc: Opaque HAL SOC handle
|
* @hal_soc: Opaque HAL SOC handle
|
||||||
* @hal_ring: Destination ring pointer
|
* @hal_ring: Destination ring pointer
|
||||||
*
|
*
|
||||||
|
* Caller takes responsibility for any locking needs.
|
||||||
|
*
|
||||||
* Return: Opaque pointer for next ring entry; NULL on failire
|
* Return: Opaque pointer for next ring entry; NULL on failire
|
||||||
*/
|
*/
|
||||||
static inline void *hal_srng_dst_peek(void *hal_soc, void *hal_ring)
|
static inline
|
||||||
|
void *hal_srng_dst_peek(void *hal_soc, void *hal_ring)
|
||||||
{
|
{
|
||||||
struct hal_srng *srng = (struct hal_srng *)hal_ring;
|
struct hal_srng *srng = (struct hal_srng *)hal_ring;
|
||||||
|
|
||||||
|
if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp)
|
||||||
|
return (void *)(&srng->ring_base_vaddr[srng->u.dst_ring.tp]);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hal_srng_dst_peek_sync - Check if there are any entries in the ring (peek)
|
||||||
|
* @hal_soc: Opaque HAL SOC handle
|
||||||
|
* @hal_ring: Destination ring pointer
|
||||||
|
*
|
||||||
|
* Sync cached head pointer with HW.
|
||||||
|
* Caller takes responsibility for any locking needs.
|
||||||
|
*
|
||||||
|
* Return: Opaque pointer for next ring entry; NULL on failire
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
void *hal_srng_dst_peek_sync(void *hal_soc, void *hal_ring)
|
||||||
|
{
|
||||||
|
struct hal_srng *srng = (struct hal_srng *)hal_ring;
|
||||||
|
|
||||||
|
srng->u.dst_ring.cached_hp =
|
||||||
|
*(volatile uint32_t *)(srng->u.dst_ring.hp_addr);
|
||||||
|
|
||||||
if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp)
|
if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp)
|
||||||
return (void *)(&(srng->ring_base_vaddr[srng->u.dst_ring.tp]));
|
return (void *)(&(srng->ring_base_vaddr[srng->u.dst_ring.tp]));
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hal_srng_dst_peek_sync_locked - Peek for any entries in the ring
|
||||||
|
* @hal_soc: Opaque HAL SOC handle
|
||||||
|
* @hal_ring: Destination ring pointer
|
||||||
|
*
|
||||||
|
* Sync cached head pointer with HW.
|
||||||
|
* This function takes up SRNG_LOCK. Should not be called with SRNG lock held.
|
||||||
|
*
|
||||||
|
* Return: Opaque pointer for next ring entry; NULL on failire
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
void *hal_srng_dst_peek_sync_locked(void *hal_soc, void *hal_ring)
|
||||||
|
{
|
||||||
|
struct hal_srng *srng = (struct hal_srng *)hal_ring;
|
||||||
|
void *ring_desc_ptr = NULL;
|
||||||
|
|
||||||
|
if (qdf_unlikely(!hal_ring)) {
|
||||||
|
qdf_print("Error: Invalid hal_ring\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRNG_LOCK(&srng->lock);
|
||||||
|
|
||||||
|
ring_desc_ptr = hal_srng_dst_peek_sync(hal_soc, hal_ring);
|
||||||
|
|
||||||
|
SRNG_UNLOCK(&srng->lock);
|
||||||
|
|
||||||
|
return ring_desc_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hal_srng_dst_num_valid - Returns number of valid entries (to be processed
|
* hal_srng_dst_num_valid - Returns number of valid entries (to be processed
|
||||||
* by SW) in destination ring
|
* by SW) in destination ring
|
||||||
|
@@ -147,6 +147,7 @@ struct CE_state;
|
|||||||
* but this does not change the number of buckets
|
* but this does not change the number of buckets
|
||||||
*/
|
*/
|
||||||
#define QCA_NAPI_NUM_BUCKETS 4
|
#define QCA_NAPI_NUM_BUCKETS 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qca_napi_stat - stats structure for execution contexts
|
* qca_napi_stat - stats structure for execution contexts
|
||||||
* @napi_schedules - number of times the schedule function is called
|
* @napi_schedules - number of times the schedule function is called
|
||||||
@@ -158,8 +159,8 @@ struct CE_state;
|
|||||||
* @napi_budget_uses - histogram of work done per execution run
|
* @napi_budget_uses - histogram of work done per execution run
|
||||||
* @time_limit_reache - count of yields due to time limit threshholds
|
* @time_limit_reache - count of yields due to time limit threshholds
|
||||||
* @rxpkt_thresh_reached - count of yields due to a work limit
|
* @rxpkt_thresh_reached - count of yields due to a work limit
|
||||||
|
* @poll_time_buckets - histogram of poll times for the napi
|
||||||
*
|
*
|
||||||
* needs to be renamed
|
|
||||||
*/
|
*/
|
||||||
struct qca_napi_stat {
|
struct qca_napi_stat {
|
||||||
uint32_t napi_schedules;
|
uint32_t napi_schedules;
|
||||||
@@ -171,6 +172,9 @@ struct qca_napi_stat {
|
|||||||
uint32_t time_limit_reached;
|
uint32_t time_limit_reached;
|
||||||
uint32_t rxpkt_thresh_reached;
|
uint32_t rxpkt_thresh_reached;
|
||||||
unsigned long long napi_max_poll_time;
|
unsigned long long napi_max_poll_time;
|
||||||
|
#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
|
||||||
|
uint32_t poll_time_buckets[QCA_NAPI_NUM_BUCKETS];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -275,10 +279,13 @@ struct qca_napi_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct hif_config_info - Place Holder for hif confiruation
|
* struct hif_config_info - Place Holder for HIF configuration
|
||||||
* @enable_self_recovery: Self Recovery
|
* @enable_self_recovery: Self Recovery
|
||||||
|
* @enable_runtime_pm: Enable Runtime PM
|
||||||
|
* @runtime_pm_delay: Runtime PM Delay
|
||||||
|
* @rx_softirq_max_yield_duration_ns: Max Yield time duration for RX Softirq
|
||||||
*
|
*
|
||||||
* Structure for holding hif ini parameters.
|
* Structure for holding HIF ini parameters.
|
||||||
*/
|
*/
|
||||||
struct hif_config_info {
|
struct hif_config_info {
|
||||||
bool enable_self_recovery;
|
bool enable_self_recovery;
|
||||||
@@ -286,6 +293,7 @@ struct hif_config_info {
|
|||||||
bool enable_runtime_pm;
|
bool enable_runtime_pm;
|
||||||
u_int32_t runtime_pm_delay;
|
u_int32_t runtime_pm_delay;
|
||||||
#endif
|
#endif
|
||||||
|
uint64_t rx_softirq_max_yield_duration_ns;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -697,6 +705,27 @@ void hif_offld_flush_cb_register(struct hif_opaque_softc *scn,
|
|||||||
void hif_offld_flush_cb_deregister(struct hif_opaque_softc *scn);
|
void hif_offld_flush_cb_deregister(struct hif_opaque_softc *scn);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
|
||||||
|
/**
|
||||||
|
* hif_exec_should_yield() - Check if hif napi context should yield
|
||||||
|
* @hif_ctx - HIF opaque context
|
||||||
|
* @grp_id - grp_id of the napi for which check needs to be done
|
||||||
|
*
|
||||||
|
* The function uses grp_id to look for NAPI and checks if NAPI needs to
|
||||||
|
* yield. HIF_EXT_GROUP_MAX_YIELD_DURATION_NS is the duration used for
|
||||||
|
* yield decision.
|
||||||
|
*
|
||||||
|
* Return: true if NAPI needs to yield, else false
|
||||||
|
*/
|
||||||
|
bool hif_exec_should_yield(struct hif_opaque_softc *hif_ctx, uint grp_id);
|
||||||
|
#else
|
||||||
|
static inline bool hif_exec_should_yield(struct hif_opaque_softc *hif_ctx,
|
||||||
|
uint grp_id)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void hif_disable_isr(struct hif_opaque_softc *hif_ctx);
|
void hif_disable_isr(struct hif_opaque_softc *hif_ctx);
|
||||||
void hif_reset_soc(struct hif_opaque_softc *hif_ctx);
|
void hif_reset_soc(struct hif_opaque_softc *hif_ctx);
|
||||||
void hif_save_htc_htt_config_endpoint(struct hif_opaque_softc *hif_ctx,
|
void hif_save_htc_htt_config_endpoint(struct hif_opaque_softc *hif_ctx,
|
||||||
@@ -915,6 +944,18 @@ enum hif_exec_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t (*ext_intr_handler)(void *, uint32_t);
|
typedef uint32_t (*ext_intr_handler)(void *, uint32_t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hif_get_int_ctx_irq_num() - retrieve an irq num for an interrupt context id
|
||||||
|
* @softc: hif opaque context owning the exec context
|
||||||
|
* @id: the id of the interrupt context
|
||||||
|
*
|
||||||
|
* Return: IRQ number of the first (zero'th) IRQ within the interrupt context ID
|
||||||
|
* 'id' registered with the OS
|
||||||
|
*/
|
||||||
|
int32_t hif_get_int_ctx_irq_num(struct hif_opaque_softc *softc,
|
||||||
|
uint8_t id);
|
||||||
|
|
||||||
uint32_t hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx);
|
uint32_t hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx);
|
||||||
uint32_t hif_register_ext_group(struct hif_opaque_softc *hif_ctx,
|
uint32_t hif_register_ext_group(struct hif_opaque_softc *hif_ctx,
|
||||||
uint32_t numirq, uint32_t irq[], ext_intr_handler handler,
|
uint32_t numirq, uint32_t irq[], ext_intr_handler handler,
|
||||||
@@ -928,6 +969,12 @@ void hif_update_pipe_callback(struct hif_opaque_softc *osc,
|
|||||||
u_int8_t pipeid,
|
u_int8_t pipeid,
|
||||||
struct hif_msg_callbacks *callbacks);
|
struct hif_msg_callbacks *callbacks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hif_print_napi_stats() - Display HIF NAPI stats
|
||||||
|
* @hif_ctx - HIF opaque context
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
void hif_print_napi_stats(struct hif_opaque_softc *hif_ctx);
|
void hif_print_napi_stats(struct hif_opaque_softc *hif_ctx);
|
||||||
|
|
||||||
/* hif_clear_napi_stats() - function clears the stats of the
|
/* hif_clear_napi_stats() - function clears the stats of the
|
||||||
|
@@ -21,7 +21,6 @@
|
|||||||
#include <hif_irq_affinity.h>
|
#include <hif_irq_affinity.h>
|
||||||
#include "qdf_module.h"
|
#include "qdf_module.h"
|
||||||
#include "qdf_net_if.h"
|
#include "qdf_net_if.h"
|
||||||
|
|
||||||
/* mapping NAPI budget 0 to internal budget 0
|
/* mapping NAPI budget 0 to internal budget 0
|
||||||
* NAPI budget 1 to internal budget [1,scaler -1]
|
* NAPI budget 1 to internal budget [1,scaler -1]
|
||||||
* NAPI budget 2 to internal budget [scaler, 2 * scaler - 1], etc
|
* NAPI budget 2 to internal budget [scaler, 2 * scaler - 1], etc
|
||||||
@@ -33,32 +32,6 @@
|
|||||||
|
|
||||||
static struct hif_exec_context *hif_exec_tasklet_create(void);
|
static struct hif_exec_context *hif_exec_tasklet_create(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* hif_clear_napi_stats() - reset NAPI stats
|
|
||||||
* @hif_ctx: hif context
|
|
||||||
*
|
|
||||||
* return: void
|
|
||||||
*/
|
|
||||||
void hif_clear_napi_stats(struct hif_opaque_softc *hif_ctx)
|
|
||||||
{
|
|
||||||
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
|
|
||||||
struct hif_exec_context *hif_ext_group;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < hif_state->hif_num_extgroup; i++) {
|
|
||||||
hif_ext_group = hif_state->hif_ext_group[i];
|
|
||||||
|
|
||||||
if (!hif_ext_group)
|
|
||||||
return;
|
|
||||||
|
|
||||||
qdf_mem_set(hif_ext_group->sched_latency_stats,
|
|
||||||
sizeof(hif_ext_group->sched_latency_stats),
|
|
||||||
0x0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qdf_export_symbol(hif_clear_napi_stats);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hif_print_napi_latency_stats() - print NAPI scheduling latency stats
|
* hif_print_napi_latency_stats() - print NAPI scheduling latency stats
|
||||||
* @hif_state: hif context
|
* @hif_state: hif context
|
||||||
@@ -127,11 +100,209 @@ static void hif_print_napi_latency_stats(struct HIF_CE_state *hif_state)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hif_print_napi_stats() - print NAPI stats
|
* hif_clear_napi_stats() - reset NAPI stats
|
||||||
* @hif_ctx: hif context
|
* @hif_ctx: hif context
|
||||||
*
|
*
|
||||||
* return: void
|
* return: void
|
||||||
*/
|
*/
|
||||||
|
void hif_clear_napi_stats(struct hif_opaque_softc *hif_ctx)
|
||||||
|
{
|
||||||
|
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
|
||||||
|
struct hif_exec_context *hif_ext_group;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < hif_state->hif_num_extgroup; i++) {
|
||||||
|
hif_ext_group = hif_state->hif_ext_group[i];
|
||||||
|
|
||||||
|
if (!hif_ext_group)
|
||||||
|
return;
|
||||||
|
|
||||||
|
qdf_mem_set(hif_ext_group->sched_latency_stats,
|
||||||
|
sizeof(hif_ext_group->sched_latency_stats),
|
||||||
|
0x0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_export_symbol(hif_clear_napi_stats);
|
||||||
|
|
||||||
|
#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
|
||||||
|
/**
|
||||||
|
* hif_get_poll_times_hist_str() - Get HIF poll times histogram string
|
||||||
|
* @stats: NAPI stats to get poll time buckets
|
||||||
|
* @buf: buffer to fill histogram string
|
||||||
|
* @buf_len: length of the buffer
|
||||||
|
*
|
||||||
|
* Return: void
|
||||||
|
*/
|
||||||
|
static void hif_get_poll_times_hist_str(struct qca_napi_stat *stats, char *buf,
|
||||||
|
uint8_t buf_len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int str_index = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < QCA_NAPI_NUM_BUCKETS; i++)
|
||||||
|
str_index += qdf_scnprintf(buf + str_index, buf_len - str_index,
|
||||||
|
"%u|", stats->poll_time_buckets[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hif_exec_fill_poll_time_histogram() - fills poll time histogram for a NAPI
|
||||||
|
* @hif_ext_group: hif_ext_group of type NAPI
|
||||||
|
*
|
||||||
|
* The function is called at the end of a NAPI poll to calculate poll time
|
||||||
|
* buckets.
|
||||||
|
*
|
||||||
|
* Return: void
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void hif_exec_fill_poll_time_histogram(struct hif_exec_context *hif_ext_group)
|
||||||
|
{
|
||||||
|
struct qca_napi_stat *napi_stat;
|
||||||
|
unsigned long long poll_time_ns;
|
||||||
|
uint32_t poll_time_us;
|
||||||
|
uint32_t bucket_size_us = 500;
|
||||||
|
uint32_t bucket;
|
||||||
|
uint32_t cpu_id = qdf_get_cpu();
|
||||||
|
|
||||||
|
poll_time_ns = sched_clock() - hif_ext_group->poll_start_time;
|
||||||
|
poll_time_us = poll_time_ns / 1000;
|
||||||
|
|
||||||
|
napi_stat = &hif_ext_group->stats[cpu_id];
|
||||||
|
if (poll_time_ns > hif_ext_group->stats[cpu_id].napi_max_poll_time)
|
||||||
|
hif_ext_group->stats[cpu_id].napi_max_poll_time = poll_time_ns;
|
||||||
|
|
||||||
|
bucket = poll_time_us / bucket_size_us;
|
||||||
|
if (bucket >= QCA_NAPI_NUM_BUCKETS)
|
||||||
|
bucket = QCA_NAPI_NUM_BUCKETS - 1;
|
||||||
|
++napi_stat->poll_time_buckets[bucket];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hif_exec_poll_should_yield() - Local function deciding if NAPI should yield
|
||||||
|
* @hif_ext_group: hif_ext_group of type NAPI
|
||||||
|
*
|
||||||
|
* Return: true if NAPI needs to yield, else false
|
||||||
|
*/
|
||||||
|
static bool hif_exec_poll_should_yield(struct hif_exec_context *hif_ext_group)
|
||||||
|
{
|
||||||
|
bool time_limit_reached = false;
|
||||||
|
unsigned long long poll_time_ns;
|
||||||
|
int cpu_id = qdf_get_cpu();
|
||||||
|
struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif);
|
||||||
|
struct hif_config_info *cfg = &scn->hif_config;
|
||||||
|
|
||||||
|
poll_time_ns = sched_clock() - hif_ext_group->poll_start_time;
|
||||||
|
time_limit_reached =
|
||||||
|
poll_time_ns > cfg->rx_softirq_max_yield_duration_ns ? 1 : 0;
|
||||||
|
|
||||||
|
if (time_limit_reached) {
|
||||||
|
hif_ext_group->stats[cpu_id].time_limit_reached++;
|
||||||
|
hif_ext_group->force_break = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return time_limit_reached;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hif_exec_should_yield(struct hif_opaque_softc *hif_ctx, uint grp_id)
|
||||||
|
{
|
||||||
|
struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
|
||||||
|
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
|
||||||
|
struct hif_exec_context *hif_ext_group;
|
||||||
|
bool ret_val = false;
|
||||||
|
|
||||||
|
if (!(grp_id < hif_state->hif_num_extgroup) ||
|
||||||
|
!(grp_id < HIF_MAX_GROUP))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hif_ext_group = hif_state->hif_ext_group[grp_id];
|
||||||
|
|
||||||
|
if (hif_ext_group->type == HIF_EXEC_NAPI_TYPE)
|
||||||
|
ret_val = hif_exec_poll_should_yield(hif_ext_group);
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hif_exec_update_service_start_time() - Update NAPI poll start time
|
||||||
|
* @hif_ext_group: hif_ext_group of type NAPI
|
||||||
|
*
|
||||||
|
* The function is called at the beginning of a NAPI poll to record the poll
|
||||||
|
* start time.
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
void hif_exec_update_service_start_time(struct hif_exec_context *hif_ext_group)
|
||||||
|
{
|
||||||
|
hif_ext_group->poll_start_time = sched_clock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hif_print_napi_stats(struct hif_opaque_softc *hif_ctx)
|
||||||
|
{
|
||||||
|
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
|
||||||
|
struct hif_exec_context *hif_ext_group;
|
||||||
|
struct qca_napi_stat *napi_stats;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Max value of uint_32 (poll_time_bucket) = 4294967295
|
||||||
|
* Thus we need 10 chars + 1 space =11 chars for each bucket value.
|
||||||
|
* +1 space for '\0'.
|
||||||
|
*/
|
||||||
|
char hist_str[(QCA_NAPI_NUM_BUCKETS * 11) + 1] = {'\0'};
|
||||||
|
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"NAPI[#]CPU[#] |scheds |polls |comps |dones |t-lim |max(us)|hist(500us buckets)");
|
||||||
|
|
||||||
|
for (i = 0;
|
||||||
|
(i < hif_state->hif_num_extgroup && hif_state->hif_ext_group[i]);
|
||||||
|
i++) {
|
||||||
|
hif_ext_group = hif_state->hif_ext_group[i];
|
||||||
|
for (j = 0; j < num_possible_cpus(); j++) {
|
||||||
|
napi_stats = &hif_ext_group->stats[j];
|
||||||
|
if (!napi_stats->napi_schedules)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hif_get_poll_times_hist_str(napi_stats,
|
||||||
|
hist_str,
|
||||||
|
sizeof(hist_str));
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_HIF,
|
||||||
|
QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"NAPI[%d]CPU[%d]: %7u %7u %7u %7u %7u %7llu %s",
|
||||||
|
i, j,
|
||||||
|
napi_stats->napi_schedules,
|
||||||
|
napi_stats->napi_polls,
|
||||||
|
napi_stats->napi_completes,
|
||||||
|
napi_stats->napi_workdone,
|
||||||
|
napi_stats->time_limit_reached,
|
||||||
|
(napi_stats->napi_max_poll_time / 1000),
|
||||||
|
hist_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hif_print_napi_latency_stats(hif_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_export_symbol(hif_print_napi_stats);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void hif_get_poll_times_hist_str(struct qca_napi_stat *stats, char *buf,
|
||||||
|
uint8_t buf_len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void hif_exec_update_service_start_time(struct hif_exec_context *hif_ext_group)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void hif_exec_fill_poll_time_histogram(struct hif_exec_context *hif_ext_group)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void hif_print_napi_stats(struct hif_opaque_softc *hif_ctx)
|
void hif_print_napi_stats(struct hif_opaque_softc *hif_ctx)
|
||||||
{
|
{
|
||||||
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
|
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
|
||||||
@@ -164,6 +335,7 @@ void hif_print_napi_stats(struct hif_opaque_softc *hif_ctx)
|
|||||||
hif_print_napi_latency_stats(hif_state);
|
hif_print_napi_latency_stats(hif_state);
|
||||||
}
|
}
|
||||||
qdf_export_symbol(hif_print_napi_stats);
|
qdf_export_symbol(hif_print_napi_stats);
|
||||||
|
#endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */
|
||||||
|
|
||||||
static void hif_exec_tasklet_schedule(struct hif_exec_context *ctx)
|
static void hif_exec_tasklet_schedule(struct hif_exec_context *ctx)
|
||||||
{
|
{
|
||||||
@@ -258,23 +430,27 @@ static void hif_latency_profile_start(struct hif_exec_context *hif_ext_group)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hif_exec_poll() - napi pool
|
* hif_exec_poll() - napi poll
|
||||||
* napi: napi struct
|
* napi: napi struct
|
||||||
* budget: budget for napi
|
* budget: budget for napi
|
||||||
*
|
*
|
||||||
* return: mapping of internal budget to napi
|
* Return: mapping of internal budget to napi
|
||||||
*/
|
*/
|
||||||
static int hif_exec_poll(struct napi_struct *napi, int budget)
|
static int hif_exec_poll(struct napi_struct *napi, int budget)
|
||||||
{
|
{
|
||||||
struct hif_napi_exec_context *exec_ctx =
|
struct hif_napi_exec_context *napi_exec_ctx =
|
||||||
qdf_container_of(napi, struct hif_napi_exec_context, napi);
|
qdf_container_of(napi, struct hif_napi_exec_context, napi);
|
||||||
struct hif_exec_context *hif_ext_group = &exec_ctx->exec_ctx;
|
struct hif_exec_context *hif_ext_group = &napi_exec_ctx->exec_ctx;
|
||||||
struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif);
|
struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif);
|
||||||
int work_done;
|
int work_done;
|
||||||
int normalized_budget = 0;
|
int normalized_budget = 0;
|
||||||
|
int actual_dones;
|
||||||
int shift = hif_ext_group->scale_bin_shift;
|
int shift = hif_ext_group->scale_bin_shift;
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
|
|
||||||
|
hif_ext_group->force_break = false;
|
||||||
|
hif_exec_update_service_start_time(hif_ext_group);
|
||||||
|
|
||||||
if (budget)
|
if (budget)
|
||||||
normalized_budget = NAPI_BUDGET_TO_INTERNAL_BUDGET(budget, shift);
|
normalized_budget = NAPI_BUDGET_TO_INTERNAL_BUDGET(budget, shift);
|
||||||
|
|
||||||
@@ -283,7 +459,9 @@ static int hif_exec_poll(struct napi_struct *napi, int budget)
|
|||||||
work_done = hif_ext_group->handler(hif_ext_group->context,
|
work_done = hif_ext_group->handler(hif_ext_group->context,
|
||||||
normalized_budget);
|
normalized_budget);
|
||||||
|
|
||||||
if (work_done < normalized_budget) {
|
actual_dones = work_done;
|
||||||
|
|
||||||
|
if (!hif_ext_group->force_break && work_done < normalized_budget) {
|
||||||
napi_complete(napi);
|
napi_complete(napi);
|
||||||
qdf_atomic_dec(&scn->active_grp_tasklet_cnt);
|
qdf_atomic_dec(&scn->active_grp_tasklet_cnt);
|
||||||
hif_ext_group->irq_enable(hif_ext_group);
|
hif_ext_group->irq_enable(hif_ext_group);
|
||||||
@@ -295,12 +473,14 @@ static int hif_exec_poll(struct napi_struct *napi, int budget)
|
|||||||
}
|
}
|
||||||
|
|
||||||
hif_ext_group->stats[cpu].napi_polls++;
|
hif_ext_group->stats[cpu].napi_polls++;
|
||||||
hif_ext_group->stats[cpu].napi_workdone += work_done;
|
hif_ext_group->stats[cpu].napi_workdone += actual_dones;
|
||||||
|
|
||||||
/* map internal budget to NAPI budget */
|
/* map internal budget to NAPI budget */
|
||||||
if (work_done)
|
if (work_done)
|
||||||
work_done = INTERNAL_BUDGET_TO_NAPI_BUDGET(work_done, shift);
|
work_done = INTERNAL_BUDGET_TO_NAPI_BUDGET(work_done, shift);
|
||||||
|
|
||||||
|
hif_exec_fill_poll_time_histogram(hif_ext_group);
|
||||||
|
|
||||||
return work_done;
|
return work_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,13 +616,18 @@ struct hif_exec_context *hif_exec_get_ctx(struct hif_opaque_softc *softc,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int32_t hif_get_int_ctx_irq_num(struct hif_opaque_softc *softc,
|
||||||
* hif_configure_ext_group_interrupts() - API to configure external group
|
uint8_t id)
|
||||||
* interrpts
|
{
|
||||||
* @hif_ctx : HIF Context
|
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(softc);
|
||||||
*
|
|
||||||
* Return: status
|
if (id < hif_state->hif_num_extgroup)
|
||||||
*/
|
return hif_state->hif_ext_group[id]->os_irq[0];
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_export_symbol(hif_get_int_ctx_irq_num);
|
||||||
|
|
||||||
uint32_t hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx)
|
uint32_t hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx)
|
||||||
{
|
{
|
||||||
struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
|
struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
|
||||||
@@ -474,6 +659,7 @@ uint32_t hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx)
|
|||||||
|
|
||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
qdf_export_symbol(hif_configure_ext_group_interrupts);
|
qdf_export_symbol(hif_configure_ext_group_interrupts);
|
||||||
|
|
||||||
#ifdef WLAN_SUSPEND_RESUME_TEST
|
#ifdef WLAN_SUSPEND_RESUME_TEST
|
||||||
@@ -610,6 +796,7 @@ uint32_t hif_register_ext_group(struct hif_opaque_softc *hif_ctx,
|
|||||||
hif_ext_group->grp_id = hif_state->hif_num_extgroup;
|
hif_ext_group->grp_id = hif_state->hif_num_extgroup;
|
||||||
hif_ext_group->hif = hif_ctx;
|
hif_ext_group->hif = hif_ctx;
|
||||||
hif_ext_group->context_name = context_name;
|
hif_ext_group->context_name = context_name;
|
||||||
|
hif_ext_group->type = type;
|
||||||
|
|
||||||
hif_state->hif_num_extgroup++;
|
hif_state->hif_num_extgroup++;
|
||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
|
@@ -68,6 +68,12 @@ struct hif_execution_ops {
|
|||||||
* @irq_disable: called before scheduling the context.
|
* @irq_disable: called before scheduling the context.
|
||||||
* @irq_enable: called when the context leaves polling mode
|
* @irq_enable: called when the context leaves polling mode
|
||||||
* @irq_name: pointer to function to return irq name/string mapped to irq number
|
* @irq_name: pointer to function to return irq name/string mapped to irq number
|
||||||
|
* @irq_lock: spinlock used while enabling/disabling IRQs
|
||||||
|
* @type: type of execution context
|
||||||
|
* @poll_start_time: hif napi poll start time in nanoseconds
|
||||||
|
* @force_break: flag to indicate if HIF execution context was forced to return
|
||||||
|
* to HIF. This means there is more work to be done. Hence do not
|
||||||
|
* call napi_complete.
|
||||||
*/
|
*/
|
||||||
struct hif_exec_context {
|
struct hif_exec_context {
|
||||||
struct hif_execution_ops *sched_ops;
|
struct hif_execution_ops *sched_ops;
|
||||||
@@ -96,6 +102,9 @@ struct hif_exec_context {
|
|||||||
bool irq_requested;
|
bool irq_requested;
|
||||||
bool irq_enabled;
|
bool irq_enabled;
|
||||||
qdf_spinlock_t irq_lock;
|
qdf_spinlock_t irq_lock;
|
||||||
|
enum hif_exec_type type;
|
||||||
|
unsigned long long poll_start_time;
|
||||||
|
bool force_break;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,7 +118,7 @@ struct hif_tasklet_exec_context {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct hif_napi_exec_context - exec_context for tasklets
|
* struct hif_napi_exec_context - exec_context for NAPI
|
||||||
* @exec_ctx: inherited data type
|
* @exec_ctx: inherited data type
|
||||||
* @netdev: dummy net device associated with the napi context
|
* @netdev: dummy net device associated with the napi context
|
||||||
* @napi: napi structure used in scheduling
|
* @napi: napi structure used in scheduling
|
||||||
|
@@ -137,6 +137,16 @@ struct wlan_cfg_dp_pdev_ctxt;
|
|||||||
* @rxdma_refill_ring: rxdma refill ring size
|
* @rxdma_refill_ring: rxdma refill ring size
|
||||||
* @rxdma_err_dst_ring: rxdma error detination ring size
|
* @rxdma_err_dst_ring: rxdma error detination ring size
|
||||||
* @raw_mode_war: enable/disable raw mode war
|
* @raw_mode_war: enable/disable raw mode war
|
||||||
|
* @enable_data_stall_detection: flag to enable data stall detection
|
||||||
|
* @disable_intra_bss_fwd: flag to disable intra bss forwarding
|
||||||
|
* @rxdma1_enable: flag to indicate if rxdma1 is enabled
|
||||||
|
* @tx_comp_loop_pkt_limit: Max # of packets to be processed in 1 tx comp loop
|
||||||
|
* @rx_reap_loop_pkt_limit: Max # of packets to be processed in 1 rx reap loop
|
||||||
|
* @rx_hp_oos_update_limit: Max # of HP OOS (out of sync) updates
|
||||||
|
* @rx_enable_eol_data_check: flag to enable check for more ring data at end of
|
||||||
|
* dp_rx_process loop
|
||||||
|
* tx_comp_enable_eol_data_check: flag to enable/disable checking for more data
|
||||||
|
* at end of tx_comp_handler loop.
|
||||||
*/
|
*/
|
||||||
struct wlan_cfg_dp_soc_ctxt {
|
struct wlan_cfg_dp_soc_ctxt {
|
||||||
int num_int_ctxts;
|
int num_int_ctxts;
|
||||||
@@ -211,6 +221,13 @@ struct wlan_cfg_dp_soc_ctxt {
|
|||||||
bool disable_intra_bss_fwd;
|
bool disable_intra_bss_fwd;
|
||||||
bool rxdma1_enable;
|
bool rxdma1_enable;
|
||||||
int max_ast_idx;
|
int max_ast_idx;
|
||||||
|
#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
|
||||||
|
uint32_t tx_comp_loop_pkt_limit;
|
||||||
|
uint32_t rx_reap_loop_pkt_limit;
|
||||||
|
uint32_t rx_hp_oos_update_limit;
|
||||||
|
bool rx_enable_eol_data_check;
|
||||||
|
bool tx_comp_enable_eol_data_check;
|
||||||
|
#endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1001,4 +1018,5 @@ int wlan_cfg_get_tx_flow_start_queue_offset(struct wlan_cfg_dp_soc_ctxt *cfg);
|
|||||||
int wlan_cfg_get_rx_defrag_min_timeout(struct wlan_cfg_dp_soc_ctxt *cfg);
|
int wlan_cfg_get_rx_defrag_min_timeout(struct wlan_cfg_dp_soc_ctxt *cfg);
|
||||||
|
|
||||||
int wlan_cfg_get_defrag_timeout_check(struct wlan_cfg_dp_soc_ctxt *cfg);
|
int wlan_cfg_get_defrag_timeout_check(struct wlan_cfg_dp_soc_ctxt *cfg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user