From b64de0cf4a6e7eb96a50234ed34293d231cfcf7f Mon Sep 17 00:00:00 2001 From: Gaurav Saini Date: Mon, 11 Sep 2023 14:34:54 +0530 Subject: [PATCH] qcacmn: Handle RX exception from IPA on WDS-EXT netdev When WDS_EXT feature is enable, Host needs to redirect the data packets to WDS extended netdevice. Change is added the support for forwarding the RX packets when received from IPA as an exception by deriving the correct netdevice interface. Change-Id: I083a1acc72023f3ebe6ea36ec05a5706f89c16bc CRs-Fixed: 3597357 --- dp/inc/cdp_txrx_cmn.h | 22 +++++++++++++++++ dp/inc/cdp_txrx_ipa.h | 27 ++++++++++++++++++++ dp/inc/cdp_txrx_ops.h | 8 ++++++ dp/wifi3.0/dp_internal.h | 10 ++++++++ dp/wifi3.0/dp_ipa.c | 31 +++++++++++++++++++++++ dp/wifi3.0/dp_ipa.h | 13 ++++++++++ dp/wifi3.0/dp_main.c | 27 ++++++++++++++++++++ dp/wifi3.0/dp_rx.c | 2 +- dp/wifi3.0/dp_rx.h | 14 +++++++++++ ipa/core/inc/wlan_ipa_core.h | 1 + ipa/core/src/wlan_ipa_core.c | 48 ++++++++++++++++++++++++++++++++++-- 11 files changed, 200 insertions(+), 3 deletions(-) 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: