xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c (revision ca827d42ad72f90d045716e688b539e53e31a7cc)
10513f0afSPeter Spreadborough /* SPDX-License-Identifier: BSD-3-Clause
20513f0afSPeter Spreadborough  * Copyright(c) 2014-2021 Broadcom
30513f0afSPeter Spreadborough  * All rights reserved.
40513f0afSPeter Spreadborough  */
50513f0afSPeter Spreadborough 
6*ca827d42SPeter Spreadborough #include <sched.h>
7*ca827d42SPeter Spreadborough #include <unistd.h>
80513f0afSPeter Spreadborough #include <rte_common.h>
90513f0afSPeter Spreadborough #include <rte_cycles.h>
100513f0afSPeter Spreadborough #include <rte_malloc.h>
110513f0afSPeter Spreadborough #include <rte_log.h>
120513f0afSPeter Spreadborough #include "bnxt.h"
130513f0afSPeter Spreadborough #include "bnxt_ulp.h"
140513f0afSPeter Spreadborough #include "bnxt_ulp_utils.h"
150513f0afSPeter Spreadborough #include "bnxt_ulp_tfc.h"
160513f0afSPeter Spreadborough #include "bnxt_tf_common.h"
170513f0afSPeter Spreadborough #include "ulp_sc_mgr.h"
180513f0afSPeter Spreadborough #include "ulp_flow_db.h"
190513f0afSPeter Spreadborough #include "ulp_template_db_enum.h"
200513f0afSPeter Spreadborough #include "ulp_template_struct.h"
210513f0afSPeter Spreadborough #include "tfc.h"
220513f0afSPeter Spreadborough #include "tfc_debug.h"
230513f0afSPeter Spreadborough #include "tfc_action_handle.h"
240513f0afSPeter Spreadborough 
250513f0afSPeter Spreadborough #define ULP_TFC_CNTR_READ_BYTES 32
260513f0afSPeter Spreadborough #define ULP_TFC_CNTR_ALIGN 32
270513f0afSPeter Spreadborough #define ULP_TFC_ACT_WORD_SZ 32
280513f0afSPeter Spreadborough 
290513f0afSPeter Spreadborough static const struct bnxt_ulp_sc_core_ops *
300513f0afSPeter Spreadborough bnxt_ulp_sc_ops_get(struct bnxt_ulp_context *ctxt)
310513f0afSPeter Spreadborough {
320513f0afSPeter Spreadborough 	int32_t rc;
330513f0afSPeter Spreadborough 	enum bnxt_ulp_device_id  dev_id;
340513f0afSPeter Spreadborough 	const struct bnxt_ulp_sc_core_ops *func_ops;
350513f0afSPeter Spreadborough 
360513f0afSPeter Spreadborough 	rc = bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id);
370513f0afSPeter Spreadborough 	if (rc)
380513f0afSPeter Spreadborough 		return NULL;
390513f0afSPeter Spreadborough 
400513f0afSPeter Spreadborough 	switch (dev_id) {
410513f0afSPeter Spreadborough 	case BNXT_ULP_DEVICE_ID_THOR2:
420513f0afSPeter Spreadborough 		func_ops = &ulp_sc_tfc_core_ops;
430513f0afSPeter Spreadborough 		break;
440513f0afSPeter Spreadborough 	case BNXT_ULP_DEVICE_ID_THOR:
450513f0afSPeter Spreadborough 	case BNXT_ULP_DEVICE_ID_STINGRAY:
460513f0afSPeter Spreadborough 	case BNXT_ULP_DEVICE_ID_WH_PLUS:
470513f0afSPeter Spreadborough 	default:
480513f0afSPeter Spreadborough 		func_ops = NULL;
490513f0afSPeter Spreadborough 		break;
500513f0afSPeter Spreadborough 	}
510513f0afSPeter Spreadborough 	return func_ops;
520513f0afSPeter Spreadborough }
530513f0afSPeter Spreadborough 
540513f0afSPeter Spreadborough int32_t ulp_sc_mgr_init(struct bnxt_ulp_context *ctxt)
550513f0afSPeter Spreadborough {
560513f0afSPeter Spreadborough 	const struct bnxt_ulp_sc_core_ops *sc_ops;
570513f0afSPeter Spreadborough 	struct bnxt_ulp_device_params *dparms;
580513f0afSPeter Spreadborough 	struct bnxt_ulp_sc_info *ulp_sc_info;
590513f0afSPeter Spreadborough 	uint32_t stats_cache_tbl_sz;
600513f0afSPeter Spreadborough 	uint32_t dev_id;
61*ca827d42SPeter Spreadborough 	uint8_t *data;
620513f0afSPeter Spreadborough 	int rc;
63*ca827d42SPeter Spreadborough 	int i;
640513f0afSPeter Spreadborough 
650513f0afSPeter Spreadborough 	if (!ctxt) {
660513f0afSPeter Spreadborough 		BNXT_DRV_DBG(DEBUG, "Invalid ULP CTXT\n");
670513f0afSPeter Spreadborough 		return -EINVAL;
680513f0afSPeter Spreadborough 	}
690513f0afSPeter Spreadborough 
700513f0afSPeter Spreadborough 	if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) {
710513f0afSPeter Spreadborough 		BNXT_DRV_DBG(DEBUG, "Failed to get device id\n");
720513f0afSPeter Spreadborough 		return -EINVAL;
730513f0afSPeter Spreadborough 	}
740513f0afSPeter Spreadborough 
750513f0afSPeter Spreadborough 	dparms = bnxt_ulp_device_params_get(dev_id);
760513f0afSPeter Spreadborough 	if (!dparms) {
770513f0afSPeter Spreadborough 		BNXT_DRV_DBG(DEBUG, "Failed to device parms\n");
780513f0afSPeter Spreadborough 		return -EINVAL;
790513f0afSPeter Spreadborough 	}
800513f0afSPeter Spreadborough 
810513f0afSPeter Spreadborough 	sc_ops = bnxt_ulp_sc_ops_get(ctxt);
820513f0afSPeter Spreadborough 	if (sc_ops == NULL) {
830513f0afSPeter Spreadborough 		BNXT_DRV_DBG(DEBUG, "Failed to get the counter ops\n");
840513f0afSPeter Spreadborough 		return -EINVAL;
850513f0afSPeter Spreadborough 	}
860513f0afSPeter Spreadborough 
870513f0afSPeter Spreadborough 	ulp_sc_info = rte_zmalloc("ulp_sc_info", sizeof(*ulp_sc_info), 0);
880513f0afSPeter Spreadborough 	if (!ulp_sc_info) {
890513f0afSPeter Spreadborough 		rc = -ENOMEM;
900513f0afSPeter Spreadborough 		goto error;
910513f0afSPeter Spreadborough 	}
920513f0afSPeter Spreadborough 
930513f0afSPeter Spreadborough 	ulp_sc_info->sc_ops = sc_ops;
940513f0afSPeter Spreadborough 	ulp_sc_info->flags = 0;
950513f0afSPeter Spreadborough 
960513f0afSPeter Spreadborough 	/* Add the SC info tbl to the ulp context. */
970513f0afSPeter Spreadborough 	bnxt_ulp_cntxt_ptr2_sc_info_set(ctxt, ulp_sc_info);
980513f0afSPeter Spreadborough 
990513f0afSPeter Spreadborough 	ulp_sc_info->num_counters = dparms->ext_flow_db_num_entries;
1000513f0afSPeter Spreadborough 	if (!ulp_sc_info->num_counters) {
1010513f0afSPeter Spreadborough 		/* No need for software counters, call fw directly */
1020513f0afSPeter Spreadborough 		BNXT_DRV_DBG(DEBUG, "Sw flow counter support not enabled\n");
1030513f0afSPeter Spreadborough 		return 0;
1040513f0afSPeter Spreadborough 	}
1050513f0afSPeter Spreadborough 
1060513f0afSPeter Spreadborough 	/*
1070513f0afSPeter Spreadborough 	 * Size is determined by the number of flows + 10% to cover IDs
1080513f0afSPeter Spreadborough 	 * used for resources.
1090513f0afSPeter Spreadborough 	 */
11067ad4000SKishore Padmanabha 	ulp_sc_info->cache_tbl_size = ulp_sc_info->num_counters +
11167ad4000SKishore Padmanabha 		(ulp_sc_info->num_counters / 10);
1120513f0afSPeter Spreadborough 	stats_cache_tbl_sz = sizeof(struct ulp_sc_tfc_stats_cache_entry) *
11367ad4000SKishore Padmanabha 		ulp_sc_info->cache_tbl_size;
1140513f0afSPeter Spreadborough 
1150513f0afSPeter Spreadborough 	ulp_sc_info->stats_cache_tbl = rte_zmalloc("ulp_stats_cache_tbl",
1160513f0afSPeter Spreadborough 						   stats_cache_tbl_sz, 0);
1170513f0afSPeter Spreadborough 	if (!ulp_sc_info->stats_cache_tbl) {
1180513f0afSPeter Spreadborough 		rc = -ENOMEM;
1190513f0afSPeter Spreadborough 		goto error;
1200513f0afSPeter Spreadborough 	}
1210513f0afSPeter Spreadborough 
1220513f0afSPeter Spreadborough 	ulp_sc_info->read_data = rte_zmalloc("ulp_stats_cache_read_data",
1230513f0afSPeter Spreadborough 					     ULP_SC_BATCH_SIZE * ULP_SC_PAGE_SIZE,
1240513f0afSPeter Spreadborough 					     ULP_SC_PAGE_SIZE);
1250513f0afSPeter Spreadborough 	if (!ulp_sc_info->read_data) {
1260513f0afSPeter Spreadborough 		rte_free(ulp_sc_info->stats_cache_tbl);
1270513f0afSPeter Spreadborough 		rc = -ENOMEM;
1280513f0afSPeter Spreadborough 		goto error;
1290513f0afSPeter Spreadborough 	}
1300513f0afSPeter Spreadborough 
131*ca827d42SPeter Spreadborough 	data = ulp_sc_info->read_data;
132*ca827d42SPeter Spreadborough 	for (i = 0; i < ULP_SC_BATCH_SIZE; i++) {
133*ca827d42SPeter Spreadborough 		ulp_sc_info->read_data_iova[i] = (uint64_t)rte_mem_virt2iova(data);
134*ca827d42SPeter Spreadborough 		data += ULP_SC_PAGE_SIZE;
135*ca827d42SPeter Spreadborough 	}
136*ca827d42SPeter Spreadborough 
1370513f0afSPeter Spreadborough 	rc = ulp_sc_mgr_thread_start(ctxt);
1380513f0afSPeter Spreadborough 	if (rc)
1390513f0afSPeter Spreadborough 		BNXT_DRV_DBG(DEBUG, "Stats counter thread start failed\n");
1400513f0afSPeter Spreadborough 
1410513f0afSPeter Spreadborough  error:
1420513f0afSPeter Spreadborough 	return rc;
1430513f0afSPeter Spreadborough }
1440513f0afSPeter Spreadborough 
1450513f0afSPeter Spreadborough /*
1460513f0afSPeter Spreadborough  * Release all resources in the Flow Counter Manager for this ulp context
1470513f0afSPeter Spreadborough  *
1480513f0afSPeter Spreadborough  * ctxt [in] The ulp context for the Flow Counter manager
1490513f0afSPeter Spreadborough  *
1500513f0afSPeter Spreadborough  */
1510513f0afSPeter Spreadborough int32_t
1520513f0afSPeter Spreadborough ulp_sc_mgr_deinit(struct bnxt_ulp_context *ctxt)
1530513f0afSPeter Spreadborough {
1540513f0afSPeter Spreadborough 	struct bnxt_ulp_sc_info *ulp_sc_info;
1550513f0afSPeter Spreadborough 
1560513f0afSPeter Spreadborough 	ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt);
1570513f0afSPeter Spreadborough 
1580513f0afSPeter Spreadborough 	if (!ulp_sc_info)
1590513f0afSPeter Spreadborough 		return -EINVAL;
1600513f0afSPeter Spreadborough 
1610513f0afSPeter Spreadborough 	if (ulp_sc_info->stats_cache_tbl)
1620513f0afSPeter Spreadborough 		rte_free(ulp_sc_info->stats_cache_tbl);
1630513f0afSPeter Spreadborough 
1640513f0afSPeter Spreadborough 	if (ulp_sc_info->read_data)
1650513f0afSPeter Spreadborough 		rte_free(ulp_sc_info->read_data);
1660513f0afSPeter Spreadborough 
1670513f0afSPeter Spreadborough 	rte_free(ulp_sc_info);
1680513f0afSPeter Spreadborough 
1690513f0afSPeter Spreadborough 	/* Safe to ignore on deinit */
1700513f0afSPeter Spreadborough 	(void)bnxt_ulp_cntxt_ptr2_sc_info_set(ctxt, NULL);
1710513f0afSPeter Spreadborough 
1720513f0afSPeter Spreadborough 	return 0;
1730513f0afSPeter Spreadborough }
1740513f0afSPeter Spreadborough 
17567ad4000SKishore Padmanabha #define ULP_SC_PERIOD_US 256
17667ad4000SKishore Padmanabha #define ULP_SC_CTX_DELAY 10000
1770513f0afSPeter Spreadborough 
1780513f0afSPeter Spreadborough static uint32_t ulp_stats_cache_main_loop(void *arg)
1790513f0afSPeter Spreadborough {
1800513f0afSPeter Spreadborough 	struct ulp_sc_tfc_stats_cache_entry *count;
18167ad4000SKishore Padmanabha 	const struct bnxt_ulp_sc_core_ops *sc_ops = NULL;
1820513f0afSPeter Spreadborough 	struct ulp_sc_tfc_stats_cache_entry *sce;
1830513f0afSPeter Spreadborough 	struct ulp_sc_tfc_stats_cache_entry *sce_end;
1840513f0afSPeter Spreadborough 	struct tfc_mpc_batch_info_t batch_info;
1850513f0afSPeter Spreadborough 	struct bnxt_ulp_sc_info *ulp_sc_info;
1860513f0afSPeter Spreadborough 	struct bnxt_ulp_context *ctxt = NULL;
1870513f0afSPeter Spreadborough 	uint16_t words = (ULP_TFC_CNTR_READ_BYTES + ULP_TFC_ACT_WORD_SZ - 1) / ULP_TFC_ACT_WORD_SZ;
1880513f0afSPeter Spreadborough 	uint32_t batch_size;
1890513f0afSPeter Spreadborough 	struct tfc *tfcp = NULL;
19067ad4000SKishore Padmanabha 	uint32_t batch, stat_cnt;
1910513f0afSPeter Spreadborough 	uint8_t *data;
1920513f0afSPeter Spreadborough 	int rc;
1930513f0afSPeter Spreadborough 
19467ad4000SKishore Padmanabha 	while (true) {
19567ad4000SKishore Padmanabha 		ctxt = NULL;
1960513f0afSPeter Spreadborough 		while (!ctxt) {
1970513f0afSPeter Spreadborough 			ctxt = bnxt_ulp_cntxt_entry_acquire(arg);
1980513f0afSPeter Spreadborough 
1990513f0afSPeter Spreadborough 			if (ctxt)
2000513f0afSPeter Spreadborough 				break;
20167ad4000SKishore Padmanabha 			/* If there are no more contexts just exit */
20267ad4000SKishore Padmanabha 			if (bnxt_ulp_cntxt_list_count() == 0)
20367ad4000SKishore Padmanabha 				goto terminate;
20467ad4000SKishore Padmanabha 			rte_delay_us_block(ULP_SC_CTX_DELAY);
2050513f0afSPeter Spreadborough 		}
2060513f0afSPeter Spreadborough 
20767ad4000SKishore Padmanabha 		/* get the stats counter info block from ulp context */
2080513f0afSPeter Spreadborough 		ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt);
20967ad4000SKishore Padmanabha 		if (unlikely(!ulp_sc_info)) {
2100513f0afSPeter Spreadborough 			bnxt_ulp_cntxt_entry_release();
2110513f0afSPeter Spreadborough 			goto terminate;
2120513f0afSPeter Spreadborough 		}
2130513f0afSPeter Spreadborough 
21467ad4000SKishore Padmanabha 		sce = ulp_sc_info->stats_cache_tbl;
21567ad4000SKishore Padmanabha 		sce_end = sce + ulp_sc_info->cache_tbl_size;
21667ad4000SKishore Padmanabha 
21767ad4000SKishore Padmanabha 		if (unlikely(!sc_ops))
2180513f0afSPeter Spreadborough 			sc_ops = ulp_sc_info->sc_ops;
2190513f0afSPeter Spreadborough 
22067ad4000SKishore Padmanabha 		stat_cnt = 0;
22167ad4000SKishore Padmanabha 		while (stat_cnt < ulp_sc_info->num_entries && (sce < sce_end)) {
2220513f0afSPeter Spreadborough 			data = ulp_sc_info->read_data;
2230513f0afSPeter Spreadborough 
2240513f0afSPeter Spreadborough 			if (bnxt_ulp_cntxt_acquire_fdb_lock(ctxt))
2250513f0afSPeter Spreadborough 				break;
2260513f0afSPeter Spreadborough 
22767ad4000SKishore Padmanabha 			rc = tfc_mpc_batch_start(&batch_info);
22867ad4000SKishore Padmanabha 			if (unlikely(rc)) {
2290513f0afSPeter Spreadborough 				PMD_DRV_LOG_LINE(ERR,
23067ad4000SKishore Padmanabha 						 "MPC batch start failed rc:%d", rc);
23167ad4000SKishore Padmanabha 				bnxt_ulp_cntxt_release_fdb_lock(ctxt);
23267ad4000SKishore Padmanabha 				break;
2330513f0afSPeter Spreadborough 			}
2340513f0afSPeter Spreadborough 
23567ad4000SKishore Padmanabha 			for (batch = 0; (batch < ULP_SC_BATCH_SIZE) &&
23667ad4000SKishore Padmanabha 			     (sce < sce_end);) {
2370513f0afSPeter Spreadborough 				if (!(sce->flags & ULP_SC_ENTRY_FLAG_VALID)) {
2380513f0afSPeter Spreadborough 					sce++;
2390513f0afSPeter Spreadborough 					continue;
2400513f0afSPeter Spreadborough 				}
24167ad4000SKishore Padmanabha 				stat_cnt++;
2420513f0afSPeter Spreadborough 				tfcp = bnxt_ulp_cntxt_tfcp_get(sce->ctxt);
24367ad4000SKishore Padmanabha 				if (unlikely(!tfcp)) {
24467ad4000SKishore Padmanabha 					bnxt_ulp_cntxt_release_fdb_lock(ctxt);
2450513f0afSPeter Spreadborough 					bnxt_ulp_cntxt_entry_release();
2460513f0afSPeter Spreadborough 					goto terminate;
2470513f0afSPeter Spreadborough 				}
2480513f0afSPeter Spreadborough 
2490513f0afSPeter Spreadborough 				/* Store the entry pointer to use for counter update */
25067ad4000SKishore Padmanabha 				batch_info.em_hdl[batch_info.count] =
25167ad4000SKishore Padmanabha 					(uint64_t)sce;
2520513f0afSPeter Spreadborough 
2530513f0afSPeter Spreadborough 				rc = sc_ops->ulp_stats_cache_update(tfcp,
2540513f0afSPeter Spreadborough 							    sce->dir,
255*ca827d42SPeter Spreadborough 							    &ulp_sc_info->read_data_iova[batch],
2560513f0afSPeter Spreadborough 							    sce->handle,
2570513f0afSPeter Spreadborough 							    &words,
2580513f0afSPeter Spreadborough 							    &batch_info,
2590513f0afSPeter Spreadborough 							    sce->reset);
26067ad4000SKishore Padmanabha 				if (unlikely(rc)) {
2610513f0afSPeter Spreadborough 					/* Abort this batch */
2620513f0afSPeter Spreadborough 					PMD_DRV_LOG_LINE(ERR,
26367ad4000SKishore Padmanabha 							 "read_counter() failed:%d", rc);
2640513f0afSPeter Spreadborough 					break;
2650513f0afSPeter Spreadborough 				}
2660513f0afSPeter Spreadborough 
2670513f0afSPeter Spreadborough 				if (sce->reset)
2680513f0afSPeter Spreadborough 					sce->reset = false;
2690513f0afSPeter Spreadborough 
2700513f0afSPeter Spreadborough 				/* Next */
2710513f0afSPeter Spreadborough 				batch++;
2720513f0afSPeter Spreadborough 				sce++;
2730513f0afSPeter Spreadborough 				data += ULP_SC_PAGE_SIZE;
2740513f0afSPeter Spreadborough 			}
2750513f0afSPeter Spreadborough 
2760513f0afSPeter Spreadborough 			batch_size = batch_info.count;
2770513f0afSPeter Spreadborough 			rc = tfc_mpc_batch_end(tfcp, &batch_info);
2780513f0afSPeter Spreadborough 
2790513f0afSPeter Spreadborough 			bnxt_ulp_cntxt_release_fdb_lock(ctxt);
2800513f0afSPeter Spreadborough 
28167ad4000SKishore Padmanabha 			if (unlikely(rc)) {
28267ad4000SKishore Padmanabha 				PMD_DRV_LOG_LINE(ERR, "MPC batch end failed rc:%d", rc);
2830513f0afSPeter Spreadborough 				batch_info.enabled = false;
2840513f0afSPeter Spreadborough 				break;
2850513f0afSPeter Spreadborough 			}
2860513f0afSPeter Spreadborough 
2870513f0afSPeter Spreadborough 			/* Process counts */
2880513f0afSPeter Spreadborough 			data = ulp_sc_info->read_data;
2890513f0afSPeter Spreadborough 
2900513f0afSPeter Spreadborough 			for (batch = 0; batch < batch_size; batch++) {
2910513f0afSPeter Spreadborough 				/* Check for error in completion */
2920513f0afSPeter Spreadborough 				if (batch_info.result[batch]) {
29367ad4000SKishore Padmanabha 					PMD_DRV_LOG_LINE(ERR, "batch:%d result:%d",
2940513f0afSPeter Spreadborough 							 batch, batch_info.result[batch]);
2950513f0afSPeter Spreadborough 				} else {
2960513f0afSPeter Spreadborough 					count = (struct ulp_sc_tfc_stats_cache_entry *)
2970513f0afSPeter Spreadborough 						((uintptr_t)batch_info.em_hdl[batch]);
2980513f0afSPeter Spreadborough 					memcpy(&count->packet_count, data, ULP_TFC_ACT_WORD_SZ);
2990513f0afSPeter Spreadborough 				}
3000513f0afSPeter Spreadborough 
3010513f0afSPeter Spreadborough 				data += ULP_SC_PAGE_SIZE;
3020513f0afSPeter Spreadborough 			}
3030513f0afSPeter Spreadborough 		}
30467ad4000SKishore Padmanabha 		bnxt_ulp_cntxt_entry_release();
30567ad4000SKishore Padmanabha 		/* Sleep to give any other threads opportunity to access ULP */
30667ad4000SKishore Padmanabha 		rte_delay_us_sleep(ULP_SC_PERIOD_US);
3070513f0afSPeter Spreadborough 	}
3080513f0afSPeter Spreadborough 
3090513f0afSPeter Spreadborough  terminate:
31067ad4000SKishore Padmanabha 	PMD_DRV_LOG_LINE(DEBUG, "Terminating the stats cachce thread");
3110513f0afSPeter Spreadborough 	return 0;
3120513f0afSPeter Spreadborough }
3130513f0afSPeter Spreadborough 
3140513f0afSPeter Spreadborough /*
3150513f0afSPeter Spreadborough  * Check if the alarm thread that walks through the flows is started
3160513f0afSPeter Spreadborough  *
3170513f0afSPeter Spreadborough  * ctxt [in] The ulp context for the flow counter manager
3180513f0afSPeter Spreadborough  *
3190513f0afSPeter Spreadborough  */
3200513f0afSPeter Spreadborough bool ulp_sc_mgr_thread_isstarted(struct bnxt_ulp_context *ctxt)
3210513f0afSPeter Spreadborough {
3220513f0afSPeter Spreadborough 	struct bnxt_ulp_sc_info *ulp_sc_info;
3230513f0afSPeter Spreadborough 
3240513f0afSPeter Spreadborough 	ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt);
3250513f0afSPeter Spreadborough 
3260513f0afSPeter Spreadborough 	if (ulp_sc_info)
3270513f0afSPeter Spreadborough 		return !!(ulp_sc_info->flags & ULP_FLAG_SC_THREAD);
3280513f0afSPeter Spreadborough 
3290513f0afSPeter Spreadborough 	return false;
3300513f0afSPeter Spreadborough }
3310513f0afSPeter Spreadborough 
3320513f0afSPeter Spreadborough /*
3330513f0afSPeter Spreadborough  * Setup the Flow counter timer thread that will fetch/accumulate raw counter
3340513f0afSPeter Spreadborough  * data from the chip's internal flow counters
3350513f0afSPeter Spreadborough  *
3360513f0afSPeter Spreadborough  * ctxt [in] The ulp context for the flow counter manager
3370513f0afSPeter Spreadborough  *
3380513f0afSPeter Spreadborough  */
3390513f0afSPeter Spreadborough int32_t
3400513f0afSPeter Spreadborough ulp_sc_mgr_thread_start(struct bnxt_ulp_context *ctxt)
3410513f0afSPeter Spreadborough {
3420513f0afSPeter Spreadborough 	struct bnxt_ulp_sc_info *ulp_sc_info;
343*ca827d42SPeter Spreadborough 	rte_thread_attr_t attr;
344*ca827d42SPeter Spreadborough 	rte_cpuset_t mask;
345*ca827d42SPeter Spreadborough 	size_t i;
3460513f0afSPeter Spreadborough 	int rc;
3470513f0afSPeter Spreadborough 
3480513f0afSPeter Spreadborough 	ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt);
3490513f0afSPeter Spreadborough 
3500513f0afSPeter Spreadborough 	if (ulp_sc_info && !(ulp_sc_info->flags & ULP_FLAG_SC_THREAD)) {
351*ca827d42SPeter Spreadborough 		rte_thread_attr_init(&attr);
352*ca827d42SPeter Spreadborough 
353*ca827d42SPeter Spreadborough 		rte_thread_get_affinity(&mask);
354*ca827d42SPeter Spreadborough 
355*ca827d42SPeter Spreadborough 		for (i = 1; i < CPU_SETSIZE; i++) {
356*ca827d42SPeter Spreadborough 			if (CPU_ISSET(i, &mask)) {
357*ca827d42SPeter Spreadborough 				CPU_ZERO(&mask);
358*ca827d42SPeter Spreadborough 				CPU_SET(i + 2, &mask);
359*ca827d42SPeter Spreadborough 				break;
360*ca827d42SPeter Spreadborough 			}
361*ca827d42SPeter Spreadborough 		}
362*ca827d42SPeter Spreadborough 
363*ca827d42SPeter Spreadborough 		rc = rte_thread_attr_set_affinity(&attr, &mask);
364*ca827d42SPeter Spreadborough 		if (rc)
365*ca827d42SPeter Spreadborough 			return rc;
366*ca827d42SPeter Spreadborough 
3670513f0afSPeter Spreadborough 		rc = rte_thread_create(&ulp_sc_info->tid,
368*ca827d42SPeter Spreadborough 				       &attr,
3690513f0afSPeter Spreadborough 				       &ulp_stats_cache_main_loop,
3700513f0afSPeter Spreadborough 				       (void *)ctxt->cfg_data);
3710513f0afSPeter Spreadborough 		if (rc)
3720513f0afSPeter Spreadborough 			return rc;
3730513f0afSPeter Spreadborough 
374*ca827d42SPeter Spreadborough 		rte_thread_set_prefixed_name(ulp_sc_info->tid, "ulp_sc_mgr");
375*ca827d42SPeter Spreadborough 
3760513f0afSPeter Spreadborough 		ulp_sc_info->flags |= ULP_FLAG_SC_THREAD;
3770513f0afSPeter Spreadborough 	}
3780513f0afSPeter Spreadborough 
3790513f0afSPeter Spreadborough 	return 0;
3800513f0afSPeter Spreadborough }
3810513f0afSPeter Spreadborough 
3820513f0afSPeter Spreadborough /*
3830513f0afSPeter Spreadborough  * Cancel the alarm handler
3840513f0afSPeter Spreadborough  *
3850513f0afSPeter Spreadborough  * ctxt [in] The ulp context for the flow counter manager
3860513f0afSPeter Spreadborough  *
3870513f0afSPeter Spreadborough  */
3880513f0afSPeter Spreadborough void ulp_sc_mgr_thread_cancel(struct bnxt_ulp_context *ctxt)
3890513f0afSPeter Spreadborough {
3900513f0afSPeter Spreadborough 	struct bnxt_ulp_sc_info *ulp_sc_info;
3910513f0afSPeter Spreadborough 
3920513f0afSPeter Spreadborough 	ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt);
3930513f0afSPeter Spreadborough 	if (!ulp_sc_info)
3940513f0afSPeter Spreadborough 		return;
3950513f0afSPeter Spreadborough 
3960513f0afSPeter Spreadborough 	ulp_sc_info->flags &= ~ULP_FLAG_SC_THREAD;
3970513f0afSPeter Spreadborough }
3980513f0afSPeter Spreadborough 
3990513f0afSPeter Spreadborough /*
4000513f0afSPeter Spreadborough  * Fill the rte_flow_query_count 'data' argument passed
4010513f0afSPeter Spreadborough  * in the rte_flow_query() with the values obtained and
4020513f0afSPeter Spreadborough  * accumulated locally.
4030513f0afSPeter Spreadborough  *
4040513f0afSPeter Spreadborough  * ctxt [in] The ulp context for the flow counter manager
4050513f0afSPeter Spreadborough  *
4060513f0afSPeter Spreadborough  * flow_id [in] The HW flow ID
4070513f0afSPeter Spreadborough  *
4080513f0afSPeter Spreadborough  * count [out] The rte_flow_query_count 'data' that is set
4090513f0afSPeter Spreadborough  *
4100513f0afSPeter Spreadborough  */
4110513f0afSPeter Spreadborough int ulp_sc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
4120513f0afSPeter Spreadborough 			       uint32_t flow_id,
4130513f0afSPeter Spreadborough 			       struct rte_flow_query_count *count)
4140513f0afSPeter Spreadborough {
4150513f0afSPeter Spreadborough 	struct ulp_sc_tfc_stats_cache_entry *sce;
4160513f0afSPeter Spreadborough 	struct bnxt_ulp_sc_info *ulp_sc_info;
417a089734aSShuanglin Wang 	struct ulp_fdb_parent_info *pc_entry;
418a089734aSShuanglin Wang 	struct bnxt_ulp_flow_db *flow_db;
419a089734aSShuanglin Wang 	uint32_t max_array;
420a089734aSShuanglin Wang 	uint32_t child_fid;
421a089734aSShuanglin Wang 	uint32_t a_idx;
422a089734aSShuanglin Wang 	uint32_t f2_cnt;
423a089734aSShuanglin Wang 	uint64_t *t;
424a089734aSShuanglin Wang 	uint64_t bs;
4250513f0afSPeter Spreadborough 	int rc = 0;
4260513f0afSPeter Spreadborough 
427a089734aSShuanglin Wang 	/* Get stats cache info */
4280513f0afSPeter Spreadborough 	ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt);
4290513f0afSPeter Spreadborough 	if (!ulp_sc_info)
4300513f0afSPeter Spreadborough 		return -ENODEV;
4310513f0afSPeter Spreadborough 
4320513f0afSPeter Spreadborough 	sce = ulp_sc_info->stats_cache_tbl;
4330513f0afSPeter Spreadborough 	sce += flow_id;
4340513f0afSPeter Spreadborough 
435a089734aSShuanglin Wang 	/* To handle the parent flow */
436a089734aSShuanglin Wang 	if (sce->flags & ULP_SC_ENTRY_FLAG_PARENT) {
437a089734aSShuanglin Wang 		flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ctxt);
438a089734aSShuanglin Wang 		if (!flow_db) {
439a089734aSShuanglin Wang 			BNXT_DRV_DBG(ERR, "parent child db validation failed\n");
440a089734aSShuanglin Wang 			return -EINVAL;
441a089734aSShuanglin Wang 		}
442a089734aSShuanglin Wang 
443a089734aSShuanglin Wang 		/* Validate the arguments and parent child entry */
444a089734aSShuanglin Wang 		pc_entry = ulp_flow_db_pc_db_entry_get(ctxt, sce->pc_idx);
445a089734aSShuanglin Wang 		if (!pc_entry) {
446a089734aSShuanglin Wang 			BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n");
447a089734aSShuanglin Wang 			return -EINVAL;
448a089734aSShuanglin Wang 		}
449a089734aSShuanglin Wang 
450a089734aSShuanglin Wang 		t = pc_entry->child_fid_bitset;
451a089734aSShuanglin Wang 		f2_cnt = pc_entry->f2_cnt;
452a089734aSShuanglin Wang 		max_array = flow_db->parent_child_db.child_bitset_size * 8 / ULP_INDEX_BITMAP_SIZE;
453a089734aSShuanglin Wang 
454a089734aSShuanglin Wang 		/* Iterate all possible child flows */
455a089734aSShuanglin Wang 		for (a_idx = 0; (a_idx < max_array) && f2_cnt; a_idx++) {
456a089734aSShuanglin Wang 			/* If it is zero, then check the next bitset */
457a089734aSShuanglin Wang 			bs = t[a_idx];
458a089734aSShuanglin Wang 			if (!bs)
459a089734aSShuanglin Wang 				continue;
460a089734aSShuanglin Wang 
461a089734aSShuanglin Wang 			/* check one bitset */
462a089734aSShuanglin Wang 			do {
463a089734aSShuanglin Wang 				/* get the next child fid */
464a089734aSShuanglin Wang 				child_fid = (a_idx * ULP_INDEX_BITMAP_SIZE) + rte_clz64(bs);
465a089734aSShuanglin Wang 				sce = ulp_sc_info->stats_cache_tbl;
466a089734aSShuanglin Wang 				sce += child_fid;
467a089734aSShuanglin Wang 
468a089734aSShuanglin Wang 				/* clear the bit for this child flow */
469a089734aSShuanglin Wang 				ULP_INDEX_BITMAP_RESET(bs, child_fid);
470a089734aSShuanglin Wang 				f2_cnt--;
471a089734aSShuanglin Wang 
472a089734aSShuanglin Wang 				/* no counter action, then ignore flows */
473a089734aSShuanglin Wang 				if (!(sce->flags & ULP_SC_ENTRY_FLAG_VALID))
474a089734aSShuanglin Wang 					continue;
475a089734aSShuanglin Wang 				count->hits += sce->packet_count;
476a089734aSShuanglin Wang 				count->hits_set = 1;
477a089734aSShuanglin Wang 				count->bytes += sce->byte_count;
478a089734aSShuanglin Wang 				count->bytes_set = 1;
479a089734aSShuanglin Wang 			} while (bs && f2_cnt);
480a089734aSShuanglin Wang 		}
481a089734aSShuanglin Wang 	} else {
482a089734aSShuanglin Wang 		/* To handle regular or child flows */
4830513f0afSPeter Spreadborough 		/* If entry is not valid return an error */
4840513f0afSPeter Spreadborough 		if (!(sce->flags & ULP_SC_ENTRY_FLAG_VALID))
4850513f0afSPeter Spreadborough 			return -EBUSY;
4860513f0afSPeter Spreadborough 
4870513f0afSPeter Spreadborough 		count->hits = sce->packet_count;
4880513f0afSPeter Spreadborough 		count->hits_set = 1;
4890513f0afSPeter Spreadborough 		count->bytes = sce->byte_count;
4900513f0afSPeter Spreadborough 		count->bytes_set = 1;
4910513f0afSPeter Spreadborough 
4920513f0afSPeter Spreadborough 		if (count->reset)
4930513f0afSPeter Spreadborough 			sce->reset = true;
494a089734aSShuanglin Wang 	}
4950513f0afSPeter Spreadborough 	return rc;
4960513f0afSPeter Spreadborough }
4970513f0afSPeter Spreadborough 
4980513f0afSPeter Spreadborough 
4990513f0afSPeter Spreadborough int ulp_sc_mgr_entry_alloc(struct bnxt_ulp_mapper_parms *parms,
5000513f0afSPeter Spreadborough 			   uint64_t counter_handle,
5010513f0afSPeter Spreadborough 			   struct bnxt_ulp_mapper_tbl_info *tbl)
5020513f0afSPeter Spreadborough {
5030513f0afSPeter Spreadborough 	struct ulp_sc_tfc_stats_cache_entry *sce;
5040513f0afSPeter Spreadborough 	struct bnxt_ulp_sc_info *ulp_sc_info;
5050513f0afSPeter Spreadborough 
5060513f0afSPeter Spreadborough 	ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(parms->ulp_ctx);
5070513f0afSPeter Spreadborough 	if (!ulp_sc_info)
5080513f0afSPeter Spreadborough 		return -ENODEV;
5090513f0afSPeter Spreadborough 
5100513f0afSPeter Spreadborough 	sce = ulp_sc_info->stats_cache_tbl;
5110513f0afSPeter Spreadborough 	sce += parms->flow_id;
5120513f0afSPeter Spreadborough 
5130513f0afSPeter Spreadborough 	/* If entry is not free return an error */
5140513f0afSPeter Spreadborough 	if (sce->flags & ULP_SC_ENTRY_FLAG_VALID) {
51567ad4000SKishore Padmanabha 		BNXT_DRV_DBG(ERR, "Entry is not free, invalid flow id %u\n",
51667ad4000SKishore Padmanabha 			     parms->flow_id);
5170513f0afSPeter Spreadborough 		return -EBUSY;
5180513f0afSPeter Spreadborough 	}
5190513f0afSPeter Spreadborough 
5200513f0afSPeter Spreadborough 	memset(sce, 0, sizeof(*sce));
5210513f0afSPeter Spreadborough 	sce->ctxt = parms->ulp_ctx;
5220513f0afSPeter Spreadborough 	sce->flags |= ULP_SC_ENTRY_FLAG_VALID;
523a089734aSShuanglin Wang 	if (parms->parent_flow)
524a089734aSShuanglin Wang 		sce->flags |= ULP_SC_ENTRY_FLAG_PARENT;
5250513f0afSPeter Spreadborough 	sce->handle = counter_handle;
5260513f0afSPeter Spreadborough 	sce->dir = tbl->direction;
5270513f0afSPeter Spreadborough 	ulp_sc_info->num_entries++;
5280513f0afSPeter Spreadborough 	return 0;
5290513f0afSPeter Spreadborough }
5300513f0afSPeter Spreadborough 
5310513f0afSPeter Spreadborough void ulp_sc_mgr_entry_free(struct bnxt_ulp_context *ulp,
5320513f0afSPeter Spreadborough 			   uint32_t fid)
5330513f0afSPeter Spreadborough {
5340513f0afSPeter Spreadborough 	struct ulp_sc_tfc_stats_cache_entry *sce;
5350513f0afSPeter Spreadborough 	struct bnxt_ulp_sc_info *ulp_sc_info;
5360513f0afSPeter Spreadborough 
5370513f0afSPeter Spreadborough 	ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ulp);
5380513f0afSPeter Spreadborough 	if (!ulp_sc_info)
5390513f0afSPeter Spreadborough 		return;
5400513f0afSPeter Spreadborough 
5410513f0afSPeter Spreadborough 	sce = ulp_sc_info->stats_cache_tbl;
5420513f0afSPeter Spreadborough 	sce += fid;
5430513f0afSPeter Spreadborough 
5440513f0afSPeter Spreadborough 	if (!(sce->flags & ULP_SC_ENTRY_FLAG_VALID)) {
54567ad4000SKishore Padmanabha 		BNXT_DRV_DBG(ERR, "Entry already free, invalid flow id %u\n",
54667ad4000SKishore Padmanabha 			     fid);
5470513f0afSPeter Spreadborough 		return;
5480513f0afSPeter Spreadborough 	}
5490513f0afSPeter Spreadborough 
5500513f0afSPeter Spreadborough 	sce->flags = 0;
5510513f0afSPeter Spreadborough 	ulp_sc_info->num_entries--;
5520513f0afSPeter Spreadborough }
553a089734aSShuanglin Wang 
554a089734aSShuanglin Wang /*
555a089734aSShuanglin Wang  * Set pc_idx for the flow if stat cache info is valid
556a089734aSShuanglin Wang  *
557a089734aSShuanglin Wang  * ctxt [in] The ulp context for the flow counter manager
558a089734aSShuanglin Wang  *
559a089734aSShuanglin Wang  * flow_id [in] The HW flow ID
560a089734aSShuanglin Wang  *
561a089734aSShuanglin Wang  * pc_idx [in] The parent flow entry idx
562a089734aSShuanglin Wang  *
563a089734aSShuanglin Wang  */
564a089734aSShuanglin Wang void ulp_sc_mgr_set_pc_idx(struct bnxt_ulp_context *ctxt,
565a089734aSShuanglin Wang 			   uint32_t flow_id,
566a089734aSShuanglin Wang 			   uint32_t pc_idx)
567a089734aSShuanglin Wang {
568a089734aSShuanglin Wang 	struct ulp_sc_tfc_stats_cache_entry *sce;
569a089734aSShuanglin Wang 	struct bnxt_ulp_sc_info *ulp_sc_info;
570a089734aSShuanglin Wang 
571a089734aSShuanglin Wang 	/* Get stats cache info */
572a089734aSShuanglin Wang 	ulp_sc_info = bnxt_ulp_cntxt_ptr2_sc_info_get(ctxt);
573a089734aSShuanglin Wang 	if (!ulp_sc_info)
574a089734aSShuanglin Wang 		return;
575a089734aSShuanglin Wang 
576a089734aSShuanglin Wang 	sce = ulp_sc_info->stats_cache_tbl;
577a089734aSShuanglin Wang 	sce += flow_id;
578a089734aSShuanglin Wang 	sce->pc_idx = pc_idx & ULP_SC_PC_IDX_MASK;
579a089734aSShuanglin Wang }
580