diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index 46fe6788c8..6f941b438a 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -21,6 +21,7 @@ #include "dp_htt.h" #include "dp_peer.h" #include "dp_types.h" +#include "dp_internal.h" #define HTT_HTC_PKT_POOL_INIT_SIZE 64 @@ -524,6 +525,10 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) peer_mac_addr = htt_t2h_mac_addr_deswizzle( (u_int8_t *) (msg_word+1), &mac_addr_deswizzle_buf[0]); + 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, vdev_id, peer_mac_addr); @@ -590,6 +595,40 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) } break; } + case HTT_T2H_MSG_TYPE_RX_ADDBA: + { + uint16_t peer_id; + uint8_t tid; + uint8_t win_sz; + uint16_t status; + struct dp_peer *peer; + + /* + * Update REO Queue Desc with new values + */ + peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word); + tid = HTT_RX_ADDBA_TID_GET(*msg_word); + win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word); + peer = dp_peer_find_by_id(soc->dp_soc, peer_id); + + if (peer) { + status = dp_addba_requestprocess_wifi3(peer, + 0, tid, 0, win_sz, 0xffff); + QDF_TRACE(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_INFO, + FL("PeerID %d BAW %d TID %d stat %d\n"), + peer_id, win_sz, tid, status); + + } else { + QDF_TRACE(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_ERROR, + FL("Peer not found peer id %d\n"), + peer_id); + } + break; + } + + default: break; }; diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index bb627f630b..721a87aafd 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -30,6 +30,23 @@ #include #include +#ifdef DP_LFR +static inline void +dp_set_ssn_valid_flag(struct hal_reo_cmd_params *params, + uint8_t valid) +{ + params->u.upd_queue_params.update_svld = 1; + params->u.upd_queue_params.svld = valid; + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "%s: Setting SSN valid bit to %d\n", + __func__, valid); +} +#else +static inline void +dp_set_ssn_valid_flag(struct hal_reo_cmd_params *params, + uint8_t valid) {}; +#endif + static inline int dp_peer_find_mac_addr_cmp( union dp_align_mac_addr *mac_addr1, union dp_align_mac_addr *mac_addr2) @@ -482,6 +499,8 @@ static int dp_rx_tid_update_wifi3(struct dp_peer *peer, int tid, uint32_t params.u.upd_queue_params.ssn = start_seq; } + dp_set_ssn_valid_flag(¶ms, 0); + dp_reo_send_cmd(soc, CMD_UPDATE_RX_REO_QUEUE, ¶ms, dp_rx_tid_update_cb, rx_tid); return 0; } @@ -738,6 +757,21 @@ static int dp_rx_tid_delete_wifi3(struct dp_peer *peer, int tid) return 0; } +#ifdef DP_LFR +static void dp_peer_setup_remaining_tids(struct dp_peer *peer) +{ + int tid; + + for (tid = 1; tid < DP_MAX_TIDS-1; tid++) { + dp_rx_tid_setup_wifi3(peer, tid, 1, 0); + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "Setting up TID %d for peer %p peer->local_id %d\n", + tid, peer, peer->local_id); + } +} +#else +static void dp_peer_setup_remaining_tids(struct dp_peer *peer) {}; +#endif /* * dp_peer_rx_init() – Initialize receive TID state * @pdev: Datapath pdev @@ -775,6 +809,11 @@ void dp_peer_rx_init(struct dp_pdev *pdev, struct dp_peer *peer) */ dp_rx_tid_setup_wifi3(peer, 0, 1, 0); + /* + * Setup the rest of TID's to handle LFR + */ + dp_peer_setup_remaining_tids(peer); + /* * Set security defaults: no PN check, no security. The target may * send a HTT SEC_IND message to overwrite these defaults. diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 4399532041..6fc8084986 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -54,4 +54,39 @@ 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 DP_LFR +/* + * dp_get_vdev_from_soc_vdev_id_wifi3() - + * Returns vdev object given the vdev id + * vdev id is unique across pdev's + * + * @soc : core DP soc context + * @vdev_id : vdev id from vdev object can be retrieved + * + * Return: struct dp_vdev*: Pointer to DP vdev object + */ +static inline struct dp_vdev * +dp_get_vdev_from_soc_vdev_id_wifi3(struct dp_soc *soc, + uint8_t vdev_id) +{ + struct dp_pdev *pdev = NULL; + struct dp_vdev *vdev = NULL; + int i; + + for (i = 0; i < MAX_PDEV_CNT && soc->pdev_list[i]; i++) { + pdev = soc->pdev_list[i]; + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + if (vdev->vdev_id == vdev_id) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_INFO, + FL("Found vdev 0x%p on pdev %d\n"), + vdev, i); + return vdev; + } + } + } + return NULL; + +} +#endif #endif /* _DP_PEER_H_ */ diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index d775203ea2..a19ba70622 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -213,7 +213,60 @@ dp_rx_deliver_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf_list) } +#ifdef DP_LFR +/* + * In case of LFR, data of a new peer might be sent up + * even before peer is added. + */ +static inline struct dp_vdev * +dp_get_vdev_from_peer(struct dp_soc *soc, + uint16_t peer_id, + struct dp_peer *peer, + struct hal_rx_mpdu_desc_info mpdu_desc_info) +{ + struct dp_vdev *vdev; + uint8_t vdev_id; + if (unlikely(!peer)) { + if (peer_id != HTT_INVALID_PEER) { + vdev_id = DP_PEER_METADATA_ID_GET( + mpdu_desc_info.peer_meta_data); + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("PeerID %d not found use vdevID %d"), + peer_id, vdev_id); + vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, + vdev_id); + } else { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("Invalid PeerID %d"), + peer_id); + return NULL; + } + } else { + vdev = peer->vdev; + } + return vdev; +} +#else +static inline struct dp_vdev * +dp_get_vdev_from_peer(struct dp_soc *soc, + uint16_t peer_id, + struct dp_peer *peer, + struct hal_rx_mpdu_desc_info mpdu_desc_info) +{ + if (unlikely(!peer)) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("Peer not found for peerID %d"), + peer_id); + return NULL; + } else { + return peer->vdev; + } +} +#endif /** * dp_rx_intrabss_fwd() - Implements the Intra-BSS forwarding logic * @@ -474,17 +527,10 @@ dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) mpdu_desc_info.peer_meta_data); peer = dp_peer_find_by_id(soc, peer_id); - if (!peer) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - FL("peer look-up failed peer id %d"), peer_id); - /* Drop & free packet */ - qdf_nbuf_free(rx_desc->nbuf); - /* Statistics */ - goto fail; - } + vdev = dp_get_vdev_from_peer(soc, peer_id, peer, + mpdu_desc_info); - vdev = peer->vdev; if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("vdev is NULL")); @@ -595,7 +641,7 @@ done: * Cannot drop these packets right away. */ /* Peer lookup failed */ - if (!peer) { + if (!peer && !vdev) { /* Drop & free packet */ qdf_nbuf_free(nbuf); @@ -604,7 +650,7 @@ done: continue; } - if (qdf_unlikely(peer->bss_peer)) { + if (peer && qdf_unlikely(peer->bss_peer)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, FL("received pkt with same src MAC")); @@ -703,7 +749,8 @@ done: dp_rx_wds_srcport_learn(soc, rx_tlv_hdr, peer, nbuf); /* Intrabss-fwd */ - if (dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, nbuf)) + if (peer && + dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, nbuf)) continue; /* Get next descriptor */ rx_bufs_used++;