diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index 574216a1be..787c7a4f61 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -1500,6 +1500,7 @@ cdp_get_peer_mac_addr_frm_id(ol_txrx_soc_handle soc, uint16_t peer_id, /** * cdp_set_vdev_dscp_tid_map(): function to set DSCP-tid map in the vap + * @soc : soc handle * @vdev: vdev handle * @map_id: id of the tid map * @@ -1523,6 +1524,36 @@ static inline void cdp_set_vdev_dscp_tid_map(ol_txrx_soc_handle soc, map_id); } +#ifdef QCA_MULTIPASS_SUPPORT +/** + * cdp_set_vlan_groupkey(): function to set vlan ID - group key map in the vap + * @soc : soc handle + * @vdev: vdev handle + * @vlan_id: vlan id + * @group_key: corresponding group key to vlan ID + * + * Return: void + */ +static inline +QDF_STATUS cdp_set_vlan_groupkey(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, + uint16_t vlan_id, uint16_t group_key) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return 0; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->set_vlan_groupkey) + return 0; + + return soc->ops->cmn_drv_ops->set_vlan_groupkey(vdev, vlan_id, + group_key); +} +#endif + /** * cdp_ath_get_total_per(): function to get hw retries * @soc : soc handle diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 537cb3135a..aea884c06c 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -936,7 +936,8 @@ enum cdp_vdev_param_type { CDP_CFG_WDS_AGING_TIMER, CDP_ENABLE_AP_BRIDGE, CDP_ENABLE_CIPHER, - CDP_ENABLE_QWRAP_ISOLATION + CDP_ENABLE_QWRAP_ISOLATION, + CDP_UPDATE_MULTIPASS }; #define TXRX_FW_STATS_TXSTATS 1 diff --git a/dp/inc/cdp_txrx_ctrl.h b/dp/inc/cdp_txrx_ctrl.h index 187ab87daf..36090e797e 100644 --- a/dp/inc/cdp_txrx_ctrl.h +++ b/dp/inc/cdp_txrx_ctrl.h @@ -467,6 +467,26 @@ cdp_peer_set_nawds(ol_txrx_soc_handle soc, (peer, value); } +#ifdef QCA_MULTIPASS_SUPPORT +static inline void +cdp_peer_set_vlan_id(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, + uint8_t *peer_mac, uint8_t vlan_id) +{ + 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->ctrl_ops || + !soc->ops->ctrl_ops->txrx_peer_set_vlan_id) + return; + + soc->ops->ctrl_ops->txrx_peer_set_vlan_id(soc, vdev, peer_mac, vlan_id); +} +#endif + /** * cdp_txrx_set_pdev_param() - set pdev parameter * @soc: opaque soc handle diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 710a3a316c..11faeb0e25 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -466,6 +466,10 @@ struct cdp_cmn_ops { QDF_STATUS (*set_vdev_tidmap_prty)(struct cdp_vdev *vdev, uint8_t prty); QDF_STATUS (*set_vdev_tidmap_tbl_id)(struct cdp_vdev *vdev, uint8_t mapid); +#ifdef QCA_MULTIPASS_SUPPORT + QDF_STATUS (*set_vlan_groupkey)(struct cdp_vdev *vdev_handle, + uint16_t vlan_id, uint16_t group_key); +#endif }; struct cdp_ctrl_ops { @@ -664,6 +668,11 @@ struct cdp_ctrl_ops { uint16_t protocol_type); #endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */ #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ +#ifdef QCA_MULTIPASS_SUPPORT + void (*txrx_peer_set_vlan_id)(ol_txrx_soc_handle soc, + struct cdp_vdev *vdev, uint8_t *peer_mac, + uint16_t vlan_id); +#endif }; struct cdp_me_ops { diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 9dc9c28361..c3ddff4d13 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -4663,6 +4663,7 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev, */ TAILQ_INIT(&vdev->peer_list); + dp_peer_multipass_list_init(vdev); if ((soc->intr_mode == DP_INTR_POLL) && wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx) != 0) { @@ -5913,6 +5914,7 @@ static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap) dp_peer_rx_bufq_resources_deinit(peer); qdf_spinlock_destroy(&peer->peer_info_lock); + dp_peer_multipass_list_remove(peer); /* * Remove the reference added during peer_attach. @@ -7654,6 +7656,9 @@ static void dp_set_vdev_param(struct cdp_vdev *vdev_handle, case CDP_ENABLE_QWRAP_ISOLATION: vdev->isolation_vdev = val; break; + case CDP_UPDATE_MULTIPASS: + vdev->multipass_en = val; + break; default: break; } @@ -9019,6 +9024,9 @@ static struct cdp_cmn_ops dp_ops_cmn = { .set_vdev_tidmap_tbl_id = dp_set_vdev_tidmap_tbl_id_wifi3, .txrx_cp_peer_del_response = dp_cp_peer_del_resp_handler, +#ifdef QCA_MULTIPASS_SUPPORT + .set_vlan_groupkey = dp_set_vlan_groupkey, +#endif }; static struct cdp_ctrl_ops dp_ops_ctrl = { @@ -9059,6 +9067,9 @@ static struct cdp_ctrl_ops dp_ops_ctrl = { dp_dump_pdev_rx_protocol_tag_stats, #endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */ #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ +#ifdef QCA_MULTIPASS_SUPPORT + .txrx_peer_set_vlan_id = dp_peer_set_vlan_id, +#endif /*QCA_MULTIPASS_SUPPORT*/ }; static struct cdp_me_ops dp_ops_me = { diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index fca020c685..0ab8c9e6b3 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -212,4 +212,66 @@ void dp_peer_update_inactive_time(struct dp_pdev *pdev, uint32_t tag_type, uint32_t *tag_buf); +#ifndef QCA_MULTIPASS_SUPPORT +/** + * dp_peer_set_vlan_id: set vlan_id for this peer + * @cdp_soc: soc handle + * @peer_mac: mac address + * @vlan_id: vlan id for peer + * + * return: void + */ +static inline +void dp_peer_set_vlan_id(struct cdp_soc_t *cdp_soc, + struct cdp_vdev *vdev_handle, uint8_t *peer_mac, + uint16_t vlan_id) +{ +} + +/** + * dp_set_vlan_groupkey: set vlan map for vdev + * @vdev_handle: pointer to vdev + * @vlan_id: vlan_id + * @group_key: group key for vlan + * + * return: set success/failure + */ +static inline +QDF_STATUS dp_set_vlan_groupkey(struct cdp_vdev *vdev_handle, + uint16_t vlan_id, uint16_t group_key) +{ + return QDF_STATUS_SUCCESS; +} + +/** + * dp_peer_multipass_list_init: initialize multipass peer list + * @vdev: pointer to vdev + * + * return: void + */ +static inline +void dp_peer_multipass_list_init(struct dp_vdev *vdev) +{ +} + +/** + * dp_peer_multipass_list_remove: remove peer from special peer list + * @peer: peer handle + * + * return: void + */ +static inline +void dp_peer_multipass_list_remove(struct dp_peer *peer) +{ +} +#else +void dp_peer_set_vlan_id(struct cdp_soc_t *cdp_soc, + struct cdp_vdev *vdev_handle, uint8_t *peer_mac, + uint16_t vlan_id); +QDF_STATUS dp_set_vlan_groupkey(struct cdp_vdev *vdev_handle, + uint16_t vlan_id, uint16_t group_key); +void dp_peer_multipass_list_init(struct dp_vdev *vdev); +void dp_peer_multipass_list_remove(struct dp_peer *peer); +#endif + #endif /* _DP_PEER_H_ */ diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index b08d9537a0..73f64088da 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -2025,6 +2025,13 @@ done: l2_hdr_offset); } + /* + * process frame for mulitpass phrase processing + */ + if (qdf_unlikely(vdev->multipass_en)) { + dp_rx_multipass_process(peer, nbuf, tid); + } + if (!dp_wds_rx_policy_check(rx_tlv_hdr, vdev, peer)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index b3602cb42b..e90ffc2535 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -1255,4 +1255,16 @@ static inline void dp_rx_flush_rx_cached(struct dp_peer *peer, bool drop) { } #endif + +#ifndef QCA_MULTIPASS_SUPPORT +static inline +bool dp_rx_multipass_process(struct dp_peer *peer, qdf_nbuf_t nbuf, uint8_t tid) +{ + return false; +} +#else +bool dp_rx_multipass_process(struct dp_peer *peer, qdf_nbuf_t nbuf, + uint8_t tid); +#endif + #endif /* _DP_RX_H */ diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index bf55f037f3..fe507f6fee 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -303,8 +303,8 @@ dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id) * Return: HTT metadata size * */ -static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf, - struct dp_tx_msdu_info_s *msdu_info) +uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info) { uint32_t *meta_data = msdu_info->meta_data; struct htt_tx_msdu_desc_ext2_t *desc_ext = @@ -323,12 +323,26 @@ static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf, htt_desc_size = sizeof(struct htt_tx_msdu_desc_ext2_t); htt_desc_size_aligned = (htt_desc_size + 7) & ~0x7; - if (vdev->mesh_vdev || msdu_info->is_tx_sniffer) { + if (vdev->mesh_vdev || msdu_info->is_tx_sniffer || + HTT_TX_MSDU_EXT2_DESC_FLAG_VALID_KEY_FLAGS_GET(msdu_info-> + meta_data[0])) { if (qdf_unlikely(qdf_nbuf_headroom(nbuf) < - htt_desc_size_aligned)) { - DP_STATS_INC(vdev, - tx_i.dropped.headroom_insufficient, 1); - return 0; + htt_desc_size_aligned)) { + nbuf = qdf_nbuf_realloc_headroom(nbuf, + htt_desc_size_aligned); + if (!nbuf) { + /* + * qdf_nbuf_realloc_headroom won't do skb_clone + * as skb_realloc_headroom does. so, no free is + * needed here. + */ + DP_STATS_INC(vdev, + tx_i.dropped.headroom_insufficient, + 1); + qdf_print(" %s[%d] skb_realloc_headroom failed", + __func__, __LINE__); + return 0; + } } /* Fill and add HTT metaheader */ hdr = qdf_nbuf_push_head(nbuf, htt_desc_size_aligned); @@ -746,6 +760,11 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, dp_tx_trace_pkt(nbuf, tx_desc->id, vdev->vdev_id); + if (qdf_unlikely(vdev->multipass_en)) { + if (!dp_tx_multipass_process(soc, vdev, nbuf, msdu_info)) + goto failure; + } + /* * For special modes (vdev_type == ocb or mesh), data frames should be * transmitted using varying transmit parameters (tx spec) which include @@ -3805,6 +3824,7 @@ QDF_STATUS dp_tx_vdev_detach(struct dp_vdev *vdev) /* Reset TX desc associated to this Vdev as NULL */ dp_tx_desc_flush(pdev, vdev, false); + dp_tx_vdev_multipass_deinit(vdev); return QDF_STATUS_SUCCESS; } diff --git a/dp/wifi3.0/dp_tx.h b/dp/wifi3.0/dp_tx.h index a5305429f3..f00006fa56 100644 --- a/dp/wifi3.0/dp_tx.h +++ b/dp/wifi3.0/dp_tx.h @@ -237,6 +237,29 @@ static inline void dp_tx_me_exit(struct dp_pdev *pdev) return; } #endif + +#ifndef QCA_MULTIPASS_SUPPORT +static inline +bool dp_tx_multipass_process(struct dp_soc *soc, struct dp_vdev *vdev, + qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info) +{ + return true; +} + +static inline +void dp_tx_vdev_multipass_deinit(struct dp_vdev *vdev) +{ +} + +#else +bool dp_tx_multipass_process(struct dp_soc *soc, struct dp_vdev *vdev, + qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info); + +void dp_tx_vdev_multipass_deinit(struct dp_vdev *vdev); +#endif + /** * dp_tx_get_queue() - Returns Tx queue IDs to be used for this Tx frame * @vdev: DP Virtual device handle @@ -310,3 +333,5 @@ static inline void dp_tx_comp_process_exception(struct dp_tx_desc_s *tx_desc) } /* TODO TX_FEATURE_NOT_YET */ #endif +uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 0d33587e3c..6d5c2286d8 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1817,6 +1817,14 @@ struct dp_vdev { uint8_t tidmap_prty; /* Self Peer in STA mode */ struct dp_peer *vap_self_peer; + + bool multipass_en; +#ifdef QCA_MULTIPASS_SUPPORT + uint16_t *iv_vlan_map; + + /* dp_peer special list */ + TAILQ_HEAD(, dp_peer) mpass_peer_list; +#endif }; @@ -1940,6 +1948,13 @@ struct dp_peer { /* average sojourn time */ qdf_ewma_tx_lag avg_sojourn_msdu[CDP_DATA_TID_MAX]; +#ifdef QCA_MULTIPASS_SUPPORT + /* node in the special peer list element */ + TAILQ_ENTRY(dp_peer) mpass_peer_list_elem; + /* vlan id for key */ + uint16_t vlan_id; +#endif + #ifdef PEER_CACHE_RX_PKTS qdf_atomic_t flush_in_progress; struct dp_peer_cached_bufq bufq_info;