diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index 620513343129..5bd16a267db6 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -694,6 +695,33 @@ cdp_peer_delete(ol_txrx_soc_handle soc, uint8_t vdev_id, soc->ops->cmn_drv_ops->txrx_peer_delete(soc, vdev_id, peer_mac, bitmap); } +#ifdef DP_RX_UDP_OVER_PEER_ROAM +static inline void +cdp_update_roaming_peer_in_vdev(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, uint32_t auth_status) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->txrx_update_roaming_peer) + return; + + soc->ops->cmn_drv_ops->txrx_update_roaming_peer(soc, vdev_id, + peer_mac, auth_status); +} +#else +static inline void +cdp_update_roaming_peer_in_vdev(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, uint32_t auth_status) +{ +} +#endif + /** * cdp_peer_detach_sync() - peer detach sync callback * @soc: datapath soc handle diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 85589c1f2c6d..70f69eaa8582 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -558,6 +558,13 @@ struct cdp_cmn_ops { QDF_STATUS (*set_vdev_pcp_tid_map)(struct cdp_soc_t *soc, uint8_t vdev_id, uint8_t pcp, uint8_t tid); +#ifdef DP_RX_UDP_OVER_PEER_ROAM + QDF_STATUS (*txrx_update_roaming_peer)(struct cdp_soc_t *soc, + uint8_t vdev_id, + uint8_t *peer_mac, + uint32_t auth_status); +#endif + #ifdef QCA_MULTIPASS_SUPPORT QDF_STATUS (*set_vlan_groupkey)(struct cdp_soc_t *soc, uint8_t vdev_id, uint16_t vlan_id, uint16_t group_key); diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 4b50d78c5779..2e513c63c093 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -7267,6 +7267,26 @@ static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc_hdl, return QDF_STATUS_SUCCESS; } +#ifdef DP_RX_UDP_OVER_PEER_ROAM +static QDF_STATUS dp_update_roaming_peer_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + uint8_t *peer_mac, + uint32_t auth_status) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, + DP_MOD_ID_CDP); + if (!vdev) + return QDF_STATUS_E_FAILURE; + + vdev->roaming_peer_status = auth_status; + qdf_mem_copy(vdev->roaming_peer_mac.raw, peer_mac, + QDF_MAC_ADDR_SIZE); + dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); + + return QDF_STATUS_SUCCESS; +} +#endif /* * dp_get_vdev_mac_addr_wifi3() – Detach txrx peer * @soc_hdl: Datapath soc handle @@ -11332,6 +11352,9 @@ static struct cdp_cmn_ops dp_ops_cmn = { .txrx_peer_ast_delete_by_pdev = dp_peer_ast_entry_del_by_pdev, .txrx_peer_delete = dp_peer_delete_wifi3, +#ifdef DP_RX_UDP_OVER_PEER_ROAM + .txrx_update_roaming_peer = dp_update_roaming_peer_wifi3, +#endif .txrx_vdev_register = dp_vdev_register_wifi3, .txrx_soc_detach = dp_soc_detach_wifi3, .txrx_soc_deinit = dp_soc_deinit_wifi3, diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 1da11b1e418f..a94f385852f4 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -2095,6 +2095,26 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc, return NULL; } +#ifdef DP_RX_UDP_OVER_PEER_ROAM +void dp_rx_reset_roaming_peer(struct dp_soc *soc, uint8_t vdev_id, + uint8_t *peer_mac_addr) +{ + struct dp_vdev *vdev = NULL; + + vdev = dp_vdev_get_ref_by_id(soc, vdev_id, DP_MOD_ID_HTT); + if (vdev) { + if (qdf_mem_cmp(vdev->roaming_peer_mac.raw, peer_mac_addr, + QDF_MAC_ADDR_SIZE) == 0) { + vdev->roaming_peer_status = + WLAN_ROAM_PEER_AUTH_STATUS_NONE; + qdf_mem_zero(vdev->roaming_peer_mac.raw, + QDF_MAC_ADDR_SIZE); + } + dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_HTT); + } +} +#endif + /** * dp_rx_peer_map_handler() - handle peer map event from firmware * @soc_handle - genereic soc handle @@ -2188,6 +2208,8 @@ dp_rx_peer_map_handler(struct dp_soc *soc, uint16_t peer_id, vdev_id, ast_hash, is_wds); } + dp_rx_reset_roaming_peer(soc, vdev_id, peer_mac_addr); + return err; } diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index 75fff6f66df6..f31b16c27b64 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -542,6 +543,28 @@ dp_peer_update_state(struct dp_soc *soc, } void dp_print_ast_stats(struct dp_soc *soc); + +#ifdef DP_RX_UDP_OVER_PEER_ROAM +/** + * dp_rx_reset_roaming_peer() - Reset the roamed peer in vdev + * @soc - dp soc pointer + * @vdev_id - vdev id + * @peer_mac_addr - mac address of the peer + * + * This function resets the roamed peer auth status and mac address + * after peer map indication of same peer is received from firmware. + * + * Return: None + */ +void dp_rx_reset_roaming_peer(struct dp_soc *soc, uint8_t vdev_id, + uint8_t *peer_mac_addr); +#else +static inline void dp_rx_reset_roaming_peer(struct dp_soc *soc, uint8_t vdev_id, + uint8_t *peer_mac_addr) +{ +} +#endif + QDF_STATUS dp_rx_peer_map_handler(struct dp_soc *soc, uint16_t peer_id, uint16_t hw_peer_id, uint8_t vdev_id, uint8_t *peer_mac_addr, uint16_t ast_hash, diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 9fd2fe6c87d0..eebc90a648c0 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -2060,6 +2061,49 @@ static inline bool dp_rx_enable_eol_data_check(struct dp_soc *soc) #endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */ #ifdef DP_RX_PKT_NO_PEER_DELIVER +#ifdef DP_RX_UDP_OVER_PEER_ROAM +/** + * dp_rx_is_udp_allowed_over_roam_peer() - check if udp data received + * during roaming + * @vdev: dp_vdev pointer + * @rx_tlv_hdr: rx tlv header + * @nbuf: pkt skb pointer + * + * This function will check if rx udp data is received from authorised + * roamed peer before peer map indication is received from FW after + * roaming. This is needed for VoIP scenarios in which packet loss + * expected during roaming is minimal. + * + * Return: bool + */ +static bool dp_rx_is_udp_allowed_over_roam_peer(struct dp_vdev *vdev, + uint8_t *rx_tlv_hdr, + qdf_nbuf_t nbuf) +{ + char *hdr_desc; + struct ieee80211_frame *wh = NULL; + + hdr_desc = HAL_RX_DESC_GET_80211_HDR(rx_tlv_hdr); + wh = (struct ieee80211_frame *)hdr_desc; + + if (vdev->roaming_peer_status == + WLAN_ROAM_PEER_AUTH_STATUS_AUTHENTICATED && + !qdf_mem_cmp(vdev->roaming_peer_mac.raw, wh->i_addr2, + QDF_MAC_ADDR_SIZE) && (qdf_nbuf_is_ipv4_udp_pkt(nbuf) || + qdf_nbuf_is_ipv6_udp_pkt(nbuf))) + return true; + + return false; +} +#else +static bool dp_rx_is_udp_allowed_over_roam_peer(struct dp_vdev *vdev, + uint8_t *rx_tlv_hdr, + qdf_nbuf_t nbuf) +{ + return false; +} +#endif + /** * dp_rx_deliver_to_stack_no_peer() - try deliver rx data even if * no corresbonding peer found @@ -2110,7 +2154,8 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) RX_PKT_TLVS_LEN + l2_hdr_offset); - if (dp_rx_is_special_frame(nbuf, frame_mask)) { + if (dp_rx_is_special_frame(nbuf, frame_mask) || + dp_rx_is_udp_allowed_over_roam_peer(vdev, rx_tlv_hdr, nbuf)) { qdf_nbuf_set_exc_frame(nbuf, 1); if (QDF_STATUS_SUCCESS != vdev->osif_rx(vdev->osif_vdev, nbuf)) diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 68a3813027d5..8dd06f7b1efb 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -2542,6 +2542,15 @@ struct dp_pdev { struct dp_peer; +#ifdef DP_RX_UDP_OVER_PEER_ROAM +#define WLAN_ROAM_PEER_AUTH_STATUS_NONE 0x0 +/** + * This macro is equivalent to macro ROAM_AUTH_STATUS_AUTHENTICATED used + * in connection mgr + */ +#define WLAN_ROAM_PEER_AUTH_STATUS_AUTHENTICATED 0x2 +#endif + /* VDEV structure for data path state */ struct dp_vdev { /* OS device abstraction */ @@ -2787,7 +2796,6 @@ struct dp_vdev { qdf_atomic_t ref_cnt; qdf_atomic_t mod_refs[DP_MOD_ID_MAX]; uint8_t num_latency_critical_conn; - #ifdef WLAN_FEATURE_TSF_UPLINK_DELAY /* Indicate if uplink delay report is enabled or not */ qdf_atomic_t ul_delay_report; @@ -2798,6 +2806,11 @@ struct dp_vdev { /* accumulative number of packets delay has accumulated */ qdf_atomic_t ul_pkts_accum; #endif /* WLAN_FEATURE_TSF_UPLINK_DELAY */ + +#ifdef DP_RX_UDP_OVER_PEER_ROAM + uint32_t roaming_peer_status; + union dp_align_mac_addr roaming_peer_mac; +#endif }; enum {