qcacmn: Add support for hash based rx steering

This change includes:
- Adding the hooks to send LRO and hash configuration to the firmware
- Configuring the REO remap registers

Change-Id: I6d83e2a2365647f2c7a6440bd1d4b42fa7df7eff
CRs-Fixed: 1094775
This commit is contained in:
Dhanashri Atre
2016-11-11 18:32:36 -08:00
committed by Sandeep Puligilla
parent ebeac94625
commit 1404917b6e
12 changed files with 283 additions and 8 deletions

View File

@@ -492,6 +492,30 @@ struct cdp_pflow_ops {
};
#endif /* CONFIG_WIN */
#define LRO_IPV4_SEED_ARR_SZ 5
#define LRO_IPV6_SEED_ARR_SZ 11
/**
* struct cdp_lro_config - set LRO init parameters
* @lro_enable: indicates whether lro is enabled
* @tcp_flag: If the TCP flags from the packet do not match
* the values in this field after masking with TCP flags mask
* below, packet is not LRO eligible
* @tcp_flag_mask: field for comparing the TCP values provided
* above with the TCP flags field in the received packet
* @toeplitz_hash_ipv4: contains seed needed to compute the flow id
* 5-tuple toeplitz hash for ipv4 packets
* @toeplitz_hash_ipv6: contains seed needed to compute the flow id
* 5-tuple toeplitz hash for ipv6 packets
*/
struct cdp_lro_hash_config {
uint32_t lro_enable;
uint32_t tcp_flag:9,
tcp_flag_mask:9;
uint32_t toeplitz_hash_ipv4[LRO_IPV4_SEED_ARR_SZ];
uint32_t toeplitz_hash_ipv6[LRO_IPV6_SEED_ARR_SZ];
};
struct ol_if_ops {
void (*peer_set_default_routing)(void *scn_handle,
uint8_t *peer_macaddr, uint8_t vdev_id,
@@ -513,7 +537,8 @@ struct ol_if_ops {
uint32_t flags);
void (*peer_del_wds_entry)(void *ol_soc_handle,
uint8_t *wds_macaddr);
QDF_STATUS (*lro_hash_config)(void *scn_handle,
struct cdp_lro_hash_config *lro_hash);
/* TODO: Add any other control path calls required to OL_IF/WMA layer */
};

View File

@@ -18,6 +18,7 @@
#include <qdf_types.h>
#include <qdf_lock.h>
#include <qdf_net_types.h>
#include <hal_api.h>
#include <hif.h>
#include <htt.h>
@@ -31,6 +32,7 @@
#include <cdp_txrx_handle.h>
#include <wlan_cfg.h>
#include "cdp_txrx_cmn_struct.h"
#include <qdf_util.h>
#define DP_INTR_POLL_TIMER_MS 100
#define DP_MCS_LENGTH (6*MAX_MCS)
@@ -723,6 +725,7 @@ static void dp_hw_link_desc_pool_cleanup(struct dp_soc *soc)
static int dp_soc_cmn_setup(struct dp_soc *soc)
{
int i;
struct hal_reo_params reo_params;
if (qdf_atomic_read(&soc->cmn_init_done))
return 0;
@@ -799,6 +802,9 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
if (!wlan_cfg_per_pdev_rx_ring(soc->wlan_cfg_ctx)) {
soc->num_reo_dest_rings =
wlan_cfg_num_reo_dest_rings(soc->wlan_cfg_ctx);
QDF_TRACE(QDF_MODULE_ID_DP,
QDF_TRACE_LEVEL_ERROR,
FL("num_reo_dest_rings %d\n"), soc->num_reo_dest_rings);
for (i = 0; i < soc->num_reo_dest_rings; i++) {
if (dp_srng_setup(soc, &soc->reo_dest_ring[i], REO_DST,
i, 0, REO_DST_RING_SIZE)) {
@@ -862,8 +868,14 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
}
dp_soc_interrupt_attach(soc);
/* Setup HW REO */
hal_reo_setup(soc->hal_soc);
qdf_mem_zero(&reo_params, sizeof(reo_params));
if (wlan_cfg_is_rx_hash_enabled(soc->wlan_cfg_ctx))
reo_params.rx_hash_enabled = true;
hal_reo_setup(soc->hal_soc, &reo_params);
qdf_atomic_set(&soc->cmn_init_done, 1);
return 0;
@@ -878,6 +890,65 @@ fail0:
static void dp_pdev_detach_wifi3(struct cdp_pdev *txrx_pdev, int force);
static void dp_lro_hash_setup(struct dp_soc *soc)
{
struct cdp_lro_hash_config lro_hash;
if (!wlan_cfg_is_lro_enabled(soc->wlan_cfg_ctx) &&
!wlan_cfg_is_rx_hash_enabled(soc->wlan_cfg_ctx)) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("LRO disabled RX hash disabled"));
return;
}
qdf_mem_zero(&lro_hash, sizeof(lro_hash));
if (wlan_cfg_is_lro_enabled(soc->wlan_cfg_ctx)) {
lro_hash.lro_enable = 1;
lro_hash.tcp_flag = QDF_TCPHDR_ACK;
lro_hash.tcp_flag_mask = QDF_TCPHDR_FIN | QDF_TCPHDR_SYN |
QDF_TCPHDR_RST | QDF_TCPHDR_ACK | QDF_TCPHDR_URG |
QDF_TCPHDR_ECE | QDF_TCPHDR_CWR;
}
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("enabled"));
qdf_get_random_bytes(lro_hash.toeplitz_hash_ipv4,
(sizeof(lro_hash.toeplitz_hash_ipv4[0]) *
LRO_IPV4_SEED_ARR_SZ));
qdf_get_random_bytes(lro_hash.toeplitz_hash_ipv6,
(sizeof(lro_hash.toeplitz_hash_ipv6[0]) *
LRO_IPV6_SEED_ARR_SZ));
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
"lro_hash: lro_enable: 0x%x"
"lro_hash: tcp_flag 0x%x tcp_flag_mask 0x%x",
lro_hash.lro_enable, lro_hash.tcp_flag,
lro_hash.tcp_flag_mask);
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("lro_hash: toeplitz_hash_ipv4:"));
qdf_trace_hex_dump(QDF_MODULE_ID_DP,
QDF_TRACE_LEVEL_ERROR,
(void *)lro_hash.toeplitz_hash_ipv4,
(sizeof(lro_hash.toeplitz_hash_ipv4[0]) *
LRO_IPV4_SEED_ARR_SZ));
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("lro_hash: toeplitz_hash_ipv6:"));
qdf_trace_hex_dump(QDF_MODULE_ID_DP,
QDF_TRACE_LEVEL_ERROR,
(void *)lro_hash.toeplitz_hash_ipv6,
(sizeof(lro_hash.toeplitz_hash_ipv6[0]) *
LRO_IPV6_SEED_ARR_SZ));
qdf_assert(soc->cdp_soc.ol_ops->lro_hash_config);
if (soc->cdp_soc.ol_ops->lro_hash_config)
(void)soc->cdp_soc.ol_ops->lro_hash_config
(soc->osif_soc, &lro_hash);
}
/*
* dp_rxdma_ring_setup() - configure the RX DMA rings
* @soc: data path SoC handle
@@ -1046,6 +1117,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc,
/* MCL */
dp_local_peer_id_pool_init(pdev);
#endif
dp_lro_hash_setup(soc);
return (struct cdp_pdev *)pdev;
@@ -1578,6 +1650,7 @@ static void dp_peer_setup_wifi3(struct cdp_vdev *vdev_hdl, void *peer_hdl)
struct dp_vdev *vdev = (struct dp_vdev *)vdev_hdl;
struct dp_pdev *pdev;
struct dp_soc *soc;
bool hash_based = 0;
/* preconditions */
qdf_assert(vdev);
@@ -1592,10 +1665,15 @@ static void dp_peer_setup_wifi3(struct cdp_vdev *vdev_hdl, void *peer_hdl)
peer->last_disassoc_rcvd = 0;
peer->last_deauth_rcvd = 0;
hash_based = wlan_cfg_is_rx_hash_enabled(soc->wlan_cfg_ctx);
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("hash based steering %d\n"), hash_based);
if (soc->cdp_soc.ol_ops->peer_set_default_routing) {
/* TODO: Check the destination ring number to be passed to FW */
soc->cdp_soc.ol_ops->peer_set_default_routing(pdev->osif_pdev,
peer->mac_addr.raw, peer->vdev->vdev_id, 0, 1);
soc->cdp_soc.ol_ops->peer_set_default_routing(
pdev->osif_pdev, peer->mac_addr.raw,
peer->vdev->vdev_id, hash_based, 1);
}
return;
}

View File

@@ -639,6 +639,10 @@ done:
* the buffer beginning where the L2 header
* begins.
*/
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
FL("rxhash: flow id toeplitz: 0x%x\n"),
hal_rx_msdu_start_toeplitz_get(rx_tlv_hdr));
l2_hdr_offset =
hal_rx_msdu_end_l3_hdr_padding_get(rx_tlv_hdr);

View File

@@ -739,6 +739,29 @@ hal_rx_msdu_start_reception_type_get(uint8_t *buf)
return reception_type;
}
#define HAL_RX_MSDU_START_FLOWID_TOEPLITZ_GET(_rx_msdu_start) \
(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_start, \
RX_MSDU_START_4_FLOW_ID_TOEPLITZ_OFFSET)), \
RX_MSDU_START_4_FLOW_ID_TOEPLITZ_MASK, \
RX_MSDU_START_4_FLOW_ID_TOEPLITZ_LSB))
/**
* hal_rx_msdu_start_toeplitz_get: API to get the toeplitz hash
* from rx_msdu_start TLV
*
* @ buf: pointer to the start of RX PKT TLV headers
* Return: toeplitz hash
*/
static inline uint32_t
hal_rx_msdu_start_toeplitz_get(uint8_t *buf)
{
struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
struct rx_msdu_start *msdu_start =
&pkt_tlvs->msdu_start_tlv.rx_msdu_start;
return HAL_RX_MSDU_START_FLOWID_TOEPLITZ_GET(msdu_start);
}
/*
* Get qos_control_valid from RX_MPDU_START
*/

View File

@@ -728,12 +728,19 @@ extern void hal_setup_link_idle_list(void *hal_soc,
void *scatter_bufs_base_vaddr[], uint32_t num_scatter_bufs,
uint32_t scatter_buf_size, uint32_t last_buf_end_offset);
/* REO parameters to be passed to hal_reo_setup */
struct hal_reo_params {
bool rx_hash_enabled;
};
/**
* hal_reo_setup - Initialize HW REO block
*
* @hal_soc: Opaque HAL SOC handle
* @reo_params: parameters needed by HAL for REO config
*/
extern void hal_reo_setup(void *hal_soc);
extern void hal_reo_setup(void *hal_soc,
struct hal_reo_params *reo_params);
enum hal_pn_type {
HAL_PN_NONE,

View File

@@ -58,6 +58,41 @@ static inline void hal_uniform_desc_hdr_setup(uint32_t *desc, uint32_t owner,
#endif
#define HAL_NON_QOS_TID 16
/**
* When hash based routing is enabled, routing of the rx packet
* is done based on the following value: 1 _ _ _ _ The last 4
* bits are based on hash[3:0]. This means the possible values
* are 0x10 to 0x1f. This value is used to look-up the
* ring ID configured in Destination_Ring_Ctrl_IX_* register.
* The Destination_Ring_Ctrl_IX_2 and Destination_Ring_Ctrl_IX_3
* registers need to be configured to set-up the 16 entries to
* map the hash values to a ring number. There are 3 bits per
* hash entry <20> which are mapped as follows:
* 0: TCL, 1:SW1, 2:SW2, * 3:SW3, 4:SW4, 5:Release, 6:FW(WIFI),
* 7: NOT_USED.
*/
#ifdef IPA_OFFLOAD
/**
* When IPA is enabled, there will be 3 available rings.
* Otherwise there will be 4.
*/
#define REO_REMAP_REGISTER_2 ( \
((0x1 << 0) | (0x2 << 3) | (0x3 << 6) | (0x1 << 9) | \
(0x2 << 12) | (0x3 << 15) | (0x1 << 18) | (0x2 << 21)) << 8)
#define REO_REMAP_REGISTER_3 ( \
((0x3 << 0) | (0x1 << 3) | (0x2 << 6) | (0x3 << 9) | \
(0x1 << 12) | (0x2 << 15) | (0x3 << 18) | (0x1 << 21)) << 8)
#else
#define REO_REMAP_REGISTER_2 ( \
((0x1 << 0) | (0x2 << 3) | (0x3 << 6) | (0x4 << 9) | \
(0x1 << 12) | (0x2 << 15) | (0x3 << 18) | (0x4 << 21)) << 8)
#define REO_REMAP_REGISTER_3 ( \
((0x1 << 0) | (0x2 << 3) | (0x3 << 6) | (0x4 << 9) | \
(0x1 << 12) | (0x2 << 15) | (0x3 << 18) | (0x4 << 21)) << 8)
#endif
/**
* hal_reo_qdesc_setup - Setup HW REO queue descriptor
*
@@ -222,8 +257,10 @@ void hal_reo_qdesc_setup(void *hal_soc, int tid, uint32_t ba_window_size,
* hal_reo_setup - Initialize HW REO block
*
* @hal_soc: Opaque HAL SOC handle
* @reo_params: parameters needed by HAL for REO config
*/
void hal_reo_setup(void *hal_soc)
void hal_reo_setup(void *hal_soc,
struct hal_reo_params *reo_params)
{
struct hal_soc *soc = (struct hal_soc *)hal_soc;
@@ -261,6 +298,31 @@ void hal_reo_setup(void *hal_soc)
SEQ_WCSS_UMAC_REO_REG_OFFSET),
(HAL_DEFAULT_REO_TIMEOUT_MS * 1000));
if (reo_params->rx_hash_enabled) {
HAL_REG_WRITE(soc,
HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR(
SEQ_WCSS_UMAC_REO_REG_OFFSET),
REO_REMAP_REGISTER_2);
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR 0x%x\n"),
HAL_REG_READ(soc,
HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR(
SEQ_WCSS_UMAC_REO_REG_OFFSET)));
HAL_REG_WRITE(soc,
HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR(
SEQ_WCSS_UMAC_REO_REG_OFFSET),
REO_REMAP_REGISTER_3);
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR 0x%x\n"),
HAL_REG_READ(soc,
HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR(
SEQ_WCSS_UMAC_REO_REG_OFFSET)));
}
/* TODO: Check if the following registers shoould be setup by host:
* AGING_CONTROL
* HIGH_MEMORY_THRESHOLD

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -70,6 +70,14 @@ typedef struct qdf_net_ethaddr {
uint8_t addr[QDF_NET_ETH_LEN];
} qdf_net_ethaddr_t;
#define QDF_TCPHDR_FIN __QDF_TCPHDR_FIN
#define QDF_TCPHDR_SYN __QDF_TCPHDR_SYN
#define QDF_TCPHDR_RST __QDF_TCPHDR_RST
#define QDF_TCPHDR_PSH __QDF_TCPHDR_PSH
#define QDF_TCPHDR_ACK __QDF_TCPHDR_ACK
#define QDF_TCPHDR_URG __QDF_TCPHDR_URG
#define QDF_TCPHDR_ECE __QDF_TCPHDR_ECE
#define QDF_TCPHDR_CWR __QDF_TCPHDR_CWR
typedef struct {
uint16_t source;

View File

@@ -535,4 +535,15 @@ int qdf_set_dma_coherent_mask(struct device *dev, uint8_t addr_bits)
return __qdf_set_dma_coherent_mask(dev, addr_bits);
}
/**
* qdf_get_random_bytes() - returns nbytes bytes of random
* data
*
* Return: random bytes of data
*/
static inline
void qdf_get_random_bytes(void *buf, int nbytes)
{
return __qdf_get_random_bytes(buf, nbytes);
}
#endif /*_QDF_UTIL_H*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -36,6 +36,7 @@
#include <qdf_types.h> /* uint8_t, etc. */
#include <asm/checksum.h>
#include <net/ip6_checksum.h>
#include <net/tcp.h>
typedef struct in6_addr __in6_addr_t;
typedef __wsum __wsum_t;
@@ -49,4 +50,12 @@ static inline int32_t __qdf_csum_ipv6(const struct in6_addr *saddr,
(struct in6_addr *)daddr, len, proto, sum);
}
#define __QDF_TCPHDR_FIN TCPHDR_FIN
#define __QDF_TCPHDR_SYN TCPHDR_SYN
#define __QDF_TCPHDR_RST TCPHDR_RST
#define __QDF_TCPHDR_PSH TCPHDR_PSH
#define __QDF_TCPHDR_ACK TCPHDR_ACK
#define __QDF_TCPHDR_URG TCPHDR_URG
#define __QDF_TCPHDR_ECE TCPHDR_ECE
#define __QDF_TCPHDR_CWR TCPHDR_CWR
#endif /* _I_QDF_NET_TYPES_H */

View File

@@ -397,5 +397,16 @@ int __qdf_set_dma_coherent_mask(struct device *dev, uint8_t addr_bits)
return dma_set_coherent_mask(dev, DMA_BIT_MASK(addr_bits));
}
#endif
/**
* qdf_get_random_bytes() - returns nbytes bytes of random
* data
*
* Return: random bytes of data
*/
static inline
void __qdf_get_random_bytes(void *buf, int nbytes)
{
return get_random_bytes(buf, nbytes);
}
#endif /*_I_QDF_UTIL_H*/

View File

@@ -85,6 +85,9 @@
#define NUM_RXDMA_RINGS_PER_PDEV 1
#endif
#define WLAN_RX_HASH_ENABLE 0
#define WLAN_LRO_ENABLE 0
static const int tx_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {
WLAN_CFG_TX_RING_MASK_0,
WLAN_CFG_TX_RING_MASK_1,
@@ -125,6 +128,8 @@ static const int rx_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {
* @int_rx_mon_ring_mask - Bitmap of Rx monitor ring interrupts mapped to each
* NAPI/Intr context
* @int_ce_ring_mask - Bitmap of CE interrupts mapped to each NAPI/Intr context
* @lro_enabled - is LRO enabled
* @rx_hash - Enable hash based steering of rx packets
*
*/
struct wlan_cfg_dp_soc_ctxt {
@@ -145,6 +150,8 @@ struct wlan_cfg_dp_soc_ctxt {
int int_rx_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS];
int int_rx_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS];
int int_ce_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS];
bool lro_enabled;
bool rx_hash;
};
/**
@@ -196,6 +203,9 @@ struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach(void)
wlan_cfg_ctx->int_rx_mon_ring_mask[i] = rx_mon_ring_mask[i];
}
wlan_cfg_ctx->rx_hash = WLAN_RX_HASH_ENABLE;
wlan_cfg_ctx->lro_enabled = WLAN_LRO_ENABLE;
return wlan_cfg_ctx;
}
@@ -371,3 +381,13 @@ int wlan_cfg_get_num_mac_rings(struct wlan_cfg_dp_pdev_ctxt *cfg)
{
return cfg->num_mac_rings;
}
bool wlan_cfg_is_lro_enabled(struct wlan_cfg_dp_soc_ctxt *cfg)
{
return cfg->lro_enabled;
}
bool wlan_cfg_is_rx_hash_enabled(struct wlan_cfg_dp_soc_ctxt *cfg)
{
return cfg->rx_hash;
}

View File

@@ -312,4 +312,21 @@ int wlan_cfg_get_rx_dma_buf_ring_size(
* Return: number of mac DMA rings per pdev
*/
int wlan_cfg_get_num_mac_rings(struct wlan_cfg_dp_pdev_ctxt *cfg);
/*
* wlan_cfg_is_lro_enabled - Return LRO enabled/disabled
* @wlan_cfg_pdev_ctx
*
* Return: true - LRO enabled false - LRO disabled
*/
bool wlan_cfg_is_lro_enabled(struct wlan_cfg_dp_soc_ctxt *cfg);
/*
* wlan_cfg_is_lro_enabled - Return RX hash enabled/disabled
* @wlan_cfg_pdev_ctx
*
* Return: true - enabled false - disabled
*/
bool wlan_cfg_is_rx_hash_enabled(struct wlan_cfg_dp_soc_ctxt *cfg);
#endif