diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index c489f143c10f..b33e8a7b8c85 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -2688,7 +2688,8 @@ cdp_wds_ext_get_peer_id(ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *mac) static inline QDF_STATUS cdp_wds_ext_set_peer_rx(ol_txrx_soc_handle soc, uint8_t vdev_id, - uint8_t *mac, ol_txrx_rx_fp rx) + uint8_t *mac, ol_txrx_rx_fp rx, + ol_osif_peer_handle osif_peer) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -2702,7 +2703,7 @@ cdp_wds_ext_set_peer_rx(ol_txrx_soc_handle soc, uint8_t vdev_id, return QDF_STATUS_E_FAULT; return soc->ops->cmn_drv_ops->set_wds_ext_peer_rx - (soc, vdev_id, mac, rx); + (soc, vdev_id, mac, rx, osif_peer); } #endif /* QCA_SUPPORT_WDS_EXTENDED */ #endif /* _CDP_TXRX_CMN_H_ */ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index e5dda324cac2..c0d445f1552a 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -563,7 +563,8 @@ struct cdp_cmn_ops { QDF_STATUS (*set_wds_ext_peer_rx)(ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *mac, - ol_txrx_rx_fp rx); + ol_txrx_rx_fp rx, + ol_osif_peer_handle osif_peer); #endif /* QCA_SUPPORT_WDS_EXTENDED */ }; diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 82964fc3706f..e1d017b3e2b6 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -2487,7 +2487,8 @@ uint16_t dp_wds_ext_get_peer_id(ol_txrx_soc_handle soc, QDF_STATUS dp_wds_ext_set_peer_rx(ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *mac, - ol_txrx_rx_fp rx); + ol_txrx_rx_fp rx, + ol_osif_peer_handle osif_peer); #endif /* QCA_SUPPORT_WDS_EXTENDED */ #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 1d9e3a61887d..dc3c79f2952b 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -12573,7 +12573,8 @@ uint16_t dp_wds_ext_get_peer_id(ol_txrx_soc_handle soc, QDF_STATUS dp_wds_ext_set_peer_rx(ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *mac, - ol_txrx_rx_fp rx) + ol_txrx_rx_fp rx, + ol_osif_peer_handle osif_peer) { struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc, mac, 0, vdev_id, @@ -12602,6 +12603,7 @@ QDF_STATUS dp_wds_ext_set_peer_rx(ol_txrx_soc_handle soc, } } + peer->wds_ext.osif_peer = osif_peer; dp_peer_unref_delete(peer, DP_MOD_ID_CDP); return status; diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index df9fc01f6d6c..71fdfaf65132 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -1340,6 +1340,89 @@ static inline int dp_rx_drop_nbuf_list(struct dp_pdev *pdev, return num_dropped; } +#ifdef QCA_SUPPORT_WDS_EXTENDED +/** + * dp_rx_wds_ext() - Make different lists for 4-address and 3-address frames + * @nbuf_head: skb list head + * @vdev: vdev + * @peer: peer + * @peer_id: peer id of new received frame + * @vdev_id: vdev_id of new received frame + * + * Return: true if peer_ids are different. + */ +static inline bool +dp_rx_is_list_ready(qdf_nbuf_t nbuf_head, + struct dp_vdev *vdev, + struct dp_peer *peer, + uint16_t peer_id, + uint8_t vdev_id) +{ + if (nbuf_head && peer && (peer->peer_id != peer_id)) + return true; + + return false; +} + +/** + * dp_rx_deliver_to_stack_ext() - Deliver to netdev per sta + * @soc: core txrx main context + * @vdev: vdev + * @peer: peer + * @nbuf_head: skb list head + * + * Return: true if packet is delivered to netdev per STA. + */ +static inline bool +dp_rx_deliver_to_stack_ext(struct dp_soc *soc, struct dp_vdev *vdev, + struct dp_peer *peer, qdf_nbuf_t nbuf_head) +{ + /* + * When extended WDS is disabled, frames are sent to AP netdevice. + */ + if (qdf_likely(!vdev->wds_ext_enabled)) + return false; + + /* + * There can be 2 cases: + * 1. Send frame to parent netdev if its not for netdev per STA + * 2. If frame is meant for netdev per STA: + * a. Send frame to appropriate netdev using registered fp. + * b. If fp is NULL, drop the frames. + */ + if (!peer->wds_ext.init) + return false; + + if (peer->osif_rx) + peer->osif_rx(peer->wds_ext.osif_peer, nbuf_head); + else + dp_rx_drop_nbuf_list(vdev->pdev, nbuf_head); + + return true; +} + +#else +static inline bool +dp_rx_is_list_ready(qdf_nbuf_t nbuf_head, + struct dp_vdev *vdev, + struct dp_peer *peer, + uint16_t peer_id, + uint8_t vdev_id) +{ + if (nbuf_head && vdev && (vdev->vdev_id != vdev_id)) + return true; + + return false; +} + +static inline bool +dp_rx_deliver_to_stack_ext(struct dp_soc *soc, struct dp_vdev *vdev, + struct dp_peer *peer, qdf_nbuf_t nbuf_head) +{ + return false; +} +#endif + #ifdef PEER_CACHE_RX_PKTS /** * dp_rx_flush_rx_cached() - flush cached rx frames @@ -1488,6 +1571,10 @@ static void dp_rx_check_delivery_to_stack(struct dp_soc *soc, struct dp_peer *peer, qdf_nbuf_t nbuf_head) { + if (qdf_unlikely(dp_rx_deliver_to_stack_ext(soc, vdev, + peer, nbuf_head))) + return; + /* Function pointer initialized only when FISA is enabled */ if (vdev->osif_fisa_rx) /* on failure send it via regular path */ @@ -2444,8 +2531,10 @@ done: rx_tlv_hdr = qdf_nbuf_data(nbuf); vdev_id = QDF_NBUF_CB_RX_VDEV_ID(nbuf); + peer_id = QDF_NBUF_CB_RX_PEER_ID(nbuf); - if (deliver_list_head && vdev && (vdev->vdev_id != vdev_id)) { + if (dp_rx_is_list_ready(deliver_list_head, vdev, peer, + peer_id, vdev_id)) { dp_rx_deliver_to_stack(soc, vdev, peer, deliver_list_head, deliver_list_tail); @@ -2457,8 +2546,6 @@ done: if (qdf_nbuf_is_rx_chfrag_start(nbuf)) tid = qdf_nbuf_get_tid_val(nbuf); - peer_id = QDF_NBUF_CB_RX_PEER_ID(nbuf); - if (qdf_unlikely(!peer)) { peer = dp_peer_get_ref_by_id(soc, peer_id, DP_MOD_ID_RX); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index cd1cfb92076c..062ca807b763 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -2636,7 +2636,7 @@ struct dp_peer_mscs_parameter { * @init: wds ext netdev state */ struct dp_wds_ext_peer { - ol_osif_vdev_handle osif_vdev; + ol_osif_peer_handle osif_peer; unsigned long init; }; #endif /* QCA_SUPPORT_WDS_EXTENDED */