diff --git a/hif/src/ce/ce_internal.h b/hif/src/ce/ce_internal.h index e9d25758db..2c445f6667 100644 --- a/hif/src/ce/ce_internal.h +++ b/hif/src/ce/ce_internal.h @@ -136,6 +136,7 @@ struct CE_state { bool force_break; /* Flag to indicate whether to * break out the DPC context */ + qdf_time_t ce_service_yield_time; unsigned int receive_count; /* count Num Of Receive Buffers * handled for one interrupt * DPC routine */ @@ -388,6 +389,9 @@ struct ce_sendlist_s { } item[CE_SENDLIST_ITEMS_MAX]; }; +bool hif_ce_service_should_yield(struct hif_softc *scn, struct CE_state + *ce_state); + #ifdef WLAN_FEATURE_FASTPATH void ce_h2t_tx_ce_cleanup(struct CE_handle *ce_hdl); void ce_t2h_msg_ce_cleanup(struct CE_handle *ce_hdl); diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index c54265948d..d34a084dd7 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -1352,7 +1352,6 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, #endif struct hif_msg_callbacks *msg_callbacks = &hif_state->msg_callbacks_current; - uint32_t count; do { #ifdef HIF_PCI @@ -1373,8 +1372,7 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context, /* Set up force_break flag if num of receices reaches * MAX_NUM_OF_RECEIVES */ ce_state->receive_count++; - count = ce_state->receive_count; - if (qdf_unlikely(hif_max_num_receives_reached(scn, count))) { + if (qdf_unlikely(hif_ce_service_should_yield(scn, ce_state))) { ce_state->force_break = 1; break; } diff --git a/hif/src/ce/ce_service.c b/hif/src/ce/ce_service.c index 60f29f1f69..dd04a01789 100644 --- a/hif/src/ce/ce_service.c +++ b/hif/src/ce/ce_service.c @@ -189,6 +189,22 @@ inline void ce_init_ce_desc_event_log(int ce_id, int size) } #endif +/** + * hif_ce_service_should_yield() - return true if the service is hogging the cpu + * @scn: hif context + * @ce_state: context of the copy engine being serviced + * + * Return: true if the service should yield + */ +bool hif_ce_service_should_yield(struct hif_softc *scn, + struct CE_state *ce_state) +{ + bool yield = qdf_system_time_after_eq(qdf_system_ticks(), + ce_state->ce_service_yield_time) || + hif_max_num_receives_reached(scn, ce_state->receive_count); + return yield; +} + /* * Support for Copy Engine hardware, which is mainly used for * communication between Host and Target over a PCIe interconnect. @@ -1738,6 +1754,7 @@ static void ce_per_engine_service_fast(struct hif_softc *scn, int ce_id) } #endif /* WLAN_FEATURE_FASTPATH */ +#define CE_PER_ENGINE_SERVICE_MAX_TIME_JIFFIES 2 /* * Guts of interrupt handler for per-engine interrupts on a particular CE. * @@ -1746,7 +1763,6 @@ static void ce_per_engine_service_fast(struct hif_softc *scn, int ce_id) * * Returns: number of messages processed */ - int ce_per_engine_service(struct hif_softc *scn, unsigned int CE_id) { struct CE_state *CE_state = scn->ce_id_to_state[CE_id]; @@ -1790,6 +1806,8 @@ int ce_per_engine_service(struct hif_softc *scn, unsigned int CE_id) /* NAPI: scn variables- thread/multi-processing safety? */ CE_state->receive_count = 0; CE_state->force_break = 0; + CE_state->ce_service_yield_time = qdf_system_ticks() + + CE_PER_ENGINE_SERVICE_MAX_TIME_JIFFIES; more_completions: if (CE_state->recv_cb) {