@@ -697,6 +697,8 @@ int hw_mod_slc_lr_alloc(struct flow_api_backend_s *be);
void hw_mod_slc_lr_free(struct flow_api_backend_s *be);
int hw_mod_slc_lr_reset(struct flow_api_backend_s *be);
int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx, int count);
+int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field, uint32_t index,
+ uint32_t value);
struct pdb_func_s {
COMMON_FUNC_INFO_S;
@@ -66,3 +66,103 @@ int hw_mod_slc_lr_rcp_flush(struct flow_api_backend_s *be, int start_idx, int co
return be->iface->slc_lr_rcp_flush(be->be_dev, &be->slc_lr, start_idx, count);
}
+
+static int hw_mod_slc_lr_rcp_mod(struct flow_api_backend_s *be, enum hw_slc_lr_e field,
+ uint32_t index, uint32_t *value, int get)
+{
+ if (index >= be->max_categories) {
+ INDEX_TOO_LARGE_LOG;
+ return INDEX_TOO_LARGE;
+ }
+
+ switch (_VER_) {
+ case 2:
+ switch (field) {
+ case HW_SLC_LR_RCP_PRESET_ALL:
+ if (get) {
+ UNSUP_FIELD_LOG;
+ return UNSUP_FIELD;
+ }
+
+ memset(&be->slc_lr.v2.rcp[index], (uint8_t)*value,
+ sizeof(struct hw_mod_slc_lr_v2_s));
+ break;
+
+ case HW_SLC_LR_RCP_FIND:
+ if (!get) {
+ UNSUP_FIELD_LOG;
+ return UNSUP_FIELD;
+ }
+
+ if (*value >= be->max_categories) {
+ INDEX_TOO_LARGE_LOG;
+ return INDEX_TOO_LARGE;
+ }
+
+ FIND_EQUAL_INDEX(be->slc_lr.v2.rcp, struct hw_mod_slc_lr_v2_s, index,
+ *value, be->max_categories);
+ break;
+
+ case HW_SLC_LR_RCP_COMPARE:
+ if (!get) {
+ UNSUP_FIELD_LOG;
+ return UNSUP_FIELD;
+ }
+
+ if (*value >= be->max_categories) {
+ INDEX_TOO_LARGE_LOG;
+ return INDEX_TOO_LARGE;
+ }
+
+ DO_COMPARE_INDEXS(be->slc_lr.v2.rcp, struct hw_mod_slc_lr_v2_s, index,
+ *value);
+ break;
+
+ case HW_SLC_LR_RCP_HEAD_SLC_EN:
+ GET_SET(be->slc_lr.v2.rcp[index].head_slc_en, value);
+ break;
+
+ case HW_SLC_LR_RCP_HEAD_DYN:
+ GET_SET(be->slc_lr.v2.rcp[index].head_dyn, value);
+ break;
+
+ case HW_SLC_LR_RCP_HEAD_OFS:
+ GET_SET_SIGNED(be->slc_lr.v2.rcp[index].head_ofs, value);
+ break;
+
+ case HW_SLC_LR_RCP_TAIL_SLC_EN:
+ GET_SET(be->slc_lr.v2.rcp[index].tail_slc_en, value);
+ break;
+
+ case HW_SLC_LR_RCP_TAIL_DYN:
+ GET_SET(be->slc_lr.v2.rcp[index].tail_dyn, value);
+ break;
+
+ case HW_SLC_LR_RCP_TAIL_OFS:
+ GET_SET_SIGNED(be->slc_lr.v2.rcp[index].tail_ofs, value);
+ break;
+
+ case HW_SLC_LR_RCP_PCAP:
+ GET_SET(be->slc_lr.v2.rcp[index].pcap, value);
+ break;
+
+ default:
+ UNSUP_FIELD_LOG;
+ return UNSUP_FIELD;
+ }
+
+ break;
+
+ default:
+ UNSUP_VER_LOG;
+ return UNSUP_VER;
+ }
+
+ return 0;
+}
+
+int hw_mod_slc_lr_rcp_set(struct flow_api_backend_s *be, enum hw_slc_lr_e field, uint32_t index,
+ uint32_t value)
+{
+ return hw_mod_slc_lr_rcp_mod(be, field, index, &value, 0);
+}
@@ -20,7 +20,13 @@ struct hw_db_inline_resource_db {
int ref;
} *cot;
+ struct hw_db_inline_resource_db_slc_lr {
+ struct hw_db_inline_slc_lr_data data;
+ int ref;
+ } *slc_lr;
+
uint32_t nb_cot;
+ uint32_t nb_slc_lr;
/* Items */
struct hw_db_inline_resource_db_cat {
@@ -55,6 +61,14 @@ int hw_db_inline_create(struct flow_nic_dev *ndev, void **db_handle)
return -1;
}
+ db->nb_slc_lr = ndev->be.max_categories;
+ db->slc_lr = calloc(db->nb_slc_lr, sizeof(struct hw_db_inline_resource_db_slc_lr));
+
+ if (db->slc_lr == NULL) {
+ hw_db_inline_destroy(db);
+ return -1;
+ }
+
db->nb_cat = ndev->be.cat.nb_cat_funcs;
db->cat = calloc(db->nb_cat, sizeof(struct hw_db_inline_resource_db_cat));
@@ -72,6 +86,7 @@ void hw_db_inline_destroy(void *db_handle)
struct hw_db_inline_resource_db *db = (struct hw_db_inline_resource_db *)db_handle;
free(db->cot);
+ free(db->slc_lr);
free(db->cat);
free(db->cfn);
@@ -95,6 +110,11 @@ void hw_db_inline_deref_idxs(struct flow_nic_dev *ndev, void *db_handle, struct
hw_db_inline_cot_deref(ndev, db_handle, *(struct hw_db_cot_idx *)&idxs[i]);
break;
+ case HW_DB_IDX_TYPE_SLC_LR:
+ hw_db_inline_slc_lr_deref(ndev, db_handle,
+ *(struct hw_db_slc_lr_idx *)&idxs[i]);
+ break;
+
default:
break;
}
@@ -235,6 +255,90 @@ void hw_db_inline_cot_deref(struct flow_nic_dev *ndev __rte_unused, void *db_han
}
}
+/******************************************************************************/
+/* SLC_LR */
+/******************************************************************************/
+
+static int hw_db_inline_slc_lr_compare(const struct hw_db_inline_slc_lr_data *data1,
+ const struct hw_db_inline_slc_lr_data *data2)
+{
+ if (!data1->head_slice_en)
+ return data1->head_slice_en == data2->head_slice_en;
+
+ return data1->head_slice_en == data2->head_slice_en &&
+ data1->head_slice_dyn == data2->head_slice_dyn &&
+ data1->head_slice_ofs == data2->head_slice_ofs;
+}
+
+struct hw_db_slc_lr_idx hw_db_inline_slc_lr_add(struct flow_nic_dev *ndev, void *db_handle,
+ const struct hw_db_inline_slc_lr_data *data)
+{
+ struct hw_db_inline_resource_db *db = (struct hw_db_inline_resource_db *)db_handle;
+ struct hw_db_slc_lr_idx idx = { .raw = 0 };
+ int found = 0;
+
+ idx.type = HW_DB_IDX_TYPE_SLC_LR;
+
+ for (uint32_t i = 1; i < db->nb_slc_lr; ++i) {
+ int ref = db->slc_lr[i].ref;
+
+ if (ref > 0 && hw_db_inline_slc_lr_compare(data, &db->slc_lr[i].data)) {
+ idx.ids = i;
+ hw_db_inline_slc_lr_ref(ndev, db, idx);
+ return idx;
+ }
+
+ if (!found && ref <= 0) {
+ found = 1;
+ idx.ids = i;
+ }
+ }
+
+ if (!found) {
+ idx.error = 1;
+ return idx;
+ }
+
+ db->slc_lr[idx.ids].ref = 1;
+ memcpy(&db->slc_lr[idx.ids].data, data, sizeof(struct hw_db_inline_slc_lr_data));
+
+ hw_mod_slc_lr_rcp_set(&ndev->be, HW_SLC_LR_RCP_HEAD_SLC_EN, idx.ids, data->head_slice_en);
+ hw_mod_slc_lr_rcp_set(&ndev->be, HW_SLC_LR_RCP_HEAD_DYN, idx.ids, data->head_slice_dyn);
+ hw_mod_slc_lr_rcp_set(&ndev->be, HW_SLC_LR_RCP_HEAD_OFS, idx.ids, data->head_slice_ofs);
+ hw_mod_slc_lr_rcp_flush(&ndev->be, idx.ids, 1);
+
+ return idx;
+}
+
+void hw_db_inline_slc_lr_ref(struct flow_nic_dev *ndev, void *db_handle,
+ struct hw_db_slc_lr_idx idx)
+{
+ (void)ndev;
+ struct hw_db_inline_resource_db *db = (struct hw_db_inline_resource_db *)db_handle;
+
+ if (!idx.error)
+ db->slc_lr[idx.ids].ref += 1;
+}
+
+void hw_db_inline_slc_lr_deref(struct flow_nic_dev *ndev, void *db_handle,
+ struct hw_db_slc_lr_idx idx)
+{
+ struct hw_db_inline_resource_db *db = (struct hw_db_inline_resource_db *)db_handle;
+
+ if (idx.error)
+ return;
+
+ db->slc_lr[idx.ids].ref -= 1;
+
+ if (db->slc_lr[idx.ids].ref <= 0) {
+ hw_mod_slc_lr_rcp_set(&ndev->be, HW_SLC_LR_RCP_PRESET_ALL, idx.ids, 0x0);
+ hw_mod_slc_lr_rcp_flush(&ndev->be, idx.ids, 1);
+
+ memset(&db->slc_lr[idx.ids].data, 0x0, sizeof(struct hw_db_inline_slc_lr_data));
+ db->slc_lr[idx.ids].ref = 0;
+ }
+}
+
/******************************************************************************/
/* CAT */
/******************************************************************************/
@@ -40,10 +40,15 @@ struct hw_db_cat_idx {
HW_DB_IDX;
};
+struct hw_db_slc_lr_idx {
+ HW_DB_IDX;
+};
+
enum hw_db_idx_type {
HW_DB_IDX_TYPE_NONE = 0,
HW_DB_IDX_TYPE_COT,
HW_DB_IDX_TYPE_CAT,
+ HW_DB_IDX_TYPE_SLC_LR,
};
/* Functionality data types */
@@ -89,6 +94,13 @@ struct hw_db_inline_cot_data {
uint32_t padding : 24;
};
+struct hw_db_inline_slc_lr_data {
+ uint32_t head_slice_en : 1;
+ uint32_t head_slice_dyn : 5;
+ uint32_t head_slice_ofs : 8;
+ uint32_t padding : 18;
+};
+
struct hw_db_inline_hsh_data {
uint32_t func;
uint64_t hash_mask;
@@ -119,6 +131,13 @@ struct hw_db_cot_idx hw_db_inline_cot_add(struct flow_nic_dev *ndev, void *db_ha
void hw_db_inline_cot_ref(struct flow_nic_dev *ndev, void *db_handle, struct hw_db_cot_idx idx);
void hw_db_inline_cot_deref(struct flow_nic_dev *ndev, void *db_handle, struct hw_db_cot_idx idx);
+struct hw_db_slc_lr_idx hw_db_inline_slc_lr_add(struct flow_nic_dev *ndev, void *db_handle,
+ const struct hw_db_inline_slc_lr_data *data);
+void hw_db_inline_slc_lr_ref(struct flow_nic_dev *ndev, void *db_handle,
+ struct hw_db_slc_lr_idx idx);
+void hw_db_inline_slc_lr_deref(struct flow_nic_dev *ndev, void *db_handle,
+ struct hw_db_slc_lr_idx idx);
+
/**/
struct hw_db_cat_idx hw_db_inline_cat_add(struct flow_nic_dev *ndev, void *db_handle,
@@ -2276,18 +2276,38 @@ static int convert_fh_to_fh_flm(struct flow_handle *fh, const uint32_t *packet_d
return 0;
}
-static int setup_flow_flm_actions(struct flow_eth_dev *dev __rte_unused,
- const struct nic_flow_def *fd __rte_unused,
+static int setup_flow_flm_actions(struct flow_eth_dev *dev,
+ const struct nic_flow_def *fd,
const struct hw_db_inline_qsl_data *qsl_data __rte_unused,
const struct hw_db_inline_hsh_data *hsh_data __rte_unused,
uint32_t group __rte_unused,
- uint32_t local_idxs[] __rte_unused,
- uint32_t *local_idx_counter __rte_unused,
+ uint32_t local_idxs[],
+ uint32_t *local_idx_counter,
uint16_t *flm_rpl_ext_ptr __rte_unused,
uint32_t *flm_ft __rte_unused,
uint32_t *flm_scrub __rte_unused,
- struct rte_flow_error *error __rte_unused)
+ struct rte_flow_error *error)
{
+ /* Setup SLC LR */
+ struct hw_db_slc_lr_idx slc_lr_idx = { .raw = 0 };
+
+ if (fd->header_strip_end_dyn != 0 || fd->header_strip_end_ofs != 0) {
+ struct hw_db_inline_slc_lr_data slc_lr_data = {
+ .head_slice_en = 1,
+ .head_slice_dyn = fd->header_strip_end_dyn,
+ .head_slice_ofs = fd->header_strip_end_ofs,
+ };
+ slc_lr_idx =
+ hw_db_inline_slc_lr_add(dev->ndev, dev->ndev->hw_db_handle, &slc_lr_data);
+ local_idxs[(*local_idx_counter)++] = slc_lr_idx.raw;
+
+ if (slc_lr_idx.error) {
+ NT_LOG(ERR, FILTER, "Could not reference SLC LR resource");
+ flow_nic_set_error(ERR_MATCH_RESOURCE_EXHAUSTION, error);
+ return -1;
+ }
+ }
+
return 0;
}
@@ -2449,6 +2469,9 @@ int initialize_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev)
if (hw_mod_cat_cot_flush(&ndev->be, 0, 1) < 0)
goto err_exit0;
+ /* SLC LR index 0 is reserved */
+ flow_nic_mark_resource_used(ndev, RES_SLC_LR_RCP, 0);
+
/* Setup filter using matching all packets violating traffic policing parameters */
flow_nic_mark_resource_used(ndev, RES_CAT_CFN, NT_VIOLATING_MBR_CFN);
@@ -2497,6 +2520,10 @@ int done_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev)
hw_mod_cat_cot_flush(&ndev->be, 0, 1);
flow_nic_free_resource(ndev, RES_CAT_CFN, 0);
+ hw_mod_slc_lr_rcp_set(&ndev->be, HW_SLC_LR_RCP_PRESET_ALL, 0, 0);
+ hw_mod_slc_lr_rcp_flush(&ndev->be, 0, 1);
+ flow_nic_free_resource(ndev, RES_SLC_LR_RCP, 0);
+
hw_mod_tpe_reset(&ndev->be);
flow_nic_free_resource(ndev, RES_TPE_RCP, 0);
flow_nic_free_resource(ndev, RES_TPE_EXT, 0);