From f3b2944efe2a3cc9ec5703e7f633fdc4c67c04f1 Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Wed, 8 Jan 2020 00:17:56 -0800 Subject: [PATCH 1/8] qcacmn: Move flow learning and operation HAL macros out of header file Move flow learning and operation HAL macros from header file hal_rx_flow.h to hal_rx_flow.c. 1) hal_rx_flow.c conditionally compiled in based on the feature 2) Function implementations are too big to be defined in hal_rx_flow.h Replicate hal_rx_flow_setup_fse specific to FISA Flow programming. Implement function to dump the FT entries. Change-Id: I7db943495eecfc064c4b696939da83d1d8ed9280 CRs-Fixed: 2599917 --- hal/wifi3.0/hal_rx_flow.c | 754 ++++++++++++++++++++++++++++++++++++++ hal/wifi3.0/hal_rx_flow.h | 482 ++---------------------- 2 files changed, 788 insertions(+), 448 deletions(-) create mode 100644 hal/wifi3.0/hal_rx_flow.c diff --git a/hal/wifi3.0/hal_rx_flow.c b/hal/wifi3.0/hal_rx_flow.c new file mode 100644 index 000000000000..43a144901acf --- /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 353f9e6f7d6b..b6af10517d0e 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 */ From 44aeb7256a75f010e2da863c9fbb6e41b441aa91 Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Wed, 8 Jan 2020 00:42:06 -0800 Subject: [PATCH 2/8] qcacmn: Allocate and Initialize the FST for FISA feature 1) Allocate the FISA software flow search table 2) Allocate DDR flow search table 3) Send HTT command to program DDR flow table in FSE module. Change-Id: I6d6084343d1a9c0298b1cf8a1ba033b2b46e6a82 CRs-Fixed: 2599917 --- dp/wifi3.0/dp_internal.h | 7 ++--- dp/wifi3.0/dp_main.c | 11 +++++--- dp/wifi3.0/dp_types.h | 55 +++++++++++++++++++++++++++++++++++----- 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index f6266ab03c72..19696e9c2846 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -1875,7 +1875,7 @@ struct dp_soc *cdp_soc_t_to_dp_soc(struct cdp_soc_t *psoc) return (struct dp_soc *)psoc; } -#ifdef WLAN_SUPPORT_RX_FLOW_TAG +#if defined(WLAN_SUPPORT_RX_FLOW_TAG) || defined(WLAN_SUPPORT_RX_FISA) /** * dp_rx_flow_update_fse_stats() - Update a flow's statistics * @pdev: pdev handle @@ -1934,7 +1934,8 @@ void dp_rx_fst_detach(struct dp_soc *soc, struct dp_pdev *pdev); */ QDF_STATUS dp_rx_flow_send_fst_fw_setup(struct dp_soc *soc, struct dp_pdev *pdev); -#else +#else /* !((WLAN_SUPPORT_RX_FLOW_TAG) || defined(WLAN_SUPPORT_RX_FISA)) */ + /** * dp_rx_fst_attach() - Initialize Rx FST and setup necessary parameters * @soc: SoC handle @@ -1959,7 +1960,7 @@ static inline void dp_rx_fst_detach(struct dp_soc *soc, struct dp_pdev *pdev) { } -#endif /* WLAN_SUPPORT_RX_FLOW_TAG */ +#endif /** * dp_get_vdev_from_soc_vdev_id_wifi3() - Returns vdev object given the vdev id diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index ca7e95e9c827..59a1466780d1 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -4885,7 +4885,7 @@ dp_rx_target_fst_config(struct dp_soc *soc) } return status; } -#else +#elif WLAN_SUPPORT_RX_FISA /** * dp_rx_target_fst_config() - Configure RX OLE FSE engine in HW * @soc: SoC handle @@ -4894,11 +4894,16 @@ dp_rx_target_fst_config(struct dp_soc *soc) */ static inline QDF_STATUS dp_rx_target_fst_config(struct dp_soc *soc) +{ + return dp_rx_flow_send_fst_fw_setup(soc, soc->pdev_list[0]); +} +#else /* WLAN_SUPPORT_RX_FISA */ +static inline QDF_STATUS +dp_rx_target_fst_config(struct dp_soc *soc) { return QDF_STATUS_SUCCESS; } - -#endif /* WLAN_SUPPORT_RX_FLOW_TAG */ +#endif /* * dp_soc_attach_target_wifi3() - SOC initialization in the target diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 4983b7826b58..8ccc2f6fbb77 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1245,13 +1245,14 @@ struct dp_soc { * invalidation bug is enabled or not */ bool is_rx_fse_full_cache_invalidate_war_enabled; -#ifdef WLAN_SUPPORT_RX_FLOW_TAG +#if defined(WLAN_SUPPORT_RX_FLOW_TAG) || defined(WLAN_SUPPORT_RX_FISA) /** * Pointer to DP RX Flow FST at SOC level if * is_rx_flow_search_table_per_pdev is false + * TBD: rx_fst[num_macs] if we decide to have per mac FST */ struct dp_rx_fst *rx_fst; -#endif /* WLAN_SUPPORT_RX_FLOW_TAG */ +#endif /* WLAN_SUPPORT_RX_FLOW_TAG || WLAN_SUPPORT_RX_FISA */ }; #ifdef IPA_OFFLOAD @@ -2193,9 +2194,10 @@ struct dp_tx_me_buf_t { uint8_t data[QDF_MAC_ADDR_SIZE]; }; -#ifdef WLAN_SUPPORT_RX_FLOW_TAG +#if defined(WLAN_SUPPORT_RX_FLOW_TAG) || defined(WLAN_SUPPORT_RX_FISA) struct hal_rx_fst; +#ifdef WLAN_SUPPORT_RX_FLOW_TAG struct dp_rx_fse { /* HAL Rx Flow Search Entry which matches HW definition */ void *hal_rx_fse; @@ -2206,9 +2208,9 @@ struct dp_rx_fse { /* Stats tracking for this flow */ struct cdp_flow_stats stats; /* Flag indicating whether flow is IPv4 address tuple */ - bool is_ipv4_addr_entry; + uint8_t is_ipv4_addr_entry; /* Flag indicating whether flow is valid */ - bool is_valid; + uint8_t is_valid; }; struct dp_rx_fst { @@ -2236,6 +2238,47 @@ struct dp_rx_fst { /* Flag to indicate completion of FSE setup in HW/FW */ bool fse_setup_done; }; -#endif /* WLAN_SUPPORT_RX_FLOW_TAG */ + +#define DP_RX_GET_SW_FT_ENTRY_SIZE sizeof(struct dp_rx_fse) +#elif WLAN_SUPPORT_RX_FISA +struct dp_fisa_rx_sw_ft { + /* HAL Rx Flow Search Entry which matches HW definition */ + void *hal_rx_fse; + /* Toeplitz hash value */ + uint32_t flow_hash; + /* Flow index, equivalent to hash value truncated to FST size */ + uint32_t flow_id; + /* Stats tracking for this flow */ + struct cdp_flow_stats stats; + /* Flag indicating whether flow is IPv4 address tuple */ + uint8_t is_ipv4_addr_entry; + /* Flag indicating whether flow is valid */ + uint8_t is_valid; + qdf_nbuf_t *head_skb; +}; + +#define DP_RX_GET_SW_FT_ENTRY_SIZE sizeof(struct dp_fisa_rx_sw_ft) + +struct dp_rx_fst { + /* Software (DP) FST */ + uint8_t *base; + /* Pointer to HAL FST */ + struct hal_rx_fst *hal_rx_fst; + /* Base physical address of HAL RX HW FST */ + uint64_t hal_rx_fst_base_paddr; + /* Maximum number of flows FSE supports */ + uint16_t max_entries; + /* Num entries in flow table */ + uint16_t num_entries; + /* SKID Length */ + uint16_t max_skid_length; + /* Hash mask to obtain legitimate hash entry */ + uint32_t hash_mask; + /* Lock for adding/deleting entries of FST */ + qdf_spinlock_t dp_rx_fst_lock; +}; + +#endif /* WLAN_SUPPORT_RX_FISA */ +#endif /* WLAN_SUPPORT_RX_FLOW_TAG || WLAN_SUPPORT_RX_FISA */ #endif /* _DP_TYPES_H_ */ From d2ceaf472c1dd582332fb5282186630a5d3c5fd0 Mon Sep 17 00:00:00 2001 From: Venkata Sharath Chandra Manchala Date: Thu, 9 Jan 2020 19:57:42 -0800 Subject: [PATCH 3/8] qcacmn: Add hal macros for fisa assist Add 6490 chip specific HAL macros to extract FISA assist from TLV header. Change-Id: I269431b2708f07b10e7e02715d8940fea27a66f6 CRs-Fixed: 2599917 --- hal/wifi3.0/hal_internal.h | 6 ++ hal/wifi3.0/hal_rx.h | 155 +++++++++++++++++++++++++++++ hal/wifi3.0/qca6290/hal_6290.c | 6 ++ hal/wifi3.0/qca6390/hal_6390.c | 6 ++ hal/wifi3.0/qca6490/hal_6490.c | 123 ++++++++++++++++++++++- hal/wifi3.0/qca6490/hal_6490_rx.h | 39 ++++++++ hal/wifi3.0/qca8074v1/hal_8074v1.c | 6 ++ hal/wifi3.0/qca8074v2/hal_8074v2.c | 6 ++ hal/wifi3.0/qcn9000/hal_9000.c | 6 ++ 9 files changed, 350 insertions(+), 3 deletions(-) diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 794d0505b6b8..d2ec603405e3 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -464,6 +464,12 @@ struct hal_hw_txrx_ops { void (*hal_rx_get_rtt_info)(void *rx_tlv, void *ppdu_info_handle); void (*hal_rx_msdu_packet_metadata_get)(uint8_t *buf, void *msdu_pkt_metadata); + uint16_t (*hal_rx_get_fisa_cumulative_l4_checksum)(uint8_t *buf); + uint16_t (*hal_rx_get_fisa_cumulative_ip_length)(uint8_t *buf); + bool (*hal_rx_get_udp_proto)(uint8_t *buf); + bool (*hal_rx_get_fisa_flow_agg_continuation)(uint8_t *buf); + uint8_t (*hal_rx_get_fisa_flow_agg_count)(uint8_t *buf); + bool (*hal_rx_get_fisa_timeout)(uint8_t *buf); }; /** diff --git a/hal/wifi3.0/hal_rx.h b/hal/wifi3.0/hal_rx.h index 6131e231c88a..c239b7a1d3ed 100644 --- a/hal/wifi3.0/hal_rx.h +++ b/hal/wifi3.0/hal_rx.h @@ -995,6 +995,14 @@ hal_rx_mpdu_peer_meta_data_set(uint8_t *buf, uint32_t peer_mdata) RX_MSDU_START_2_TCP_PROTO_MASK, \ RX_MSDU_START_2_TCP_PROTO_LSB)) +#define HAL_RX_TLV_GET_UDP_PROTO(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_start_tlv.rx_msdu_start), \ + RX_MSDU_START_2_UDP_PROTO_OFFSET)), \ + RX_MSDU_START_2_UDP_PROTO_MASK, \ + RX_MSDU_START_2_UDP_PROTO_LSB)) + #define HAL_RX_TLV_GET_IPV6(buf) \ (_HAL_MS( \ (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ @@ -3461,4 +3469,151 @@ hal_rx_msdu_metadata_get(hal_soc_handle_t hal_soc_hdl, uint8_t *buf, return hal_soc->ops->hal_rx_msdu_packet_metadata_get(buf, msdu_md); } + +/** + * hal_rx_get_fisa_cumulative_l4_checksum: API to get cumulative_l4_checksum + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cumulative_l4_checksum + */ +static inline uint16_t +hal_rx_get_fisa_cumulative_l4_checksum(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (!hal_soc->ops->hal_rx_get_fisa_cumulative_l4_checksum) + return 0; + + return hal_soc->ops->hal_rx_get_fisa_cumulative_l4_checksum(buf); +} + +/** + * hal_rx_get_fisa_cumulative_ip_length: API to get cumulative_ip_length + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cumulative_ip_length + */ +static inline uint16_t +hal_rx_get_fisa_cumulative_ip_length(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (hal_soc->ops->hal_rx_get_fisa_cumulative_ip_length) + return hal_soc->ops->hal_rx_get_fisa_cumulative_ip_length(buf); + + return 0; +} + +/** + * hal_rx_get_udp_proto: API to get UDP proto field + * from rx_msdu_start TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: UDP proto field value + */ +static inline bool +hal_rx_get_udp_proto(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (hal_soc->ops->hal_rx_get_udp_proto) + return hal_soc->ops->hal_rx_get_udp_proto(buf); + + return 0; +} + +/** + * hal_rx_get_fisa_flow_agg_continuation: API to get fisa flow_agg_continuation + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow_agg_continuation bit field value + */ +static inline bool +hal_rx_get_fisa_flow_agg_continuation(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (hal_soc->ops->hal_rx_get_fisa_flow_agg_continuation) + return hal_soc->ops->hal_rx_get_fisa_flow_agg_continuation(buf); + + return 0; +} + +/** + * hal_rx_get_fisa_flow_agg_count: API to get fisa flow_agg count from + * rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow_agg count value + */ +static inline uint8_t +hal_rx_get_fisa_flow_agg_count(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (hal_soc->ops->hal_rx_get_fisa_flow_agg_count) + return hal_soc->ops->hal_rx_get_fisa_flow_agg_count(buf); + + return 0; +} + +/** + * hal_rx_get_fisa_timeout: API to get fisa time out from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: fisa flow_agg timeout bit value + */ +static inline bool +hal_rx_get_fisa_timeout(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (hal_soc->ops->hal_rx_get_fisa_timeout) + return hal_soc->ops->hal_rx_get_fisa_timeout(buf); + + return 0; +} #endif /* _HAL_RX_H */ diff --git a/hal/wifi3.0/qca6290/hal_6290.c b/hal/wifi3.0/qca6290/hal_6290.c index 4c617574db6b..822a7a9b22c5 100644 --- a/hal/wifi3.0/qca6290/hal_6290.c +++ b/hal/wifi3.0/qca6290/hal_6290.c @@ -1081,6 +1081,12 @@ struct hal_hw_txrx_ops qca6290_hal_hw_txrx_ops = { NULL, /* rx - msdu end fast path info fields */ hal_rx_msdu_packet_metadata_get_generic, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; struct hal_hw_srng_config hw_srng_table_6290[] = { diff --git a/hal/wifi3.0/qca6390/hal_6390.c b/hal/wifi3.0/qca6390/hal_6390.c index 8dc7ca0cb831..4e52c193f532 100644 --- a/hal/wifi3.0/qca6390/hal_6390.c +++ b/hal/wifi3.0/qca6390/hal_6390.c @@ -1077,6 +1077,12 @@ struct hal_hw_txrx_ops qca6390_hal_hw_txrx_ops = { NULL, /* rx - msdu end fast path info fields */ hal_rx_msdu_packet_metadata_get_generic, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; struct hal_hw_srng_config hw_srng_table_6390[] = { diff --git a/hal/wifi3.0/qca6490/hal_6490.c b/hal/wifi3.0/qca6490/hal_6490.c index 08523c94ecd2..36a8bd314f34 100644 --- a/hal/wifi3.0/qca6490/hal_6490.c +++ b/hal/wifi3.0/qca6490/hal_6490.c @@ -316,7 +316,7 @@ static void hal_rx_dump_msdu_end_tlv_6490(void *msduend, struct rx_msdu_end *msdu_end = (struct rx_msdu_end *)msduend; QDF_TRACE(QDF_MODULE_ID_DP, dbg_level, - "rx_msdu_end tlv (1/2) - " + "rx_msdu_end tlv (1/3) - " "rxpcu_mpdu_filter_in_category: %x " "sw_frame_group_id: %x " "phy_ppdu_id: %x " @@ -363,7 +363,7 @@ static void hal_rx_dump_msdu_end_tlv_6490(void *msduend, msdu_end->amsdu_parser_error); QDF_TRACE(QDF_MODULE_ID_DP, dbg_level, - "rx_msdu_end tlv (2/2)- " + "rx_msdu_end tlv (2/3)- " "sa_is_valid: %x " "da_is_valid: %x " "da_is_mcbc: %x " @@ -412,6 +412,18 @@ static void hal_rx_dump_msdu_end_tlv_6490(void *msduend, msdu_end->fse_metadata, msdu_end->cce_metadata, msdu_end->sa_sw_peer_id); + QDF_TRACE(QDF_MODULE_ID_DP, dbg_level, + "rx_msdu_end tlv (3/3)" + "aggregation_count %x " + "flow_aggregation_continuation %x " + "fisa_timeout %x " + "cumulative_l4_checksum %x " + "cumulative_ip_length %x", + msdu_end->aggregation_count, + msdu_end->flow_aggregation_continuation, + msdu_end->fisa_timeout, + msdu_end->cumulative_l4_checksum, + msdu_end->cumulative_ip_length); } /* @@ -1258,6 +1270,30 @@ hal_rx_msdu_cce_metadata_get_6490(uint8_t *buf) return HAL_RX_MSDU_END_CCE_METADATA_GET(msdu_end); } +/** + * hal_rx_msdu_get_flow_params_6490: API to get flow index, flow index invalid + * and flow index timeout from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * @flow_invalid: pointer to return value of flow_idx_valid + * @flow_timeout: pointer to return value of flow_idx_timeout + * @flow_index: pointer to return value of flow_idx + * + * Return: none + */ +static inline void +hal_rx_msdu_get_flow_params_6490(uint8_t *buf, + bool *flow_invalid, + bool *flow_timeout, + uint32_t *flow_index) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + *flow_invalid = HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); + *flow_timeout = HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); + *flow_index = HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + /** * hal_rx_tlv_get_tcp_chksum_6490() - API to get tcp checksum * @buf: rx_tlv_hdr @@ -1298,6 +1334,81 @@ static inline qdf_iomem_t hal_get_window_address_6490(struct hal_soc *hal_soc, return addr; } +/** + * hal_rx_get_fisa_cumulative_l4_checksum_6490() - Retrieve cumulative + * checksum + * @buf: buffer pointer + * + * Return: cumulative checksum + */ +static inline +uint16_t hal_rx_get_fisa_cumulative_l4_checksum_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_FISA_CUMULATIVE_L4_CHECKSUM(buf); +} + +/** + * hal_rx_get_fisa_cumulative_ip_length_6490() - Retrieve cumulative + * ip length + * @buf: buffer pointer + * + * Return: cumulative length + */ +static inline +uint16_t hal_rx_get_fisa_cumulative_ip_length_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_FISA_CUMULATIVE_IP_LENGTH(buf); +} + +/** + * hal_rx_get_udp_proto_6490() - Retrieve udp proto value + * @buf: buffer + * + * Return: udp proto bit + */ +static inline +bool hal_rx_get_udp_proto_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_UDP_PROTO(buf); +} + +/** + * hal_rx_get_flow_agg_continuation_6490() - retrieve flow agg + * continuation + * @buf: buffer + * + * Return: flow agg + */ +static inline +bool hal_rx_get_flow_agg_continuation_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_FLOW_AGGR_CONT(buf); +} + +/** + * hal_rx_get_flow_agg_count_6490()- Retrieve flow agg count + * @buf: buffer + * + * Return: flow agg count + */ +static inline +uint8_t hal_rx_get_flow_agg_count_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_FLOW_AGGR_COUNT(buf); +} + +/** + * hal_rx_get_fisa_timeout_6490() - Retrieve fisa timeout + * @buf: buffer + * + * Return: fisa timeout + */ +static inline +bool hal_rx_get_fisa_timeout_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_FISA_TIMEOUT(buf); +} + struct hal_hw_txrx_ops qca6490_hal_hw_txrx_ops = { /* init and setup */ hal_srng_dst_hw_init_generic, @@ -1383,13 +1494,19 @@ struct hal_hw_txrx_ops qca6490_hal_hw_txrx_ops = { hal_rx_msdu_flow_idx_timeout_6490, hal_rx_msdu_fse_metadata_get_6490, hal_rx_msdu_cce_metadata_get_6490, - NULL, + hal_rx_msdu_get_flow_params_6490, hal_rx_tlv_get_tcp_chksum_6490, hal_rx_get_rx_sequence_6490, NULL, NULL, /* rx - msdu end fast path info fields */ hal_rx_msdu_packet_metadata_get_generic, + hal_rx_get_fisa_cumulative_l4_checksum_6490, + hal_rx_get_fisa_cumulative_ip_length_6490, + hal_rx_get_udp_proto_6490, + hal_rx_get_flow_agg_continuation_6490, + hal_rx_get_flow_agg_count_6490, + hal_rx_get_fisa_timeout_6490, }; struct hal_hw_srng_config hw_srng_table_6490[] = { diff --git a/hal/wifi3.0/qca6490/hal_6490_rx.h b/hal/wifi3.0/qca6490/hal_6490_rx.h index d1f31b6c6372..bd2ac82d25c3 100644 --- a/hal/wifi3.0/qca6490/hal_6490_rx.h +++ b/hal/wifi3.0/qca6490/hal_6490_rx.h @@ -363,4 +363,43 @@ RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_RESERVED_0A_OFFSET)) RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_MASK, \ RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_LSB)) +#define HAL_RX_TLV_GET_FLOW_AGGR_CONT(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_17_FLOW_AGGREGATION_CONTINUATION_OFFSET)), \ + RX_MSDU_END_17_FLOW_AGGREGATION_CONTINUATION_MASK, \ + RX_MSDU_END_17_FLOW_AGGREGATION_CONTINUATION_LSB)) + +#define HAL_RX_TLV_GET_FLOW_AGGR_COUNT(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_17_AGGREGATION_COUNT_OFFSET)), \ + RX_MSDU_END_17_AGGREGATION_COUNT_MASK, \ + RX_MSDU_END_17_AGGREGATION_COUNT_LSB)) + +#define HAL_RX_TLV_GET_FISA_TIMEOUT(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_17_FISA_TIMEOUT_OFFSET)), \ + RX_MSDU_END_17_FISA_TIMEOUT_MASK, \ + RX_MSDU_END_17_FISA_TIMEOUT_LSB)) + +#define HAL_RX_TLV_GET_FISA_CUMULATIVE_L4_CHECKSUM(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_18_CUMULATIVE_L4_CHECKSUM_OFFSET)), \ + RX_MSDU_END_18_CUMULATIVE_L4_CHECKSUM_MASK, \ + RX_MSDU_END_18_CUMULATIVE_L4_CHECKSUM_LSB)) + +#define HAL_RX_TLV_GET_FISA_CUMULATIVE_IP_LENGTH(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_18_CUMULATIVE_IP_LENGTH_OFFSET)), \ + RX_MSDU_END_18_CUMULATIVE_IP_LENGTH_MASK, \ + RX_MSDU_END_18_CUMULATIVE_IP_LENGTH_LSB)) #endif diff --git a/hal/wifi3.0/qca8074v1/hal_8074v1.c b/hal/wifi3.0/qca8074v1/hal_8074v1.c index 35c2fa970f0f..8e26a2924c8f 100644 --- a/hal/wifi3.0/qca8074v1/hal_8074v1.c +++ b/hal/wifi3.0/qca8074v1/hal_8074v1.c @@ -1077,6 +1077,12 @@ struct hal_hw_txrx_ops qca8074_hal_hw_txrx_ops = { NULL, /* rx - msdu fast path info fields */ hal_rx_msdu_packet_metadata_get_generic, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; struct hal_hw_srng_config hw_srng_table_8074[] = { diff --git a/hal/wifi3.0/qca8074v2/hal_8074v2.c b/hal/wifi3.0/qca8074v2/hal_8074v2.c index 44142b38e62a..b19d1dd682b5 100644 --- a/hal/wifi3.0/qca8074v2/hal_8074v2.c +++ b/hal/wifi3.0/qca8074v2/hal_8074v2.c @@ -1082,6 +1082,12 @@ struct hal_hw_txrx_ops qca8074v2_hal_hw_txrx_ops = { #endif /* rx - msdu fast path info fields */ hal_rx_msdu_packet_metadata_get_generic, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; struct hal_hw_srng_config hw_srng_table_8074v2[] = { diff --git a/hal/wifi3.0/qcn9000/hal_9000.c b/hal/wifi3.0/qcn9000/hal_9000.c index 300468bf614c..cca448de5f21 100644 --- a/hal/wifi3.0/qcn9000/hal_9000.c +++ b/hal/wifi3.0/qcn9000/hal_9000.c @@ -1460,6 +1460,12 @@ struct hal_hw_txrx_ops qcn9000_hal_hw_txrx_ops = { NULL, /* rx - msdu fast path info fields */ hal_rx_msdu_packet_metadata_get_9000, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; struct hal_hw_srng_config hw_srng_table_9000[] = { From 5d73e075e86edce8224017fcd50e11ea5f84ef22 Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Wed, 8 Jan 2020 16:50:25 -0800 Subject: [PATCH 4/8] qcacmn: Add support to deliver the packets to FISA Hook FISA specific callback to deliver the Rx packets to FISA frame work. Change-Id: Ia16c857764c0c3bf99c3855eac01659eb03c7608 CRs-Fixed: 2599917 --- dp/inc/cdp_txrx_cmn_struct.h | 21 +++++++ dp/wifi3.0/dp_htt.c | 115 +++++++++++++++++++++++++++++++++-- dp/wifi3.0/dp_htt.h | 13 ++++ dp/wifi3.0/dp_internal.h | 3 + dp/wifi3.0/dp_main.c | 70 ++++++++++++++++++--- dp/wifi3.0/dp_rx.c | 38 ++++++++++-- dp/wifi3.0/dp_types.h | 41 ++++++++++++- 7 files changed, 283 insertions(+), 18 deletions(-) diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index e973f348af1f..f4ca38746dbc 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -79,6 +79,7 @@ #define CDP_BUNDLE_STATS 23 #define CDP_CREDIT_STATS 24 #define CDP_DISCONNECT_STATS 25 +#define CDP_DP_RX_FISA_STATS 26 #define WME_AC_TO_TID(_ac) ( \ ((_ac) == WME_AC_VO) ? 6 : \ @@ -284,6 +285,7 @@ enum cdp_host_txrx_stats { TXRX_PDEV_CFG_PARAMS = 10, TXRX_NAPI_STATS = 11, TXRX_SOC_INTERRUPT_STATS = 12, + TXRX_SOC_FSE_STATS = 13, TXRX_HOST_STATS_MAX, }; @@ -729,6 +731,11 @@ typedef bool (*ol_txrx_tx_flow_control_is_pause_fp)(void *osif_dev); */ typedef QDF_STATUS(*ol_txrx_rx_fp)(void *osif_dev, qdf_nbuf_t msdu_list); +typedef QDF_STATUS(*ol_txrx_fisa_rx_fp)(void *soc, + void *dp_vdev, + qdf_nbuf_t msdu_list); + +typedef QDF_STATUS(*ol_txrx_fisa_flush_fp)(void *soc, int ring_num); /** * ol_txrx_rx_flush_fp - receive function to hand batches of data * frames from txrx to OS shim @@ -905,6 +912,8 @@ struct ol_txrx_ops { ol_txrx_rx_mon_fp mon; ol_txrx_stats_rx_fp stats_rx; ol_txrx_rsim_rx_decap_fp rsim_rx_decap; + ol_txrx_fisa_rx_fp osif_fisa_rx; + ol_txrx_fisa_flush_fp osif_fisa_flush; } rx; /* proxy arp function pointer - specified by OS shim, stored by txrx */ ol_txrx_proxy_arp_fp proxy_arp; @@ -2234,6 +2243,14 @@ struct cdp_peer_cookie { uint8_t cookie; }; +#ifdef WLAN_SUPPORT_RX_FISA +struct cdp_flow_stats { + uint32_t aggr_count; + uint32_t curr_aggr_count; + uint32_t flush_count; + uint32_t bytes_aggregated; +}; +#else /** * cdp_flow_stats - Per-Flow (5-tuple) statistics * @msdu_count: number of rx msdus matching this flow @@ -2244,6 +2261,7 @@ struct cdp_peer_cookie { struct cdp_flow_stats { uint32_t msdu_count; }; +#endif /** * cdp_flow_fst_operation - RX FST operations allowed @@ -2278,6 +2296,9 @@ enum cdp_flow_protocol_type { * @l4_protocol: protocol type in flow (TCP/UDP) */ struct cdp_rx_flow_tuple_info { +#ifdef WLAN_SUPPORT_RX_FISA + uint8_t tuple_populated; +#endif uint32_t dest_ip_127_96; uint32_t dest_ip_95_64; uint32_t dest_ip_63_32; diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index 14cfe6509983..c165a155660b 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -4686,8 +4686,8 @@ dp_htt_rx_flow_fst_setup(struct dp_pdev *pdev, DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_RX_FSE_SETUP_CFG, htt_logger_bufp); - qdf_info("HTT_H2T RX_FSE_SETUP sent to FW for pdev = %u", - fse_setup_info->pdev_id); + dp_info("HTT_H2T RX_FSE_SETUP sent to FW for pdev = %u", + fse_setup_info->pdev_id); QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_DEBUG, (void *)fse_setup_info->hash_key, fse_setup_info->hash_key_len); @@ -4731,6 +4731,7 @@ dp_htt_rx_flow_fse_operation(struct dp_pdev *pdev, if (!qdf_nbuf_put_tail(msg, sizeof(struct htt_h2t_msg_rx_fse_operation_t))) { qdf_err("Failed to expand head for HTT_RX_FSE_OPERATION msg"); + qdf_nbuf_free(msg); return QDF_STATUS_E_FAILURE; } @@ -4829,8 +4830,114 @@ dp_htt_rx_flow_fse_operation(struct dp_pdev *pdev, DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_RX_FSE_OPERATION_CFG, htt_logger_bufp); - qdf_info("HTT_H2T RX_FSE_OPERATION_CFG sent to FW for pdev = %u", - fse_op_info->pdev_id); + dp_info("HTT_H2T RX_FSE_OPERATION_CFG sent to FW for pdev = %u", + fse_op_info->pdev_id); + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_htt_rx_fisa_config(): Send HTT msg to configure FISA + * @pdev: DP pdev handle + * @fse_op_info: Flow entry parameters + * + * Return: Success when HTT message is sent, error on failure + */ +QDF_STATUS +dp_htt_rx_fisa_config(struct dp_pdev *pdev, + struct dp_htt_rx_fisa_cfg *fisa_config) +{ + struct htt_soc *soc = pdev->soc->htt_handle; + struct dp_htt_htc_pkt *pkt; + qdf_nbuf_t msg; + u_int32_t *msg_word; + struct htt_h2t_msg_type_fisa_config_t *htt_fisa_config; + uint8_t *htt_logger_bufp; + uint32_t len; + + len = HTT_MSG_BUF_SIZE(sizeof(struct htt_h2t_msg_type_fisa_config_t)); + + msg = qdf_nbuf_alloc(soc->osdev, + len, + /* reserve room for the HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, + 4, + TRUE); + if (!msg) + return QDF_STATUS_E_NOMEM; + + /* + * Set the length of the message. + * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added + * separately during the below call to qdf_nbuf_push_head. + * The contribution from the HTC header is added separately inside HTC. + */ + if (!qdf_nbuf_put_tail(msg, + sizeof(struct htt_h2t_msg_type_fisa_config_t))) { + qdf_err("Failed to expand head for HTT_RX_FSE_OPERATION msg"); + qdf_nbuf_free(msg); + return QDF_STATUS_E_FAILURE; + } + + /* fill in the message contents */ + msg_word = (u_int32_t *)qdf_nbuf_data(msg); + + memset(msg_word, 0, sizeof(struct htt_h2t_msg_type_fisa_config_t)); + /* rewind beyond alignment pad to get to the HTC header reserved area */ + qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + htt_logger_bufp = (uint8_t *)msg_word; + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_FISA_CFG); + + htt_fisa_config = (struct htt_h2t_msg_type_fisa_config_t *)msg_word; + + HTT_RX_FSE_OPERATION_PDEV_ID_SET(*msg_word, htt_fisa_config->pdev_id); + + msg_word++; + HTT_RX_FISA_CONFIG_FISA_ENABLE_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_IPSEC_SKIP_SEARCH_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_NON_TCP_SKIP_SEARCH_SET(*msg_word, 0); + HTT_RX_FISA_CONFIG_ADD_IPV4_FIXED_HDR_LEN_SET(*msg_word, 0); + HTT_RX_FISA_CONFIG_ADD_IPV6_FIXED_HDR_LEN_SET(*msg_word, 0); + HTT_RX_FISA_CONFIG_ADD_TCP_FIXED_HDR_LEN_SET(*msg_word, 0); + HTT_RX_FISA_CONFIG_ADD_UDP_HDR_LEN_SET(*msg_word, 0); + HTT_RX_FISA_CONFIG_CHKSUM_CUM_IP_LEN_EN_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_TID_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_TA_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_QOS_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_RAW_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_DECRYPT_ERR_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_MSDU_DROP_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_FISA_AGGR_LIMIT_SET(*msg_word, 0xf); + + msg_word++; + htt_fisa_config->fisa_timeout_threshold = fisa_config->fisa_timeout; + + pkt = htt_htc_pkt_alloc(soc); + if (!pkt) { + qdf_err("Fail to allocate dp_htt_htc_pkt buffer"); + qdf_assert(0); + qdf_nbuf_free(msg); + return QDF_STATUS_E_RESOURCES; /* failure */ + } + + pkt->soc_ctxt = NULL; /* not used during send-done callback */ + + SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, + dp_htt_h2t_send_complete_free_netbuf, + qdf_nbuf_data(msg), + qdf_nbuf_len(msg), + soc->htc_endpoint, + 1); /* tag - not relevant here */ + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + + DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_RX_FISA_CFG, + htt_logger_bufp); + + dp_info("HTT_H2T_MSG_TYPE_RX_FISA_CFG sent to FW for pdev = %u", + fisa_config->pdev_id); return QDF_STATUS_SUCCESS; } diff --git a/dp/wifi3.0/dp_htt.h b/dp/wifi3.0/dp_htt.h index 364506d66d7d..56853b071c77 100644 --- a/dp/wifi3.0/dp_htt.h +++ b/dp/wifi3.0/dp_htt.h @@ -289,6 +289,19 @@ struct dp_htt_rx_flow_fst_operation { struct cdp_rx_flow_info *rx_flow; }; +/** + * struct dp_htt_rx_fisa_config - Rx fisa config + * @pdev_id: DP Pdev identifier + * @fisa_timeout: fisa aggregation timeout + */ +struct dp_htt_rx_fisa_cfg { + uint8_t pdev_id; + uint32_t fisa_timeout; +}; + +QDF_STATUS dp_htt_rx_fisa_config(struct dp_pdev *pdev, + struct dp_htt_rx_fisa_cfg *fisa_config); + /* * htt_soc_initialize() - SOC level HTT initialization * @htt_soc: Opaque htt SOC handle diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 19696e9c2846..7e2b7a0e9d8a 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -2031,4 +2031,7 @@ void dp_is_hw_dbs_enable(struct dp_soc *soc, int *max_mac_rings); +#if defined(WLAN_SUPPORT_RX_FISA) +void dp_rx_dump_fisa_table(struct dp_soc *soc); +#endif /* WLAN_SUPPORT_RX_FISA */ #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 59a1466780d1..1113c3315a83 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -46,6 +46,9 @@ #include "dp_rx_mon.h" #include "htt_stats.h" #include "dp_htt.h" +#ifdef WLAN_SUPPORT_RX_FISA +#include +#endif #include "htt_ppdu_stats.h" #include "qdf_mem.h" /* qdf_mem_malloc,free */ #include "cfg_ucfg_api.h" @@ -314,6 +317,7 @@ const int dp_stats_mapping_table[][STATS_TYPE_MAX] = { {TXRX_FW_STATS_INVALID, TXRX_SOC_CFG_PARAMS}, {TXRX_FW_STATS_INVALID, TXRX_PDEV_CFG_PARAMS}, {TXRX_FW_STATS_INVALID, TXRX_SOC_INTERRUPT_STATS}, + {TXRX_FW_STATS_INVALID, TXRX_SOC_FSE_STATS}, }; /* MCL specific functions */ @@ -4885,25 +4889,57 @@ dp_rx_target_fst_config(struct dp_soc *soc) } return status; } -#elif WLAN_SUPPORT_RX_FISA +#elif defined(WLAN_SUPPORT_RX_FISA) /** * dp_rx_target_fst_config() - Configure RX OLE FSE engine in HW * @soc: SoC handle * * Return: Success */ -static inline QDF_STATUS -dp_rx_target_fst_config(struct dp_soc *soc) +static inline QDF_STATUS dp_rx_target_fst_config(struct dp_soc *soc) { + /* Check if it is enabled in the INI */ + if (!soc->fisa_enable) { + dp_err("RX FISA feature is disabled"); + return QDF_STATUS_E_NOSUPPORT; + } + return dp_rx_flow_send_fst_fw_setup(soc, soc->pdev_list[0]); } -#else /* WLAN_SUPPORT_RX_FISA */ -static inline QDF_STATUS -dp_rx_target_fst_config(struct dp_soc *soc) + +#define FISA_MAX_TIMEOUT 0xffffffff +#define FISA_DISABLE_TIMEOUT 0 +static QDF_STATUS dp_rx_fisa_config(struct dp_soc *soc) +{ + struct dp_htt_rx_fisa_cfg fisa_config; + + fisa_config.pdev_id = 0; + fisa_config.fisa_timeout = FISA_MAX_TIMEOUT; + + return dp_htt_rx_fisa_config(soc->pdev_list[0], &fisa_config); +} +#else /* !WLAN_SUPPORT_RX_FISA */ +static inline QDF_STATUS dp_rx_target_fst_config(struct dp_soc *soc) { return QDF_STATUS_SUCCESS; } -#endif +#endif /* !WLAN_SUPPORT_RX_FISA */ + +#ifndef WLAN_SUPPORT_RX_FISA +static QDF_STATUS dp_rx_fisa_config(struct dp_soc *soc) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS dp_rx_dump_fisa_stats(struct dp_soc *soc) +{ + return QDF_STATUS_SUCCESS; +} + +static void dp_rx_dump_fisa_table(struct dp_soc *soc) +{ +} +#endif /* !WLAN_SUPPORT_RX_FISA */ /* * dp_soc_attach_target_wifi3() - SOC initialization in the target @@ -4932,11 +4968,20 @@ dp_soc_attach_target_wifi3(struct cdp_soc_t *cdp_soc) } status = dp_rx_target_fst_config(soc); - if (status != QDF_STATUS_SUCCESS) { + if (status != QDF_STATUS_SUCCESS && + status != QDF_STATUS_E_NOSUPPORT) { dp_err("Failed to send htt fst setup config message to target"); return status; } + if (status == QDF_STATUS_SUCCESS) { + status = dp_rx_fisa_config(soc); + if (status != QDF_STATUS_SUCCESS) { + dp_err("Failed to send htt FISA config message to target"); + return status; + } + } + DP_STATS_INIT(soc); /* initialize work queue for stats processing */ @@ -5096,6 +5141,8 @@ static QDF_STATUS dp_vdev_register_wifi3(struct cdp_soc_t *soc, vdev->osif_rx_flush = txrx_ops->rx.rx_flush; vdev->osif_gro_flush = txrx_ops->rx.rx_gro_flush; vdev->osif_rsim_rx_decap = txrx_ops->rx.rsim_rx_decap; + vdev->osif_fisa_rx = txrx_ops->rx.osif_fisa_rx; + vdev->osif_fisa_flush = txrx_ops->rx.osif_fisa_flush; vdev->osif_get_key = txrx_ops->get_key; vdev->osif_rx_mon = txrx_ops->rx.mon; vdev->osif_tx_free_ext = txrx_ops->tx.tx_free_ext; @@ -7440,6 +7487,7 @@ static void dp_txrx_stats_help(void) dp_info(" 28 -- Host REO Queue Statistics"); dp_info(" 29 -- Host Soc cfg param Statistics"); dp_info(" 30 -- Host pdev cfg param Statistics"); + dp_info(" 31 -- Host FISA stats"); } /** @@ -7502,6 +7550,8 @@ dp_print_host_stats(struct dp_vdev *vdev, case TXRX_SOC_INTERRUPT_STATS: dp_print_soc_interrupt_stats(pdev->soc); break; + case TXRX_SOC_FSE_STATS: + dp_rx_dump_fisa_table(pdev->soc); default: dp_info("Wrong Input For TxRx Host Stats"); dp_txrx_stats_help(); @@ -8952,6 +9002,10 @@ static QDF_STATUS dp_txrx_dump_stats(struct cdp_soc_t *psoc, uint16_t value, /* TODO: NOT IMPLEMENTED */ break; + case CDP_DP_RX_FISA_STATS: + dp_rx_dump_fisa_stats(soc); + break; + default: status = QDF_STATUS_E_INVAL; break; diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 6526c48c6ab8..a0b66a771603 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -1348,7 +1348,13 @@ void dp_rx_deliver_to_stack(struct dp_soc *soc, vdev->osif_rsim_rx_decap(vdev->osif_vdev, &nbuf_head, &nbuf_tail, peer->mac_addr.raw); } - vdev->osif_rx(vdev->osif_vdev, nbuf_head); + + /* Function pointer initialized only when FISA is enabled */ + if (vdev->osif_fisa_rx) + /* on failure send it via regular path */ + vdev->osif_fisa_rx(soc, vdev, nbuf_head); + else + vdev->osif_rx(vdev->osif_vdev, nbuf_head); } /** @@ -1739,6 +1745,28 @@ uint32_t dp_rx_srng_get_num_pending(hal_soc_handle_t hal_soc, return num_pending; } +#ifdef WLAN_SUPPORT_RX_FISA +/* + * dp_rx_skip_tlvs() - Skip TLVs only if FISA is not enabled + * @vdev: DP vdev context + * @nbuf: nbuf whose data pointer is adjusted + * @size: size to be adjusted + * + * Return: None + */ +static void dp_rx_skip_tlvs(struct dp_vdev *vdev, qdf_nbuf_t nbuf, int size) +{ + /* TLVs include FISA info do not skip them yet */ + if (!vdev->osif_fisa_rx) + qdf_nbuf_pull_head(nbuf, size); +} +#else /* !WLAN_SUPPORT_RX_FISA */ +static void dp_rx_skip_tlvs(struct dp_vdev *vdev, qdf_nbuf_t nbuf, int size) +{ + qdf_nbuf_pull_head(nbuf, size); +} +#endif /* !WLAN_SUPPORT_RX_FISA */ + /** * dp_rx_process() - Brain of the Rx processing functionality * Called from the bottom half (tasklet/NET_RX_SOFTIRQ) @@ -2185,9 +2213,8 @@ done: RX_PKT_TLVS_LEN; qdf_nbuf_set_pktlen(nbuf, pkt_len); - qdf_nbuf_pull_head(nbuf, - RX_PKT_TLVS_LEN + - msdu_metadata.l3_hdr_pad); + dp_rx_skip_tlvs(vdev, nbuf, RX_PKT_TLVS_LEN + + msdu_metadata.l3_hdr_pad); } /* @@ -2355,6 +2382,9 @@ done: } } + if (vdev->osif_fisa_flush) + vdev->osif_fisa_flush(soc, reo_ring_num); + if (vdev && vdev->osif_gro_flush && rx_ol_pkt_cnt) { vdev->osif_gro_flush(vdev->osif_vdev, reo_ring_num); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 8ccc2f6fbb77..ac4500b67fb0 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1252,6 +1252,9 @@ struct dp_soc { * TBD: rx_fst[num_macs] if we decide to have per mac FST */ struct dp_rx_fst *rx_fst; +#ifdef WLAN_SUPPORT_RX_FISA + uint8_t fisa_enable; +#endif #endif /* WLAN_SUPPORT_RX_FLOW_TAG || WLAN_SUPPORT_RX_FISA */ }; @@ -1810,6 +1813,10 @@ struct dp_vdev { ol_txrx_rx_fp osif_rx; /* callback to deliver rx frames to the OS */ ol_txrx_rx_fp osif_rx_stack; + /* Callback to handle rx fisa frames */ + ol_txrx_fisa_rx_fp osif_fisa_rx; + ol_txrx_fisa_flush_fp osif_fisa_flush; + /* call back function to flush out queued rx packets*/ ol_txrx_rx_flush_fp osif_rx_flush; ol_txrx_rsim_rx_decap_fp osif_rsim_rx_decap; @@ -2241,9 +2248,16 @@ struct dp_rx_fst { #define DP_RX_GET_SW_FT_ENTRY_SIZE sizeof(struct dp_rx_fse) #elif WLAN_SUPPORT_RX_FISA + +enum fisa_aggr_ret { + FISA_AGGR_DONE, + FISA_AGGR_NOT_ELIGIBLE, + FISA_FLUSH_FLOW +}; + struct dp_fisa_rx_sw_ft { /* HAL Rx Flow Search Entry which matches HW definition */ - void *hal_rx_fse; + void *hw_fse; /* Toeplitz hash value */ uint32_t flow_hash; /* Flow index, equivalent to hash value truncated to FST size */ @@ -2254,7 +2268,26 @@ struct dp_fisa_rx_sw_ft { uint8_t is_ipv4_addr_entry; /* Flag indicating whether flow is valid */ uint8_t is_valid; - qdf_nbuf_t *head_skb; + uint8_t is_populated; + uint8_t is_flow_udp; + uint8_t is_flow_tcp; + qdf_nbuf_t head_skb; + uint16_t cumulative_l4_checksum; + uint16_t adjusted_cumulative_ip_length; + uint16_t cur_aggr; + uint16_t napi_flush_cumulative_l4_checksum; + uint16_t napi_flush_cumulative_ip_length; + qdf_nbuf_t last_skb; + uint32_t head_skb_ip_hdr_offset; + uint32_t head_skb_l4_hdr_offset; + struct cdp_rx_flow_tuple_info rx_flow_tuple_info; + uint8_t napi_id; + struct dp_vdev *vdev; + uint64_t bytes_aggregated; + uint32_t flush_count; + uint32_t aggr_count; + uint8_t do_not_aggregate; + uint16_t hal_cumultive_ip_len; }; #define DP_RX_GET_SW_FT_ENTRY_SIZE sizeof(struct dp_fisa_rx_sw_ft) @@ -2276,6 +2309,10 @@ struct dp_rx_fst { uint32_t hash_mask; /* Lock for adding/deleting entries of FST */ qdf_spinlock_t dp_rx_fst_lock; + uint32_t add_flow_count; + uint32_t del_flow_count; + uint32_t hash_collision_cnt; + struct dp_soc *soc_hdl; }; #endif /* WLAN_SUPPORT_RX_FISA */ From b896f0eaded286d5e265c891545f39f50dc16a00 Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Mon, 20 Jan 2020 18:45:36 -0800 Subject: [PATCH 5/8] qcacmn: Add NULL check for vdev before accessing Add NULL check for valid vdev before accessing it. Change-Id: I977671bd7f612a30e1cb3b72d6b46200eaf1a34c CRs-Fixed: 2606040 --- dp/wifi3.0/dp_rx.c | 2 +- dp/wifi3.0/dp_types.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index a0b66a771603..89138173246c 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -2382,7 +2382,7 @@ done: } } - if (vdev->osif_fisa_flush) + if (vdev && vdev->osif_fisa_flush) vdev->osif_fisa_flush(soc, reo_ring_num); if (vdev && vdev->osif_gro_flush && rx_ol_pkt_cnt) { diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index ac4500b67fb0..defdccc43eba 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -2288,6 +2288,7 @@ struct dp_fisa_rx_sw_ft { uint32_t aggr_count; uint8_t do_not_aggregate; uint16_t hal_cumultive_ip_len; + struct dp_soc *soc_hdl; }; #define DP_RX_GET_SW_FT_ENTRY_SIZE sizeof(struct dp_fisa_rx_sw_ft) From 3227df4b10bc903e4c877c035eb824dc54e2759c Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Mon, 20 Jan 2020 21:10:51 -0800 Subject: [PATCH 6/8] qcacmn: Tag FSE/FISA HTT setup commands as HTC_TX_PACKET_TAG_RUNTIME_PUT FSE setup, FSE cache flush and FISA config commands do not have response, tag them as HTC_TX_PACKET_TAG_RUNTIME_PUT so that get on runtime_pm is released. Without this target fails to go to runtime_pm suspend. Change-Id: Ibb14484dd50c62bb4680b41acf93ce3da1bec796 CRs-Fixed: 2606884 --- dp/wifi3.0/dp_htt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index c165a155660b..8c55c2c7aa56 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -4679,7 +4679,7 @@ dp_htt_rx_flow_fst_setup(struct dp_pdev *pdev, qdf_nbuf_data(msg), qdf_nbuf_len(msg), soc->htc_endpoint, - 1); /* tag - not relevant here */ + HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); @@ -4823,7 +4823,7 @@ dp_htt_rx_flow_fse_operation(struct dp_pdev *pdev, qdf_nbuf_data(msg), qdf_nbuf_len(msg), soc->htc_endpoint, - 1); /* tag - not relevant here */ + HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); @@ -4929,7 +4929,7 @@ dp_htt_rx_fisa_config(struct dp_pdev *pdev, qdf_nbuf_data(msg), qdf_nbuf_len(msg), soc->htc_endpoint, - 1); /* tag - not relevant here */ + HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); From b666fe52b7f836932613fd034217c310830ffaba Mon Sep 17 00:00:00 2001 From: nwzhao Date: Wed, 11 Dec 2019 16:30:50 -0800 Subject: [PATCH 7/8] qcacmn: DebugFS Improvements for WMI logs 1)Configurable number of bytes to log 2)Add support to record only specific WMI command/events Separate buffers are added to save user specified WMI commands and events 1.To record specific wmi cmd, e.g. WMI_VDEV_START_REQUEST_CMDID echo 0x5003 > /sys/kernel/debug/WMI_SOC0_PDEV0/filtered_wmi_cmds 2.To record specific wmi evt, e.g. WMI_MGMT_RX_EVENTID echo 0x7001 > /sys/kernel/debug/WMI_SOC0_PDEV0/filtered_wmi_evts Results of recorded specific WMI command/events: 1. WMI commands, e.g.: cat /sys/kernel/debug/WMI_SOC0_PDEV0/wmi_filtered_command_log 2. WMI events, e.g.: cat /sys/kernel/debug/WMI_SOC0_PDEV0/wmi_filtered_event_log CRs-Fixed: 2597854 Change-Id: I1e90a13ac0717f1f37ba998fb1d06a990d3f4fa2 --- wmi/inc/wmi_filtered_logging.h | 199 +++++++++++++ wmi/inc/wmi_unified_priv.h | 46 +++ wmi/src/wmi_filtered_logging.c | 513 +++++++++++++++++++++++++++++++++ wmi/src/wmi_unified.c | 38 ++- 4 files changed, 789 insertions(+), 7 deletions(-) create mode 100644 wmi/inc/wmi_filtered_logging.h create mode 100644 wmi/src/wmi_filtered_logging.c diff --git a/wmi/inc/wmi_filtered_logging.h b/wmi/inc/wmi_filtered_logging.h new file mode 100644 index 000000000000..087002757012 --- /dev/null +++ b/wmi/inc/wmi_filtered_logging.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2015-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. + */ + +#ifndef WMI_FILTERED_LOGGING_H +#define WMI_FILTERED_LOGGING_H + +#include +#include "wmi_unified_priv.h" + +#ifdef WMI_INTERFACE_FILTERED_EVENT_LOGGING +/** + * wmi_specific_cmd_record() - Record user specified command + * @wmi_handle: handle to WMI + * @id: cmd id + * @buf: buf containing cmd details + * + * Check if the command id is in target list, + * if found, record it. + * + * Context: the function will not sleep, caller is expected to hold + * proper locking. + * + * Return: none + */ +void wmi_specific_cmd_record(wmi_unified_t wmi_handle, + uint32_t id, uint8_t *buf); + +/** + * wmi_specific_evt_record() - Record user specified event + * @wmi_handle: handle to WMI + * @id: cmd id + * @buf: buf containing event details + * + * Check if the event id is in target list, + * if found, record it. + * + * Context: the function will not sleep, caller is expected to hold + * proper locking. + * + * Return: none + */ +void wmi_specific_evt_record(wmi_unified_t wmi_handle, + uint32_t id, uint8_t *buf); + +/** + * wmi_filtered_logging_init() - initialize filtered logging + * @wmi_handle: handle to WMI + * + * Context: the function will not sleep, no lock needed + * + * Return: none + */ +void wmi_filtered_logging_init(wmi_unified_t wmi_handle); + +/** + * wmi_filtered_logging_free() - free the buffers for filtered logging + * @wmi_handle: handle to WMI + * + * Context: the function will not sleep, no lock needed + * + * Return: none + */ +void wmi_filtered_logging_free(wmi_unified_t wmi_handle); + +/* + * Debugfs read/write functions + */ +/** + * debug_filtered_wmi_cmds_show() - debugfs read function for filtered_wmi_cmds + * @m: seq_file handle + * @v: not used, offset of read + * Return: number of bytes read + */ +int debug_filtered_wmi_cmds_show(qdf_debugfs_file_t m, void *v); + +/** + * debug_filtered_wmi_evts_show() - debugfs read function for filtered_wmi_evts + * @m: seq_file handle + * @v: not used, offset of read + * Return: number of bytes read + */ +int debug_filtered_wmi_evts_show(qdf_debugfs_file_t m, void *v); + +/** + * debug_wmi_filtered_command_log_show() - debugfs read function for + * wmi_filtered_command_log + * @m: seq_file handle + * @v: not used, offset of read + * Return: number of bytes read + */ +int debug_wmi_filtered_command_log_show(qdf_debugfs_file_t m, void *v); + +/** + * debug_wmi_filtered_event_log_show() - debugfs read function for + * wmi_filtered_event_log + * @m: seq_file handle + * @v: not used, offset of read + * Return: number of bytes read + */ +int debug_wmi_filtered_event_log_show(qdf_debugfs_file_t m, void *v); + +/** + * debug_wmi_filtered_wmi_cmds_write() - debugfs write for filtered_wmi_cmds + * + * @file: file handler to access wmi_handle + * @buf: received data buffer + * @count: length of received buffer + * @ppos: Not used + * + * Return: count + */ +ssize_t debug_filtered_wmi_cmds_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos); + +/** + * debug_wmi_filtered_wmi_evts_write() - debugfs write for filtered_wmi_evts + * + * @file: file handler to access wmi_handle + * @buf: received data buffer + * @count: length of received buffer + * @ppos: Not used + * + * Return: count + */ +ssize_t debug_filtered_wmi_evts_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos); + +/** + * debug_wmi_filtered_command_log_write() - debugfs write for + * filtered_command_log + * + * @file: file handler to access wmi_handle + * @buf: received data buffer + * @count: length of received buffer + * @ppos: Not used + * + * Return: count + */ +ssize_t debug_wmi_filtered_command_log_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos); + +/** + * debug_wmi_filtered_event_log_write() - debugfs write for filtered_event_log + * + * @file: file handler to access wmi_handle + * @buf: received data buffer + * @count: length of received buffer + * @ppos: Not used + * + * Return: count + */ +ssize_t debug_wmi_filtered_event_log_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos); + +#else /* WMI_INTERFACE_FILTERED_EVENT_LOGGING */ + +static inline void wmi_specific_cmd_record(wmi_unified_t wmi_handle, + uint32_t id, uint8_t *buf) +{ + /* do nothing */ +} + +static inline void wmi_specific_evt_record(wmi_unified_t wmi_handle, + uint32_t id, uint8_t *buf) +{ + /* do nothing */ +} + +static inline void wmi_filtered_logging_init(wmi_unified_t wmi_handle) +{ + /* do nothing */ +} + +static inline void wmi_filtered_logging_free(wmi_unified_t wmi_handle) +{ + /* do nothing */ +} +#endif /* end of WMI_INTERFACE_FILTERED_EVENT_LOGGING */ + +#endif /*WMI_FILTERED_LOGGING_H*/ diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index f9d6f5f613a5..6ca4bca6c9d2 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -116,7 +116,9 @@ struct wmi_ext_dbg_msg { #define WMI_EVENT_DEBUG_MAX_ENTRY (1024) #endif +#ifndef WMI_EVENT_DEBUG_ENTRY_MAX_LENGTH #define WMI_EVENT_DEBUG_ENTRY_MAX_LENGTH (16) +#endif /* wmi_mgmt commands */ #ifndef WMI_MGMT_EVENT_DEBUG_MAX_ENTRY @@ -127,6 +129,16 @@ struct wmi_ext_dbg_msg { #define WMI_DIAG_RX_EVENT_DEBUG_MAX_ENTRY (256) #endif +#ifdef WMI_INTERFACE_FILTERED_EVENT_LOGGING +#ifndef WMI_FILTERED_CMD_EVT_SUPPORTED +#define WMI_FILTERED_CMD_EVT_SUPPORTED (10) +#endif + +#ifndef WMI_FILTERED_CMD_EVT_MAX_NUM_ENTRY +#define WMI_FILTERED_CMD_EVT_MAX_NUM_ENTRY (1024) +#endif +#endif /* WMI_INTERFACE_FILTERED_EVENT_LOGGING */ + #define wmi_alert(params...) QDF_TRACE_FATAL(QDF_MODULE_ID_WMI, ## params) #define wmi_err(params...) QDF_TRACE_ERROR(QDF_MODULE_ID_WMI, ## params) #define wmi_warn(params...) QDF_TRACE_WARN(QDF_MODULE_ID_WMI, ## params) @@ -234,6 +246,14 @@ struct wmi_log_buf_t { * @wmi_id_to_name - Function refernce to API to convert Command id to * string name * @wmi_log_debugfs_dir - refernce to debugfs directory + * @filtered_wmi_cmds - Buffer to save inputs from user on + * which WMI commands to record + * @filtered_wmi_cmds_idx - target cmd index + * @filtered_wmi_evts - Buffer to save inputs from user on + * which WMI event to record + * @filtered_wmi_evts_idx - target evt index + * @wmi_filtered_command_log - buffer to record user specified WMI commands + * @wmi_filtered_event_log - buffer to record user specified WMI events */ struct wmi_debug_log_info { struct wmi_log_buf_t wmi_command_log_buf_info; @@ -250,6 +270,25 @@ struct wmi_debug_log_info { qdf_spinlock_t wmi_record_lock; bool wmi_logging_enable; struct dentry *wmi_log_debugfs_dir; + +#ifdef WMI_INTERFACE_FILTERED_EVENT_LOGGING + uint32_t *filtered_wmi_cmds; + uint32_t filtered_wmi_cmds_idx; + uint32_t *filtered_wmi_evts; + uint32_t filtered_wmi_evts_idx; + struct wmi_log_buf_t *wmi_filtered_command_log; + struct wmi_log_buf_t *wmi_filtered_event_log; +#endif +}; + +/** + * enum WMI_RECORD_TYPE - User specified WMI logging types + * @ WMI_CMD - wmi command id + * @ WMI_EVT - wmi event id + */ +enum WMI_RECORD_TYPE { + WMI_CMD = 1, + WMI_EVT = 2, }; #endif /*WMI_INTERFACE_EVENT_LOGGING */ @@ -2210,7 +2249,14 @@ struct wmi_host_abi_version { uint32_t abi_version_ns_3; }; +/* number of debugfs entries used */ +#ifdef WMI_INTERFACE_FILTERED_EVENT_LOGGING +/* filtered logging added 4 more entries */ +#define NUM_DEBUG_INFOS 13 +#else #define NUM_DEBUG_INFOS 9 +#endif + struct wmi_unified { void *scn_handle; /* handle to device */ osdev_t osdev; /* handle to use OS-independent services */ diff --git a/wmi/src/wmi_filtered_logging.c b/wmi/src/wmi_filtered_logging.c new file mode 100644 index 000000000000..46bfe651bc40 --- /dev/null +++ b/wmi/src/wmi_filtered_logging.c @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2015-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 "wmi_filtered_logging.h" + +static struct wmi_log_buf_t *wmi_log_buf_allocate(void) +{ + struct wmi_log_buf_t *cmd_log_buf; + int buf_size = WMI_FILTERED_CMD_EVT_MAX_NUM_ENTRY * + sizeof(struct wmi_command_debug); + + cmd_log_buf = qdf_mem_malloc(sizeof(struct wmi_log_buf_t)); + if (!cmd_log_buf) + return NULL; + + cmd_log_buf->buf = qdf_mem_malloc(buf_size); + if (!cmd_log_buf->buf) { + qdf_mem_free(cmd_log_buf); + return NULL; + } + cmd_log_buf->length = 0; + cmd_log_buf->buf_tail_idx = 0; + cmd_log_buf->size = WMI_FILTERED_CMD_EVT_MAX_NUM_ENTRY; + cmd_log_buf->p_buf_tail_idx = &cmd_log_buf->buf_tail_idx; + + return cmd_log_buf; +} + +void wmi_filtered_logging_init(wmi_unified_t wmi_handle) +{ + int buf_size = WMI_FILTERED_CMD_EVT_SUPPORTED * sizeof(int); + + /* alloc buffer to save user inputs, for WMI_CMD */ + wmi_handle->log_info.filtered_wmi_cmds = + qdf_mem_malloc(buf_size); + if (!wmi_handle->log_info.filtered_wmi_cmds) + return; + + wmi_handle->log_info.filtered_wmi_cmds_idx = 0; + + /* alloc buffer to save user interested WMI commands */ + wmi_handle->log_info.wmi_filtered_command_log = wmi_log_buf_allocate(); + if (!wmi_handle->log_info.wmi_filtered_command_log) + goto fail1; + + /* alloc buffer to save user inputs, for WMI_EVT */ + wmi_handle->log_info.filtered_wmi_evts = + qdf_mem_malloc(buf_size); + if (!wmi_handle->log_info.filtered_wmi_evts) + goto fail2; + + wmi_handle->log_info.filtered_wmi_evts_idx = 0; + + /* alloc buffer to save user interested WMI events */ + wmi_handle->log_info.wmi_filtered_event_log = wmi_log_buf_allocate(); + if (!wmi_handle->log_info.wmi_filtered_event_log) + goto fail3; + + return; + +fail3: + qdf_mem_free(wmi_handle->log_info.filtered_wmi_evts); + wmi_handle->log_info.filtered_wmi_evts = NULL; +fail2: + qdf_mem_free(wmi_handle->log_info.wmi_filtered_command_log); + wmi_handle->log_info.wmi_filtered_command_log = NULL; +fail1: + qdf_mem_free(wmi_handle->log_info.filtered_wmi_cmds); + wmi_handle->log_info.filtered_wmi_cmds = NULL; +} + +void wmi_filtered_logging_free(wmi_unified_t wmi_handle) +{ + if (!wmi_handle) + return; + + qdf_mem_free(wmi_handle->log_info.filtered_wmi_cmds); + wmi_handle->log_info.filtered_wmi_cmds = NULL; + qdf_mem_free(wmi_handle->log_info.filtered_wmi_evts); + wmi_handle->log_info.filtered_wmi_evts = NULL; + + if (wmi_handle->log_info.wmi_filtered_command_log) { + qdf_mem_free(wmi_handle->log_info. + wmi_filtered_command_log->buf); + wmi_handle->log_info.wmi_filtered_command_log->buf = NULL; + qdf_mem_free(wmi_handle->log_info.wmi_filtered_command_log); + wmi_handle->log_info.wmi_filtered_command_log = NULL; + } + if (wmi_handle->log_info.wmi_filtered_event_log) { + qdf_mem_free(wmi_handle->log_info. + wmi_filtered_event_log->buf); + wmi_handle->log_info.wmi_filtered_event_log->buf = NULL; + qdf_mem_free(wmi_handle->log_info.wmi_filtered_event_log); + wmi_handle->log_info.wmi_filtered_event_log = NULL; + } +} + +/* + * Reset the buffer which saves user interested cmds/evts + */ +static int wmi_reset_filtered_buffers(wmi_unified_t wmi_handle, + struct wmi_log_buf_t *cmd_log_buf) +{ + int buf_size = WMI_FILTERED_CMD_EVT_MAX_NUM_ENTRY * + sizeof(struct wmi_command_debug); + + if (!cmd_log_buf) + return 0; + + cmd_log_buf->length = 0; + cmd_log_buf->buf_tail_idx = 0; + cmd_log_buf->size = WMI_FILTERED_CMD_EVT_MAX_NUM_ENTRY; + cmd_log_buf->p_buf_tail_idx = &cmd_log_buf->buf_tail_idx; + qdf_mem_zero(cmd_log_buf->buf, buf_size); + return 0; +} + +/* + * Check if id is in id list, + * return true if found. + */ +static bool wmi_id_in_list(uint32_t *id_list, uint32_t id) +{ + int i; + + if (!id_list) + return false; + + for (i = 0; i < WMI_FILTERED_CMD_EVT_SUPPORTED; i++) { + if (id == id_list[i]) { + /* id already in target list */ + return true; + } + } + return false; +} + +/* + * Add command or event ids to list to be recorded + */ +static int wmi_add_to_record_list(wmi_unified_t wmi_handle, + uint32_t id, + enum WMI_RECORD_TYPE record_type) +{ + uint32_t *target_list; + + if (record_type == WMI_CMD) { + target_list = wmi_handle->log_info.filtered_wmi_cmds; + /* check if id already in target list */ + if (wmi_id_in_list(target_list, id)) + return 0; + if (wmi_handle->log_info.filtered_wmi_cmds_idx >= + WMI_FILTERED_CMD_EVT_SUPPORTED) { + wmi_handle->log_info.filtered_wmi_cmds_idx = 0; + } + target_list[wmi_handle->log_info.filtered_wmi_cmds_idx] = id; + wmi_handle->log_info.filtered_wmi_cmds_idx++; + } else if (record_type == WMI_EVT) { + target_list = wmi_handle->log_info.filtered_wmi_evts; + /* check if id already in target list */ + if (wmi_id_in_list(target_list, id)) + return 0; + if (wmi_handle->log_info.filtered_wmi_evts_idx >= + WMI_FILTERED_CMD_EVT_SUPPORTED) { + wmi_handle->log_info.filtered_wmi_evts_idx = 0; + } + target_list[wmi_handle->log_info.filtered_wmi_evts_idx] = id; + wmi_handle->log_info.filtered_wmi_evts_idx++; + } else { + return -EINVAL; + } + return 0; +} + +static void wmi_specific_cmd_evt_record(uint32_t id, uint8_t *buf, + struct wmi_log_buf_t *log_buffer) +{ + int idx; + struct wmi_command_debug *tmpbuf = + (struct wmi_command_debug *)log_buffer->buf; + + if (*log_buffer->p_buf_tail_idx >= WMI_FILTERED_CMD_EVT_MAX_NUM_ENTRY) + *log_buffer->p_buf_tail_idx = 0; + + idx = *log_buffer->p_buf_tail_idx; + tmpbuf[idx].command = id; + qdf_mem_copy(tmpbuf[idx].data, buf, + WMI_EVENT_DEBUG_ENTRY_MAX_LENGTH); + tmpbuf[idx].time = qdf_get_log_timestamp(); + (*log_buffer->p_buf_tail_idx)++; + log_buffer->length++; +} + +void wmi_specific_cmd_record(wmi_unified_t wmi_handle, + uint32_t id, uint8_t *buf) +{ + uint32_t *target_list; + struct wmi_log_buf_t *log_buffer; + + target_list = wmi_handle->log_info.filtered_wmi_cmds; + if (!target_list) + return; + + log_buffer = wmi_handle->log_info.wmi_filtered_command_log; + if (!log_buffer) + return; + + if (wmi_id_in_list(target_list, id)) { + /* id in target list, need to be recorded */ + wmi_specific_cmd_evt_record(id, buf, log_buffer); + } +} + +void wmi_specific_evt_record(wmi_unified_t wmi_handle, + uint32_t id, uint8_t *buf) +{ + uint32_t *target_list; + struct wmi_log_buf_t *log_buffer; + + target_list = wmi_handle->log_info.filtered_wmi_evts; + if (!target_list) + return; + + log_buffer = wmi_handle->log_info.wmi_filtered_event_log; + if (!log_buffer) + return; + + if (wmi_id_in_list(target_list, id)) { + /* id in target list, need to be recorded */ + wmi_specific_cmd_evt_record(id, buf, log_buffer); + } +} + +/* + * Debugfs read/write functions + */ +static int wmi_filtered_seq_printf(qdf_debugfs_file_t m, const char *f, ...) +{ + va_list args; + + va_start(args, f); + seq_vprintf(m, f, args); + va_end(args); + + return 0; +} + +/* + * debugfs show/read for filtered_wmi_cmds + */ +int debug_filtered_wmi_cmds_show(qdf_debugfs_file_t m, void *v) +{ + wmi_unified_t wmi_handle = (wmi_unified_t)m->private; + int i; + int *target_list; + + target_list = wmi_handle->log_info.filtered_wmi_cmds; + if (!target_list) + return 0; + + for (i = 0; i < WMI_FILTERED_CMD_EVT_SUPPORTED; i++) { + if (target_list[i] != 0) { + wmi_filtered_seq_printf(m, "0x%x ", + target_list[i]); + } + } + wmi_filtered_seq_printf(m, "\n"); + + return 0; +} + +int debug_filtered_wmi_evts_show(qdf_debugfs_file_t m, void *v) +{ + wmi_unified_t wmi_handle = (wmi_unified_t)m->private; + int i; + int *target_list; + + target_list = wmi_handle->log_info.filtered_wmi_evts; + if (!target_list) + return 0; + for (i = 0; i < WMI_FILTERED_CMD_EVT_SUPPORTED; i++) { + if (target_list[i] != 0) { + wmi_filtered_seq_printf(m, "0x%x ", + target_list[i]); + } + } + wmi_filtered_seq_printf(m, "\n"); + + return 0; +} + +static int wmi_log_show(wmi_unified_t wmi_handle, void *buf, + qdf_debugfs_file_t m) +{ + struct wmi_log_buf_t *wmi_log = (struct wmi_log_buf_t *)buf; + int pos, nread, outlen; + int i; + uint64_t secs, usecs; + int wmi_ring_size = 100; + + qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock); + if (!wmi_log->length) { + qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock); + return wmi_filtered_seq_printf(m, + "Nothing to read!\n"); + } + if (wmi_log->length <= wmi_ring_size) + nread = wmi_log->length; + else + nread = wmi_ring_size; + + if (*wmi_log->p_buf_tail_idx == 0) + /* tail can be 0 after wrap-around */ + pos = wmi_ring_size - 1; + else + pos = *wmi_log->p_buf_tail_idx - 1; + + outlen = wmi_filtered_seq_printf(m, "Length = %d\n", wmi_log->length); + qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock); + while (nread--) { + struct wmi_event_debug *wmi_record; + + wmi_record = &(((struct wmi_event_debug *)wmi_log->buf)[pos]); + qdf_log_timestamp_to_secs(wmi_record->time, &secs, + &usecs); + outlen += wmi_filtered_seq_printf(m, "Event ID = %x\n", + (wmi_record->event)); + outlen += + wmi_filtered_seq_printf(m, + "Event TIME = [%llu.%06llu]\n", + secs, usecs); + outlen += wmi_filtered_seq_printf(m, "CMD = "); + for (i = 0; i < (WMI_EVENT_DEBUG_ENTRY_MAX_LENGTH / + sizeof(uint32_t)); i++) + outlen += wmi_filtered_seq_printf(m, "%x ", + wmi_record->data[i]); + outlen += wmi_filtered_seq_printf(m, "\n"); + if (pos == 0) + pos = wmi_ring_size - 1; + else + pos--; + } + return outlen; +} + +int debug_wmi_filtered_command_log_show(qdf_debugfs_file_t m, void *v) +{ + wmi_unified_t wmi_handle = (wmi_unified_t)m->private; + struct wmi_log_buf_t *wmi_log = + wmi_handle->log_info.wmi_filtered_command_log; + + if (!wmi_log) + return 0; + return wmi_log_show(wmi_handle, wmi_log, m); +} + +int debug_wmi_filtered_event_log_show(qdf_debugfs_file_t m, void *v) +{ + wmi_unified_t wmi_handle = (wmi_unified_t)m->private; + struct wmi_log_buf_t *wmi_log = + wmi_handle->log_info.wmi_filtered_event_log; + + if (!wmi_log) + return 0; + return wmi_log_show(wmi_handle, wmi_log, m); +} + +ssize_t debug_filtered_wmi_cmds_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + wmi_unified_t wmi_handle = + ((struct seq_file *)file->private_data)->private; + int k, ret; + char locbuf[12] = {0}; + int buf_size = WMI_FILTERED_CMD_EVT_SUPPORTED * sizeof(int); + + if ((!buf) || (count > 8 || count <= 0)) + return -EFAULT; + + if (!wmi_handle->log_info.filtered_wmi_cmds) + return -EFAULT; + + if (copy_from_user(locbuf, buf, count)) + return -EFAULT; + + ret = qdf_kstrtoint(locbuf, 16, &k); + if (ret) + return -EINVAL; + + if (k == 0xffff) { + qdf_mem_zero(wmi_handle->log_info.filtered_wmi_cmds, buf_size); + wmi_handle->log_info.filtered_wmi_cmds_idx = 0; + return count; + } + + if (wmi_add_to_record_list(wmi_handle, k, WMI_CMD)) { + WMI_LOGE("Add cmd %d to WMI_CMD list failed"); + return 0; + } + + return count; +} + +ssize_t debug_filtered_wmi_evts_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + wmi_unified_t wmi_handle = + ((struct seq_file *)file->private_data)->private; + int k, ret; + char locbuf[12] = {0}; + int buf_size = WMI_FILTERED_CMD_EVT_SUPPORTED * sizeof(int); + + if ((!buf) || (count > 8 || count <= 0)) + return -EFAULT; + + if (!wmi_handle->log_info.filtered_wmi_evts) + return -EFAULT; + + if (copy_from_user(locbuf, buf, count)) + return -EFAULT; + + ret = qdf_kstrtoint(locbuf, 16, &k); + if (ret) + return -EINVAL; + + if (k == 0xffff) { + qdf_mem_zero(wmi_handle->log_info.filtered_wmi_evts, buf_size); + wmi_handle->log_info.filtered_wmi_evts_idx = 0; + return count; + } + + if (wmi_add_to_record_list(wmi_handle, k, WMI_EVT)) { + WMI_LOGE("Add cmd %d to WMI_EVT list failed"); + return 0; + } + + return count; +} + +ssize_t debug_wmi_filtered_command_log_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + wmi_unified_t wmi_handle = + ((struct seq_file *)file->private_data)->private; + int k, ret; + char locbuf[12] = {0}; + struct wmi_log_buf_t *cmd_log_buf; + + if ((!buf) || (count > 8 || count <= 0)) + return -EFAULT; + + if (copy_from_user(locbuf, buf, count)) + return -EFAULT; + + ret = qdf_kstrtoint(locbuf, 16, &k); + if (ret) + return -EINVAL; + + if (k != 0xffff) + return -EINVAL; + + cmd_log_buf = wmi_handle->log_info.wmi_filtered_command_log; + if (wmi_reset_filtered_buffers(wmi_handle, cmd_log_buf)) + WMI_LOGE("reset WMI CMD filtered_buffers failed"); + return count; +} + +ssize_t debug_wmi_filtered_event_log_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + wmi_unified_t wmi_handle = + ((struct seq_file *)file->private_data)->private; + int k, ret; + char locbuf[12] = {0}; + struct wmi_log_buf_t *cmd_log_buf; + + if ((!buf) || (count > 8 || count <= 0)) + return -EFAULT; + + if (copy_from_user(locbuf, buf, count)) + return -EFAULT; + + ret = qdf_kstrtoint(locbuf, 16, &k); + if (ret) + return -EINVAL; + + if (k != 0xffff) + return -EINVAL; + + cmd_log_buf = wmi_handle->log_info.wmi_filtered_event_log; + if (wmi_reset_filtered_buffers(wmi_handle, cmd_log_buf)) + WMI_LOGE("reset WMI EVT filtered_buffers failed"); + return count; +} diff --git a/wmi/src/wmi_unified.c b/wmi/src/wmi_unified.c index e4fbab3b9e12..ee7a415d483e 100644 --- a/wmi/src/wmi_unified.c +++ b/wmi/src/wmi_unified.c @@ -36,6 +36,8 @@ #include #include +#include +#include "wmi_filtered_logging.h" /* This check for CONFIG_WIN temporary added due to redeclaration compilation error in MCL. Error is caused due to inclusion of wmi.h in wmi_unified_api.h @@ -101,7 +103,7 @@ typedef PREPACK struct { #ifdef WMI_INTERFACE_EVENT_LOGGING #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)) /* TODO Cleanup this backported function */ -static int wmi_bp_seq_printf(struct seq_file *m, const char *f, ...) +static int wmi_bp_seq_printf(qdf_debugfs_file_t m, const char *f, ...) { va_list args; @@ -813,6 +815,8 @@ static QDF_STATUS wmi_log_init(struct wmi_unified *wmi_handle) qdf_spinlock_create(&wmi_handle->log_info.wmi_record_lock); wmi_handle->log_info.wmi_logging_enable = 1; + wmi_filtered_logging_init(wmi_handle); + return QDF_STATUS_SUCCESS; } #endif @@ -827,6 +831,8 @@ static QDF_STATUS wmi_log_init(struct wmi_unified *wmi_handle) #ifdef WMI_INTERFACE_EVENT_LOGGING_DYNAMIC_ALLOC static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle) { + wmi_filtered_logging_free(wmi_handle); + if (wmi_handle->log_info.wmi_command_log_buf_info.buf) qdf_mem_free(wmi_handle->log_info.wmi_command_log_buf_info.buf); if (wmi_handle->log_info.wmi_command_tx_cmp_log_buf_info.buf) @@ -850,6 +856,7 @@ static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle) qdf_mem_free( wmi_handle->log_info.wmi_diag_event_log_buf_info.buf); wmi_handle->log_info.wmi_logging_enable = 0; + qdf_spinlock_destroy(&wmi_handle->log_info.wmi_record_lock); } #else @@ -1357,6 +1364,12 @@ GENERATE_DEBUG_STRUCTS(wmi_mgmt_command_tx_cmp_log); GENERATE_DEBUG_STRUCTS(wmi_mgmt_event_log); GENERATE_DEBUG_STRUCTS(wmi_enable); GENERATE_DEBUG_STRUCTS(wmi_log_size); +#ifdef WMI_INTERFACE_FILTERED_EVENT_LOGGING +GENERATE_DEBUG_STRUCTS(filtered_wmi_cmds); +GENERATE_DEBUG_STRUCTS(filtered_wmi_evts); +GENERATE_DEBUG_STRUCTS(wmi_filtered_command_log); +GENERATE_DEBUG_STRUCTS(wmi_filtered_event_log); +#endif struct wmi_debugfs_info wmi_debugfs_infos[NUM_DEBUG_INFOS] = { DEBUG_FOO(wmi_command_log), @@ -1368,6 +1381,12 @@ struct wmi_debugfs_info wmi_debugfs_infos[NUM_DEBUG_INFOS] = { DEBUG_FOO(wmi_mgmt_event_log), DEBUG_FOO(wmi_enable), DEBUG_FOO(wmi_log_size), +#ifdef WMI_INTERFACE_FILTERED_EVENT_LOGGING + DEBUG_FOO(filtered_wmi_cmds), + DEBUG_FOO(filtered_wmi_evts), + DEBUG_FOO(wmi_filtered_command_log), + DEBUG_FOO(wmi_filtered_event_log), +#endif }; @@ -1484,7 +1503,7 @@ void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd, qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock); WMI_MGMT_COMMAND_RECORD(wmi_handle, cmd, (uint8_t *)data); - + wmi_specific_cmd_record(wmi_handle, cmd, (uint8_t *)data); qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock); } #else @@ -1839,9 +1858,11 @@ QDF_STATUS wmi_unified_cmd_send_fl(wmi_unified_t wmi_handle, wmi_buf_t buf, * WMI mgmt command already recorded in wmi_mgmt_cmd_record */ if (wmi_handle->ops->is_management_record(cmd_id) == false) { - WMI_COMMAND_RECORD(wmi_handle, cmd_id, - qdf_nbuf_data(buf) + - wmi_handle->soc->buf_offset_command); + uint8_t *tmpbuf = (uint8_t *)qdf_nbuf_data(buf) + + wmi_handle->soc->buf_offset_command; + + WMI_COMMAND_RECORD(wmi_handle, cmd_id, tmpbuf); + wmi_specific_cmd_record(wmi_handle, cmd_id, tmpbuf); } qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock); } @@ -2430,8 +2451,11 @@ void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf) * as its already logged in WMI RX event buffer */ } else { - WMI_EVENT_RECORD(wmi_handle, id, ((uint8_t *) data + - wmi_handle->soc->buf_offset_event)); + uint8_t *tmpbuf = (uint8_t *)data + + wmi_handle->soc->buf_offset_event; + + WMI_EVENT_RECORD(wmi_handle, id, tmpbuf); + wmi_specific_evt_record(wmi_handle, id, tmpbuf); } qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock); } From 85d4f035876ba2e05c29e4e1bf82c303bfaac61f Mon Sep 17 00:00:00 2001 From: gaurank kathpalia Date: Fri, 7 Feb 2020 15:44:13 +0530 Subject: [PATCH 8/8] qcacmn: Set DBS scan if ndp peers are active Currently on the STA interface if the scan comes the driver puts it to NON-DBS scan if the high accuracy request comes, but if the NDP peers are active this causes a throughput loss as scan takes much time to complete. Fix is to do a DBS scan if the NDP peers are attached to a NDI interface. Change-Id: I798fd388f2bf010304ba1f6777680cf4d1f3ccfb CRs-Fixed: 2615541 --- umac/scan/core/src/wlan_scan_manager.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/umac/scan/core/src/wlan_scan_manager.c b/umac/scan/core/src/wlan_scan_manager.c index eecbfc0ad285..ed2aa5573886 100644 --- a/umac/scan/core/src/wlan_scan_manager.c +++ b/umac/scan/core/src/wlan_scan_manager.c @@ -434,6 +434,7 @@ scm_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req) { struct wlan_objmgr_psoc *psoc; uint32_t scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT; + bool ndi_present; psoc = wlan_vdev_get_psoc(req->vdev); @@ -447,6 +448,15 @@ scm_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req) goto end; } + ndi_present = policy_mgr_mode_specific_connection_count(psoc, + PM_NDI_MODE, + NULL); + + if (ndi_present && !policy_mgr_is_hw_dbs_2x2_capable(psoc)) { + scm_debug("NDP present go for DBS scan"); + goto end; + } + if (req->scan_req.scan_policy_high_accuracy) { scm_debug("high accuracy scan received, going for non-dbs scan"); scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS; @@ -550,6 +560,8 @@ int scm_scan_get_burst_duration(int max_ch_time, bool miracast_enabled) return burst_duration; } +#define SCM_ACTIVE_DWELL_TIME_NAN 40 + /** * scm_req_update_concurrency_params() - update scan req params depending on * concurrent mode present. @@ -759,6 +771,17 @@ static void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev, req->scan_req.dwell_time_active; } } + + if (ndi_present) { + req->scan_req.dwell_time_active = + QDF_MIN(req->scan_req.dwell_time_active, + SCM_ACTIVE_DWELL_TIME_NAN); + req->scan_req.dwell_time_active_2g = + QDF_MIN(req->scan_req.dwell_time_active_2g, + SCM_ACTIVE_DWELL_TIME_NAN); + scm_debug("NDP active modify dwell time 2ghz %d", + req->scan_req.dwell_time_active_2g); + } } /**