diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index 6dcd25b905..40ad6857e9 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -2992,6 +2992,28 @@ cdp_wds_ext_get_peer_osif_handle( (soc, vdev_id, mac, osif_peer); } +/** + * cdp_wds_ext_set_bit() - set wds-ext peer bit + * @soc: soc handle + * @mac: peer mac address + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_wds_ext_set_bit(ol_txrx_soc_handle soc, uint8_t *mac) +{ + if (!soc || !soc->ops) { + dp_cdp_debug("Invalid Instance"); + QDF_BUG(0); + return QDF_STATUS_E_FAULT; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->set_wds_ext_peer_bit) + return QDF_STATUS_E_FAULT; + + return soc->ops->cmn_drv_ops->set_wds_ext_peer_bit(soc, mac); +} #endif /* QCA_SUPPORT_WDS_EXTENDED */ /** diff --git a/dp/inc/cdp_txrx_ipa.h b/dp/inc/cdp_txrx_ipa.h index 48ad93adda..979f6ecad9 100644 --- a/dp/inc/cdp_txrx_ipa.h +++ b/dp/inc/cdp_txrx_ipa.h @@ -650,6 +650,33 @@ cdp_ipa_set_perf_level(ol_txrx_soc_handle soc, int client, return QDF_STATUS_SUCCESS; } +#ifdef QCA_SUPPORT_WDS_EXTENDED +/** + * cdp_ipa_rx_wdsext_iface() - Forward RX exception packets to wdsext interface + * @soc: data path soc handle + * @peer_id: Peer id to get respective peer + * @skb: socket buffer + * + * Return: true if packets sent to wds ext interface, else false. + */ +static inline bool +cdp_ipa_rx_wdsext_iface(ol_txrx_soc_handle soc, uint8_t peer_id, + qdf_nbuf_t skb) +{ + if (!soc || !soc->ops || !soc->ops->ipa_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return false; + } + + if (soc->ops->ipa_ops->ipa_rx_wdsext_iface) + return soc->ops->ipa_ops->ipa_rx_wdsext_iface(soc, peer_id, + skb); + + return false; +} +#endif + /** * cdp_ipa_rx_intrabss_fwd() - Perform intra-bss fwd for IPA RX path * diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 447cdc7bc6..cc617e000d 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -710,6 +710,8 @@ struct cdp_cmn_ops { uint8_t vdev_id, uint8_t *mac, ol_osif_peer_handle *osif_peer); + QDF_STATUS (*set_wds_ext_peer_bit)(ol_txrx_soc_handle soc, + uint8_t *mac); #endif /* QCA_SUPPORT_WDS_EXTENDED */ void (*txrx_drain)(ol_txrx_soc_handle soc); int (*get_free_desc_poolsize)(struct cdp_soc_t *soc); @@ -2204,6 +2206,7 @@ struct cdp_throttle_ops { * @ipa_rx_buf_smmu_pool_mapping: Create SMMU mapping for Rx * @ipa_set_smmu_mapped: Set IPA SMMU mapped value * @ipa_get_smmu_mapped: Get IPA SMMU mapped value + * @ipa_rx_wdsext_iface: Forward RX exception packets to wdsext interface * @ipa_rx_super_rule_setup: Setup cce super rules based on filter tuple * @ipa_ast_create: Create/Update ast entry * @ipa_get_wdi_version: Get WDI version @@ -2308,6 +2311,11 @@ struct cdp_ipa_ops { QDF_STATUS (*ipa_set_smmu_mapped)(struct cdp_soc_t *soc_hdl, int val); int (*ipa_get_smmu_mapped)(struct cdp_soc_t *soc_hdl); +#ifdef QCA_SUPPORT_WDS_EXTENDED + bool (*ipa_rx_wdsext_iface)(struct cdp_soc_t *soc_hdl, + uint8_t peer_id, + qdf_nbuf_t nbuf_head); +#endif #ifdef IPA_OPT_WIFI_DP QDF_STATUS (*ipa_rx_super_rule_setup)(struct cdp_soc_t *soc_hdl, void *flt_params); diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 57db8d39fc..28228f7fb4 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -4416,6 +4416,16 @@ QDF_STATUS dp_wds_ext_get_peer_osif_handle( uint8_t *mac, ol_osif_peer_handle *osif_peer); +/** + * dp_wds_ext_set_peer_bit(): function to set wds-ext peer bit + * @soc: Datapath soc handle + * @mac: Peer mac address + * + * Return: QDF_STATUS_SUCCESS on success + * QDF_STATUS_E_INVAL if peer is not found + */ +QDF_STATUS dp_wds_ext_set_peer_bit(ol_txrx_soc_handle soc, uint8_t *mac); + #endif /* QCA_SUPPORT_WDS_EXTENDED */ #ifdef DP_MEM_PRE_ALLOC diff --git a/dp/wifi3.0/dp_ipa.c b/dp/wifi3.0/dp_ipa.c index f068f0fa75..f303c66a48 100644 --- a/dp/wifi3.0/dp_ipa.c +++ b/dp/wifi3.0/dp_ipa.c @@ -3560,6 +3560,37 @@ QDF_STATUS dp_ipa_set_perf_level(int client, uint32_t max_supported_bw_mbps, return QDF_STATUS_SUCCESS; } +#ifdef QCA_SUPPORT_WDS_EXTENDED +/** + * dp_ipa_rx_wdsext_iface() - Forward RX exception packets to wdsext interface + * @soc_hdl: data path soc handle + * @peer_id: Peer id to get respective peer + * @skb: socket buffer + * + * Return: true on success, else false + */ +bool dp_ipa_rx_wdsext_iface(struct cdp_soc_t *soc_hdl, uint8_t peer_id, + qdf_nbuf_t skb) +{ + struct dp_txrx_peer *txrx_peer; + dp_txrx_ref_handle txrx_ref_handle = NULL; + struct dp_soc *dp_soc = cdp_soc_t_to_dp_soc(soc_hdl); + bool status = false; + + txrx_peer = dp_tgt_txrx_peer_get_ref_by_id(soc_hdl, peer_id, + &txrx_ref_handle, + DP_MOD_ID_IPA); + + if (qdf_likely(txrx_peer)) { + if (dp_rx_deliver_to_stack_ext(dp_soc, txrx_peer->vdev, + txrx_peer, skb) + status = true; + dp_txrx_peer_unref_delete(txrx_ref_handle, DP_MOD_ID_IPA); + } + return status; +} +#endif + /** * dp_ipa_intrabss_send() - send IPA RX intra-bss frames * @pdev: pdev diff --git a/dp/wifi3.0/dp_ipa.h b/dp/wifi3.0/dp_ipa.h index 998620aa80..2d96dea0a1 100644 --- a/dp/wifi3.0/dp_ipa.h +++ b/dp/wifi3.0/dp_ipa.h @@ -362,6 +362,19 @@ int dp_ipa_pcie_link_up(struct cdp_soc_t *soc_hdl); void dp_ipa_pcie_link_down(struct cdp_soc_t *soc_hdl); #endif +#ifdef QCA_SUPPORT_WDS_EXTENDED +/** + * dp_ipa_rx_wdsext_iface() - Forward RX exception packets to wdsext interface + * @soc_hdl: data path SoC handle + * @peer_id: Peer ID to get respective peer + * @skb: socket buffer + * + * Return: bool + */ +bool dp_ipa_rx_wdsext_iface(struct cdp_soc_t *soc_hdl, uint8_t peer_id, + qdf_nbuf_t skb); +#endif + /** * dp_ipa_rx_intrabss_fwd() - Perform intra-bss fwd for IPA RX path * diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 9cfafdb351..7566c91a3d 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -12272,6 +12272,7 @@ static struct cdp_cmn_ops dp_ops_cmn = { #ifdef QCA_SUPPORT_WDS_EXTENDED .set_wds_ext_peer_rx = dp_wds_ext_set_peer_rx, .get_wds_ext_peer_osif_handle = dp_wds_ext_get_peer_osif_handle, + .set_wds_ext_peer_bit = dp_wds_ext_set_peer_bit, #endif /* QCA_SUPPORT_WDS_EXTENDED */ #if defined(FEATURE_RUNTIME_PM) || defined(DP_POWER_SAVE) @@ -13142,6 +13143,9 @@ static struct cdp_ipa_ops dp_ops_ipa = { .ipa_rx_buf_smmu_pool_mapping = dp_ipa_rx_buf_pool_smmu_mapping, .ipa_set_smmu_mapped = dp_ipa_set_smmu_mapped, .ipa_get_smmu_mapped = dp_ipa_get_smmu_mapped, +#ifdef QCA_SUPPORT_WDS_EXTENDED + .ipa_rx_wdsext_iface = dp_ipa_rx_wdsext_iface, +#endif #ifdef QCA_ENHANCED_STATS_SUPPORT .ipa_update_peer_rx_stats = dp_ipa_update_peer_rx_stats, #endif @@ -14046,6 +14050,29 @@ QDF_STATUS dp_wds_ext_get_peer_osif_handle( return QDF_STATUS_SUCCESS; } + +QDF_STATUS dp_wds_ext_set_peer_bit(ol_txrx_soc_handle soc, uint8_t *mac) +{ + struct dp_txrx_peer *txrx_peer = NULL; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc, + mac, 0, DP_VDEV_ALL, + DP_MOD_ID_IPA); + if (!peer) { + dp_cdp_debug("%pK: Peer is NULL!\n", (struct dp_soc *)soc); + return QDF_STATUS_E_INVAL; + } + + txrx_peer = dp_get_txrx_peer(peer); + if (!txrx_peer) { + dp_peer_unref_delete(peer, DP_MOD_ID_IPA); + return QDF_STATUS_E_INVAL; + } + qdf_atomic_test_and_set_bit(WDS_EXT_PEER_INIT_BIT, + &txrx_peer->wds_ext.init); + dp_peer_unref_delete(peer, DP_MOD_ID_IPA); + + return QDF_STATUS_SUCCESS; +} #endif /* QCA_SUPPORT_WDS_EXTENDED */ /** diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index cc4febdd7b..17be69d840 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -2013,7 +2013,7 @@ static inline int dp_rx_drop_nbuf_list(struct dp_pdev *pdev, * * Return: true if packet is delivered to netdev per STA. */ -static inline bool +bool dp_rx_deliver_to_stack_ext(struct dp_soc *soc, struct dp_vdev *vdev, struct dp_txrx_peer *txrx_peer, qdf_nbuf_t nbuf_head) { diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 98756fe924..bd2c7badb1 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -3478,6 +3478,20 @@ dp_rx_is_list_ready(qdf_nbuf_t nbuf_head, return false; } + +/** + * dp_rx_deliver_to_stack_ext() - Deliver to netdev per sta + * @soc: core txrx main context + * @vdev: vdev + * @txrx_peer: txrx peer + * @nbuf_head: skb list head + * + * Return: true if packet is delivered to netdev per STA. + */ +bool +dp_rx_deliver_to_stack_ext(struct dp_soc *soc, struct dp_vdev *vdev, + struct dp_txrx_peer *txrx_peer, + qdf_nbuf_t nbuf_head); #else static inline bool dp_rx_is_list_ready(qdf_nbuf_t nbuf_head, diff --git a/ipa/core/inc/wlan_ipa_core.h b/ipa/core/inc/wlan_ipa_core.h index 0b381cacce..b3895c0015 100644 --- a/ipa/core/inc/wlan_ipa_core.h +++ b/ipa/core/inc/wlan_ipa_core.h @@ -25,6 +25,7 @@ #include "wlan_ipa_priv.h" #include "wlan_ipa_public_struct.h" +#define WLAN_IPA_NBUF_CB_PEER_ID_OFFSET 5 /** * wlan_ipa_is_enabled() - Is IPA enabled? * @ipa_cfg: IPA config diff --git a/ipa/core/src/wlan_ipa_core.c b/ipa/core/src/wlan_ipa_core.c index beda48c538..ad3ab9d5aa 100644 --- a/ipa/core/src/wlan_ipa_core.c +++ b/ipa/core/src/wlan_ipa_core.c @@ -1298,9 +1298,11 @@ wlan_ipa_send_to_nw_queue(struct wlan_ipa_iface_context *iface_ctx, } #endif /* QCA_IPA_LL_TX_FLOW_CONTROL */ +#if defined(IPA_OFFLOAD) && defined(QCA_SUPPORT_WDS_EXTENDED) /** * wlan_ipa_send_skb_to_network() - Send skb to kernel * @skb: network buffer + * @peer_id: Peer id to get respective peer * @iface_ctx: IPA interface context * * Called when a network buffer is received which should not be routed @@ -1309,7 +1311,46 @@ wlan_ipa_send_to_nw_queue(struct wlan_ipa_iface_context *iface_ctx, * Return: None */ static void -wlan_ipa_send_skb_to_network(qdf_nbuf_t skb, +wlan_ipa_send_skb_to_network(qdf_nbuf_t skb, uint8_t peer_id, + struct wlan_ipa_iface_context *iface_ctx) +{ + struct wlan_ipa_priv *ipa_ctx; + + ipa_ctx = iface_ctx->ipa_ctx; + + if (!iface_ctx->dev) { + ipa_debug_rl("Invalid interface"); + ipa_ctx->ipa_rx_internal_drop_count++; + dev_kfree_skb_any(skb); + return; + } + + skb->destructor = wlan_ipa_uc_rt_debug_destructor; + + if (wlan_ipa_send_to_nw_defer(iface_ctx, skb)) { + wlan_ipa_send_to_nw_queue(iface_ctx, skb); + } else { + if (!cdp_ipa_rx_wdsext_iface(ipa_ctx->dp_soc, peer_id, skb)) { + if (ipa_ctx->send_to_nw) + ipa_ctx->send_to_nw(skb, iface_ctx->dev); + } + ipa_ctx->ipa_rx_net_send_count++; + } +} +#else +/** + * wlan_ipa_send_skb_to_network() - Send skb to kernel + * @skb: network buffer + * @peer_id: Peer id to get respective peer + * @iface_ctx: IPA interface context + * + * Called when a network buffer is received which should not be routed + * to the IPA module. + * + * Return: None + */ +static void +wlan_ipa_send_skb_to_network(qdf_nbuf_t skb, uint8_t peer_id, struct wlan_ipa_iface_context *iface_ctx) { struct wlan_ipa_priv *ipa_ctx; @@ -1334,6 +1375,7 @@ wlan_ipa_send_skb_to_network(qdf_nbuf_t skb, ipa_ctx->ipa_rx_net_send_count++; } } +#endif /** * wlan_ipa_eapol_intrabss_fwd_check() - Check if eapol pkt intrabss fwd is @@ -1550,6 +1592,7 @@ static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt, struct wlan_ipa_iface_context *iface_context; bool is_eapol_wapi = false; struct qdf_mac_addr peer_mac_addr = QDF_MAC_ADDR_ZERO_INIT; + uint8_t peer_id; ipa_ctx = (struct wlan_ipa_priv *)priv; if (!ipa_ctx) { @@ -1668,7 +1711,8 @@ static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt, iface_context->session_id); } - wlan_ipa_send_skb_to_network(skb, iface_context); + peer_id = (uint8_t)skb->cb[WLAN_IPA_NBUF_CB_PEER_ID_OFFSET]; + wlan_ipa_send_skb_to_network(skb, peer_id, iface_context); break; default: