-
-/**
- * Validates EM number of entries requested
- *
- * [in] tbl_scope_cb
- * Pointer to table scope control block to be populated
- *
- * [in] parms
- * Pointer to input parameters
- *
- * Returns:
- * 0 - Success
- * -EINVAL - Parameter error
- */
-static int
-tf_em_validate_num_entries(struct tf_tbl_scope_cb *tbl_scope_cb,
- struct tf_alloc_tbl_scope_parms *parms)
-{
- uint32_t cnt;
-
- if (parms->rx_mem_size_in_mb != 0) {
- uint32_t key_b = 2 * ((parms->rx_max_key_sz_in_bits / 8) + 1);
- uint32_t action_b = ((parms->rx_max_action_entry_sz_in_bits / 8)
- + 1);
- uint32_t num_entries = (parms->rx_mem_size_in_mb *
- TF_MEGABYTE) / (key_b + action_b);
-
- if (num_entries < TF_EM_MIN_ENTRIES) {
- TFP_DRV_LOG(ERR, "EEM: Insufficient memory requested:"
- "%uMB\n",
- parms->rx_mem_size_in_mb);
- return -EINVAL;
- }
-
- cnt = TF_EM_MIN_ENTRIES;
- while (num_entries > cnt &&
- cnt <= TF_EM_MAX_ENTRIES)
- cnt *= 2;
-
- if (cnt > TF_EM_MAX_ENTRIES) {
- TFP_DRV_LOG(ERR, "EEM: Invalid number of Tx requested: "
- "%u\n",
- (parms->tx_num_flows_in_k * TF_KILOBYTE));
- return -EINVAL;
- }
-
- parms->rx_num_flows_in_k = cnt / TF_KILOBYTE;
- } else {
- if ((parms->rx_num_flows_in_k * TF_KILOBYTE) <
- TF_EM_MIN_ENTRIES ||
- (parms->rx_num_flows_in_k * TF_KILOBYTE) >
- tbl_scope_cb->em_caps[TF_DIR_RX].max_entries_supported) {
- TFP_DRV_LOG(ERR,
- "EEM: Invalid number of Rx flows "
- "requested:%u max:%u\n",
- parms->rx_num_flows_in_k * TF_KILOBYTE,
- tbl_scope_cb->em_caps[TF_DIR_RX].max_entries_supported);
- return -EINVAL;
- }
-
- /* must be a power-of-2 supported value
- * in the range 32K - 128M
- */
- cnt = TF_EM_MIN_ENTRIES;
- while ((parms->rx_num_flows_in_k * TF_KILOBYTE) != cnt &&
- cnt <= TF_EM_MAX_ENTRIES)
- cnt *= 2;
-
- if (cnt > TF_EM_MAX_ENTRIES) {
- TFP_DRV_LOG(ERR,
- "EEM: Invalid number of Rx requested: %u\n",
- (parms->rx_num_flows_in_k * TF_KILOBYTE));
- return -EINVAL;
- }
- }
-
- if (parms->tx_mem_size_in_mb != 0) {
- uint32_t key_b = 2 * (parms->tx_max_key_sz_in_bits / 8 + 1);
- uint32_t action_b = ((parms->tx_max_action_entry_sz_in_bits / 8)
- + 1);
- uint32_t num_entries = (parms->tx_mem_size_in_mb *
- (TF_KILOBYTE * TF_KILOBYTE)) /
- (key_b + action_b);
-
- if (num_entries < TF_EM_MIN_ENTRIES) {
- TFP_DRV_LOG(ERR,
- "EEM: Insufficient memory requested:%uMB\n",
- parms->rx_mem_size_in_mb);
- return -EINVAL;
- }
-
- cnt = TF_EM_MIN_ENTRIES;
- while (num_entries > cnt &&
- cnt <= TF_EM_MAX_ENTRIES)
- cnt *= 2;
-
- if (cnt > TF_EM_MAX_ENTRIES) {
- TFP_DRV_LOG(ERR,
- "EEM: Invalid number of Tx requested: %u\n",
- (parms->tx_num_flows_in_k * TF_KILOBYTE));
- return -EINVAL;
- }
-
- parms->tx_num_flows_in_k = cnt / TF_KILOBYTE;
- } else {
- if ((parms->tx_num_flows_in_k * TF_KILOBYTE) <
- TF_EM_MIN_ENTRIES ||
- (parms->tx_num_flows_in_k * TF_KILOBYTE) >
- tbl_scope_cb->em_caps[TF_DIR_TX].max_entries_supported) {
- TFP_DRV_LOG(ERR,
- "EEM: Invalid number of Tx flows "
- "requested:%u max:%u\n",
- (parms->tx_num_flows_in_k * TF_KILOBYTE),
- tbl_scope_cb->em_caps[TF_DIR_TX].max_entries_supported);
- return -EINVAL;
- }
-
- cnt = TF_EM_MIN_ENTRIES;
- while ((parms->tx_num_flows_in_k * TF_KILOBYTE) != cnt &&
- cnt <= TF_EM_MAX_ENTRIES)
- cnt *= 2;
-
- if (cnt > TF_EM_MAX_ENTRIES) {
- TFP_DRV_LOG(ERR,
- "EEM: Invalid number of Tx requested: %u\n",
- (parms->tx_num_flows_in_k * TF_KILOBYTE));
- return -EINVAL;
- }
- }
-
- if (parms->rx_num_flows_in_k != 0 &&
- (parms->rx_max_key_sz_in_bits / 8 == 0)) {
- TFP_DRV_LOG(ERR,
- "EEM: Rx key size required: %u\n",
- (parms->rx_max_key_sz_in_bits));
- return -EINVAL;
- }
-
- if (parms->tx_num_flows_in_k != 0 &&
- (parms->tx_max_key_sz_in_bits / 8 == 0)) {
- TFP_DRV_LOG(ERR,
- "EEM: Tx key size required: %u\n",
- (parms->tx_max_key_sz_in_bits));
- return -EINVAL;
- }
- /* Rx */
- tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].num_entries =
- parms->rx_num_flows_in_k * TF_KILOBYTE;
- tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].entry_size =
- parms->rx_max_key_sz_in_bits / 8;
-
- tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY1_TABLE].num_entries =
- parms->rx_num_flows_in_k * TF_KILOBYTE;
- tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY1_TABLE].entry_size =
- parms->rx_max_key_sz_in_bits / 8;
-
- tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_RECORD_TABLE].num_entries =
- parms->rx_num_flows_in_k * TF_KILOBYTE;
- tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_RECORD_TABLE].entry_size =
- parms->rx_max_action_entry_sz_in_bits / 8;
-
- tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_EFC_TABLE].num_entries = 0;
-
- /* Tx */
- tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY0_TABLE].num_entries =
- parms->tx_num_flows_in_k * TF_KILOBYTE;
- tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY0_TABLE].entry_size =
- parms->tx_max_key_sz_in_bits / 8;
-
- tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY1_TABLE].num_entries =
- parms->tx_num_flows_in_k * TF_KILOBYTE;
- tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_KEY1_TABLE].entry_size =
- parms->tx_max_key_sz_in_bits / 8;
-
- tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_RECORD_TABLE].num_entries =
- parms->tx_num_flows_in_k * TF_KILOBYTE;
- tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_RECORD_TABLE].entry_size =
- parms->tx_max_action_entry_sz_in_bits / 8;
-
- tbl_scope_cb->em_ctx_info[TF_DIR_TX].em_tables[TF_EFC_TABLE].num_entries = 0;
-
- return 0;
-}
-
-/** insert EEM entry API
- *
- * returns:
- * 0
- * TF_ERR - unable to get lock
- *
- * insert callback returns:
- * 0
- * TF_ERR_EM_DUP - key is already in table
- */
-static int
-tf_insert_eem_entry(struct tf_tbl_scope_cb *tbl_scope_cb,
- struct tf_insert_em_entry_parms *parms)
-{
- uint32_t mask;
- uint32_t key0_hash;
- uint32_t key1_hash;
- uint32_t key0_index;
- uint32_t key1_index;
- struct cfa_p4_eem_64b_entry key_entry;
- uint32_t index;
- enum hcapi_cfa_em_table_type table_type;
- uint32_t gfid;
- struct hcapi_cfa_hwop op;
- struct hcapi_cfa_key_tbl key_tbl;
- struct hcapi_cfa_key_data key_obj;
- struct hcapi_cfa_key_loc key_loc;
- uint64_t big_hash;
- int rc;
-
- /* Get mask to use on hash */
- mask = tf_em_get_key_mask(tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE].num_entries);
-
- if (!mask)
- return -EINVAL;
-
-#ifdef TF_EEM_DEBUG
- dump_raw((uint8_t *)parms->key, TF_HW_EM_KEY_MAX_SIZE + 4, "In Key");
-#endif
-
- big_hash = hcapi_cfa_key_hash((uint64_t *)parms->key,
- (TF_HW_EM_KEY_MAX_SIZE + 4) * 8);
- key0_hash = (uint32_t)(big_hash >> 32);
- key1_hash = (uint32_t)(big_hash & 0xFFFFFFFF);
-
- key0_index = key0_hash & mask;
- key1_index = key1_hash & mask;
-
-#ifdef TF_EEM_DEBUG
- TFP_DRV_LOG(DEBUG, "Key0 hash:0x%08x\n", key0_hash);
- TFP_DRV_LOG(DEBUG, "Key1 hash:0x%08x\n", key1_hash);
-#endif
- /*
- * Use the "result" arg to populate all of the key entry then
- * store the byte swapped "raw" entry in a local copy ready
- * for insertion in to the table.
- */
- tf_em_create_key_entry((struct cfa_p4_eem_entry_hdr *)parms->em_record,
- ((uint8_t *)parms->key),
- &key_entry);
-
- /*
- * Try to add to Key0 table, if that does not work then
- * try the key1 table.
- */
- index = key0_index;
- op.opcode = HCAPI_CFA_HWOPS_ADD;
- key_tbl.base0 = (uint8_t *)
- &tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE];
- key_obj.offset = (index * TF_EM_KEY_RECORD_SIZE) % TF_EM_PAGE_SIZE;
- key_obj.data = (uint8_t *)&key_entry;
- key_obj.size = TF_EM_KEY_RECORD_SIZE;
-
- rc = hcapi_cfa_key_hw_op(&op,
- &key_tbl,
- &key_obj,
- &key_loc);
-
- if (rc == 0) {
- table_type = TF_KEY0_TABLE;
- } else {
- index = key1_index;
-
- key_tbl.base0 = (uint8_t *)
- &tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY1_TABLE];
- key_obj.offset =
- (index * TF_EM_KEY_RECORD_SIZE) % TF_EM_PAGE_SIZE;
-
- rc = hcapi_cfa_key_hw_op(&op,
- &key_tbl,
- &key_obj,
- &key_loc);
- if (rc != 0)
- return rc;
-
- table_type = TF_KEY1_TABLE;
- }
-
- TF_SET_GFID(gfid,
- index,
- table_type);
- TF_SET_FLOW_ID(parms->flow_id,
- gfid,
- TF_GFID_TABLE_EXTERNAL,
- parms->dir);
- TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
- 0,
- 0,
- 0,
- index,
- 0,
- table_type);
-
- return 0;
-}
-
-/** delete EEM hash entry API
- *
- * returns:
- * 0
- * -EINVAL - parameter error
- * TF_NO_SESSION - bad session ID
- * TF_ERR_TBL_SCOPE - invalid table scope
- * TF_ERR_TBL_IF - invalid table interface
- *
- * insert callback returns
- * 0
- * TF_NO_EM_MATCH - entry not found
- */
-static int
-tf_delete_eem_entry(struct tf_tbl_scope_cb *tbl_scope_cb,
- struct tf_delete_em_entry_parms *parms)
-{
- enum hcapi_cfa_em_table_type hash_type;
- uint32_t index;
- struct hcapi_cfa_hwop op;
- struct hcapi_cfa_key_tbl key_tbl;
- struct hcapi_cfa_key_data key_obj;
- struct hcapi_cfa_key_loc key_loc;
- int rc;
-
- if (parms->flow_handle == 0)
- return -EINVAL;
-
- TF_GET_HASH_TYPE_FROM_FLOW_HANDLE(parms->flow_handle, hash_type);
- TF_GET_INDEX_FROM_FLOW_HANDLE(parms->flow_handle, index);
-
- op.opcode = HCAPI_CFA_HWOPS_DEL;
- key_tbl.base0 = (uint8_t *)
- &tbl_scope_cb->em_ctx_info[parms->dir].em_tables[(hash_type == 0 ?
- TF_KEY0_TABLE :
- TF_KEY1_TABLE)];
- key_obj.offset = (index * TF_EM_KEY_RECORD_SIZE) % TF_EM_PAGE_SIZE;
- key_obj.data = NULL;
- key_obj.size = TF_EM_KEY_RECORD_SIZE;
-
- rc = hcapi_cfa_key_hw_op(&op,
- &key_tbl,
- &key_obj,
- &key_loc);
-
- if (!rc)
- return rc;
-
- return 0;
-}
-
-/** insert EM hash entry API
- *
- * returns:
- * 0 - Success
- * -EINVAL - Error
- */