diff --git a/core/dp/ol/inc/ol_txrx_osif_api.h b/core/dp/ol/inc/ol_txrx_osif_api.h index 69b6dcf6d1c5..1bc73d28a550 100644 --- a/core/dp/ol/inc/ol_txrx_osif_api.h +++ b/core/dp/ol/inc/ol_txrx_osif_api.h @@ -279,5 +279,6 @@ void ol_txrx_flush_rx_frames(struct ol_txrx_peer_t *peer, #if defined(FEATURE_LRO) void ol_register_lro_flush_cb(void (handler)(void *), void *data); +void ol_deregister_lro_flush_cb(void); #endif #endif /* _OL_TXRX_OSIF_API__H_ */ diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 566a5ced1607..528b121763b1 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -3112,6 +3112,18 @@ CDF_STATUS ol_txrx_register_pause_cb(ol_tx_pause_callback_fp pause_cb) #endif #if defined(FEATURE_LRO) +/** + * ol_txrx_lro_flush_handler() - LRO flush handler + * @context: dev handle + * @rxpkt: rx data + * @staid: station id + * + * This function handles an LRO flush indication. + * If the rx thread is enabled, it will be invoked by the rx + * thread else it will be called in the tasklet context + * + * Return: none + */ void ol_txrx_lro_flush_handler(void *context, void *rxpkt, uint16_t staid) @@ -3132,6 +3144,15 @@ void ol_txrx_lro_flush_handler(void *context, "%s: lro_flush_cb NULL", __func__); } +/** + * ol_txrx_lro_flush() - LRO flush callback + * @data: opaque data pointer + * + * This is the callback registered with CE to trigger + * an LRO flush + * + * Return: none + */ void ol_txrx_lro_flush(void *data) { p_cds_sched_context sched_ctx = get_cds_sched_ctxt(); @@ -3151,7 +3172,8 @@ void ol_txrx_lro_flush(void *data) return; } - pkt->callback = (cds_ol_rx_thread_cb) ol_txrx_lro_flush_handler; + pkt->callback = + (cds_ol_rx_thread_cb) ol_txrx_lro_flush_handler; pkt->context = pdev; pkt->Rxpkt = NULL; pkt->staId = 0; @@ -3159,6 +3181,16 @@ void ol_txrx_lro_flush(void *data) } } +/** + * ol_register_lro_flush_cb() - register the LRO flush callback + * @handler: callback function + * @data: opaque data pointer to be passed back + * + * Store the LRO flush callback provided and in turn + * register OL's LRO flush handler with CE + * + * Return: none + */ void ol_register_lro_flush_cb(void (handler)(void *), void *data) { struct ol_softc *hif_device = @@ -3170,4 +3202,25 @@ void ol_register_lro_flush_cb(void (handler)(void *), void *data) ce_lro_flush_cb_register(hif_device, ol_txrx_lro_flush, pdev); } + +/** + * ol_deregister_lro_flush_cb() - deregister the LRO flush + * callback + * + * Remove the LRO flush callback provided and in turn + * deregister OL's LRO flush handler with CE + * + * Return: none + */ +void ol_deregister_lro_flush_cb(void) +{ + struct ol_softc *hif_device = + (struct ol_softc *)cds_get_context(CDF_MODULE_ID_HIF); + struct ol_txrx_pdev_t *pdev = cds_get_context(CDF_MODULE_ID_TXRX); + + ce_lro_flush_cb_deregister(hif_device); + + pdev->lro_info.lro_flush_cb = NULL; + pdev->lro_info.lro_data = NULL; +} #endif /* FEATURE_LRO */ diff --git a/core/hdd/src/wlan_hdd_lro.c b/core/hdd/src/wlan_hdd_lro.c index 14b9be616658..a84e839b6967 100644 --- a/core/hdd/src/wlan_hdd_lro.c +++ b/core/hdd/src/wlan_hdd_lro.c @@ -138,14 +138,7 @@ static void hdd_lro_desc_info_init(struct hdd_lro_s *hdd_info) */ static void hdd_lro_desc_pool_deinit(struct hdd_lro_desc_pool *lro_desc_pool) { - - if (lro_desc_pool->lro_desc_array) { - cdf_mem_free(lro_desc_pool->lro_desc_array); - lro_desc_pool->lro_desc_array = NULL; - } - INIT_LIST_HEAD(&lro_desc_pool->lro_free_list_head); - cdf_spinlock_destroy(&lro_desc_pool->lro_pool_lock); } @@ -161,19 +154,10 @@ static void hdd_lro_desc_pool_deinit(struct hdd_lro_desc_pool *lro_desc_pool) */ static void hdd_lro_desc_info_deinit(struct hdd_lro_s *hdd_info) { - int i; struct hdd_lro_desc_info *desc_info = &hdd_info->lro_desc_info; - cdf_mem_free(hdd_info->lro_mgr->lro_arr); - hdd_info->lro_mgr->lro_arr = NULL; hdd_lro_desc_pool_deinit(&desc_info->lro_desc_pool); - /* Free the a list of LRO desc for each entry of the hash table */ - for (i = 0; i < LRO_DESC_TABLE_SZ; i++) - INIT_LIST_HEAD(&desc_info->lro_hash_table[i].lro_desc_list); - cdf_spinlock_destroy(&desc_info->lro_hash_lock); - cdf_mem_free(desc_info->lro_hash_table); - desc_info->lro_hash_table = NULL; } /** @@ -605,9 +589,18 @@ void hdd_lro_disable(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter) NL80211_IFTYPE_STATION != adapter->wdev.iftype) return; - hdd_lro_desc_info_deinit(&adapter->lro_info); - cdf_mem_free(adapter->lro_info.lro_mgr); - adapter->lro_info.lro_mgr = NULL; + /* Deregister the flush callback */ + ol_deregister_lro_flush_cb(); + + if (adapter->lro_info.lro_mgr) { + hdd_lro_desc_info_deinit(&adapter->lro_info); + cdf_mem_free(adapter->lro_info.lro_mgr); + adapter->lro_info.lro_mgr = NULL; + adapter->lro_info.lro_desc_info. + lro_desc_pool.lro_desc_array = NULL; + adapter->lro_info.lro_desc_info. + lro_hash_table = NULL; + } return; } diff --git a/core/hif/src/ce/ce_api.h b/core/hif/src/ce/ce_api.h index 8bde74dba5d7..2b8565982d02 100644 --- a/core/hif/src/ce/ce_api.h +++ b/core/hif/src/ce/ce_api.h @@ -467,5 +467,6 @@ bool ce_check_rx_pending(struct ol_softc *scn, int ce_id); #if defined(FEATURE_LRO) void ce_lro_flush_cb_register(struct ol_softc *scn, void (handler)(void *), void *data); +void ce_lro_flush_cb_deregister(struct ol_softc *scn); #endif #endif /* __COPY_ENGINE_API_H__ */ diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index 452fcc6b2782..d79ba203e761 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -2584,10 +2584,65 @@ u32 shadow_dst_wr_ind_addr(struct ol_softc *scn, u32 ctrl_addr) } #endif +#if defined(FEATURE_LRO) +/** + * ce_lro_flush_cb_register() - register the LRO flush + * callback + * @scn: HIF context + * @handler: callback function + * @data: opaque data pointer to be passed back + * + * Store the LRO flush callback provided + * + * Return: none + */ void ce_lro_flush_cb_register(struct ol_softc *scn, void (handler)(void *), void *data) { - struct CE_state *ce_state = scn->ce_id_to_state[CE_HTT_T2H_MSG]; - ce_state->lro_flush_cb = handler; - ce_state->lro_data = data; + uint8_t ul, dl; + int ul_polled, dl_polled; + + CDF_ASSERT(scn != NULL); + + if (CDF_STATUS_SUCCESS != + hif_map_service_to_pipe(scn, HTT_DATA_MSG_SVC, + &ul, &dl, &ul_polled, &dl_polled)) { + printk("%s cannot map service to pipe\n", __FUNCTION__); + return; + } else { + struct CE_state *ce_state; + ce_state = scn->ce_id_to_state[dl]; + ce_state->lro_flush_cb = handler; + ce_state->lro_data = data; + } } + +/** + * ce_lro_flush_cb_deregister() - deregister the LRO flush + * callback + * @scn: HIF context + * + * Remove the LRO flush callback + * + * Return: none + */ +void ce_lro_flush_cb_deregister(struct ol_softc *scn) +{ + uint8_t ul, dl; + int ul_polled, dl_polled; + + CDF_ASSERT(scn != NULL); + + if (CDF_STATUS_SUCCESS != + hif_map_service_to_pipe(scn, HTT_DATA_MSG_SVC, + &ul, &dl, &ul_polled, &dl_polled)) { + printk("%s cannot map service to pipe\n", __FUNCTION__); + return; + } else { + struct CE_state *ce_state; + ce_state = scn->ce_id_to_state[dl]; + ce_state->lro_flush_cb = NULL; + ce_state->lro_data = NULL; + } +} +#endif diff --git a/core/hif/src/ce/ce_tasklet.c b/core/hif/src/ce/ce_tasklet.c index 6bb550e3c8c9..420905909a2b 100644 --- a/core/hif/src/ce/ce_tasklet.c +++ b/core/hif/src/ce/ce_tasklet.c @@ -214,8 +214,7 @@ static void ce_tasklet(unsigned long data) ce_per_engine_service(scn, tasklet_entry->ce_id); - if (tasklet_entry->ce_id == CE_HTT_T2H_MSG && - CE_state->lro_flush_cb != NULL) { + if (CE_state->lro_flush_cb != NULL) { CE_state->lro_flush_cb(CE_state->lro_data); } diff --git a/core/hif/src/hif_napi.c b/core/hif/src/hif_napi.c index f33fb8747bc3..8b194c812388 100644 --- a/core/hif/src/hif_napi.c +++ b/core/hif/src/hif_napi.c @@ -38,6 +38,7 @@ #include #include #include +#include enum napi_decision_vector { HIF_NAPI_NOEVENT = 0, @@ -399,6 +400,7 @@ int hif_napi_poll(struct napi_struct *napi, int budget) int cpu = smp_processor_id(); struct ol_softc *hif; struct qca_napi_info *napi_info; + struct CE_state *ce_state; NAPI_DEBUG("%s -->(.., budget=%d)\n", budget); @@ -413,6 +415,12 @@ int hif_napi_poll(struct napi_struct *napi, int budget) __func__, rc); napi_info->stats[cpu].napi_workdone += rc; normalized = (rc / napi_info->scale); + + ce_state = hif->ce_id_to_state[NAPI_ID2PIPE(napi_info->id)]; + if (ce_state->lro_flush_cb != NULL) { + ce_state->lro_flush_cb(ce_state->lro_data); + } + /* do not return 0, if there was some work done, even if it is below the scale */ if (rc)