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:
Pamidipati, Vijay
2017-06-26 23:47:39 +05:30
committed by snandini
orang tua a7b6842a72
melakukan b8bbf16192
7 mengubah file dengan 614 tambahan dan 113 penghapusan

Melihat File

@@ -485,6 +485,7 @@ enum cdp_vdev_param_type {
CDP_ENABLE_WDS, CDP_ENABLE_WDS,
CDP_ENABLE_PROXYSTA, CDP_ENABLE_PROXYSTA,
CDP_UPDATE_TDLS_FLAGS, CDP_UPDATE_TDLS_FLAGS,
CDP_CFG_WDS_AGING_TIMER,
}; };
#define TXRX_FW_STATS_TXSTATS 1 #define TXRX_FW_STATS_TXSTATS 1

Melihat File

@@ -40,6 +40,7 @@
#include "qdf_mem.h" /* qdf_mem_malloc,free */ #include "qdf_mem.h" /* qdf_mem_malloc,free */
#define DP_INTR_POLL_TIMER_MS 10 #define DP_INTR_POLL_TIMER_MS 10
#define DP_WDS_AGING_TIMER_DEFAULT_MS 6000
#define DP_MCS_LENGTH (6*MAX_MCS) #define DP_MCS_LENGTH (6*MAX_MCS)
#define DP_NSS_LENGTH (6*SS_COUNT) #define DP_NSS_LENGTH (6*SS_COUNT)
#define DP_RXDMA_ERR_LENGTH (6*MAX_RXDMA_ERRORS) #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_MONITOR_DESC_RING_SIZE 1024
#define RXDMA_ERR_DST_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 * dp_soc_cmn_setup() - Common SoC level initializion
* @soc: Datapath SOC handle * @soc: Datapath SOC handle
@@ -1035,6 +1127,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
goto fail1; goto fail1;
} }
dp_soc_wds_attach(soc);
/* Setup HW REO */ /* Setup HW REO */
qdf_mem_zero(&reo_params, sizeof(reo_params)); 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); dp_reo_desc_freelist_destroy(soc);
wlan_cfg_soc_detach(soc->wlan_cfg_ctx); wlan_cfg_soc_detach(soc->wlan_cfg_ctx);
dp_soc_wds_detach(soc);
qdf_mem_free(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)); qdf_mem_zero(peer, sizeof(struct dp_peer));
TAILQ_INIT(&peer->ast_entry_list); TAILQ_INIT(&peer->ast_entry_list);
qdf_mem_copy(&peer->self_ast_entry.mac_addr, peer_mac_addr,
DP_MAC_ADDR_LEN); dp_peer_add_ast(soc, peer, peer_mac_addr, 1);
peer->self_ast_entry.peer = peer;
TAILQ_INSERT_TAIL(&peer->ast_entry_list, &peer->self_ast_entry,
ast_entry_elem);
qdf_spinlock_create(&peer->peer_info_lock); 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; vdev->vap_bss_peer = peer;
} }
#ifndef CONFIG_WIN #ifndef CONFIG_WIN
dp_local_peer_id_alloc(pdev, peer); dp_local_peer_id_alloc(pdev, peer);
#endif #endif
@@ -2257,8 +2352,6 @@ void dp_peer_unref_delete(void *peer_handle)
struct dp_peer *tmppeer; struct dp_peer *tmppeer;
int found = 0; int found = 0;
uint16_t peer_id; 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 * 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 #ifdef notyet
qdf_mempool_free(soc->osdev, soc->mempool_ol_ath_peer, peer); qdf_mempool_free(soc->osdev, soc->mempool_ol_ath_peer, peer);
#else #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); qdf_mem_free(peer);
#endif #endif
if (soc->cdp_soc.ol_ops->peer_unref_delete) { 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: case CDP_UPDATE_TDLS_FLAGS:
vdev->tdls_link_connected = val; vdev->tdls_link_connected = val;
break; 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: default:
break; break;
} }
@@ -3913,6 +4003,48 @@ static struct cdp_wds_ops dp_ops_wds = {
.vdev_set_wds = dp_vdev_set_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 = { static struct cdp_cmn_ops dp_ops_cmn = {
.txrx_soc_attach_target = dp_soc_attach_target_wifi3, .txrx_soc_attach_target = dp_soc_attach_target_wifi3,
.txrx_vdev_attach = dp_vdev_attach_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_pdev_detach = dp_pdev_detach_wifi3,
.txrx_peer_create = dp_peer_create_wifi3, .txrx_peer_create = dp_peer_create_wifi3,
.txrx_peer_setup = dp_peer_setup_wifi3, .txrx_peer_setup = dp_peer_setup_wifi3,
#ifdef CONFIG_WIN
.txrx_peer_teardown = dp_peer_teardown_wifi3,
#else
.txrx_peer_teardown = NULL, .txrx_peer_teardown = NULL,
#endif
.txrx_peer_delete = dp_peer_delete_wifi3, .txrx_peer_delete = dp_peer_delete_wifi3,
.txrx_vdev_register = dp_vdev_register_wifi3, .txrx_vdev_register = dp_vdev_register_wifi3,
.txrx_soc_detach = dp_soc_detach_wifi3, .txrx_soc_detach = dp_soc_detach_wifi3,

Melihat File

@@ -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_MULT 2
#define DP_PEER_HASH_LOAD_SHIFT 0 #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) static int dp_peer_find_hash_attach(struct dp_soc *soc)
{ {
int i, hash_elems, log2; 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); 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 #if ATH_SUPPORT_WRAP
static struct dp_peer *dp_peer_find_hash_find(struct dp_soc *soc, 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) 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); dp_peer_find_map_detach(soc);
return 1; 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 */ 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); 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 *peer_mac_addr, uint16_t peer_id, uint16_t hw_peer_id,
uint8_t vdev_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__, "%s: ref_cnt: %d", __func__,
qdf_atomic_read(&peer->ref_cnt)); qdf_atomic_read(&peer->ref_cnt));
soc->peer_id_to_obj_map[peer_id] = peer; 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)) { if (dp_peer_find_add_id_to_obj(peer, peer_id)) {
/* TBDXXX: assert for now */ /* TBDXXX: assert for now */
QDF_ASSERT(0); QDF_ASSERT(0);
} }
return; return peer;
}
}
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;
}
} }
ast_entry = (struct dp_ast_entry *) return NULL;
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;
} }
/** /**
@@ -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_soc *soc = (struct dp_soc *)soc_handle;
struct dp_peer *peer = NULL; struct dp_peer *peer = NULL;
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, 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 " "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, "%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 * in this case just add the ast entry to the existing
* peer ast_list. * peer ast_list.
*/ */
if (!peer) { if (!peer)
dp_peer_find_add_id(soc, peer_mac_addr, peer_id, peer = dp_peer_find_add_id(soc, peer_mac_addr, peer_id,
hw_peer_id, vdev_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);
}
} else { dp_peer_map_ast(soc, peer, peer_mac_addr,
dp_peer_add_ast(soc, peer, peer_mac_addr, hw_peer_id, vdev_id);
hw_peer_id, vdev_id);
}
} }
void void
@@ -565,6 +822,7 @@ dp_peer_find_detach(struct dp_soc *soc)
{ {
dp_peer_find_map_detach(soc); dp_peer_find_map_detach(soc);
dp_peer_find_hash_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, static void dp_rx_tid_update_cb(struct dp_soc *soc, void *cb_ctxt,

Melihat File

@@ -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, uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle,
uint16_t peer_id, uint8_t *peer_mac); 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 #ifdef DP_LFR
/* /*
* dp_get_vdev_from_soc_vdev_id_wifi3() - * dp_get_vdev_from_soc_vdev_id_wifi3() -

Melihat File

@@ -344,7 +344,7 @@ void dp_rx_add_to_free_desc_list(union dp_rx_desc_list_elem_t **head,
* *
* Return: void: * Return: void:
*/ */
#ifndef CONFIG_MCL #ifdef FEATURE_WDS
static inline void static inline void
dp_rx_wds_srcport_learn(struct dp_soc *soc, dp_rx_wds_srcport_learn(struct dp_soc *soc,
uint8_t *rx_tlv_hdr, 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), memcpy(wds_src_mac, (qdf_nbuf_data(nbuf) + IEEE80211_ADDR_LEN),
IEEE80211_ADDR_LEN); IEEE80211_ADDR_LEN);
if (!hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr)) { if (qdf_unlikely(!hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr))) {
ret = soc->cdp_soc.ol_ops->peer_add_wds_entry( if (!dp_peer_add_ast(soc, ta_peer, wds_src_mac, 0)) {
ta_peer->vdev->pdev->osif_pdev, ret = soc->cdp_soc.ol_ops->peer_add_wds_entry(
wds_src_mac, ta_peer->vdev->pdev->osif_pdev,
ta_peer->mac_addr.raw, wds_src_mac,
flags); ta_peer->mac_addr.raw,
} else if (sa_sw_peer_id != ta_peer->peer_ids[0]) { flags);
ret = soc->cdp_soc.ol_ops->peer_update_wds_entry( }
ta_peer->vdev->pdev->osif_pdev, } else {
wds_src_mac, /*
ta_peer->mac_addr.raw, * Get the AST entry from HW SA index and mark it as active
flags); */
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; return;
} }
#else #else
static inline void static inline void
dp_rx_wds_srcport_learn(struct dp_soc *soc, dp_rx_wds_srcport_learn(struct dp_soc *soc,
uint8_t *rx_tlv_hdr, uint8_t *rx_tlv_hdr,
struct dp_peer *ta_peer, struct dp_peer *ta_peer,
qdf_nbuf_t nbuf) qdf_nbuf_t nbuf)
{ {
} }
#endif #endif
uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf); uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf);
#define DP_RX_LIST_APPEND(head, tail, elem) \ #define DP_RX_LIST_APPEND(head, tail, elem) \
do { \ do { \
if (!(head)) { \ if (!(head)) { \
(head) = (elem); \ (head) = (elem); \
} else { \ } else { \
qdf_nbuf_set_next((tail), (elem)); \ qdf_nbuf_set_next((tail), (elem)); \
} \ } \
(tail) = (elem); \ (tail) = (elem); \
qdf_nbuf_set_next((tail), NULL); \ qdf_nbuf_set_next((tail), NULL); \
} while (0) } while (0)

Melihat File

@@ -104,6 +104,15 @@ union dp_tx_desc_list_elem_t;
struct dp_soc; struct dp_soc;
union dp_rx_desc_list_elem_t; 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_MUTEX_TYPE qdf_spinlock_t
#define DP_FRAME_IS_MULTICAST(_a) (*(_a) & 0x01) #define DP_FRAME_IS_MULTICAST(_a) (*(_a) & 0x01)
@@ -380,12 +389,48 @@ struct reo_desc_list_node {
struct dp_rx_tid rx_tid; 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 { struct dp_ast_entry {
uint16_t ast_idx; uint16_t ast_idx;
uint8_t mac_addr[DP_MAC_ADDR_LEN]; /* MAC address */
uint8_t next_hop; union dp_align_mac_addr mac_addr;
struct dp_peer *peer; 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 { struct mect_entry {
@@ -617,6 +662,14 @@ struct dp_soc {
bool process_tx_status; bool process_tx_status;
struct dp_ast_entry *ast_table[WLAN_UMAC_PSOC_MAX_PEERS]; 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 #ifdef DP_INTR_POLL_BASED
/*interrupt timer*/ /*interrupt timer*/
@@ -668,19 +721,6 @@ enum dp_nac_param_cmd {
/* IEEE80211_NAC_PARAM_LIST */ /* IEEE80211_NAC_PARAM_LIST */
DP_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 * struct dp_neighbour_peer - neighbour peer list type for smart mesh
@@ -920,6 +960,9 @@ struct dp_vdev {
/* WDS enabled */ /* WDS enabled */
bool wds_enabled; bool wds_enabled;
/* WDS Aging timer period */
uint32_t wds_aging_timer_val;
/* NAWDS enabled */ /* NAWDS enabled */
bool nawds_enabled; bool nawds_enabled;
@@ -968,7 +1011,7 @@ struct dp_peer {
/* VDEV to which this peer is associated */ /* VDEV to which this peer is associated */
struct dp_vdev *vdev; struct dp_vdev *vdev;
struct dp_ast_entry self_ast_entry; struct dp_ast_entry *self_ast_entry;
qdf_atomic_t ref_cnt; qdf_atomic_t ref_cnt;

Melihat File

@@ -813,6 +813,31 @@ hal_rx_msdu_end_l3_hdr_padding_get(uint8_t *buf)
return l3_header_padding; 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) \ #define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end) \
(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \
RX_MSDU_END_5_SA_IS_VALID_OFFSET)), \ RX_MSDU_END_5_SA_IS_VALID_OFFSET)), \