diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index 33594885d165..4848771ae04b 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -257,6 +257,138 @@ static inline void cdp_peer_setup peer); } +static inline int cdp_peer_add_ast + (ol_txrx_soc_handle soc, struct cdp_peer *peer_handle, + uint8_t *mac_addr, enum cdp_txrx_ast_entry_type type, uint32_t flags) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return 0; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_add_ast) + return 0; + + return soc->ops->cmn_drv_ops->txrx_peer_add_ast(soc, + peer_handle, + mac_addr, + type, + flags); +} + +static inline int cdp_peer_update_ast + (ol_txrx_soc_handle soc, void *ast_handle, + struct cdp_peer *peer_handle, uint32_t flags) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return 0; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_update_ast) + return 0; + + return soc->ops->cmn_drv_ops->txrx_peer_update_ast(soc, + peer_handle, + ast_handle, + flags); +} + +static inline void cdp_peer_del_ast + (ol_txrx_soc_handle soc, void *ast_handle) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_del_ast) + return; + + soc->ops->cmn_drv_ops->txrx_peer_del_ast(soc, ast_handle); +} + +static inline void *cdp_peer_ast_hash_find + (ol_txrx_soc_handle soc, uint8_t *ast_mac_addr) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return NULL; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_ast_hash_find) + return NULL; + + return soc->ops->cmn_drv_ops->txrx_peer_ast_hash_find(soc, + ast_mac_addr); +} + +static inline uint8_t cdp_peer_ast_get_pdev_id + (ol_txrx_soc_handle soc, void *ast_handle) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return 0xff; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_ast_get_pdev_id) + return 0xff; + + return soc->ops->cmn_drv_ops->txrx_peer_ast_get_pdev_id(soc, + ast_handle); +} + +static inline uint8_t cdp_peer_ast_get_next_hop + (ol_txrx_soc_handle soc, void *ast_handle) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return 0xff; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_ast_get_next_hop) + return 0xff; + + return soc->ops->cmn_drv_ops->txrx_peer_ast_get_next_hop(soc, + ast_handle); +} + +static inline void cdp_peer_ast_set_type + (ol_txrx_soc_handle soc, void *ast_handle, + enum cdp_txrx_ast_entry_type type) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_peer_ast_set_type) + return; + + soc->ops->cmn_drv_ops->txrx_peer_ast_set_type(soc, ast_handle, type); +} + static inline void cdp_peer_teardown (ol_txrx_soc_handle soc, struct cdp_vdev *vdev, void *peer) { diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 0b4d404c8c84..e30ddb4e0742 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -274,9 +274,10 @@ enum ol_txrx_peer_state { */ enum cdp_txrx_ast_entry_type { CDP_TXRX_AST_TYPE_NONE, /* static ast entry for connected peer */ - CDP_TXRX_AST_TYPE_STATIC,/* static ast entry for connected peer */ + CDP_TXRX_AST_TYPE_STATIC, /* static ast entry for connected peer */ CDP_TXRX_AST_TYPE_WDS, /* WDS peer ast entry type*/ CDP_TXRX_AST_TYPE_MEC, /* Multicast echo ast entry type */ + CDP_TXRX_AST_TYPE_WDS_HM, /* HM WDS entry */ CDP_TXRX_AST_TYPE_MAX }; diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 4ac7ecff02d4..2a481dcbf60a 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -80,6 +80,31 @@ struct cdp_cmn_ops { void (*txrx_peer_teardown) (struct cdp_vdev *vdev_hdl, void *peer_hdl); + int (*txrx_peer_add_ast) + (ol_txrx_soc_handle soc, struct cdp_peer *peer_hdl, + uint8_t *mac_addr, enum cdp_txrx_ast_entry_type type, + uint32_t flags); + + void (*txrx_peer_del_ast) + (ol_txrx_soc_handle soc, void *ast_hdl); + + int (*txrx_peer_update_ast) + (ol_txrx_soc_handle soc, struct cdp_peer *peer_hdl, + void *ast_hdl, uint32_t flags); + + void *(*txrx_peer_ast_hash_find) + (ol_txrx_soc_handle soc, uint8_t *ast_mac_addr); + + uint8_t (*txrx_peer_ast_get_pdev_id) + (ol_txrx_soc_handle soc, void *ast_hdl); + + uint8_t (*txrx_peer_ast_get_next_hop) + (ol_txrx_soc_handle soc, void *ast_hdl); + + void (*txrx_peer_ast_set_type) + (ol_txrx_soc_handle soc, void *ast_hdl, + enum cdp_txrx_ast_entry_type type); + void (*txrx_peer_delete)(void *peer, uint32_t bitmap); int (*txrx_set_monitor_mode)(struct cdp_vdev *vdev, @@ -636,13 +661,13 @@ struct ol_if_ops { int (*peer_unref_delete)(void *scn_handle, uint8_t vdev_id, uint8_t *peer_macaddr); bool (*is_hw_dbs_2x2_capable)(struct wlan_objmgr_psoc *psoc); - int (*peer_add_wds_entry)(void *ol_osif_vdev_handle, + int (*peer_add_wds_entry)(void *ol_soc_handle, const uint8_t *dest_macaddr, uint8_t *peer_macaddr, uint32_t flags); - int (*peer_update_wds_entry)(void *ol_osif_vdev_handle, + int (*peer_update_wds_entry)(void *ol_soc_handle, uint8_t *dest_macaddr, uint8_t *peer_macaddr, uint32_t flags); - void (*peer_del_wds_entry)(void *ol_osif_vdev_handle, + 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); diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 3da879197adb..52b1ed8fa860 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -61,6 +61,9 @@ static void dp_pkt_log_con_service(struct cdp_pdev *ppdev, void *scn); #endif #endif static void dp_pktlogmod_exit(struct dp_pdev *handle); +static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, + uint8_t *peer_mac_addr); +static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap); #define DP_INTR_POLL_TIMER_MS 10 #define DP_WDS_AGING_TIMER_DEFAULT_MS 120000 @@ -282,6 +285,83 @@ const int dp_stats_mapping_table[][STATS_TYPE_MAX] = { {TXRX_FW_STATS_INVALID, TXRX_SRNG_PTR_STATS}, }; +static int dp_peer_add_ast_wifi3(struct cdp_soc_t *soc_hdl, + struct cdp_peer *peer_hdl, + uint8_t *mac_addr, + enum cdp_txrx_ast_entry_type type, + uint32_t flags) +{ + + return dp_peer_add_ast((struct dp_soc *)soc_hdl, + (struct dp_peer *)peer_hdl, + mac_addr, + type, + flags); +} + +static void dp_peer_del_ast_wifi3(struct cdp_soc_t *soc_hdl, + void *ast_entry_hdl) +{ + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + qdf_spin_lock_bh(&soc->ast_lock); + dp_peer_del_ast((struct dp_soc *)soc_hdl, + (struct dp_ast_entry *)ast_entry_hdl); + qdf_spin_unlock_bh(&soc->ast_lock); +} + +static int dp_peer_update_ast_wifi3(struct cdp_soc_t *soc_hdl, + struct cdp_peer *peer_hdl, + void *ast_entry_hdl, + uint32_t flags) +{ + int status; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + qdf_spin_lock_bh(&soc->ast_lock); + status = dp_peer_update_ast(soc, + (struct dp_peer *)peer_hdl, + (struct dp_ast_entry *)ast_entry_hdl, + flags); + qdf_spin_unlock_bh(&soc->ast_lock); + return status; +} + +static void *dp_peer_ast_hash_find_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t *ast_mac_addr) +{ + struct dp_ast_entry *ast_entry; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + qdf_spin_lock_bh(&soc->ast_lock); + ast_entry = dp_peer_ast_hash_find(soc, ast_mac_addr); + qdf_spin_unlock_bh(&soc->ast_lock); + return (void *)ast_entry; +} + +static uint8_t dp_peer_ast_get_pdev_id_wifi3(struct cdp_soc_t *soc_hdl, + void *ast_entry_hdl) +{ + return dp_peer_ast_get_pdev_id((struct dp_soc *)soc_hdl, + (struct dp_ast_entry *)ast_entry_hdl); +} + +static uint8_t dp_peer_ast_get_next_hop_wifi3(struct cdp_soc_t *soc_hdl, + void *ast_entry_hdl) +{ + return dp_peer_ast_get_next_hop((struct dp_soc *)soc_hdl, + (struct dp_ast_entry *)ast_entry_hdl); +} + +static void dp_peer_ast_set_type_wifi3( + struct cdp_soc_t *soc_hdl, + void *ast_entry_hdl, + enum cdp_txrx_ast_entry_type type) +{ + dp_peer_ast_set_type((struct dp_soc *)soc_hdl, + (struct dp_ast_entry *)ast_entry_hdl, + type); +} + + + /** * dp_srng_find_ring_in_mask() - find which ext_group a ring belongs * @ring_num: ring num of the ring being queried @@ -468,14 +548,20 @@ static void dp_print_ast_stats(struct dp_soc *soc) " type = %d" " next_hop = %d" " is_active = %d" - " is_bss = %d", + " is_bss = %d" + " ast_idx = %d" + " pdev_id = %d" + " vdev_id = %d", ++num_entries, ase->mac_addr.raw, ase->peer->mac_addr.raw, ase->type, ase->next_hop, ase->is_active, - ase->is_bss); + ase->is_bss, + ase->ast_idx, + ase->pdev_id, + ase->vdev_id); } } } @@ -1462,8 +1548,12 @@ static void dp_wds_aging_timer_fn(void *soc_hdl) DP_PEER_ITERATE_ASE_LIST(peer, ase, temp_ase) { /* * Do not expire static ast entries + * and HM WDS entries */ - if (ase->type == CDP_TXRX_AST_TYPE_STATIC) + if (ase->type == + CDP_TXRX_AST_TYPE_STATIC || + ase->type == + CDP_TXRX_AST_TYPE_WDS_HM) continue; if (ase->is_active) { @@ -1472,11 +1562,6 @@ static void dp_wds_aging_timer_fn(void *soc_hdl) } DP_STATS_INC(soc, ast.aged_out, 1); - - soc->cdp_soc.ol_ops->peer_del_wds_entry( - vdev->osif_vdev, - ase->mac_addr.raw); - dp_peer_del_ast(soc, ase); } } @@ -3015,6 +3100,10 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev, "Created vdev %pK (%pM)", vdev, vdev->mac_addr.raw); DP_STATS_INIT(vdev); + if (wlan_op_mode_sta == vdev->opmode) + dp_peer_create_wifi3((struct cdp_vdev *)vdev, + vdev->mac_addr.raw); + return (struct cdp_vdev *)vdev; fail1: @@ -3112,6 +3201,9 @@ static void dp_vdev_detach_wifi3(struct cdp_vdev *vdev_handle, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, FL("deleting vdev object %pK (%pM)"), vdev, vdev->mac_addr.raw); + if (wlan_op_mode_sta == vdev->opmode) + dp_peer_delete_wifi3(vdev->vap_bss_peer, 0); + qdf_mem_free(vdev); if (callback) @@ -3157,7 +3249,7 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, /* store provided params */ peer->vdev = vdev; - dp_peer_add_ast(soc, peer, peer_mac_addr, dp_ast_type_static); + dp_peer_add_ast(soc, peer, peer_mac_addr, CDP_TXRX_AST_TYPE_STATIC, 0); qdf_spinlock_create(&peer->peer_info_lock); @@ -3179,7 +3271,11 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, qdf_atomic_inc(&peer->ref_cnt); /* add this peer into the vdev's list */ - TAILQ_INSERT_TAIL(&vdev->peer_list, peer, peer_list_elem); + if (wlan_op_mode_sta == vdev->opmode) + TAILQ_INSERT_HEAD(&vdev->peer_list, peer, peer_list_elem); + else + TAILQ_INSERT_TAIL(&vdev->peer_list, peer, peer_list_elem); + qdf_spin_unlock_bh(&soc->peer_ref_mutex); /* TODO: See if hash based search is required */ @@ -6087,16 +6183,11 @@ static inline void dp_peer_delete_ast_entries(struct dp_soc *soc, struct dp_peer *peer) { struct dp_ast_entry *ast_entry, *temp_ast_entry; - qdf_spin_lock_bh(&soc->ast_lock); - DP_PEER_ITERATE_ASE_LIST(peer, ast_entry, temp_ast_entry) { - if (ast_entry->next_hop) { - soc->cdp_soc.ol_ops->peer_del_wds_entry( - peer->vdev->osif_vdev, - ast_entry->mac_addr.raw); - } + qdf_spin_lock_bh(&soc->ast_lock); + DP_PEER_ITERATE_ASE_LIST(peer, ast_entry, temp_ast_entry) dp_peer_del_ast(soc, ast_entry); - } + qdf_spin_unlock_bh(&soc->ast_lock); } #else @@ -6176,6 +6267,13 @@ static struct cdp_cmn_ops dp_ops_cmn = { #else .txrx_peer_teardown = NULL, #endif + .txrx_peer_add_ast = dp_peer_add_ast_wifi3, + .txrx_peer_del_ast = dp_peer_del_ast_wifi3, + .txrx_peer_update_ast = dp_peer_update_ast_wifi3, + .txrx_peer_ast_hash_find = dp_peer_ast_hash_find_wifi3, + .txrx_peer_ast_get_pdev_id = dp_peer_ast_get_pdev_id_wifi3, + .txrx_peer_ast_get_next_hop = dp_peer_ast_get_next_hop_wifi3, + .txrx_peer_ast_set_type = dp_peer_ast_set_type_wifi3, .txrx_peer_delete = dp_peer_delete_wifi3, .txrx_vdev_register = dp_vdev_register_wifi3, .txrx_soc_detach = dp_soc_detach_wifi3, diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 1eee462af9ab..03b5efd3e480 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -314,20 +314,15 @@ static inline void dp_peer_ast_hash_remove(struct dp_soc *soc, * 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) + uint8_t *ast_mac_addr) { 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], + qdf_mem_copy(&local_mac_addr_aligned.raw[0], ast_mac_addr, DP_MAC_ADDR_LEN); - mac_addr = &local_mac_addr_aligned; - } + 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) { @@ -408,10 +403,23 @@ static inline void dp_peer_map_ast(struct dp_soc *soc, * 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, enum dp_ast_type is_self) +int dp_peer_add_ast(struct dp_soc *soc, + struct dp_peer *peer, + uint8_t *mac_addr, + enum cdp_txrx_ast_entry_type type, + uint32_t flags) { struct dp_ast_entry *ast_entry; + struct dp_vdev *vdev = peer->vdev; + uint8_t next_node_mac[6]; + bool ret = 1; + + if (!vdev) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + FL("Peers vdev is NULL")); + QDF_ASSERT(0); + return ret; + } QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: peer %pK mac %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -421,13 +429,14 @@ int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer, qdf_spin_lock_bh(&soc->ast_lock); /* If AST entry already exists , just return from here */ - ast_entry = dp_peer_ast_hash_find(soc, mac_addr, 0); + ast_entry = dp_peer_ast_hash_find(soc, mac_addr); + if (ast_entry) { if (ast_entry->type == CDP_TXRX_AST_TYPE_MEC) ast_entry->is_active = TRUE; qdf_spin_unlock_bh(&soc->ast_lock); - return 1; + return ret; } ast_entry = (struct dp_ast_entry *) @@ -438,22 +447,28 @@ int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer, QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, FL("fail to allocate ast_entry")); QDF_ASSERT(0); - return 1; + return ret; } qdf_mem_copy(&ast_entry->mac_addr.raw[0], mac_addr, DP_MAC_ADDR_LEN); ast_entry->peer = peer; + ast_entry->pdev_id = vdev->pdev->pdev_id; + ast_entry->vdev_id = vdev->vdev_id; - switch (is_self) { - case dp_ast_type_static: + switch (type) { + case CDP_TXRX_AST_TYPE_STATIC: peer->self_ast_entry = ast_entry; ast_entry->type = CDP_TXRX_AST_TYPE_STATIC; break; - case dp_ast_type_wds: + case CDP_TXRX_AST_TYPE_WDS: ast_entry->next_hop = 1; ast_entry->type = CDP_TXRX_AST_TYPE_WDS; break; - case dp_ast_type_mec: + case CDP_TXRX_AST_TYPE_WDS_HM: + ast_entry->next_hop = 1; + ast_entry->type = CDP_TXRX_AST_TYPE_WDS_HM; + break; + case CDP_TXRX_AST_TYPE_MEC: ast_entry->next_hop = 1; ast_entry->type = CDP_TXRX_AST_TYPE_MEC; break; @@ -467,7 +482,21 @@ int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer, DP_STATS_INC(soc, ast.added, 1); dp_peer_ast_hash_add(soc, ast_entry); qdf_spin_unlock_bh(&soc->ast_lock); - return 0; + + if (ast_entry->type == CDP_TXRX_AST_TYPE_WDS) + qdf_mem_copy(next_node_mac, peer->mac_addr.raw, 6); + else + qdf_mem_copy(next_node_mac, peer->vdev->mac_addr.raw, 6); + + if (ast_entry->type != CDP_TXRX_AST_TYPE_STATIC) { + ret = soc->cdp_soc.ol_ops->peer_add_wds_entry( + peer->vdev->osif_vdev, + mac_addr, + next_node_mac, + flags); + } + + return ret; } /* @@ -481,31 +510,117 @@ int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer, * * Return: None */ -void dp_peer_del_ast(struct dp_soc *soc, - struct dp_ast_entry *ast_entry) +void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) { struct dp_peer *peer = ast_entry->peer; + + if (ast_entry->next_hop) + soc->cdp_soc.ol_ops->peer_del_wds_entry(peer->vdev->osif_vdev, + ast_entry->mac_addr.raw); + soc->ast_table[ast_entry->ast_idx] = NULL; TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); DP_STATS_INC(soc, ast.deleted, 1); dp_peer_ast_hash_remove(soc, ast_entry); qdf_mem_free(ast_entry); } + +/* + * dp_peer_update_ast() - Delete and free AST entry + * @soc: SoC handle + * @peer: peer to which ast node belongs + * @ast_entry: AST entry of the node + * @flags: wds or hmwds + * + * This function update the AST entry to the roamed peer and soc tables + * It assumes caller has taken the ast lock to protect the access to these + * tables + * + * Return: 0 if ast entry is updated successfully + * 1 failure + */ +int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer, + struct dp_ast_entry *ast_entry, uint32_t flags) +{ + bool ret = 1; + + ast_entry->peer = peer; + if (ast_entry->type != CDP_TXRX_AST_TYPE_STATIC) { + ret = soc->cdp_soc.ol_ops->peer_update_wds_entry( + peer->vdev->osif_vdev, + ast_entry->mac_addr.raw, + peer->mac_addr.raw, + flags); + } + return ret; +} + +/* + * dp_peer_ast_get_pdev_id() - get pdev_id from the ast entry + * @soc: SoC handle + * @ast_entry: AST entry of the node + * + * This function gets the pdev_id from the ast entry. + * + * Return: (uint8_t) pdev_id + */ +uint8_t dp_peer_ast_get_pdev_id(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + return ast_entry->pdev_id; +} + +/* + * dp_peer_ast_get_next_hop() - get next_hop from the ast entry + * @soc: SoC handle + * @ast_entry: AST entry of the node + * + * This function gets the next hop from the ast entry. + * + * Return: (uint8_t) next_hop + */ +uint8_t dp_peer_ast_get_next_hop(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + return ast_entry->next_hop; +} + +/* + * dp_peer_ast_set_type() - set type from the ast entry + * @soc: SoC handle + * @ast_entry: AST entry of the node + * + * This function sets the type in the ast entry. + * + * Return: + */ +void dp_peer_ast_set_type(struct dp_soc *soc, + struct dp_ast_entry *ast_entry, + enum cdp_txrx_ast_entry_type type) +{ + ast_entry->type = type; +} + #else int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer, - uint8_t *mac_addr, enum dp_ast_type is_self) + uint8_t *mac_addr, enum cdp_txrx_ast_entry_type type, + uint32_t flags) { return 1; } -void dp_peer_del_ast(struct dp_soc *soc, - struct dp_ast_entry *ast_entry) +void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) { } +int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer, + struct dp_ast_entry *ast_entry, uint32_t flags) +{ + return 1; +} struct dp_ast_entry *dp_peer_ast_hash_find(struct dp_soc *soc, - uint8_t *ast_mac_addr, int mac_addr_is_aligned) + uint8_t *ast_mac_addr) { return NULL; } @@ -525,6 +640,25 @@ static inline void dp_peer_map_ast(struct dp_soc *soc, static void dp_peer_ast_hash_detach(struct dp_soc *soc) { } + +void dp_peer_ast_set_type(struct dp_soc *soc, + struct dp_ast_entry *ast_entry, + enum cdp_txrx_ast_entry_type type) +{ +} + +uint8_t dp_peer_ast_get_pdev_id(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + return 0xff; +} + + +uint8_t dp_peer_ast_get_next_hop(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + return 0xff; +} #endif #if ATH_SUPPORT_WRAP diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 7264dbb42f28..b7c562027161 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018 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 @@ -54,13 +54,28 @@ 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); - int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer, - uint8_t *mac_addr, enum dp_ast_type is_self); -void dp_peer_del_ast(struct dp_soc *soc, - struct dp_ast_entry *ast_entry); + uint8_t *mac_addr, enum cdp_txrx_ast_entry_type type, + uint32_t flags); + +void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry); + +int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer, + struct dp_ast_entry *ast_entry, uint32_t flags); + struct dp_ast_entry *dp_peer_ast_hash_find(struct dp_soc *soc, - uint8_t *ast_mac_addr, int mac_addr_is_aligned); + uint8_t *ast_mac_addr); + +uint8_t dp_peer_ast_get_pdev_id(struct dp_soc *soc, + struct dp_ast_entry *ast_entry); + + +uint8_t dp_peer_ast_get_next_hop(struct dp_soc *soc, + struct dp_ast_entry *ast_entry); + +void dp_peer_ast_set_type(struct dp_soc *soc, + struct dp_ast_entry *ast_entry, + enum cdp_txrx_ast_entry_type type); /* * dp_get_vdev_from_soc_vdev_id_wifi3() - diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 4a868307df8c..afe6695af8d2 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -365,14 +365,12 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc, IEEE80211_ADDR_LEN); 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, - dp_ast_type_wds)) { - ret = soc->cdp_soc.ol_ops->peer_add_wds_entry( - ta_peer->vdev->osif_vdev, + ret = dp_peer_add_ast(soc, + ta_peer, wds_src_mac, - ta_peer->mac_addr.raw, + CDP_TXRX_AST_TYPE_WDS, flags); - } + } else { /* * Get the AST entry from HW SA index and mark it as active @@ -391,13 +389,8 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc, 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->osif_vdev, - wds_src_mac, - ta_peer->mac_addr.raw, - flags); - } + if (ast && sa_sw_peer_id != ta_peer->peer_ids[0]) + dp_peer_update_ast(soc, ta_peer, ast, flags); } return; } diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 77f121055244..112089787938 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -66,7 +66,7 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, { struct dp_vdev *vdev = peer->vdev; struct dp_ast_entry *ase; - uint16_t sa_idx; + uint16_t sa_idx = 0; uint8_t *data; /* @@ -99,7 +99,8 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, if (hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr)) { sa_idx = hal_rx_msdu_end_sa_idx_get(rx_tlv_hdr); - if ((sa_idx < 0) || (sa_idx > (WLAN_UMAC_PSOC_MAX_PEERS * 2))) { + if ((sa_idx < 0) || + (sa_idx >= (WLAN_UMAC_PSOC_MAX_PEERS * 2))) { qdf_spin_unlock_bh(&soc->ast_lock); QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "invalid sa_idx: %d", sa_idx); @@ -107,10 +108,34 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, } ase = soc->ast_table[sa_idx]; + if (!ase) { + /* We do not get a peer map event for STA and without + * this event we don't know what is STA's sa_idx. + * For this reason the AST is still not associated to + * any index postion in ast_table. + * In these kind of scenarios where sa is valid but + * ast is not in ast_table, we use the below API to get + * AST entry for STA's own mac_address. + */ + ase = dp_peer_ast_hash_find(soc, + &data[DP_MAC_ADDR_LEN]); + + } } else - ase = dp_peer_ast_hash_find(soc, &data[DP_MAC_ADDR_LEN], 0); + ase = dp_peer_ast_hash_find(soc, &data[DP_MAC_ADDR_LEN]); if (ase) { + ase->ast_idx = sa_idx; + soc->ast_table[sa_idx] = ase; + + if (ase->pdev_id != vdev->pdev->pdev_id) { + qdf_spin_unlock_bh(&soc->ast_lock); + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_INFO, + "Detected DBDC Root AP"); + return false; + } + if ((ase->type == CDP_TXRX_AST_TYPE_MEC) || (ase->peer != peer)) { qdf_spin_unlock_bh(&soc->ast_lock); diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index bdfb18411686..44458117d756 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -1605,7 +1605,8 @@ static qdf_nbuf_t dp_tx_prepare_nawds(struct dp_vdev *vdev, qdf_nbuf_t nbuf, qdf_nbuf_t nbuf_copy; qdf_spin_lock_bh(&(soc->ast_lock)); - ast_entry = dp_peer_ast_hash_find(soc, (uint8_t *)(eh->ether_shost), 0); + ast_entry = dp_peer_ast_hash_find(soc, (uint8_t *)(eh->ether_shost)); + if (ast_entry) sa_peer = ast_entry->peer; @@ -2028,7 +2029,8 @@ void dp_tx_reinject_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status) qdf_spin_lock_bh(&(soc->ast_lock)); - ast_entry = dp_peer_ast_hash_find(soc, (uint8_t *)(eh->ether_shost), 0); + ast_entry = dp_peer_ast_hash_find(soc, (uint8_t *)(eh->ether_shost)); + if (ast_entry) sa_peer = ast_entry->peer; @@ -2364,14 +2366,12 @@ void dp_tx_mec_handler(struct dp_vdev *vdev, uint8_t *status) mac_addr[(DP_MAC_ADDR_LEN - 1) - i] = status[(DP_MAC_ADDR_LEN - 2) + i]; - if (qdf_mem_cmp(mac_addr, vdev->mac_addr.raw, DP_MAC_ADDR_LEN) && - !dp_peer_add_ast(soc, peer, mac_addr, dp_ast_type_mec)) { - soc->cdp_soc.ol_ops->peer_add_wds_entry( - vdev->osif_vdev, + if (qdf_mem_cmp(mac_addr, vdev->mac_addr.raw, DP_MAC_ADDR_LEN)) + dp_peer_add_ast(soc, + peer, mac_addr, - vdev->mac_addr.raw, + CDP_TXRX_AST_TYPE_MEC, flags); - } } #else static void dp_tx_mec_handler(struct dp_vdev *vdev, uint8_t *status) diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 4d65a7e5a610..6bf8802f1f40 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -555,6 +555,8 @@ union dp_align_mac_addr { * (used for aging out/expiry) * @ase_list_elem: node in peer AST list * @is_bss: flag to indicate if entry corresponds to bss peer + * @pdev_id: pdev ID + * @vdev_id: vdev ID * @type: flag to indicate type of the entry(static/WDS/MEC) * @hash_list_elem: node in soc AST hash list (mac address used as hash) */ @@ -566,6 +568,8 @@ struct dp_ast_entry { bool next_hop; bool is_active; bool is_bss; + uint8_t pdev_id; + uint8_t vdev_id; enum cdp_txrx_ast_entry_type type; TAILQ_ENTRY(dp_ast_entry) ase_list_elem; TAILQ_ENTRY(dp_ast_entry) hash_list_elem;