qcacmn: Add support for WDS aging
Add support for monitoring receive traffic from WDS nodes and aging out inactive WDS nodes Change-Id: Iedea826832a5421714c00bccadc6e0dc4acd4c7e CRs-Fixed: 2004658
This commit is contained in:

committed by
snandini

parent
a7b6842a72
commit
b8bbf16192
@@ -485,6 +485,7 @@ enum cdp_vdev_param_type {
|
||||
CDP_ENABLE_WDS,
|
||||
CDP_ENABLE_PROXYSTA,
|
||||
CDP_UPDATE_TDLS_FLAGS,
|
||||
CDP_CFG_WDS_AGING_TIMER,
|
||||
};
|
||||
|
||||
#define TXRX_FW_STATS_TXSTATS 1
|
||||
|
@@ -40,6 +40,7 @@
|
||||
#include "qdf_mem.h" /* qdf_mem_malloc,free */
|
||||
|
||||
#define DP_INTR_POLL_TIMER_MS 10
|
||||
#define DP_WDS_AGING_TIMER_DEFAULT_MS 6000
|
||||
#define DP_MCS_LENGTH (6*MAX_MCS)
|
||||
#define DP_NSS_LENGTH (6*SS_COUNT)
|
||||
#define DP_RXDMA_ERR_LENGTH (6*MAX_RXDMA_ERRORS)
|
||||
@@ -877,6 +878,97 @@ static void dp_hw_link_desc_pool_cleanup(struct dp_soc *soc)
|
||||
#define RXDMA_MONITOR_DESC_RING_SIZE 1024
|
||||
#define RXDMA_ERR_DST_RING_SIZE 1024
|
||||
|
||||
/*
|
||||
* dp_wds_aging_timer_fn() - Timer callback function for WDS aging
|
||||
* @soc: Datapath SOC handle
|
||||
*
|
||||
* This is a timer function used to age out stale WDS nodes from
|
||||
* AST table
|
||||
*/
|
||||
#ifdef FEATURE_WDS
|
||||
static void dp_wds_aging_timer_fn(void *soc_hdl)
|
||||
{
|
||||
struct dp_soc *soc = (struct dp_soc *) soc_hdl;
|
||||
struct dp_pdev *pdev;
|
||||
struct dp_vdev *vdev;
|
||||
struct dp_peer *peer;
|
||||
struct dp_ast_entry *ase;
|
||||
int i;
|
||||
|
||||
qdf_spin_lock_bh(&soc->ast_lock);
|
||||
|
||||
for (i = 0; i < MAX_PDEV_CNT && soc->pdev_list[i]; i++) {
|
||||
pdev = soc->pdev_list[i];
|
||||
DP_PDEV_ITERATE_VDEV_LIST(pdev, vdev) {
|
||||
DP_VDEV_ITERATE_PEER_LIST(vdev, peer) {
|
||||
DP_PEER_ITERATE_ASE_LIST(peer, ase) {
|
||||
/*
|
||||
* Do not expire static ast entries
|
||||
*/
|
||||
if (ase->is_static)
|
||||
continue;
|
||||
|
||||
if (ase->is_active) {
|
||||
ase->is_active = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
soc->cdp_soc.ol_ops->peer_del_wds_entry(
|
||||
pdev->osif_pdev,
|
||||
ase->mac_addr.raw);
|
||||
|
||||
dp_peer_del_ast(soc, ase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
|
||||
if (qdf_atomic_read(&soc->cmn_init_done))
|
||||
qdf_timer_mod(&soc->wds_aging_timer, DP_WDS_AGING_TIMER_DEFAULT_MS);
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_soc_wds_attach() - Setup WDS timer and AST table
|
||||
* @soc: Datapath SOC handle
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void dp_soc_wds_attach(struct dp_soc *soc)
|
||||
{
|
||||
qdf_spinlock_create(&soc->ast_lock);
|
||||
|
||||
qdf_timer_init(soc->osdev, &soc->wds_aging_timer,
|
||||
dp_wds_aging_timer_fn, (void *)soc,
|
||||
QDF_TIMER_TYPE_WAKE_APPS);
|
||||
|
||||
qdf_timer_mod(&soc->wds_aging_timer, DP_WDS_AGING_TIMER_DEFAULT_MS);
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_soc_wds_detach() - Detach WDS data structures and timers
|
||||
* @txrx_soc: DP SOC handle
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void dp_soc_wds_detach(struct dp_soc *soc)
|
||||
{
|
||||
qdf_timer_stop(&soc->wds_aging_timer);
|
||||
qdf_timer_free(&soc->wds_aging_timer);
|
||||
qdf_spinlock_destroy(&soc->ast_lock);
|
||||
}
|
||||
#else
|
||||
static void dp_soc_wds_attach(struct dp_soc *soc)
|
||||
{
|
||||
}
|
||||
|
||||
static void dp_soc_wds_detach(struct dp_soc *soc)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dp_soc_cmn_setup() - Common SoC level initializion
|
||||
* @soc: Datapath SOC handle
|
||||
@@ -1035,6 +1127,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
dp_soc_wds_attach(soc);
|
||||
|
||||
/* Setup HW REO */
|
||||
qdf_mem_zero(&reo_params, sizeof(reo_params));
|
||||
|
||||
@@ -1578,6 +1672,9 @@ static void dp_soc_detach_wifi3(void *txrx_soc)
|
||||
|
||||
dp_reo_desc_freelist_destroy(soc);
|
||||
wlan_cfg_soc_detach(soc->wlan_cfg_ctx);
|
||||
|
||||
dp_soc_wds_detach(soc);
|
||||
|
||||
qdf_mem_free(soc);
|
||||
}
|
||||
|
||||
@@ -1960,11 +2057,8 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle,
|
||||
qdf_mem_zero(peer, sizeof(struct dp_peer));
|
||||
|
||||
TAILQ_INIT(&peer->ast_entry_list);
|
||||
qdf_mem_copy(&peer->self_ast_entry.mac_addr, peer_mac_addr,
|
||||
DP_MAC_ADDR_LEN);
|
||||
peer->self_ast_entry.peer = peer;
|
||||
TAILQ_INSERT_TAIL(&peer->ast_entry_list, &peer->self_ast_entry,
|
||||
ast_entry_elem);
|
||||
|
||||
dp_peer_add_ast(soc, peer, peer_mac_addr, 1);
|
||||
|
||||
qdf_spinlock_create(&peer->peer_info_lock);
|
||||
|
||||
@@ -2008,6 +2102,7 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle,
|
||||
vdev->vap_bss_peer = peer;
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_WIN
|
||||
dp_local_peer_id_alloc(pdev, peer);
|
||||
#endif
|
||||
@@ -2257,8 +2352,6 @@ void dp_peer_unref_delete(void *peer_handle)
|
||||
struct dp_peer *tmppeer;
|
||||
int found = 0;
|
||||
uint16_t peer_id;
|
||||
uint16_t hw_peer_id;
|
||||
struct dp_ast_entry *ast_entry;
|
||||
|
||||
/*
|
||||
* Hold the lock all the way from checking if the peer ref count
|
||||
@@ -2342,17 +2435,6 @@ void dp_peer_unref_delete(void *peer_handle)
|
||||
#ifdef notyet
|
||||
qdf_mempool_free(soc->osdev, soc->mempool_ol_ath_peer, peer);
|
||||
#else
|
||||
TAILQ_FOREACH(ast_entry, &peer->ast_entry_list,
|
||||
ast_entry_elem) {
|
||||
hw_peer_id = ast_entry->ast_idx;
|
||||
if (peer->self_ast_entry.ast_idx != hw_peer_id)
|
||||
qdf_mem_free(ast_entry);
|
||||
else
|
||||
peer->self_ast_entry.ast_idx =
|
||||
HTT_INVALID_PEER;
|
||||
|
||||
soc->ast_table[hw_peer_id] = NULL;
|
||||
}
|
||||
qdf_mem_free(peer);
|
||||
#endif
|
||||
if (soc->cdp_soc.ol_ops->peer_unref_delete) {
|
||||
@@ -3584,6 +3666,14 @@ static void dp_set_vdev_param(struct cdp_vdev *vdev_handle,
|
||||
case CDP_UPDATE_TDLS_FLAGS:
|
||||
vdev->tdls_link_connected = val;
|
||||
break;
|
||||
case CDP_CFG_WDS_AGING_TIMER:
|
||||
if (val == 0)
|
||||
qdf_timer_stop(&vdev->pdev->soc->wds_aging_timer);
|
||||
else if (val != vdev->wds_aging_timer_val)
|
||||
qdf_timer_mod(&vdev->pdev->soc->wds_aging_timer, val);
|
||||
|
||||
vdev->wds_aging_timer_val = val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -3913,6 +4003,48 @@ static struct cdp_wds_ops dp_ops_wds = {
|
||||
.vdev_set_wds = dp_vdev_set_wds,
|
||||
};
|
||||
|
||||
/*
|
||||
* dp_peer_delete_ast_entries(): Delete all AST entries for a peer
|
||||
* @soc - datapath soc handle
|
||||
* @peer - datapath peer handle
|
||||
*
|
||||
* Delete the AST entries belonging to a peer
|
||||
*/
|
||||
#ifdef FEATURE_WDS
|
||||
static inline void dp_peer_delete_ast_entries(struct dp_soc *soc,
|
||||
struct dp_peer *peer)
|
||||
{
|
||||
struct dp_ast_entry *ast_entry;
|
||||
qdf_spin_lock_bh(&soc->ast_lock);
|
||||
DP_PEER_ITERATE_ASE_LIST(peer, ast_entry) {
|
||||
if (ast_entry->next_hop) {
|
||||
soc->cdp_soc.ol_ops->peer_del_wds_entry(
|
||||
soc->osif_soc,
|
||||
ast_entry->mac_addr.raw);
|
||||
}
|
||||
|
||||
dp_peer_del_ast(soc, ast_entry);
|
||||
}
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
}
|
||||
#else
|
||||
static inline void dp_peer_delete_ast_entries(struct dp_soc *soc,
|
||||
struct dp_peer *peer)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WIN
|
||||
static void dp_peer_teardown_wifi3(struct cdp_vdev *vdev_hdl, void *peer_hdl)
|
||||
{
|
||||
struct dp_vdev *vdev = (struct dp_vdev *) vdev_hdl;
|
||||
struct dp_peer *peer = (struct dp_peer *) peer_hdl;
|
||||
struct dp_soc *soc = (struct dp_soc *) vdev->pdev->soc;
|
||||
|
||||
dp_peer_delete_ast_entries(soc, peer);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct cdp_cmn_ops dp_ops_cmn = {
|
||||
.txrx_soc_attach_target = dp_soc_attach_target_wifi3,
|
||||
.txrx_vdev_attach = dp_vdev_attach_wifi3,
|
||||
@@ -3921,7 +4053,11 @@ static struct cdp_cmn_ops dp_ops_cmn = {
|
||||
.txrx_pdev_detach = dp_pdev_detach_wifi3,
|
||||
.txrx_peer_create = dp_peer_create_wifi3,
|
||||
.txrx_peer_setup = dp_peer_setup_wifi3,
|
||||
#ifdef CONFIG_WIN
|
||||
.txrx_peer_teardown = dp_peer_teardown_wifi3,
|
||||
#else
|
||||
.txrx_peer_teardown = NULL,
|
||||
#endif
|
||||
.txrx_peer_delete = dp_peer_delete_wifi3,
|
||||
.txrx_vdev_register = dp_vdev_register_wifi3,
|
||||
.txrx_soc_detach = dp_soc_detach_wifi3,
|
||||
|
@@ -124,6 +124,9 @@ static int dp_peer_find_add_id_to_obj(
|
||||
#define DP_PEER_HASH_LOAD_MULT 2
|
||||
#define DP_PEER_HASH_LOAD_SHIFT 0
|
||||
|
||||
#define DP_AST_HASH_LOAD_MULT 2
|
||||
#define DP_AST_HASH_LOAD_SHIFT 0
|
||||
|
||||
static int dp_peer_find_hash_attach(struct dp_soc *soc)
|
||||
{
|
||||
int i, hash_elems, log2;
|
||||
@@ -186,6 +189,300 @@ void dp_peer_find_hash_add(struct dp_soc *soc, struct dp_peer *peer)
|
||||
qdf_spin_unlock_bh(&soc->peer_ref_mutex);
|
||||
}
|
||||
|
||||
#ifdef FEATURE_WDS
|
||||
/*
|
||||
* dp_peer_ast_hash_attach() - Allocate and initialize AST Hash Table
|
||||
* @soc: SoC handle
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static int dp_peer_ast_hash_attach(struct dp_soc *soc)
|
||||
{
|
||||
int i, hash_elems, log2;
|
||||
|
||||
hash_elems = ((WLAN_UMAC_PSOC_MAX_PEERS * DP_AST_HASH_LOAD_MULT) >>
|
||||
DP_AST_HASH_LOAD_SHIFT);
|
||||
|
||||
log2 = dp_log2_ceil(hash_elems);
|
||||
hash_elems = 1 << log2;
|
||||
|
||||
soc->ast_hash.mask = hash_elems - 1;
|
||||
soc->ast_hash.idx_bits = log2;
|
||||
|
||||
/* allocate an array of TAILQ peer object lists */
|
||||
soc->ast_hash.bins = qdf_mem_malloc(
|
||||
hash_elems * sizeof(TAILQ_HEAD(anonymous_tail_q,
|
||||
dp_ast_entry)));
|
||||
|
||||
if (!soc->ast_hash.bins)
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
|
||||
for (i = 0; i < hash_elems; i++)
|
||||
TAILQ_INIT(&soc->ast_hash.bins[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_peer_ast_hash_detach() - Free AST Hash table
|
||||
* @soc: SoC handle
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void dp_peer_ast_hash_detach(struct dp_soc *soc)
|
||||
{
|
||||
qdf_mem_free(soc->ast_hash.bins);
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_peer_ast_hash_index() - Compute the AST hash from MAC address
|
||||
* @soc: SoC handle
|
||||
*
|
||||
* Return: AST hash
|
||||
*/
|
||||
static inline uint32_t dp_peer_ast_hash_index(struct dp_soc *soc,
|
||||
union dp_align_mac_addr *mac_addr)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
index =
|
||||
mac_addr->align2.bytes_ab ^
|
||||
mac_addr->align2.bytes_cd ^
|
||||
mac_addr->align2.bytes_ef;
|
||||
index ^= index >> soc->ast_hash.idx_bits;
|
||||
index &= soc->ast_hash.mask;
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_peer_ast_hash_add() - Add AST entry into hash table
|
||||
* @soc: SoC handle
|
||||
*
|
||||
* This function adds the AST entry into SoC AST hash table
|
||||
* It assumes caller has taken the ast lock to protect the access to this table
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline void dp_peer_ast_hash_add(struct dp_soc *soc,
|
||||
struct dp_ast_entry *ase)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
index = dp_peer_ast_hash_index(soc, &ase->mac_addr);
|
||||
TAILQ_INSERT_TAIL(&soc->ast_hash.bins[index], ase, hash_list_elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_peer_ast_hash_remove() - Look up and remove AST entry from hash table
|
||||
* @soc: SoC handle
|
||||
*
|
||||
* This function removes the AST entry from soc AST hash table
|
||||
* It assumes caller has taken the ast lock to protect the access to this table
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline void dp_peer_ast_hash_remove(struct dp_soc *soc,
|
||||
struct dp_ast_entry *ase)
|
||||
{
|
||||
unsigned index;
|
||||
struct dp_ast_entry *tmpase;
|
||||
int found = 0;
|
||||
|
||||
index = dp_peer_ast_hash_index(soc, &ase->mac_addr);
|
||||
/* Check if tail is not empty before delete*/
|
||||
QDF_ASSERT(!TAILQ_EMPTY(&soc->ast_hash.bins[index]));
|
||||
|
||||
TAILQ_FOREACH(tmpase, &soc->ast_hash.bins[index], hash_list_elem) {
|
||||
if (tmpase == ase) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QDF_ASSERT(found);
|
||||
TAILQ_REMOVE(&soc->ast_hash.bins[index], ase, hash_list_elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_peer_ast_hash_find() - Find AST entry by MAC address
|
||||
* @soc: SoC handle
|
||||
*
|
||||
* It assumes caller has taken the ast lock to protect the access to
|
||||
* AST hash table
|
||||
*
|
||||
* Return: AST entry
|
||||
*/
|
||||
struct dp_ast_entry *dp_peer_ast_hash_find(struct dp_soc *soc,
|
||||
uint8_t *ast_mac_addr, int mac_addr_is_aligned)
|
||||
{
|
||||
union dp_align_mac_addr local_mac_addr_aligned, *mac_addr;
|
||||
unsigned index;
|
||||
struct dp_ast_entry *ase;
|
||||
|
||||
if (mac_addr_is_aligned) {
|
||||
mac_addr = (union dp_align_mac_addr *) ast_mac_addr;
|
||||
} else {
|
||||
qdf_mem_copy(
|
||||
&local_mac_addr_aligned.raw[0],
|
||||
ast_mac_addr, DP_MAC_ADDR_LEN);
|
||||
mac_addr = &local_mac_addr_aligned;
|
||||
}
|
||||
|
||||
index = dp_peer_ast_hash_index(soc, mac_addr);
|
||||
TAILQ_FOREACH(ase, &soc->ast_hash.bins[index], hash_list_elem) {
|
||||
if (dp_peer_find_mac_addr_cmp(mac_addr, &ase->mac_addr) == 0) {
|
||||
return ase;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_peer_map_ast() - Map the ast entry with HW AST Index
|
||||
* @soc: SoC handle
|
||||
* @peer: peer to which ast node belongs
|
||||
* @mac_addr: MAC address of ast node
|
||||
* @hw_peer_id: HW AST Index returned by target in peer map event
|
||||
* @vdev_id: vdev id for VAP to which the peer belongs to
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline void dp_peer_map_ast(struct dp_soc *soc,
|
||||
struct dp_peer *peer, uint8_t *mac_addr, uint16_t hw_peer_id,
|
||||
uint8_t vdev_id)
|
||||
{
|
||||
struct dp_ast_entry *ast_entry;
|
||||
|
||||
if (!peer) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: peer %p ID %d vid %d mac %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
__func__, peer, hw_peer_id, vdev_id, mac_addr[0],
|
||||
mac_addr[1], mac_addr[2], mac_addr[3],
|
||||
mac_addr[4], mac_addr[5]);
|
||||
|
||||
qdf_spin_lock_bh(&soc->ast_lock);
|
||||
TAILQ_FOREACH(ast_entry, &peer->ast_entry_list, ase_list_elem) {
|
||||
if (!(qdf_mem_cmp(mac_addr, ast_entry->mac_addr.raw,
|
||||
DP_MAC_ADDR_LEN))) {
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
ast_entry->ast_idx = hw_peer_id;
|
||||
soc->ast_table[hw_peer_id] = ast_entry;
|
||||
ast_entry->is_active = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
|
||||
if (soc->cdp_soc.ol_ops->peer_map_event) {
|
||||
soc->cdp_soc.ol_ops->peer_map_event(soc->osif_soc,
|
||||
peer->peer_ids[0], hw_peer_id, vdev_id,
|
||||
mac_addr);
|
||||
}
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"AST entry not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_peer_add_ast() - Allocate and add AST entry into peer list
|
||||
* @soc: SoC handle
|
||||
* @peer: peer to which ast node belongs
|
||||
* @mac_addr: MAC address of ast node
|
||||
* @is_self: Is this base AST entry with peer mac address
|
||||
*
|
||||
* This API is used by WDS source port learning funtion to
|
||||
* add a new AST entry into peer AST list
|
||||
*
|
||||
* Return: 0 if new entry is allocated,
|
||||
* 1 if entry already exists or if allocation has failed
|
||||
*/
|
||||
int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
|
||||
uint8_t *mac_addr, bool is_self)
|
||||
{
|
||||
struct dp_ast_entry *ast_entry;
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: peer %p mac %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
__func__, peer, mac_addr[0], mac_addr[1], mac_addr[2],
|
||||
mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||
|
||||
qdf_spin_lock_bh(&soc->ast_lock);
|
||||
|
||||
/* If AST entry already exists , just return from here */
|
||||
if (dp_peer_ast_hash_find(soc, mac_addr, 0)) {
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ast_entry = (struct dp_ast_entry *)
|
||||
qdf_mem_malloc(sizeof(struct dp_ast_entry));
|
||||
|
||||
if (!ast_entry) {
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("fail to allocate ast_entry"));
|
||||
QDF_ASSERT(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
qdf_mem_copy(&ast_entry->mac_addr.raw[0], mac_addr, DP_MAC_ADDR_LEN);
|
||||
ast_entry->peer = peer;
|
||||
|
||||
if (is_self) {
|
||||
peer->self_ast_entry = ast_entry;
|
||||
ast_entry->is_static = TRUE;
|
||||
} else {
|
||||
ast_entry->next_hop = 1;
|
||||
ast_entry->is_static = FALSE;
|
||||
}
|
||||
|
||||
ast_entry->is_active = TRUE;
|
||||
TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry, ase_list_elem);
|
||||
dp_peer_ast_hash_add(soc, ast_entry);
|
||||
qdf_spin_unlock_bh(&soc->ast_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_peer_del_ast() - Delete and free AST entry
|
||||
* @soc: SoC handle
|
||||
* @ast_entry: AST entry of the node
|
||||
*
|
||||
* This function removes the AST entry from peer and soc tables
|
||||
* It assumes caller has taken the ast lock to protect the access to these
|
||||
* tables
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void dp_peer_del_ast(struct dp_soc *soc,
|
||||
struct dp_ast_entry *ast_entry)
|
||||
{
|
||||
struct dp_peer *peer = ast_entry->peer;
|
||||
soc->ast_table[ast_entry->ast_idx] = NULL;
|
||||
TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem);
|
||||
dp_peer_ast_hash_remove(soc, ast_entry);
|
||||
qdf_mem_free(ast_entry);
|
||||
}
|
||||
#else
|
||||
static int dp_peer_ast_hash_attach(struct dp_soc *soc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static void dp_peer_ast_hash_detach(struct dp_soc *soc)
|
||||
{
|
||||
}
|
||||
static inline void dp_peer_map_ast(struct dp_soc *soc, struct dp_peer *peer,
|
||||
uint8_t *mac_addr, uint16_t hw_peer_id, uint8_t vdev_id)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if ATH_SUPPORT_WRAP
|
||||
static struct dp_peer *dp_peer_find_hash_find(struct dp_soc *soc,
|
||||
uint8_t *peer_mac_addr, int mac_addr_is_aligned, uint8_t vdev_id)
|
||||
@@ -315,6 +612,12 @@ int dp_peer_find_attach(struct dp_soc *soc)
|
||||
dp_peer_find_map_detach(soc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dp_peer_ast_hash_attach(soc)) {
|
||||
dp_peer_find_hash_detach(soc);
|
||||
dp_peer_find_map_detach(soc);
|
||||
return 1;
|
||||
}
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
@@ -383,7 +686,7 @@ static void dp_rx_tid_stats_cb(struct dp_soc *soc, void *cb_ctxt,
|
||||
queue_status->hole_cnt);
|
||||
}
|
||||
|
||||
static inline void dp_peer_find_add_id(struct dp_soc *soc,
|
||||
static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc,
|
||||
uint8_t *peer_mac_addr, uint16_t peer_id, uint16_t hw_peer_id,
|
||||
uint8_t vdev_id)
|
||||
{
|
||||
@@ -411,55 +714,16 @@ static inline void dp_peer_find_add_id(struct dp_soc *soc,
|
||||
"%s: ref_cnt: %d", __func__,
|
||||
qdf_atomic_read(&peer->ref_cnt));
|
||||
soc->peer_id_to_obj_map[peer_id] = peer;
|
||||
peer->self_ast_entry.ast_idx = hw_peer_id;
|
||||
soc->ast_table[hw_peer_id] = &peer->self_ast_entry;
|
||||
|
||||
if (dp_peer_find_add_id_to_obj(peer, peer_id)) {
|
||||
/* TBDXXX: assert for now */
|
||||
QDF_ASSERT(0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dp_peer_add_ast(struct dp_soc *soc,
|
||||
struct dp_peer *peer, uint8_t *peer_mac_addr, uint16_t hw_peer_id,
|
||||
uint8_t vdev_id)
|
||||
{
|
||||
struct dp_ast_entry *ast_entry;
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: peer %p ID %d vid %d mac %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
__func__, peer, hw_peer_id, vdev_id, peer_mac_addr[0],
|
||||
peer_mac_addr[1], peer_mac_addr[2], peer_mac_addr[3],
|
||||
peer_mac_addr[4], peer_mac_addr[5]);
|
||||
|
||||
TAILQ_FOREACH(ast_entry, &peer->ast_entry_list, ast_entry_elem) {
|
||||
if (!(qdf_mem_cmp(peer_mac_addr, ast_entry->mac_addr,
|
||||
DP_MAC_ADDR_LEN))) {
|
||||
soc->ast_table[ast_entry->ast_idx] = NULL;
|
||||
ast_entry->ast_idx = hw_peer_id;
|
||||
soc->ast_table[hw_peer_id] = ast_entry;
|
||||
return;
|
||||
}
|
||||
return peer;
|
||||
}
|
||||
|
||||
ast_entry = (struct dp_ast_entry *)
|
||||
qdf_mem_malloc(sizeof(struct dp_ast_entry));
|
||||
|
||||
if (!ast_entry) {
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("fail to allocate ast_entry for: %d"), hw_peer_id);
|
||||
QDF_ASSERT(0);
|
||||
}
|
||||
|
||||
qdf_mem_copy(&ast_entry->mac_addr, peer_mac_addr, DP_MAC_ADDR_LEN);
|
||||
ast_entry->peer = peer;
|
||||
ast_entry->next_hop = 1;
|
||||
TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry, ast_entry_elem);
|
||||
soc->ast_table[hw_peer_id] = ast_entry;
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -483,7 +747,6 @@ dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, uint16_t hw_peer_id,
|
||||
struct dp_soc *soc = (struct dp_soc *)soc_handle;
|
||||
struct dp_peer *peer = NULL;
|
||||
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
|
||||
"peer_map_event (soc:%p): peer_id %di, hw_peer_id %d, peer_mac "
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x, vdev_id %d\n", soc, peer_id,
|
||||
@@ -506,18 +769,12 @@ dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, uint16_t hw_peer_id,
|
||||
* in this case just add the ast entry to the existing
|
||||
* peer ast_list.
|
||||
*/
|
||||
if (!peer) {
|
||||
dp_peer_find_add_id(soc, peer_mac_addr, peer_id,
|
||||
hw_peer_id, vdev_id);
|
||||
if (soc->cdp_soc.ol_ops->peer_map_event) {
|
||||
soc->cdp_soc.ol_ops->peer_map_event(soc->osif_soc,
|
||||
peer_id, hw_peer_id, vdev_id, peer_mac_addr);
|
||||
}
|
||||
if (!peer)
|
||||
peer = dp_peer_find_add_id(soc, peer_mac_addr, peer_id,
|
||||
hw_peer_id, vdev_id);
|
||||
|
||||
} else {
|
||||
dp_peer_add_ast(soc, peer, peer_mac_addr,
|
||||
hw_peer_id, vdev_id);
|
||||
}
|
||||
dp_peer_map_ast(soc, peer, peer_mac_addr,
|
||||
hw_peer_id, vdev_id);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -565,6 +822,7 @@ dp_peer_find_detach(struct dp_soc *soc)
|
||||
{
|
||||
dp_peer_find_map_detach(soc);
|
||||
dp_peer_find_hash_detach(soc);
|
||||
dp_peer_ast_hash_detach(soc);
|
||||
}
|
||||
|
||||
static void dp_rx_tid_update_cb(struct dp_soc *soc, void *cb_ctxt,
|
||||
|
@@ -54,6 +54,23 @@ void dp_rx_sec_ind_handler(void *soc_handle, uint16_t peer_id,
|
||||
uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle,
|
||||
uint16_t peer_id, uint8_t *peer_mac);
|
||||
|
||||
#ifdef FEATURE_WDS
|
||||
int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
|
||||
uint8_t *mac_addr, bool is_self);
|
||||
void dp_peer_del_ast(struct dp_soc *soc,
|
||||
struct dp_ast_entry *ast_entry);
|
||||
#else
|
||||
static inline int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer,
|
||||
uint8_t *mac_addr, bool is_self)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void dp_peer_del_ast(struct dp_soc *soc,
|
||||
struct dp_ast_entry *ast_entry)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DP_LFR
|
||||
/*
|
||||
* dp_get_vdev_from_soc_vdev_id_wifi3() -
|
||||
|
@@ -344,7 +344,7 @@ void dp_rx_add_to_free_desc_list(union dp_rx_desc_list_elem_t **head,
|
||||
*
|
||||
* Return: void:
|
||||
*/
|
||||
#ifndef CONFIG_MCL
|
||||
#ifdef FEATURE_WDS
|
||||
static inline void
|
||||
dp_rx_wds_srcport_learn(struct dp_soc *soc,
|
||||
uint8_t *rx_tlv_hdr,
|
||||
@@ -359,40 +359,61 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc,
|
||||
memcpy(wds_src_mac, (qdf_nbuf_data(nbuf) + IEEE80211_ADDR_LEN),
|
||||
IEEE80211_ADDR_LEN);
|
||||
|
||||
if (!hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr)) {
|
||||
ret = soc->cdp_soc.ol_ops->peer_add_wds_entry(
|
||||
ta_peer->vdev->pdev->osif_pdev,
|
||||
wds_src_mac,
|
||||
ta_peer->mac_addr.raw,
|
||||
flags);
|
||||
} else if (sa_sw_peer_id != ta_peer->peer_ids[0]) {
|
||||
ret = soc->cdp_soc.ol_ops->peer_update_wds_entry(
|
||||
ta_peer->vdev->pdev->osif_pdev,
|
||||
wds_src_mac,
|
||||
ta_peer->mac_addr.raw,
|
||||
flags);
|
||||
if (qdf_unlikely(!hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr))) {
|
||||
if (!dp_peer_add_ast(soc, ta_peer, wds_src_mac, 0)) {
|
||||
ret = soc->cdp_soc.ol_ops->peer_add_wds_entry(
|
||||
ta_peer->vdev->pdev->osif_pdev,
|
||||
wds_src_mac,
|
||||
ta_peer->mac_addr.raw,
|
||||
flags);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Get the AST entry from HW SA index and mark it as active
|
||||
*/
|
||||
struct dp_ast_entry *ast;
|
||||
uint16_t sa_idx = hal_rx_msdu_end_sa_idx_get(rx_tlv_hdr);
|
||||
ast = soc->ast_table[sa_idx];
|
||||
|
||||
/*
|
||||
* Ensure we are updating the right AST entry by
|
||||
* validating ast_idx.
|
||||
* There is a possibility we might arrive here without
|
||||
* AST MAP event , so this check is mandatory
|
||||
*/
|
||||
if (ast && (ast->ast_idx == sa_idx)) {
|
||||
ast->is_active = TRUE;
|
||||
}
|
||||
|
||||
if (sa_sw_peer_id != ta_peer->peer_ids[0]) {
|
||||
ret = soc->cdp_soc.ol_ops->peer_update_wds_entry(
|
||||
ta_peer->vdev->pdev->osif_pdev,
|
||||
wds_src_mac,
|
||||
ta_peer->mac_addr.raw,
|
||||
flags);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
static inline void
|
||||
dp_rx_wds_srcport_learn(struct dp_soc *soc,
|
||||
uint8_t *rx_tlv_hdr,
|
||||
struct dp_peer *ta_peer,
|
||||
qdf_nbuf_t nbuf)
|
||||
uint8_t *rx_tlv_hdr,
|
||||
struct dp_peer *ta_peer,
|
||||
qdf_nbuf_t nbuf)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf);
|
||||
#define DP_RX_LIST_APPEND(head, tail, elem) \
|
||||
do { \
|
||||
if (!(head)) { \
|
||||
(head) = (elem); \
|
||||
} else { \
|
||||
qdf_nbuf_set_next((tail), (elem)); \
|
||||
} \
|
||||
(tail) = (elem); \
|
||||
do { \
|
||||
if (!(head)) { \
|
||||
(head) = (elem); \
|
||||
} else { \
|
||||
qdf_nbuf_set_next((tail), (elem)); \
|
||||
} \
|
||||
(tail) = (elem); \
|
||||
qdf_nbuf_set_next((tail), NULL); \
|
||||
} while (0)
|
||||
|
||||
|
@@ -104,6 +104,15 @@ union dp_tx_desc_list_elem_t;
|
||||
struct dp_soc;
|
||||
union dp_rx_desc_list_elem_t;
|
||||
|
||||
#define DP_PDEV_ITERATE_VDEV_LIST(_pdev, _vdev) \
|
||||
TAILQ_FOREACH((_vdev), &(_pdev)->vdev_list, vdev_list_elem)
|
||||
|
||||
#define DP_VDEV_ITERATE_PEER_LIST(_vdev, _peer) \
|
||||
TAILQ_FOREACH((_peer), &(_vdev)->peer_list, peer_list_elem)
|
||||
|
||||
#define DP_PEER_ITERATE_ASE_LIST(_peer, _ase) \
|
||||
TAILQ_FOREACH((_ase), &peer->ast_entry_list, ase_list_elem)
|
||||
|
||||
#define DP_MUTEX_TYPE qdf_spinlock_t
|
||||
|
||||
#define DP_FRAME_IS_MULTICAST(_a) (*(_a) & 0x01)
|
||||
@@ -380,12 +389,48 @@ struct reo_desc_list_node {
|
||||
struct dp_rx_tid rx_tid;
|
||||
};
|
||||
|
||||
#define DP_MAC_ADDR_LEN 6
|
||||
union dp_align_mac_addr {
|
||||
uint8_t raw[DP_MAC_ADDR_LEN];
|
||||
struct {
|
||||
uint16_t bytes_ab;
|
||||
uint16_t bytes_cd;
|
||||
uint16_t bytes_ef;
|
||||
} align2;
|
||||
struct {
|
||||
uint32_t bytes_abcd;
|
||||
uint16_t bytes_ef;
|
||||
} align4;
|
||||
struct {
|
||||
uint16_t bytes_ab;
|
||||
uint32_t bytes_cdef;
|
||||
} align4_2;
|
||||
};
|
||||
|
||||
/*
|
||||
* dp_ast_entry
|
||||
*
|
||||
* @ast_idx: Hardware AST Index
|
||||
* @mac_addr: MAC Address for this AST entry
|
||||
* @peer: Next Hop peer (for non-WDS nodes, this will be point to
|
||||
* associated peer with this MAC address)
|
||||
* @next_hop: Set to 1 if this is for a WDS node
|
||||
* @is_active: flag to indicate active data traffic on this node
|
||||
* (used for aging out/expiry)
|
||||
* @is_static: flag to indicate static entry (should not be expired)
|
||||
* @ase_list_elem: node in peer AST list
|
||||
* @hash_list_elem: node in soc AST hash list (mac address used as hash)
|
||||
*/
|
||||
struct dp_ast_entry {
|
||||
uint16_t ast_idx;
|
||||
uint8_t mac_addr[DP_MAC_ADDR_LEN];
|
||||
uint8_t next_hop;
|
||||
/* MAC address */
|
||||
union dp_align_mac_addr mac_addr;
|
||||
struct dp_peer *peer;
|
||||
TAILQ_ENTRY(dp_ast_entry) ast_entry_elem;
|
||||
bool next_hop;
|
||||
bool is_active;
|
||||
bool is_static;
|
||||
TAILQ_ENTRY(dp_ast_entry) ase_list_elem;
|
||||
TAILQ_ENTRY(dp_ast_entry) hash_list_elem;
|
||||
};
|
||||
|
||||
struct mect_entry {
|
||||
@@ -617,6 +662,14 @@ struct dp_soc {
|
||||
bool process_tx_status;
|
||||
|
||||
struct dp_ast_entry *ast_table[WLAN_UMAC_PSOC_MAX_PEERS];
|
||||
struct {
|
||||
unsigned mask;
|
||||
unsigned idx_bits;
|
||||
TAILQ_HEAD(, dp_ast_entry) * bins;
|
||||
} ast_hash;
|
||||
|
||||
qdf_spinlock_t ast_lock;
|
||||
qdf_timer_t wds_aging_timer;
|
||||
|
||||
#ifdef DP_INTR_POLL_BASED
|
||||
/*interrupt timer*/
|
||||
@@ -668,19 +721,6 @@ enum dp_nac_param_cmd {
|
||||
/* IEEE80211_NAC_PARAM_LIST */
|
||||
DP_NAC_PARAM_LIST,
|
||||
};
|
||||
#define DP_MAC_ADDR_LEN 6
|
||||
union dp_align_mac_addr {
|
||||
uint8_t raw[DP_MAC_ADDR_LEN];
|
||||
struct {
|
||||
uint16_t bytes_ab;
|
||||
uint16_t bytes_cd;
|
||||
uint16_t bytes_ef;
|
||||
} align2;
|
||||
struct {
|
||||
uint32_t bytes_abcd;
|
||||
uint16_t bytes_ef;
|
||||
} align4;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dp_neighbour_peer - neighbour peer list type for smart mesh
|
||||
@@ -920,6 +960,9 @@ struct dp_vdev {
|
||||
/* WDS enabled */
|
||||
bool wds_enabled;
|
||||
|
||||
/* WDS Aging timer period */
|
||||
uint32_t wds_aging_timer_val;
|
||||
|
||||
/* NAWDS enabled */
|
||||
bool nawds_enabled;
|
||||
|
||||
@@ -968,7 +1011,7 @@ struct dp_peer {
|
||||
/* VDEV to which this peer is associated */
|
||||
struct dp_vdev *vdev;
|
||||
|
||||
struct dp_ast_entry self_ast_entry;
|
||||
struct dp_ast_entry *self_ast_entry;
|
||||
|
||||
qdf_atomic_t ref_cnt;
|
||||
|
||||
|
@@ -813,6 +813,31 @@ hal_rx_msdu_end_l3_hdr_padding_get(uint8_t *buf)
|
||||
return l3_header_padding;
|
||||
}
|
||||
|
||||
#define HAL_RX_MSDU_END_SA_IDX_GET(_rx_msdu_end) \
|
||||
(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \
|
||||
RX_MSDU_END_13_SA_IDX_OFFSET)), \
|
||||
RX_MSDU_END_13_SA_IDX_MASK, \
|
||||
RX_MSDU_END_13_SA_IDX_LSB))
|
||||
|
||||
/**
|
||||
* hal_rx_msdu_end_sa_idx_get(): API to get the
|
||||
* sa_idx from rx_msdu_end TLV
|
||||
*
|
||||
* @ buf: pointer to the start of RX PKT TLV headers
|
||||
* Return: sa_idx (SA AST index)
|
||||
*/
|
||||
static inline uint16_t
|
||||
hal_rx_msdu_end_sa_idx_get(uint8_t *buf)
|
||||
{
|
||||
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;
|
||||
uint8_t sa_idx;
|
||||
|
||||
sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end);
|
||||
|
||||
return sa_idx;
|
||||
}
|
||||
|
||||
#define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end) \
|
||||
(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \
|
||||
RX_MSDU_END_5_SA_IS_VALID_OFFSET)), \
|
||||
|
Reference in New Issue
Block a user