diff --git a/hal/wifi3.0/hal_rx_flow.c b/hal/wifi3.0/hal_rx_flow.c new file mode 100644 index 0000000000..43a144901a --- /dev/null +++ b/hal/wifi3.0/hal_rx_flow.c @@ -0,0 +1,754 @@ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "qdf_module.h" +#include "dp_types.h" +#include "hal_rx_flow.h" + +#if defined(WLAN_SUPPORT_RX_FISA) +void hal_rx_dump_fse_table(struct hal_rx_fst *fst) +{ + int i = 0; + struct rx_flow_search_entry *fse = + (struct rx_flow_search_entry *)fst->base_vaddr; + + dp_info("Number flow table entries %d", fst->add_flow_count); + for (i = 0; i < fst->max_entries; i++) { + if (fse[i].valid) { + dp_info("index %d:" + " src_ip_127_96 0x%x" + " src_ip_95_640 0x%x" + " src_ip_63_32 0x%x" + " src_ip_31_0 0x%x" + " dest_ip_127_96 0x%x" + " dest_ip_95_64 0x%x" + " dest_ip_63_32 0x%x" + " dest_ip_31_0 0x%x" + " src_port 0x%x" + " dest_port 0x%x" + " l4_protocol 0x%x" + " valid 0x%x" + " reo_destination_indication 0x%x" + " msdu_drop 0x%x" + " reo_destination_handler 0x%x" + " metadata 0x%x" + " aggregation_count0x%x" + " lro_eligible 0x%x" + " msdu_count 0x%x" + " msdu_byte_count 0x%x" + " timestamp 0x%x" + " cumulative_l4_checksum 0x%x" + " cumulative_ip_length 0x%x" + " tcp_sequence_number 0x%x", + i, + fse[i].src_ip_127_96, + fse[i].src_ip_95_64, + fse[i].src_ip_63_32, + fse[i].src_ip_31_0, + fse[i].dest_ip_127_96, + fse[i].dest_ip_95_64, + fse[i].dest_ip_63_32, + fse[i].dest_ip_31_0, + fse[i].src_port, + fse[i].dest_port, + fse[i].l4_protocol, + fse[i].valid, + fse[i].reo_destination_indication, + fse[i].msdu_drop, + fse[i].reo_destination_handler, + fse[i].metadata, + fse[i].aggregation_count, + fse[i].lro_eligible, + fse[i].msdu_count, + fse[i].msdu_byte_count, + fse[i].timestamp, + fse[i].cumulative_l4_checksum, + fse[i].cumulative_ip_length, + fse[i].tcp_sequence_number); + } + } +} +#else +void hal_rx_dump_fse_table(struct hal_rx_fst *fst) +{ +} +#endif + +/** + * hal_rx_flow_setup_fse() - Setup a flow search entry in HW FST + * @fst: Pointer to the Rx Flow Search Table + * @table_offset: offset into the table where the flow is to be setup + * @flow: Flow Parameters + * + * Return: Success/Failure + */ +#ifdef WLAN_SUPPORT_RX_FLOW_TAG +void * +hal_rx_flow_setup_fse(struct hal_rx_fst *fst, uint32_t table_offset, + struct hal_rx_flow *flow) +{ + uint8_t *fse; + bool fse_valid; + + if (table_offset >= fst->max_entries) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "HAL FSE table offset %u exceeds max entries %u", + table_offset, fst->max_entries); + return NULL; + } + + fse = (uint8_t *)fst->base_vaddr + + (table_offset * HAL_RX_FST_ENTRY_SIZE); + + fse_valid = HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); + + if (fse_valid) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "HAL FSE %pK already valid", fse); + return NULL; + } + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96, + qdf_htonl(flow->tuple_info.src_ip_127_96)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64, + qdf_htonl(flow->tuple_info.src_ip_95_64)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32, + qdf_htonl(flow->tuple_info.src_ip_63_32)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0, + qdf_htonl(flow->tuple_info.src_ip_31_0)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96, + qdf_htonl(flow->tuple_info.dest_ip_127_96)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64, + qdf_htonl(flow->tuple_info.dest_ip_95_64)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32, + qdf_htonl(flow->tuple_info.dest_ip_63_32)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0, + qdf_htonl(flow->tuple_info.dest_ip_31_0)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, DEST_PORT, + (flow->tuple_info.dest_port)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, SRC_PORT, + (flow->tuple_info.src_port)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL, + flow->tuple_info.l4_protocol); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER, + flow->reo_destination_handler); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, VALID, 1); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_10, METADATA, + flow->fse_metadata); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, REO_DESTINATION_INDICATION); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, REO_DESTINATION_INDICATION) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_11, + REO_DESTINATION_INDICATION, + flow->reo_destination_indication); + + /* Reset all the other fields in FSE */ + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, RESERVED_9); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_DROP); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, RESERVED_11); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_COUNT); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_12, MSDU_BYTE_COUNT); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_13, TIMESTAMP); + + return fse; +} +#elif defined(WLAN_SUPPORT_RX_FISA) +/** + * hal_rx_flow_setup_fse() - Setup a flow search entry in HW FST + * @fst: Pointer to the Rx Flow Search Table + * @table_offset: offset into the table where the flow is to be setup + * @flow: Flow Parameters + * + * Flow table entry fields are updated in host byte order, little endian order. + * + * Return: Success/Failure + */ +void * +hal_rx_flow_setup_fse(struct hal_rx_fst *fst, uint32_t table_offset, + struct hal_rx_flow *flow) +{ + uint8_t *fse; + bool fse_valid; + + if (table_offset >= fst->max_entries) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "HAL FSE table offset %u exceeds max entries %u", + table_offset, fst->max_entries); + return NULL; + } + + fse = (uint8_t *)fst->base_vaddr + + (table_offset * HAL_RX_FST_ENTRY_SIZE); + + fse_valid = HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); + + if (fse_valid) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "HAL FSE %pK already valid", fse); + return NULL; + } + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96, + (flow->tuple_info.src_ip_127_96)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64, + (flow->tuple_info.src_ip_95_64)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32, + (flow->tuple_info.src_ip_63_32)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0, + (flow->tuple_info.src_ip_31_0)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96, + (flow->tuple_info.dest_ip_127_96)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64, + (flow->tuple_info.dest_ip_95_64)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32, + (flow->tuple_info.dest_ip_63_32)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0, + (flow->tuple_info.dest_ip_31_0)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, DEST_PORT, + (flow->tuple_info.dest_port)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, SRC_PORT, + (flow->tuple_info.src_port)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL, + flow->tuple_info.l4_protocol); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER, + flow->reo_destination_handler); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, VALID, 1); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_10, METADATA, + (flow->fse_metadata)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_INDICATION); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_INDICATION) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, + REO_DESTINATION_INDICATION, + flow->reo_destination_indication); + + /* Reset all the other fields in FSE */ + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, RESERVED_9); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, MSDU_DROP); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_COUNT); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_12, MSDU_BYTE_COUNT); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_13, TIMESTAMP); + + return fse; +} +#endif /* WLAN_SUPPORT_RX_FISA */ +qdf_export_symbol(hal_rx_flow_setup_fse); + +/** + * hal_rx_flow_delete_entry() - Delete a flow from the Rx Flow Search Table + * @fst: Pointer to the Rx Flow Search Table + * @hal_rx_fse: Pointer to the Rx Flow that is to be deleted from the FST + * + * Return: Success/Failure + */ +inline QDF_STATUS +hal_rx_flow_delete_entry(struct hal_rx_fst *fst, void *hal_rx_fse) +{ + uint8_t *fse = (uint8_t *)hal_rx_fse; + + if (!HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID)) + return QDF_STATUS_E_NOENT; + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); + + return QDF_STATUS_SUCCESS; +} +qdf_export_symbol(hal_rx_flow_delete_entry); + +/** + * hal_rx_fst_key_configure() - Configure the Toeplitz key in the FST + * @fst: Pointer to the Rx Flow Search Table + * + * Return: Success/Failure + */ +static void hal_rx_fst_key_configure(struct hal_rx_fst *fst) +{ + uint8_t key_bytes[HAL_FST_HASH_KEY_SIZE_BYTES]; + + qdf_mem_copy(key_bytes, fst->key, HAL_FST_HASH_KEY_SIZE_BYTES); + + /** + * The Toeplitz algorithm as per the Microsoft spec works in a + * “big-endian” manner, using the MSBs of the key to hash the + * initial bytes of the input going on to use up the lower order bits + * of the key to hash further bytes of the input until the LSBs of the + * key are used finally. + * + * So first, rightshift 320-bit input key 5 times to get 315 MS bits + */ + key_bitwise_shift_left(key_bytes, HAL_FST_HASH_KEY_SIZE_BYTES, 5); + key_reverse(fst->shifted_key, key_bytes, HAL_FST_HASH_KEY_SIZE_BYTES); +} + +/** + * hal_rx_fst_get_base() - Retrieve the virtual base address of the Rx FST + * @fst: Pointer to the Rx Flow Search Table + * + * Return: Success/Failure + */ +static inline void *hal_rx_fst_get_base(struct hal_rx_fst *fst) +{ + return fst->base_vaddr; +} + +/** + * hal_rx_fst_get_fse_size() - Retrieve the size of each entry(flow) in Rx FST + * + * Return: size of each entry/flow in Rx FST + */ +static inline uint32_t hal_rx_fst_get_fse_size(void) +{ + return HAL_RX_FST_ENTRY_SIZE; +} + +/** + * hal_rx_flow_get_tuple_info() - Retrieve the 5-tuple flow info for an entry + * @hal_fse: Pointer to the Flow in Rx FST + * @tuple_info: 5-tuple info of the flow returned to the caller + * + * Return: Success/Failure + */ +QDF_STATUS hal_rx_flow_get_tuple_info(void *hal_fse, + struct hal_flow_tuple_info *tuple_info) +{ + if (!hal_fse || !tuple_info) + return QDF_STATUS_E_INVAL; + + if (!HAL_GET_FLD(hal_fse, RX_FLOW_SEARCH_ENTRY_9, VALID)) + return QDF_STATUS_E_NOENT; + + tuple_info->src_ip_127_96 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_0, + SRC_IP_127_96)); + tuple_info->src_ip_95_64 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_1, + SRC_IP_95_64)); + tuple_info->src_ip_63_32 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_2, + SRC_IP_63_32)); + tuple_info->src_ip_31_0 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_3, + SRC_IP_31_0)); + tuple_info->dest_ip_127_96 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_4, + DEST_IP_127_96)); + tuple_info->dest_ip_95_64 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_5, + DEST_IP_95_64)); + tuple_info->dest_ip_63_32 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_6, + DEST_IP_63_32)); + tuple_info->dest_ip_31_0 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_7, + DEST_IP_31_0)); + tuple_info->dest_port = HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_8, + DEST_PORT); + tuple_info->src_port = HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_8, + SRC_PORT); + tuple_info->l4_protocol = HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_9, + L4_PROTOCOL); + + return QDF_STATUS_SUCCESS; +} + +/** + * hal_flow_toeplitz_create_cache() - Calculate hashes for each possible + * byte value with the key taken as is + * + * @fst: FST Handle + * @key: Hash Key + * + * Return: Success/Failure + */ +static void hal_flow_toeplitz_create_cache(struct hal_rx_fst *fst) +{ + int bit; + int val; + int i; + uint8_t *key = fst->shifted_key; + + /* + * Initialise to first 32 bits of the key; shift in further key material + * through the loop + */ + uint32_t cur_key = (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | + key[3]; + + for (i = 0; i < HAL_FST_HASH_KEY_SIZE_BYTES; i++) { + uint8_t new_key_byte; + uint32_t shifted_key[8]; + + if (i + 4 < HAL_FST_HASH_KEY_SIZE_BYTES) + new_key_byte = key[i + 4]; + else + new_key_byte = 0; + + shifted_key[0] = cur_key; + + for (bit = 1; bit < 8; bit++) { + /* + * For each iteration, shift out one more bit of the + * current key and shift in one more bit of the new key + * material + */ + shifted_key[bit] = cur_key << bit | + new_key_byte >> (8 - bit); + } + + for (val = 0; val < (1 << 8); val++) { + uint32_t hash = 0; + int mask; + + /* + * For each bit set in the input, XOR in + * the appropriately shifted key + */ + for (bit = 0, mask = 1 << 7; bit < 8; bit++, mask >>= 1) + if ((val & mask)) + hash ^= shifted_key[bit]; + + fst->key_cache[i][val] = hash; + } + + cur_key = cur_key << 8 | new_key_byte; + } +} + +/** + * hal_rx_fst_attach() - Initialize Rx flow search table in HW FST + * + * @qdf_dev: QDF device handle + * @hal_fst_base_paddr: Pointer to the physical base address of the Rx FST + * @max_entries: Max number of flows allowed in the FST + * @max_search: Number of collisions allowed in the hash-based FST + * @hash_key: Toeplitz key used for the hash FST + * + * Return: + */ +struct hal_rx_fst * +hal_rx_fst_attach(qdf_device_t qdf_dev, + uint64_t *hal_fst_base_paddr, uint16_t max_entries, + uint16_t max_search, uint8_t *hash_key) +{ + struct hal_rx_fst *fst = qdf_mem_malloc(sizeof(struct hal_rx_fst)); + + if (!fst) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + FL("hal fst allocation failed,")); + return NULL; + } + + qdf_mem_set(fst, 0, sizeof(struct hal_rx_fst)); + + fst->key = hash_key; + fst->max_skid_length = max_search; + fst->max_entries = max_entries; + fst->hash_mask = max_entries - 1; + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "HAL FST allocation %x %d * %d\n", fst, + fst->max_entries, HAL_RX_FST_ENTRY_SIZE); + + fst->base_vaddr = (uint8_t *)qdf_mem_alloc_consistent(qdf_dev, + qdf_dev->dev, + (fst->max_entries * HAL_RX_FST_ENTRY_SIZE), + &fst->base_paddr); + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, + "hal_rx_fst base address 0x%x", fst->base_paddr); + if (!fst->base_vaddr) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + FL("hal fst->base_vaddr allocation failed")); + qdf_mem_free(fst); + return NULL; + } + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_DEBUG, + (void *)fst->key, HAL_FST_HASH_KEY_SIZE_BYTES); + + qdf_mem_set((uint8_t *)fst->base_vaddr, 0, + (fst->max_entries * HAL_RX_FST_ENTRY_SIZE)); + + hal_rx_fst_key_configure(fst); + hal_flow_toeplitz_create_cache(fst); + *hal_fst_base_paddr = (uint64_t)fst->base_paddr; + return fst; +} +qdf_export_symbol(hal_rx_fst_attach); + +/** + * hal_rx_fst_detach() - De-init the Rx flow search table from HW + * + * @rx_fst: Pointer to the Rx FST + * @qdf_dev: QDF device handle + * + * Return: + */ +void hal_rx_fst_detach(struct hal_rx_fst *rx_fst, + qdf_device_t qdf_dev) +{ + if (!rx_fst || !qdf_dev) + return; + + qdf_mem_free_consistent(qdf_dev, qdf_dev->dev, + rx_fst->max_entries * HAL_RX_FST_ENTRY_SIZE, + rx_fst->base_vaddr, rx_fst->base_paddr, 0); + + qdf_mem_free(rx_fst); +} +qdf_export_symbol(hal_rx_fst_detach); + +/** + * hal_flow_toeplitz_hash() - Calculate Toeplitz hash by using the cached key + * + * @hal_fst: FST Handle + * @flow: Flow Parameters + * + * Return: Success/Failure + */ +uint32_t +hal_flow_toeplitz_hash(void *hal_fst, struct hal_rx_flow *flow) +{ + int i, j; + uint32_t hash = 0; + struct hal_rx_fst *fst = (struct hal_rx_fst *)hal_fst; + uint32_t input[HAL_FST_HASH_KEY_SIZE_WORDS]; + uint8_t *tuple; + + qdf_mem_zero(input, HAL_FST_HASH_KEY_SIZE_BYTES); + *(uint32_t *)&input[0] = qdf_htonl(flow->tuple_info.src_ip_127_96); + *(uint32_t *)&input[1] = qdf_htonl(flow->tuple_info.src_ip_95_64); + *(uint32_t *)&input[2] = qdf_htonl(flow->tuple_info.src_ip_63_32); + *(uint32_t *)&input[3] = qdf_htonl(flow->tuple_info.src_ip_31_0); + *(uint32_t *)&input[4] = qdf_htonl(flow->tuple_info.dest_ip_127_96); + *(uint32_t *)&input[5] = qdf_htonl(flow->tuple_info.dest_ip_95_64); + *(uint32_t *)&input[6] = qdf_htonl(flow->tuple_info.dest_ip_63_32); + *(uint32_t *)&input[7] = qdf_htonl(flow->tuple_info.dest_ip_31_0); + *(uint32_t *)&input[8] = (flow->tuple_info.dest_port << 16) | + (flow->tuple_info.src_port); + *(uint32_t *)&input[9] = flow->tuple_info.l4_protocol; + + tuple = (uint8_t *)input; + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + tuple, sizeof(input)); + for (i = 0, j = HAL_FST_HASH_DATA_SIZE - 1; + i < HAL_FST_HASH_KEY_SIZE_BYTES && j >= 0; i++, j--) { + hash ^= fst->key_cache[i][tuple[j]]; + } + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW, + "Hash value %u %u truncated hash %u\n", hash, + (hash >> 12), (hash >> 12) % (fst->max_entries)); + + hash >>= 12; + hash &= (fst->max_entries - 1); + + return hash; +} +qdf_export_symbol(hal_flow_toeplitz_hash); + +/** + * hal_rx_get_hal_hash() - Retrieve hash index of a flow in the FST table + * + * @hal_fst: HAL Rx FST Handle + * @flow_hash: Flow hash computed from flow tuple + * + * Return: hash index truncated to the size of the hash table + */ +uint32_t hal_rx_get_hal_hash(struct hal_rx_fst *hal_fst, uint32_t flow_hash) +{ + uint32_t trunc_hash = flow_hash; + + /* Take care of hash wrap around scenario */ + if (flow_hash >= hal_fst->max_entries) + trunc_hash &= hal_fst->hash_mask; + return trunc_hash; +} +qdf_export_symbol(hal_rx_get_hal_hash); + +/** + * hal_rx_insert_flow_entry() - Add a flow into the FST table + * + * @hal_fst: HAL Rx FST Handle + * @flow_hash: Flow hash computed from flow tuple + * @flow_tuple_info: Flow tuple used to compute the hash + * @flow_index: Hash index of the flow in the table when inserted successfully + * + * Return: Success if flow is inserted into the table, error otherwise + */ +QDF_STATUS +hal_rx_insert_flow_entry(struct hal_rx_fst *fst, uint32_t flow_hash, + void *flow_tuple_info, uint32_t *flow_idx) +{ + int i; + void *hal_fse; + uint32_t hal_hash; + struct hal_flow_tuple_info hal_tuple_info = { 0 }; + QDF_STATUS status; + + for (i = 0; i < fst->max_skid_length; i++) { + hal_hash = hal_rx_get_hal_hash(fst, (flow_hash + i)); + hal_fse = (uint8_t *)fst->base_vaddr + + (hal_hash * HAL_RX_FST_ENTRY_SIZE); + status = hal_rx_flow_get_tuple_info(hal_fse, &hal_tuple_info); + if (status == QDF_STATUS_E_NOENT) + break; + + /* Find the matching flow entry in HW FST */ + if (!qdf_mem_cmp(&hal_tuple_info, + flow_tuple_info, + sizeof(struct hal_flow_tuple_info))) { + dp_err("Duplicate flow entry in FST %u at skid %u ", + hal_hash, i); + return QDF_STATUS_E_EXISTS; + } + } + if (i == fst->max_skid_length) { + dp_err("Max skid length reached for hash %u", flow_hash); + return QDF_STATUS_E_RANGE; + } + *flow_idx = hal_hash; + dp_info("flow_hash = %u, skid_entry = %d, flow_addr = %pK flow_idx = %d", + flow_hash, i, hal_fse, *flow_idx); + + return QDF_STATUS_SUCCESS; +} +qdf_export_symbol(hal_rx_insert_flow_entry); + +/** + * hal_rx_find_flow_from_tuple() - Find a flow in the FST table + * + * @fst: HAL Rx FST Handle + * @flow_hash: Flow hash computed from flow tuple + * @flow_tuple_info: Flow tuple used to compute the hash + * @flow_index: Hash index of the flow in the table when found + * + * Return: Success if matching flow is found in the table, error otherwise + */ +QDF_STATUS +hal_rx_find_flow_from_tuple(struct hal_rx_fst *fst, uint32_t flow_hash, + void *flow_tuple_info, uint32_t *flow_idx) +{ + int i; + void *hal_fse; + uint32_t hal_hash; + struct hal_flow_tuple_info hal_tuple_info = { 0 }; + QDF_STATUS status; + + for (i = 0; i < fst->max_skid_length; i++) { + hal_hash = hal_rx_get_hal_hash(fst, (flow_hash + i)); + hal_fse = (uint8_t *)fst->base_vaddr + + (hal_hash * HAL_RX_FST_ENTRY_SIZE); + status = hal_rx_flow_get_tuple_info(hal_fse, &hal_tuple_info); + if (status != QDF_STATUS_SUCCESS) + continue; + + /* Find the matching flow entry in HW FST */ + if (!qdf_mem_cmp(&hal_tuple_info, + flow_tuple_info, + sizeof(struct hal_flow_tuple_info))) { + break; + } + } + + if (i == fst->max_skid_length) { + dp_err("Max skid length reached for hash %u", flow_hash); + return QDF_STATUS_E_RANGE; + } + + *flow_idx = hal_hash; + dp_info("flow_hash = %u, skid_entry = %d, flow_addr = %pK flow_idx = %d", + flow_hash, i, hal_fse, *flow_idx); + + return QDF_STATUS_SUCCESS; +} +qdf_export_symbol(hal_rx_find_flow_from_tuple); diff --git a/hal/wifi3.0/hal_rx_flow.h b/hal/wifi3.0/hal_rx_flow.h index 353f9e6f7d..b6af10517d 100644 --- a/hal/wifi3.0/hal_rx_flow.h +++ b/hal/wifi3.0/hal_rx_flow.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -99,6 +99,8 @@ struct hal_rx_fst { uint16_t max_skid_length; uint16_t hash_mask; uint32_t key_cache[HAL_FST_HASH_KEY_SIZE_BYTES][1 << 8]; + uint32_t add_flow_count; + uint32_t del_flow_count; }; /** @@ -109,108 +111,9 @@ struct hal_rx_fst { * * Return: Success/Failure */ -static void * -hal_rx_flow_setup_fse(struct hal_rx_fst *fst, uint32_t table_offset, - struct hal_rx_flow *flow) -{ - uint8_t *fse; - bool fse_valid; - - if (table_offset >= fst->max_entries) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "HAL FSE table offset %u exceeds max entries %u", - table_offset, fst->max_entries); - return NULL; - } - - fse = (uint8_t *)fst->base_vaddr + - (table_offset * HAL_RX_FST_ENTRY_SIZE); - - fse_valid = HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); - - if (fse_valid) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, - "HAL FSE %pK already valid", fse); - return NULL; - } - - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96) = - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96, - qdf_htonl(flow->tuple_info.src_ip_127_96)); - - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64) = - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64, - qdf_htonl(flow->tuple_info.src_ip_95_64)); - - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32) = - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32, - qdf_htonl(flow->tuple_info.src_ip_63_32)); - - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0) = - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0, - qdf_htonl(flow->tuple_info.src_ip_31_0)); - - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96) = - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96, - qdf_htonl(flow->tuple_info.dest_ip_127_96)); - - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64) = - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64, - qdf_htonl(flow->tuple_info.dest_ip_95_64)); - - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32) = - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32, - qdf_htonl(flow->tuple_info.dest_ip_63_32)); - - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0) = - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0, - qdf_htonl(flow->tuple_info.dest_ip_31_0)); - - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT); - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT) |= - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, DEST_PORT, - (flow->tuple_info.dest_port)); - - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT); - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT) |= - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, SRC_PORT, - (flow->tuple_info.src_port)); - - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL); - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL) |= - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL, - flow->tuple_info.l4_protocol); - - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER); - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER) |= - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER, - flow->reo_destination_handler); - - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID) |= - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, VALID, 1); - - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA); - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA) = - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_10, METADATA, - flow->fse_metadata); - - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, REO_DESTINATION_INDICATION); - HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, REO_DESTINATION_INDICATION) |= - HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_11, - REO_DESTINATION_INDICATION, - flow->reo_destination_indication); - - /* Reset all the other fields in FSE */ - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, RESERVED_9); - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_DROP); - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, RESERVED_11); - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_COUNT); - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_12, MSDU_BYTE_COUNT); - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_13, TIMESTAMP); - - return fse; -} +void *hal_rx_flow_setup_fse(struct hal_rx_fst *fst, + uint32_t table_offset, + struct hal_rx_flow *flow); /** * hal_rx_flow_delete_entry() - Delete a flow from the Rx Flow Search Table @@ -219,64 +122,8 @@ hal_rx_flow_setup_fse(struct hal_rx_fst *fst, uint32_t table_offset, * * Return: Success/Failure */ -static inline QDF_STATUS -hal_rx_flow_delete_entry(struct hal_rx_fst *fst, void *hal_rx_fse) -{ - uint8_t *fse = (uint8_t *)hal_rx_fse; - - if (!HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID)) - return QDF_STATUS_E_NOENT; - - HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); - - return QDF_STATUS_SUCCESS; -} - -/** - * hal_rx_fst_key_configure() - Configure the Toeplitz key in the FST - * @fst: Pointer to the Rx Flow Search Table - * - * Return: Success/Failure - */ -static void hal_rx_fst_key_configure(struct hal_rx_fst *fst) -{ - uint8_t key_bytes[HAL_FST_HASH_KEY_SIZE_BYTES]; - - qdf_mem_copy(key_bytes, fst->key, HAL_FST_HASH_KEY_SIZE_BYTES); - - /** - * The Toeplitz algorithm as per the Microsoft spec works in a - * “big-endian” manner, using the MSBs of the key to hash the - * initial bytes of the input going on to use up the lower order bits - * of the key to hash further bytes of the input until the LSBs of the - * key are used finally. - * - * So first, rightshift 320-bit input key 5 times to get 315 MS bits - */ - key_bitwise_shift_left(key_bytes, HAL_FST_HASH_KEY_SIZE_BYTES, 5); - key_reverse(fst->shifted_key, key_bytes, HAL_FST_HASH_KEY_SIZE_BYTES); -} - -/** - * hal_rx_fst_get_base() - Retrieve the virtual base address of the Rx FST - * @fst: Pointer to the Rx Flow Search Table - * - * Return: Success/Failure - */ -static inline void *hal_rx_fst_get_base(struct hal_rx_fst *fst) -{ - return fst->base_vaddr; -} - -/** - * hal_rx_fst_get_fse_size() - Retrieve the size of each entry(flow) in Rx FST - * - * Return: size of each entry/flow in Rx FST - */ -static inline uint32_t hal_rx_fst_get_fse_size(void) -{ - return HAL_RX_FST_ENTRY_SIZE; -} +QDF_STATUS +hal_rx_flow_delete_entry(struct hal_rx_fst *fst, void *hal_rx_fse); /** * hal_rx_flow_get_tuple_info() - Retrieve the 5-tuple flow info for an entry @@ -286,103 +133,7 @@ static inline uint32_t hal_rx_fst_get_fse_size(void) * Return: Success/Failure */ QDF_STATUS hal_rx_flow_get_tuple_info(void *hal_fse, - struct hal_flow_tuple_info *tuple_info) -{ - if (!hal_fse || !tuple_info) - return QDF_STATUS_E_INVAL; - - if (!HAL_GET_FLD(hal_fse, RX_FLOW_SEARCH_ENTRY_9, VALID)) - return QDF_STATUS_E_NOENT; - - tuple_info->src_ip_127_96 = qdf_ntohl(HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96)); - tuple_info->src_ip_95_64 = qdf_ntohl(HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64)); - tuple_info->src_ip_63_32 = qdf_ntohl(HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32)); - tuple_info->src_ip_31_0 = qdf_ntohl(HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0)); - tuple_info->dest_ip_127_96 = - qdf_ntohl(HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96)); - tuple_info->dest_ip_95_64 = qdf_ntohl(HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64)); - tuple_info->dest_ip_63_32 = qdf_ntohl(HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32)); - tuple_info->dest_ip_31_0 = qdf_ntohl(HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0)); - tuple_info->dest_port = (HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_8, DEST_PORT)); - tuple_info->src_port = (HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_8, SRC_PORT)); - tuple_info->l4_protocol = HAL_GET_FLD(hal_fse, - RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL); - - return QDF_STATUS_SUCCESS; -} - -/** - * hal_flow_toeplitz_create_cache() - Calculate hashes for each possible - * byte value with the key taken as is - * - * @fst: FST Handle - * @key: Hash Key - * - * Return: Success/Failure - */ -void hal_flow_toeplitz_create_cache(struct hal_rx_fst *fst) -{ - int bit; - int val; - int i; - uint8_t *key = fst->shifted_key; - - /* - * Initialise to first 32 bits of the key; shift in further key material - * through the loop - */ - uint32_t cur_key = (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | - key[3]; - - for (i = 0; i < HAL_FST_HASH_KEY_SIZE_BYTES; i++) { - uint8_t new_key_byte; - uint32_t shifted_key[8]; - - if (i + 4 < HAL_FST_HASH_KEY_SIZE_BYTES) - new_key_byte = key[i + 4]; - else - new_key_byte = 0; - - shifted_key[0] = cur_key; - - for (bit = 1; bit < 8; bit++) { - /* - * For each iteration, shift out one more bit of the - * current key and shift in one more bit of the new key - * material - */ - shifted_key[bit] = cur_key << bit | - new_key_byte >> (8 - bit); - } - - for (val = 0; val < (1 << 8); val++) { - uint32_t hash = 0; - int mask; - - /* - * For each bit set in the input, XOR in - * the appropriately shifted key - */ - for (bit = 0, mask = 1 << 7; bit < 8; bit++, mask >>= 1) - if ((val & mask)) - hash ^= shifted_key[bit]; - - fst->key_cache[i][val] = hash; - } - - cur_key = cur_key << 8 | new_key_byte; - } -} + struct hal_flow_tuple_info *tuple_info); /** * hal_rx_fst_attach() - Initialize Rx flow search table in HW FST @@ -395,52 +146,10 @@ void hal_flow_toeplitz_create_cache(struct hal_rx_fst *fst) * * Return: */ -static struct hal_rx_fst * +struct hal_rx_fst * hal_rx_fst_attach(qdf_device_t qdf_dev, uint64_t *hal_fst_base_paddr, uint16_t max_entries, - uint16_t max_search, uint8_t *hash_key) -{ - struct hal_rx_fst *fst = qdf_mem_malloc(sizeof(struct hal_rx_fst)); - - if (!fst) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - FL("hal fst allocation failed,")); - return NULL; - } - - qdf_mem_set(fst, 0, sizeof(struct hal_rx_fst)); - - fst->key = hash_key; - fst->max_skid_length = max_search; - fst->max_entries = max_entries; - fst->hash_mask = max_entries - 1; - - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, - "HAL FST allocation %x %d * %d\n", fst, - fst->max_entries, HAL_RX_FST_ENTRY_SIZE); - - fst->base_vaddr = (uint8_t *)qdf_mem_alloc_consistent(qdf_dev, - qdf_dev->dev, - (fst->max_entries * HAL_RX_FST_ENTRY_SIZE), - &fst->base_paddr); - - if (!fst->base_vaddr) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - FL("hal fst->base_vaddr allocation failed")); - qdf_mem_free(fst); - return NULL; - } - QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_DEBUG, - (void *)fst->key, HAL_FST_HASH_KEY_SIZE_BYTES); - - qdf_mem_set((uint8_t *)fst->base_vaddr, 0, - (fst->max_entries * HAL_RX_FST_ENTRY_SIZE)); - - hal_rx_fst_key_configure(fst); - hal_flow_toeplitz_create_cache(fst); - *hal_fst_base_paddr = (uint64_t)fst->base_paddr; - return fst; -} + uint16_t max_search, uint8_t *hash_key); /** * hal_rx_fst_detach() - De-init the Rx flow search table from HW @@ -450,85 +159,7 @@ hal_rx_fst_attach(qdf_device_t qdf_dev, * * Return: */ -void hal_rx_fst_detach(struct hal_rx_fst *rx_fst, - qdf_device_t qdf_dev) -{ - if (!rx_fst || !qdf_dev) - return; - - qdf_mem_free_consistent(qdf_dev, qdf_dev->dev, - rx_fst->max_entries * HAL_RX_FST_ENTRY_SIZE, - rx_fst->base_vaddr, rx_fst->base_paddr, 0); - - qdf_mem_free(rx_fst); -} - -/** - * hal_flow_toeplitz_hash() - Calculate Toeplitz hash by using the cached key - * - * @hal_fst: FST Handle - * @flow: Flow Parameters - * - * Return: Success/Failure - */ -static inline uint32_t -hal_flow_toeplitz_hash(void *hal_fst, struct hal_rx_flow *flow) -{ - int i, j; - uint32_t hash = 0; - struct hal_rx_fst *fst = (struct hal_rx_fst *)hal_fst; - uint32_t input[HAL_FST_HASH_KEY_SIZE_WORDS]; - uint8_t *tuple; - - qdf_mem_zero(input, HAL_FST_HASH_KEY_SIZE_BYTES); - *(uint32_t *)&input[0] = qdf_htonl(flow->tuple_info.src_ip_127_96); - *(uint32_t *)&input[1] = qdf_htonl(flow->tuple_info.src_ip_95_64); - *(uint32_t *)&input[2] = qdf_htonl(flow->tuple_info.src_ip_63_32); - *(uint32_t *)&input[3] = qdf_htonl(flow->tuple_info.src_ip_31_0); - *(uint32_t *)&input[4] = qdf_htonl(flow->tuple_info.dest_ip_127_96); - *(uint32_t *)&input[5] = qdf_htonl(flow->tuple_info.dest_ip_95_64); - *(uint32_t *)&input[6] = qdf_htonl(flow->tuple_info.dest_ip_63_32); - *(uint32_t *)&input[7] = qdf_htonl(flow->tuple_info.dest_ip_31_0); - *(uint32_t *)&input[8] = (flow->tuple_info.dest_port << 16) | - (flow->tuple_info.src_port); - *(uint32_t *)&input[9] = flow->tuple_info.l4_protocol; - - tuple = (uint8_t *)input; - QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - tuple, sizeof(input)); - for (i = 0, j = HAL_FST_HASH_DATA_SIZE - 1; - i < HAL_FST_HASH_KEY_SIZE_BYTES && j >= 0; i++, j--) { - hash ^= fst->key_cache[i][tuple[j]]; - } - - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW, - "Hash value %u %u truncated hash %u\n", hash, - (hash >> 12), (hash >> 12) % (fst->max_entries)); - - hash >>= 12; - hash &= (fst->max_entries - 1); - - return hash; -} - -/** - * hal_rx_get_hal_hash() - Retrieve hash index of a flow in the FST table - * - * @hal_fst: HAL Rx FST Handle - * @flow_hash: Flow hash computed from flow tuple - * - * Return: hash index truncated to the size of the hash table - */ -inline -uint32_t hal_rx_get_hal_hash(struct hal_rx_fst *hal_fst, uint32_t flow_hash) -{ - uint32_t trunc_hash = flow_hash; - - /* Take care of hash wrap around scenario */ - if (flow_hash >= hal_fst->max_entries) - trunc_hash &= hal_fst->hash_mask; - return trunc_hash; -} +void hal_rx_fst_detach(struct hal_rx_fst *rx_fst, qdf_device_t qdf_dev); /** * hal_rx_insert_flow_entry() - Add a flow into the FST table @@ -542,40 +173,7 @@ uint32_t hal_rx_get_hal_hash(struct hal_rx_fst *hal_fst, uint32_t flow_hash) */ QDF_STATUS hal_rx_insert_flow_entry(struct hal_rx_fst *fst, uint32_t flow_hash, - void *flow_tuple_info, uint32_t *flow_idx) { - int i; - void *hal_fse; - uint32_t hal_hash; - struct hal_flow_tuple_info hal_tuple_info = { 0 }; - QDF_STATUS status; - - for (i = 0; i < fst->max_skid_length; i++) { - hal_hash = hal_rx_get_hal_hash(fst, (flow_hash + i)); - hal_fse = (uint8_t *)fst->base_vaddr + - (hal_hash * HAL_RX_FST_ENTRY_SIZE); - status = hal_rx_flow_get_tuple_info(hal_fse, &hal_tuple_info); - if (QDF_STATUS_E_NOENT == status) - break; - - /* Find the matching flow entry in HW FST */ - if (!qdf_mem_cmp(&hal_tuple_info, - flow_tuple_info, - sizeof(struct hal_flow_tuple_info))) { - dp_err("Duplicate flow entry in FST %u at skid %u ", - hal_hash, i); - return QDF_STATUS_E_EXISTS; - } - } - if (i == fst->max_skid_length) { - dp_err("Max skid length reached for hash %u", flow_hash); - return QDF_STATUS_E_RANGE; - } - *flow_idx = hal_hash; - dp_info("flow_hash = %u, skid_entry = %d, flow_addr = %pK flow_idx = %d", - flow_hash, i, hal_fse, *flow_idx); - - return QDF_STATUS_SUCCESS; -} + void *flow_tuple_info, uint32_t *flow_idx); /** * hal_rx_find_flow_from_tuple() - Find a flow in the FST table @@ -589,40 +187,28 @@ hal_rx_insert_flow_entry(struct hal_rx_fst *fst, uint32_t flow_hash, */ QDF_STATUS hal_rx_find_flow_from_tuple(struct hal_rx_fst *fst, uint32_t flow_hash, - void *flow_tuple_info, uint32_t *flow_idx) -{ - int i; - void *hal_fse; - uint32_t hal_hash; - struct hal_flow_tuple_info hal_tuple_info = { 0 }; - QDF_STATUS status; + void *flow_tuple_info, uint32_t *flow_idx); - for (i = 0; i < fst->max_skid_length; i++) { - hal_hash = hal_rx_get_hal_hash(fst, (flow_hash + i)); - hal_fse = (uint8_t *)fst->base_vaddr + - (hal_hash * HAL_RX_FST_ENTRY_SIZE); - status = hal_rx_flow_get_tuple_info(hal_fse, &hal_tuple_info); - if (QDF_STATUS_SUCCESS != status) - continue; +/** + * hal_rx_get_hal_hash() - Retrieve hash index of a flow in the FST table + * + * @hal_fst: HAL Rx FST Handle + * @flow_hash: Flow hash computed from flow tuple + * + * Return: hash index truncated to the size of the hash table + */ +uint32_t hal_rx_get_hal_hash(struct hal_rx_fst *hal_fst, uint32_t flow_hash); - /* Find the matching flow entry in HW FST */ - if (!qdf_mem_cmp(&hal_tuple_info, - flow_tuple_info, - sizeof(struct hal_flow_tuple_info))) { - break; - } - } - - if (i == fst->max_skid_length) { - dp_err("Max skid length reached for hash %u", flow_hash); - return QDF_STATUS_E_RANGE; - } - - *flow_idx = hal_hash; - dp_info("flow_hash = %u, skid_entry = %d, flow_addr = %pK flow_idx = %d", - flow_hash, i, hal_fse, *flow_idx); - - return QDF_STATUS_SUCCESS; -} +/** + * hal_flow_toeplitz_hash() - Calculate Toeplitz hash by using the cached key + * + * @hal_fst: FST Handle + * @flow: Flow Parameters + * + * Return: Success/Failure + */ +uint32_t +hal_flow_toeplitz_hash(void *hal_fst, struct hal_rx_flow *flow); +void hal_rx_dump_fse_table(struct hal_rx_fst *fst); #endif /* HAL_RX_FLOW_H */