diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index deec56a07d..bb5c47d6dc 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -1711,12 +1711,22 @@ void cdp_if_mgmt_drain(ol_txrx_soc_handle soc, soc->ops->cmn_drv_ops->txrx_if_mgmt_drain(ni, force); } +/* cdp_peer_map_attach() - CDP API to allocate PEER map memory + * @soc: opaque soc handle + * @max_peers: number of peers created in FW + * @peer_map_unmap_v2: flag indicates HTT peer map v2 is enabled in FW + * + * + * Return: void + */ static inline void -cdp_peer_map_attach(ol_txrx_soc_handle soc, uint32_t max_peers) +cdp_peer_map_attach(ol_txrx_soc_handle soc, uint32_t max_peers, + bool peer_map_unmap_v2) { if (soc && soc->ops && soc->ops->cmn_drv_ops && soc->ops->cmn_drv_ops->txrx_peer_map_attach) - soc->ops->cmn_drv_ops->txrx_peer_map_attach(soc, max_peers); + soc->ops->cmn_drv_ops->txrx_peer_map_attach(soc, max_peers, + peer_map_unmap_v2); } /** diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 34ab041090..fe293fae39 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -331,7 +331,8 @@ struct cdp_cmn_ops { uint8_t ac, uint32_t *value); QDF_STATUS (*txrx_peer_map_attach)(ol_txrx_soc_handle soc, - uint32_t num_peers); + uint32_t num_peers, + bool peer_map_unmap_v2); void (*txrx_pdev_set_ctrl_pdev)(struct cdp_pdev *pdev_hdl, struct cdp_ctrl_objmgr_pdev *ctrl_pdev); diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index 8a63799ee0..da2027faa5 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -2950,6 +2950,8 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) u_int16_t peer_id; u_int16_t hw_peer_id; u_int8_t vdev_id; + u_int8_t is_wds; + struct dp_soc *dpsoc = (struct dp_soc *)soc->dp_soc; peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word); hw_peer_id = @@ -2963,16 +2965,28 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) "HTT_T2H_MSG_TYPE_PEER_MAP msg for peer id %d vdev id %d n", peer_id, vdev_id); + /* + * check if peer already exists for this peer_id, if so + * this peer map event is in response for a wds peer add + * wmi command sent during wds source port learning. + * in this case just add the ast entry to the existing + * peer ast_list. + */ + is_wds = !!(dpsoc->peer_id_to_obj_map[peer_id]); dp_rx_peer_map_handler(soc->dp_soc, peer_id, hw_peer_id, - vdev_id, peer_mac_addr); + vdev_id, peer_mac_addr, 0, + is_wds); break; } case HTT_T2H_MSG_TYPE_PEER_UNMAP: { u_int16_t peer_id; + u_int8_t vdev_id; peer_id = HTT_RX_PEER_UNMAP_PEER_ID_GET(*msg_word); + vdev_id = HTT_RX_PEER_UNMAP_VDEV_ID_GET(*msg_word); - dp_rx_peer_unmap_handler(soc->dp_soc, peer_id); + dp_rx_peer_unmap_handler(soc->dp_soc, peer_id, + vdev_id, NULL, 0); break; } case HTT_T2H_MSG_TYPE_SEC_IND: @@ -3073,6 +3087,64 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) dp_txrx_fw_stats_handler(soc->dp_soc, htt_t2h_msg); break; } + case HTT_T2H_MSG_TYPE_PEER_MAP_V2: + { + u_int8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN]; + u_int8_t *peer_mac_addr; + u_int16_t peer_id; + u_int16_t hw_peer_id; + u_int8_t vdev_id; + bool is_wds; + u_int16_t ast_hash; + + peer_id = HTT_RX_PEER_MAP_V2_SW_PEER_ID_GET(*msg_word); + hw_peer_id = + HTT_RX_PEER_MAP_V2_HW_PEER_ID_GET(*(msg_word + 2)); + vdev_id = HTT_RX_PEER_MAP_V2_VDEV_ID_GET(*msg_word); + peer_mac_addr = + htt_t2h_mac_addr_deswizzle((u_int8_t *)(msg_word + 1), + &mac_addr_deswizzle_buf[0]); + is_wds = + HTT_RX_PEER_MAP_V2_NEXT_HOP_GET(*(msg_word + 3)); + ast_hash = + HTT_RX_PEER_MAP_V2_AST_HASH_VALUE_GET(*(msg_word + 3)); + QDF_TRACE(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_INFO, + "HTT_T2H_MSG_TYPE_PEER_MAP msg for peer id %d vdev id %d n", + peer_id, vdev_id); + + dp_rx_peer_map_handler(soc->dp_soc, peer_id, + hw_peer_id, vdev_id, + peer_mac_addr, ast_hash, + is_wds); + break; + } + case HTT_T2H_MSG_TYPE_PEER_UNMAP_V2: + { + u_int8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN]; + u_int8_t *peer_mac_addr; + u_int16_t peer_id; + u_int8_t vdev_id; + u_int8_t is_wds; + + peer_id = + HTT_RX_PEER_UNMAP_V2_SW_PEER_ID_GET(*msg_word); + vdev_id = HTT_RX_PEER_UNMAP_V2_VDEV_ID_GET(*msg_word); + peer_mac_addr = + htt_t2h_mac_addr_deswizzle((u_int8_t *)(msg_word + 1), + &mac_addr_deswizzle_buf[0]); + is_wds = + HTT_RX_PEER_UNMAP_V2_NEXT_HOP_GET(*(msg_word + 2)); + QDF_TRACE(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_INFO, + "HTT_T2H_MSG_TYPE_PEER_MAP msg for peer id %d vdev id %d n", + peer_id, vdev_id); + + dp_rx_peer_unmap_handler(soc->dp_soc, peer_id, + vdev_id, peer_mac_addr, + is_wds); + break; + } default: break; }; diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index dfef3177de..cfa1c9a571 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -3728,7 +3728,8 @@ static void dp_vdev_flush_peers(struct dp_vdev *vdev) qdf_spin_unlock_bh(&soc->peer_ref_mutex); for (i = 0; i < j ; i++) - dp_rx_peer_unmap_handler(soc, peer_ids[i]); + dp_rx_peer_unmap_handler(soc, peer_ids[i], vdev->vdev_id, + NULL, 0); qdf_mem_free(peer_ids); @@ -7645,7 +7646,8 @@ static QDF_STATUS dp_config_for_nac_rssi(struct cdp_vdev *vdev_handle, #endif static QDF_STATUS dp_peer_map_attach_wifi3(struct cdp_soc_t *soc_hdl, - uint32_t max_peers) + uint32_t max_peers, + bool peer_map_unmap_v2) { struct dp_soc *soc = (struct dp_soc *)soc_hdl; @@ -7656,6 +7658,8 @@ static QDF_STATUS dp_peer_map_attach_wifi3(struct cdp_soc_t *soc_hdl, if (dp_peer_find_attach(soc)) return QDF_STATUS_E_FAILURE; + soc->is_peer_map_unmap_v2 = peer_map_unmap_v2; + return QDF_STATUS_SUCCESS; } diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index e38a4e71b7..7266ce7556 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -342,12 +342,13 @@ struct dp_ast_entry *dp_peer_ast_hash_find(struct dp_soc *soc, * @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 + * @ast_hash: ast hash value in HW * * 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) + uint8_t vdev_id, uint16_t ast_hash) { struct dp_ast_entry *ast_entry; enum cdp_txrx_ast_entry_type peer_type = CDP_TXRX_AST_TYPE_STATIC; @@ -372,6 +373,7 @@ static inline void dp_peer_map_ast(struct dp_soc *soc, ast_entry->is_active = TRUE; peer_type = ast_entry->type; ast_entry_found = TRUE; + ast_entry->ast_hash_value = ast_hash; } } @@ -677,7 +679,7 @@ static int dp_peer_ast_hash_attach(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) + uint8_t vdev_id, uint16_t ast_hash) { return; } @@ -947,7 +949,14 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc, QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, "%s: ref_cnt: %d", __func__, qdf_atomic_read(&peer->ref_cnt)); - soc->peer_id_to_obj_map[peer_id] = peer; + if (!soc->peer_id_to_obj_map[peer_id]) + soc->peer_id_to_obj_map[peer_id] = peer; + else { + /* Peer map event came for peer_id which + * is already mapped, this is not expected + */ + QDF_ASSERT(0); + } if (dp_peer_find_add_id_to_obj(peer, peer_id)) { /* TBDXXX: assert for now */ @@ -965,8 +974,10 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc, * @soc_handle - genereic soc handle * @peeri_id - peer_id from firmware * @hw_peer_id - ast index for this peer - * vdev_id - vdev ID - * peer_mac_addr - macc assress of the peer + * @vdev_id - vdev ID + * @peer_mac_addr - mac address of the peer + * @ast_hash - ast hash value + * @is_wds - flag to indicate peer map event for WDS ast entry * * associate the peer_id that firmware provided with peer entry * and update the ast table in the host with the hw_peer_id. @@ -975,8 +986,10 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc, */ void -dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, uint16_t hw_peer_id, - uint8_t vdev_id, uint8_t *peer_mac_addr) +dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, + uint16_t hw_peer_id, uint8_t vdev_id, + uint8_t *peer_mac_addr, uint16_t ast_hash, + uint8_t is_wds) { struct dp_soc *soc = (struct dp_soc *)soc_handle; struct dp_peer *peer = NULL; @@ -988,50 +1001,66 @@ dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, uint16_t hw_peer_id, peer_mac_addr[2], peer_mac_addr[3], peer_mac_addr[4], peer_mac_addr[5], vdev_id); - peer = soc->peer_id_to_obj_map[peer_id]; - if ((hw_peer_id < 0) || (hw_peer_id > (WLAN_UMAC_PSOC_MAX_PEERS * 2))) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "invalid hw_peer_id: %d", hw_peer_id); qdf_assert_always(0); } - /* - * check if peer already exists for this peer_id, if so - * this peer map event is in response for a wds peer add - * wmi command sent during wds source port learning. - * in this case just add the ast entry to the existing - * peer ast_list. + /* Peer map event for WDS ast entry get the peer from + * obj map */ - if (!peer) + if (is_wds) { + peer = soc->peer_id_to_obj_map[peer_id]; + } else { peer = dp_peer_find_add_id(soc, peer_mac_addr, peer_id, - hw_peer_id, vdev_id); + hw_peer_id, vdev_id); - if (peer) { - qdf_assert_always(peer->vdev); - /* - * For every peer MAp message search and set if bss_peer - */ - if (!(qdf_mem_cmp(peer->mac_addr.raw, peer->vdev->mac_addr.raw, - DP_MAC_ADDR_LEN))) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - "vdev bss_peer!!!!"); - peer->bss_peer = 1; - peer->vdev->vap_bss_peer = peer; + if (peer) { + /* + * For every peer MAp message search and set if bss_peer + */ + if (!(qdf_mem_cmp(peer->mac_addr.raw, + peer->vdev->mac_addr.raw, + DP_MAC_ADDR_LEN))) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_INFO_HIGH, + "vdev bss_peer!!!!"); + peer->bss_peer = 1; + peer->vdev->vap_bss_peer = peer; + } + + if (peer->vdev->opmode == wlan_op_mode_sta) + peer->vdev->bss_ast_hash = ast_hash; } } dp_peer_map_ast(soc, peer, peer_mac_addr, - hw_peer_id, vdev_id); + hw_peer_id, vdev_id, ast_hash); } +/** + * dp_rx_peer_unmap_handler() - handle peer unmap event from firmware + * @soc_handle - genereic soc handle + * @peeri_id - peer_id from firmware + * @vdev_id - vdev ID + * @peer_mac_addr - mac address of the peer + * @is_wds - flag to indicate peer map event for WDS ast entry + * + * Return: none + */ void -dp_rx_peer_unmap_handler(void *soc_handle, uint16_t peer_id) +dp_rx_peer_unmap_handler(void *soc_handle, uint16_t peer_id, + uint8_t vdev_id, uint8_t *peer_mac_addr, + uint8_t is_wds) { struct dp_peer *peer; struct dp_soc *soc = (struct dp_soc *)soc_handle; uint8_t i; + if (is_wds) + return; + peer = __dp_peer_find_by_id(soc, peer_id); QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 8c8aafe3ff..2a456b81bc 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -69,8 +69,12 @@ dp_peer_find_by_id(struct dp_soc *soc, } void dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, - uint16_t hw_peer_id, uint8_t vdev_id, uint8_t *peer_mac_addr); -void dp_rx_peer_unmap_handler(void *soc_handle, uint16_t peer_id); + uint16_t hw_peer_id, uint8_t vdev_id, + uint8_t *peer_mac_addr, uint16_t ast_hash, + uint8_t is_wds); +void dp_rx_peer_unmap_handler(void *soc_handle, uint16_t peer_id, + uint8_t vdev_id, uint8_t *peer_mac_addr, + uint8_t is_wds); void dp_rx_sec_ind_handler(void *soc_handle, uint16_t peer_id, enum htt_sec_type sec_type, int is_unicast, u_int32_t *michael_key, u_int32_t *rx_pn); @@ -83,6 +87,9 @@ int dp_peer_add_ast(struct dp_soc *soc, struct dp_peer *peer, void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry); +void dp_peer_ast_unmap_handler(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); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 1e63c19519..498a571816 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -599,7 +599,7 @@ union dp_align_mac_addr { uint32_t bytes_abcd; uint16_t bytes_ef; } align4; - struct { + struct __attribute__((__packed__)) { uint16_t bytes_ab; uint32_t bytes_cdef; } align4_2; @@ -619,6 +619,8 @@ union dp_align_mac_addr { * @is_bss: flag to indicate if entry corresponds to bss peer * @pdev_id: pdev ID * @vdev_id: vdev ID + * @ast_hash_value: hast value in HW + * @ref_cnt: reference count * @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) */ @@ -632,6 +634,8 @@ struct dp_ast_entry { bool is_bss; uint8_t pdev_id; uint8_t vdev_id; + uint16_t ast_hash_value; + qdf_atomic_t ref_cnt; enum cdp_txrx_ast_entry_type type; TAILQ_ENTRY(dp_ast_entry) ase_list_elem; TAILQ_ENTRY(dp_ast_entry) hash_list_elem; @@ -921,6 +925,8 @@ struct dp_soc { /* Smart monitor capability for HKv2 */ uint8_t hw_nac_monitor_support; + /* Flag to indicate if HTT v2 is enabled*/ + bool is_peer_map_unmap_v2; }; #ifdef IPA_OFFLOAD @@ -1401,6 +1407,8 @@ struct dp_vdev { /* SWAR for HW: Enable WEP bit in the AMSDU frames for RAW mode */ bool raw_mode_war; + /* AST hash value for BSS peer in HW valid for STA VAP*/ + uint16_t bss_ast_hash; }; diff --git a/target_if/init_deinit/src/init_event_handler.c b/target_if/init_deinit/src/init_event_handler.c index 3d2786eacd..aa288dc3c1 100644 --- a/target_if/init_deinit/src/init_event_handler.c +++ b/target_if/init_deinit/src/init_event_handler.c @@ -320,6 +320,7 @@ static int init_deinit_ready_event_handler(ol_scn_t scn_handle, wmi_legacy_service_ready_callback legacy_callback; uint8_t num_radios, i; uint32_t max_peers; + target_resource_config *tgt_cfg; if (!scn_handle) { target_if_err("scn handle NULL"); @@ -374,10 +375,11 @@ static int init_deinit_ready_event_handler(ol_scn_t scn_handle, * allocate peer memory in this case */ if (ready_ev.num_total_peer != 0) { - max_peers = info->wlan_res_cfg.num_peers + - ready_ev.num_extra_peer + 1; + tgt_cfg = &info->wlan_res_cfg; + max_peers = tgt_cfg->num_peers + ready_ev.num_extra_peer + 1; - cdp_peer_map_attach(wlan_psoc_get_dp_handle(psoc), max_peers); + cdp_peer_map_attach(wlan_psoc_get_dp_handle(psoc), max_peers, + tgt_cfg->peer_map_unmap_v2); } /* Indicate to the waiting thread that the ready diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index c2709aeb9f..b4295b7d7e 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -6176,6 +6176,7 @@ struct wmi_host_fw_abi_ver { * @use_pdev_id: * @max_num_dbs_scan_duty_cycle: max dbs can duty cycle value * @cce_disable: disable cce component + * @peer_map_unmap_v2: enable peer map/unmap version 2 messaging * @twt_ap_pdev_count: Number of MAC on which AP TWT feature is supported * @twt_ap_sta_count: Max no of STA with which TWT sessions can be formed * by the AP @@ -6252,6 +6253,7 @@ typedef struct { uint32_t use_pdev_id; uint32_t max_num_dbs_scan_duty_cycle; bool cce_disable; + bool peer_map_unmap_v2; uint32_t twt_ap_pdev_count; uint32_t twt_ap_sta_count; uint32_t max_bssid_indicator; diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index a2a3bfbaec..2eed73a4f1 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -12921,6 +12921,8 @@ void wmi_copy_resource_config(wmi_resource_config *resource_cfg, WMI_RSRC_CFG_FLAG_TCL_CCE_DISABLE_SET(resource_cfg->flag1, 1); wmi_copy_twt_resource_config(resource_cfg, tgt_res_cfg); + resource_cfg->peer_map_unmap_v2_support = + tgt_res_cfg->peer_map_unmap_v2; } /* copy_hw_mode_id_in_init_cmd() - Helper routine to copy hw_mode in init cmd