qcacmn: Multicast support for MLO

Multicast support for MLO
1. Following functions are newly added.
	dp_rx_igmp_handler()
	dp_tx_mlo_mcast_handler_be()
	dp_rx_mlo_mcast_handler_be()
	dp_mlo_get_mcast_primary_vdev()

Change-Id: If215f843369e6e2621ef302b924e524c86f0d30b
This commit is contained in:
Sai Rupesh Chevuru
2021-11-23 19:39:15 +05:30
committed by Madan Koyyalamudi
父節點 64d845ab39
當前提交 b43e679a58
共有 17 個文件被更改,包括 709 次插入54 次删除

查看文件

@@ -1238,6 +1238,22 @@ dp_mlo_peer_find_hash_add_be(struct dp_soc *soc, struct dp_peer *peer)
}
#endif
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \
defined(WLAN_MCAST_MLO)
static void dp_txrx_set_mlo_mcast_primary_vdev_param_be(
struct dp_vdev_be *be_vdev,
cdp_config_param_type val)
{
be_vdev->mcast_primary = val.cdp_vdev_param_mcast_vdev;
}
#else
static void dp_txrx_set_mlo_mcast_primary_vdev_param_be(
struct dp_vdev_be *be_vdev,
cdp_config_param_type val)
{
}
#endif
#ifdef DP_TX_IMPLICIT_RBM_MAPPING
static void dp_tx_implicit_rbm_set_be(struct dp_soc *soc,
uint8_t tx_ring_id,
@@ -1348,6 +1364,9 @@ QDF_STATUS dp_txrx_set_vdev_param_be(struct dp_soc *soc,
if (vdev->tx_encap_type == htt_cmn_pkt_type_raw)
dp_tx_update_bank_profile(be_soc, be_vdev);
break;
case CDP_SET_MCAST_VDEV:
dp_txrx_set_mlo_mcast_primary_vdev_param_be(be_vdev, val);
break;
default:
dp_warn("invalid param %d", param);
break;
@@ -1438,6 +1457,10 @@ void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops)
arch_ops->txrx_set_vdev_param = dp_txrx_set_vdev_param_be;
#ifdef WLAN_FEATURE_11BE_MLO
#ifdef WLAN_MCAST_MLO
arch_ops->dp_tx_mcast_handler = dp_tx_mlo_mcast_handler_be;
arch_ops->dp_rx_mcast_handler = dp_rx_mlo_igmp_handler;
#endif
arch_ops->mlo_peer_find_hash_detach =
dp_mlo_peer_find_hash_detach_wrapper;
arch_ops->mlo_peer_find_hash_attach =

查看文件

@@ -256,6 +256,14 @@ struct dp_vdev_be {
#ifdef WLAN_MLO_MULTI_CHIP
/* partner list used for Intra-BSS */
uint8_t partner_vdev_list[WLAN_MAX_MLO_CHIPS][WLAN_MAX_MLO_LINKS_PER_SOC];
#ifdef WLAN_FEATURE_11BE_MLO
#ifdef WLAN_MCAST_MLO
/* DP MLO seq number */
uint16_t seq_num;
/* MLO Mcast primary vdev */
bool mcast_primary;
#endif
#endif
#endif
};
@@ -320,6 +328,39 @@ dp_mlo_get_peer_hash_obj(struct dp_soc *soc)
}
void dp_clr_mlo_ptnr_list(struct dp_soc *soc, struct dp_vdev *vdev);
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MCAST_MLO)
typedef void dp_ptnr_vdev_iter_func(struct dp_vdev_be *be_vdev,
struct dp_vdev *ptnr_vdev,
void *arg);
/*
* dp_mcast_mlo_iter_ptnr_vdev - API to iterate through ptnr vdev list
* @be_soc: dp_soc_be pointer
* @be_vdev: dp_vdev_be pointer
* @func : function to be called for each peer
* @arg : argument need to be passed to func
* @mod_id: module id
*
* Return: None
*/
void dp_mcast_mlo_iter_ptnr_vdev(struct dp_soc_be *be_soc,
struct dp_vdev_be *be_vdev,
dp_ptnr_vdev_iter_func func,
void *arg,
enum dp_mod_id mod_id);
/*
* dp_mlo_get_mcast_primary_vdev- get ref to mcast primary vdev
* @be_soc: dp_soc_be pointer
* @be_vdev: dp_vdev_be pointer
* @mod_id: module id
*
* Return: mcast primary DP VDEV handle on success, NULL on failure
*/
struct dp_vdev *dp_mlo_get_mcast_primary_vdev(struct dp_soc_be *be_soc,
struct dp_vdev_be *be_vdev,
enum dp_mod_id mod_id);
#endif
#else
typedef struct dp_soc_be *dp_mld_peer_hash_obj_t;

查看文件

@@ -1072,6 +1072,72 @@ struct dp_rx_desc *dp_rx_desc_cookie_2_va_be(struct dp_soc *soc,
return (struct dp_rx_desc *)dp_cc_desc_find(soc, cookie);
}
#if defined(WLAN_FEATURE_11BE_MLO)
#if defined(WLAN_MLO_MULTI_CHIP) && defined(WLAN_MCAST_MLO)
static inline void dp_rx_dummy_src_mac(qdf_nbuf_t nbuf)
{
qdf_ether_header_t *eh =
(qdf_ether_header_t *)qdf_nbuf_data(nbuf);
eh->ether_shost[0] = 0x4d; /* M */
eh->ether_shost[1] = 0x4c; /* L */
eh->ether_shost[2] = 0x4d; /* M */
eh->ether_shost[3] = 0x43; /* C */
eh->ether_shost[4] = 0x41; /* A */
eh->ether_shost[5] = 0x53; /* S */
}
bool dp_rx_mlo_igmp_handler(struct dp_soc *soc,
struct dp_vdev *vdev,
struct dp_peer *peer,
qdf_nbuf_t nbuf)
{
struct dp_vdev *mcast_primary_vdev = NULL;
struct dp_vdev_be *be_vdev = dp_get_be_vdev_from_dp_vdev(vdev);
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
if (!(qdf_nbuf_is_ipv4_igmp_pkt(buf) ||
qdf_nbuf_is_ipv6_igmp_pkt(buf)))
return false;
if (vdev->mcast_enhancement_en || be_vdev->mcast_primary)
goto send_pkt;
mcast_primary_vdev = dp_mlo_get_mcast_primary_vdev(be_soc, be_vdev,
DP_MOD_ID_RX);
if (!mcast_primary_vdev) {
dp_rx_debug("Non mlo vdev");
goto send_pkt;
}
dp_rx_dummy_src_mac(nbuf);
dp_rx_deliver_to_stack(mcast_primary_vdev->pdev->soc,
mcast_primary_vdev,
peer,
nbuf,
NULL);
dp_vdev_unref_delete(mcast_primary_vdev->pdev->soc,
mcast_primary_vdev,
DP_MOD_ID_RX);
return true;
send_pkt:
dp_rx_deliver_to_stack(be_vdev->vdev.pdev->soc,
&be_vdev->vdev,
peer,
nbuf,
NULL);
return true;
}
#else
bool dp_rx_mlo_igmp_handler(struct dp_soc *soc,
struct dp_vdev *vdev,
struct dp_peer *peer,
qdf_nbuf_t nbuf)
{
return false;
}
#endif
#endif
#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
uint32_t dp_rx_nf_process(struct dp_intr *int_ctx,
hal_ring_handle_t hal_ring_hdl,

查看文件

@@ -209,4 +209,23 @@ dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t reo_ring_num)
return soc;
}
#endif
#ifdef WLAN_FEATURE_11BE_MLO
#ifdef WLAN_MCAST_MLO
/**
* dp_rx_mlo_igmp_handler() - Rx handler for Mcast packets
* @soc: Handle to DP Soc structure
* @vdev: DP vdev handle
* @peer: DP peer handle
* @nbuf: nbuf to be enqueued
*
* Return: true when packet sent to stack, false failure
*/
bool dp_rx_mlo_igmp_handler(struct dp_soc *soc,
struct dp_vdev *vdev,
struct dp_peer *peer,
qdf_nbuf_t nbuf);
#endif
#endif
#endif

查看文件

@@ -38,6 +38,14 @@
#define DP_TX_BANK_LOCK_RELEASE(lock) qdf_spin_unlock_bh(lock)
#endif
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
#ifdef WLAN_MCAST_MLO
/* MLO peer id for reinject*/
#define DP_MLO_MCAST_REINJECT_PEER_ID 0XFFFD
#define MAX_GSN_NUM 0x0FFF
#endif
#endif
extern uint8_t sec_type_map[MAX_CDP_SEC_TYPE];
#ifdef DP_USE_REDUCED_PEER_ID_FIELD_WIDTH
@@ -156,6 +164,93 @@ static inline uint8_t dp_tx_get_rbm_id_be(struct dp_soc *soc,
}
#endif
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \
defined(WLAN_MCAST_MLO)
void
dp_tx_mlo_mcast_pkt_send(struct dp_vdev_be *be_vdev,
struct dp_vdev *ptnr_vdev,
void *arg)
{
qdf_nbuf_t nbuf = (qdf_nbuf_t)arg;
qdf_nbuf_t nbuf_clone;
struct dp_vdev_be *be_ptnr_vdev = NULL;
struct dp_tx_msdu_info_s msdu_info;
be_ptnr_vdev = dp_get_be_vdev_from_dp_vdev(ptnr_vdev);
if (be_vdev != be_ptnr_vdev) {
nbuf_clone = qdf_nbuf_clone(nbuf);
if (qdf_unlikely(!nbuf_clone)) {
dp_tx_debug("nbuf clone failed");
return;
}
} else {
nbuf_clone = nbuf;
}
qdf_mem_zero(&msdu_info, sizeof(msdu_info));
dp_tx_get_queue(ptnr_vdev, nbuf_clone, &msdu_info.tx_queue);
msdu_info.gsn = be_vdev->seq_num;
be_ptnr_vdev->seq_num = be_vdev->seq_num;
nbuf_clone = dp_tx_send_msdu_single(
ptnr_vdev,
nbuf_clone,
&msdu_info,
DP_MLO_MCAST_REINJECT_PEER_ID,
NULL);
if (qdf_unlikely(nbuf_clone)) {
dp_info("pkt send failed");
qdf_nbuf_free(nbuf_clone);
return;
}
}
static inline void
dp_tx_vdev_id_set_hal_tx_desc(uint32_t *hal_tx_desc_cached,
struct dp_vdev *vdev,
struct dp_tx_msdu_info_s *msdu_info)
{
hal_tx_desc_set_vdev_id(hal_tx_desc_cached, msdu_info->vdev_id);
}
void dp_tx_mlo_mcast_handler_be(struct dp_soc *soc,
struct dp_vdev *vdev,
qdf_nbuf_t nbuf)
{
struct dp_vdev_be *be_vdev = dp_get_be_vdev_from_dp_vdev(vdev);
struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
/* send frame on partner vdevs */
dp_mcast_mlo_iter_ptnr_vdev(be_soc, be_vdev,
dp_tx_mlo_mcast_pkt_send,
nbuf, DP_MOD_ID_TX);
/* send frame on mcast primary vdev */
dp_tx_mlo_mcast_pkt_send(be_vdev, vdev, nbuf);
if (qdf_unlikely(be_vdev->seq_num > MAX_GSN_NUM))
be_vdev->seq_num = 0;
else
be_vdev->seq_num++;
}
#else
static inline void
dp_tx_vdev_id_set_hal_tx_desc(uint32_t *hal_tx_desc_cached,
struct dp_vdev *vdev,
struct dp_tx_msdu_info_s *msdu_info)
{
hal_tx_desc_set_vdev_id(hal_tx_desc_cached, vdev->vdev_id);
}
#endif
#if defined(WLAN_FEATURE_11BE_MLO) && !defined(WLAN_MLO_MULTI_CHIP) && \
!defined(WLAN_MCAST_MLO)
void dp_tx_mlo_mcast_handler_be(struct dp_soc *soc,
struct dp_vdev *vdev,
qdf_nbuf_t nbuf)
{
}
#endif
QDF_STATUS
dp_tx_hw_enqueue_be(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc, uint16_t fw_metadata,
@@ -229,7 +324,7 @@ dp_tx_hw_enqueue_be(struct dp_soc *soc, struct dp_vdev *vdev,
hal_tx_desc_set_bank_id(hal_tx_desc_cached, be_vdev->bank_id);
hal_tx_desc_set_vdev_id(hal_tx_desc_cached, vdev->vdev_id);
dp_tx_vdev_id_set_hal_tx_desc(hal_tx_desc_cached, vdev, msdu_info);
if (tid != HTT_TX_EXT_TID_INVALID)
hal_tx_desc_set_hlos_tid(hal_tx_desc_cached, tid);

查看文件

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021 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
@@ -139,6 +140,35 @@ void dp_tx_desc_pool_deinit_be(struct dp_soc *soc,
struct dp_tx_desc_pool_s *tx_desc_pool,
uint8_t pool_id);
#ifdef WLAN_FEATURE_11BE_MLO
#ifdef WLAN_MCAST_MLO
/**
* dp_tx_mlo_mcast_handler_be() - Tx handler for Mcast packets
* @soc: Handle to DP Soc structure
* @vdev: DP vdev handle
* @nbuf: nbuf to be enqueued
*
* Return: None
*/
void dp_tx_mlo_mcast_handler_be(struct dp_soc *soc,
struct dp_vdev *vdev,
qdf_nbuf_t nbuf);
#ifdef WLAN_MLO_MULTI_CHIP
/**
* dp_tx_mlo_mcast_pkt_send() - handler to send MLO Mcast packets
* @be_vdev: Handle to DP be_vdev structure
* @ptnr_vdev: DP ptnr_vdev handle
* @nbuf: nbuf to be enqueued
*
* Return: None
*/
void dp_tx_mlo_mcast_pkt_send(struct dp_vdev_be *be_vdev,
struct dp_vdev *ptnr_vdev,
void *arg);
#endif
#endif
#endif
#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
/**
* dp_tx_comp_nf_handler() - Tx completion ring Near full scenario handler

查看文件

@@ -472,3 +472,77 @@ dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t reo_ring_num)
return soc;
}
#ifdef WLAN_MCAST_MLO
void dp_mcast_mlo_iter_ptnr_vdev(struct dp_soc_be *be_soc,
struct dp_vdev_be *be_vdev,
dp_ptnr_vdev_iter_func func,
void *arg,
enum dp_mod_id mod_id)
{
int i = 0;
int j = 0;
struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) {
struct dp_soc *ptnr_soc =
dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i);
if (!ptnr_soc)
continue;
for (j = 0 ; j < WLAN_MAX_MLO_LINKS_PER_SOC ; j++) {
struct dp_vdev *ptnr_vdev;
ptnr_vdev = dp_vdev_get_ref_by_id(
ptnr_soc,
be_vdev->partner_vdev_list[i][j],
mod_id);
if (!ptnr_vdev)
continue;
(*func)(be_vdev, ptnr_vdev, arg);
dp_vdev_unref_delete(ptnr_vdev->pdev->soc,
ptnr_vdev,
mod_id);
}
}
}
qdf_export_symbol(dp_mcast_mlo_iter_ptnr_vdev);
struct dp_vdev *dp_mlo_get_mcast_primary_vdev(struct dp_soc_be *be_soc,
struct dp_vdev_be *be_vdev,
enum dp_mod_id mod_id)
{
int i = 0;
int j = 0;
struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) {
struct dp_soc *ptnr_soc =
dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i);
if (!ptnr_soc)
continue;
for (j = 0 ; j < WLAN_MAX_MLO_LINKS_PER_SOC ; j++) {
struct dp_vdev *ptnr_vdev = NULL;
struct dp_vdev_be *be_ptnr_vdev = NULL;
ptnr_vdev = dp_vdev_get_ref_by_id(
ptnr_soc,
be_vdev->partner_vdev_list[i][j],
mod_id);
if (!ptnr_vdev)
continue;
be_ptnr_vdev = dp_get_be_vdev_from_dp_vdev(ptnr_vdev);
if (be_ptnr_vdev->mcast_primary)
return ptnr_vdev;
dp_vdev_unref_delete(be_ptnr_vdev->vdev.pdev->soc,
&be_ptnr_vdev->vdev,
mod_id);
}
}
return NULL;
}
qdf_export_symbol(dp_mlo_get_mcast_primary_vdev);
#endif