From 9ee4b9e84a6b8bc2a9bab4d5d34b8475e262a2d7 Mon Sep 17 00:00:00 2001 From: Mohit Khanna Date: Fri, 11 Nov 2016 18:17:32 -0800 Subject: [PATCH] qcacmn: Use sched_clock instead of jiffies to calc yield time The current implementation uses jiffies to calculate the yield time and yields after 2 jiffies. The problem with this is that we end up yielding anywhere between 1 - 2 jiffies as each jiffies are incremented by 10 ms intervals. Sometimes we are taking more than 2 jiffies to yield. This prevents the update of deferrable_timer if its being done at the same CPU where hif_napi_poll is executing. This may result in the CPU frequencies not being updated resulting in some fluctuations. Use sched_clock kernel API to calculate the precise yield time. Reduce the yield time to 10ms. Some stats here - How many times did we have to yield because of time (%)0.670391061 Total Number of completes 1790 Total Number of complete 0 12 - When we yielded, how much did we exceed the time limit(10ms) by (ms) Average 1.327444 Max 3.381667 Min 0.037709 - How many HTT Messages did we process when we had to yield Average 22.41667 Max 33 Min 18 - How much time did we take when we had to yield 10ms + delta above - How much time did we take when we did not yield (ms) Average 0.907641 Max 8.649 Min 0 - How many HTT Messages did we process when we did not have to yield Average 2.193476 Max 24 Min 1 Change-Id: I0d42c716ab8941b1de22a456447797c9ba5475c8 CRs-Fixed: 1089902 --- hif/src/ce/ce_internal.h | 3 ++- hif/src/ce/ce_service.c | 17 +++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/hif/src/ce/ce_internal.h b/hif/src/ce/ce_internal.h index ff649a62a120..d1fe30905ff7 100644 --- a/hif/src/ce/ce_internal.h +++ b/hif/src/ce/ce_internal.h @@ -139,7 +139,8 @@ struct CE_state { bool force_break; /* Flag to indicate whether to * break out the DPC context */ - qdf_time_t ce_service_yield_time; + /* time in nanoseconds to yield control of napi poll */ + unsigned long long ce_service_yield_time; unsigned int receive_count; /* count Num Of Receive Buffers * handled for one interrupt * DPC routine */ diff --git a/hif/src/ce/ce_service.c b/hif/src/ce/ce_service.c index 2b84936ca70e..4a57a43b99d2 100644 --- a/hif/src/ce/ce_service.c +++ b/hif/src/ce/ce_service.c @@ -219,8 +219,9 @@ bool hif_ce_service_should_yield(struct hif_softc *scn, { bool yield, time_limit_reached, rxpkt_thresh_reached = 0; - time_limit_reached = qdf_system_time_after_eq(qdf_system_ticks(), - ce_state->ce_service_yield_time); + time_limit_reached = + sched_clock() > ce_state->ce_service_yield_time ? 1 : 0; + if (!time_limit_reached) rxpkt_thresh_reached = hif_max_num_receives_reached (scn, ce_state->receive_count); @@ -1839,7 +1840,6 @@ more_data: FAST_RX_SOFTWARE_INDEX_UPDATE, NULL, NULL, sw_index); dest_ring->sw_index = sw_index; - ce_fastpath_rx_handle(ce_state, cmpl_msdus, MSG_FLUSH_NUM, ctrl_addr); @@ -1910,7 +1910,11 @@ 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 +/* Maximum amount of time in nano seconds before which the CE per engine service + * should yield. ~1 jiffie. + */ +#define CE_PER_ENGINE_SERVICE_MAX_YIELD_TIME_NS (10 * 1000 * 1000) + /* * Guts of interrupt handler for per-engine interrupts on a particular CE. * @@ -1947,8 +1951,9 @@ int ce_per_engine_service(struct hif_softc *scn, unsigned int CE_id) /* Clear force_break flag and re-initialize receive_count to 0 */ 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; + CE_state->ce_service_yield_time = + sched_clock() + + (unsigned long long)CE_PER_ENGINE_SERVICE_MAX_YIELD_TIME_NS; qdf_spin_lock(&CE_state->ce_index_lock);