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
parent 64d845ab39
commit b43e679a58
17 changed files with 709 additions and 54 deletions

View File

@@ -1243,6 +1243,7 @@ enum cdp_pdev_param_type {
* @cdp_vdev_param_peer_tid_latency_enable: set peer tid latency enable flag
* @cdp_vdev_param_mesh_tid: config tatency tid on vdev
* @cdp_vdev_param_dscp_tid_map_id: set dscp to tid map id
* @cdp_vdev_param_mcast_vdev: set mcast vdev params
*
* @cdp_pdev_param_dbg_snf: Enable debug sniffer feature
* @cdp_pdev_param_bpr_enable: Enable bcast probe feature
@@ -1314,6 +1315,7 @@ typedef union cdp_config_param_t {
uint8_t cdp_vdev_param_peer_tid_latency_enable;
uint8_t cdp_vdev_param_mesh_tid;
uint8_t cdp_vdev_param_dscp_tid_map_id;
bool cdp_vdev_param_mcast_vdev;
/* pdev params */
bool cdp_pdev_param_cptr_latcy;
@@ -1433,6 +1435,7 @@ enum cdp_pdev_bpr_param {
* @CDP_ENABLE_PEER_TID_LATENCY: set peer tid latency enable flag
* @CDP_SET_VAP_MESH_TID : Set latency tid in vap
* @CDP_UPDATE_DSCP_TO_TID_MAP: Set DSCP to TID map id
* @CDP_SET_MCAST_VDEV : Set primary mcast vdev
*/
enum cdp_vdev_param_type {
CDP_ENABLE_NAWDS,
@@ -1470,7 +1473,8 @@ enum cdp_vdev_param_type {
#ifdef WLAN_VENDOR_SPECIFIC_BAR_UPDATE
CDP_SKIP_BAR_UPDATE_AP,
#endif
CDP_UPDATE_DSCP_TO_TID_MAP
CDP_UPDATE_DSCP_TO_TID_MAP,
CDP_SET_MCAST_VDEV,
};
/*

View File

@@ -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 =

View File

@@ -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;

View File

@@ -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,

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -327,6 +327,105 @@ dp_htt_h2t_send_complete(void *context, HTC_PACKET *htc_pkt)
#endif /* ENABLE_CE4_COMP_DISABLE_HTT_HTC_MISC_LIST */
#ifdef WLAN_MCAST_MLO
/*
* dp_htt_h2t_add_tcl_metadata_verg() - Add tcl_metadata verion
* @htt_soc: HTT SOC handle
* @msg: Pointer to nbuf
*
* Return: 0 on success; error code on failure
*/
static int dp_htt_h2t_add_tcl_metadata_ver(struct htt_soc *soc, qdf_nbuf_t *msg)
{
uint32_t *msg_word;
*msg = qdf_nbuf_alloc(
soc->osdev,
HTT_MSG_BUF_SIZE(HTT_VER_REQ_BYTES + HTT_TCL_METADATA_VER_SZ),
/* reserve room for the HTC header */
HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
if (!*msg)
return QDF_STATUS_E_NOMEM;
/*
* Set the length of the message.
* The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
* separately during the below call to qdf_nbuf_push_head.
* The contribution from the HTC header is added separately inside HTC.
*/
if (!qdf_nbuf_put_tail(*msg,
HTT_VER_REQ_BYTES + HTT_TCL_METADATA_VER_SZ)) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Failed to expand head for HTT_H2T_MSG_TYPE_VERSION_REQ msg",
__func__);
return QDF_STATUS_E_FAILURE;
}
/* fill in the message contents */
msg_word = (u_int32_t *)qdf_nbuf_data(*msg);
/* rewind beyond alignment pad to get to the HTC header reserved area */
qdf_nbuf_push_head(*msg, HTC_HDR_ALIGNMENT_PADDING);
*msg_word = 0;
HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ);
/* word 1 */
msg_word++;
*msg_word = 0;
HTT_OPTION_TLV_TAG_SET(*msg_word, HTT_OPTION_TLV_TAG_TCL_METADATA_VER);
HTT_OPTION_TLV_LENGTH_SET(*msg_word, HTT_TCL_METADATA_VER_SZ);
HTT_OPTION_TLV_TCL_METADATA_VER_SET(*msg_word,
HTT_OPTION_TLV_TCL_METADATA_V2);
return QDF_STATUS_SUCCESS;
}
#else
/*
* dp_htt_h2t_add_tcl_metadata_verg() - Add tcl_metadata verion
* @htt_soc: HTT SOC handle
* @msg: Pointer to nbuf
*
* Return: 0 on success; error code on failure
*/
static int dp_htt_h2t_add_tcl_metadata_ver(struct htt_soc *soc, qdf_nbuf_t *msg)
{
uint32_t *msg_word;
*msg = qdf_nbuf_alloc(
soc->osdev,
HTT_MSG_BUF_SIZE(HTT_VER_REQ_BYTES),
/* reserve room for the HTC header */
HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
if (!*msg)
return QDF_STATUS_E_NOMEM;
/*
* Set the length of the message.
* The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
* separately during the below call to qdf_nbuf_push_head.
* The contribution from the HTC header is added separately inside HTC.
*/
if (!qdf_nbuf_put_tail(*msg, HTT_VER_REQ_BYTES)) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Failed to expand head for HTT_H2T_MSG_TYPE_VERSION_REQ msg",
__func__);
return QDF_STATUS_E_FAILURE;
}
/* fill in the message contents */
msg_word = (u_int32_t *)qdf_nbuf_data(*msg);
/* rewind beyond alignment pad to get to the HTC header reserved area */
qdf_nbuf_push_head(*msg, HTC_HDR_ALIGNMENT_PADDING);
*msg_word = 0;
HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ);
return QDF_STATUS_SUCCESS;
}
#endif
/*
* htt_h2t_ver_req_msg() - Send HTT version request message to target
* @htt_soc: HTT SOC handle
@@ -336,39 +435,12 @@ dp_htt_h2t_send_complete(void *context, HTC_PACKET *htc_pkt)
static int htt_h2t_ver_req_msg(struct htt_soc *soc)
{
struct dp_htt_htc_pkt *pkt;
qdf_nbuf_t msg;
uint32_t *msg_word;
qdf_nbuf_t msg = NULL;
QDF_STATUS status;
msg = qdf_nbuf_alloc(
soc->osdev,
HTT_MSG_BUF_SIZE(HTT_VER_REQ_BYTES),
/* reserve room for the HTC header */
HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
if (!msg)
return QDF_STATUS_E_NOMEM;
/*
* Set the length of the message.
* The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
* separately during the below call to qdf_nbuf_push_head.
* The contribution from the HTC header is added separately inside HTC.
*/
if (qdf_nbuf_put_tail(msg, HTT_VER_REQ_BYTES) == NULL) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%s: Failed to expand head for HTT_H2T_MSG_TYPE_VERSION_REQ msg",
__func__);
return QDF_STATUS_E_FAILURE;
}
/* fill in the message contents */
msg_word = (u_int32_t *) qdf_nbuf_data(msg);
/* rewind beyond alignment pad to get to the HTC header reserved area */
qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
*msg_word = 0;
HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ);
status = dp_htt_h2t_add_tcl_metadata_ver(soc, &msg);
if (status != QDF_STATUS_SUCCESS)
return status;
pkt = htt_htc_pkt_alloc(soc);
if (!pkt) {

View File

@@ -111,6 +111,14 @@ cdp_dump_flow_pool_info(struct cdp_soc_t *soc)
#define WLAN_SYSFS_STAT_REQ_WAIT_MS 3000
#endif
#ifdef WLAN_MCAST_MLO
#define DP_TX_TCL_METADATA_PDEV_ID_SET(_var, _val) \
HTT_TX_TCL_METADATA_V2_PDEV_ID_SET(_var, _val)
#else
#define DP_TX_TCL_METADATA_PDEV_ID_SET(_var, _val) \
HTT_TX_TCL_METADATA_PDEV_ID_SET(_var, _val)
#endif
QDF_COMPILE_TIME_ASSERT(max_rx_rings_check,
MAX_REO_DEST_RINGS == CDP_MAX_RX_RINGS);
@@ -11136,7 +11144,7 @@ dp_soc_handle_pdev_mode_change
qdf_spin_lock_bh(&pdev->vdev_list_lock);
TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
HTT_TX_TCL_METADATA_PDEV_ID_SET(vdev->htt_tcl_metadata,
DP_TX_TCL_METADATA_PDEV_ID_SET(vdev->htt_tcl_metadata,
hw_pdev_id);
vdev->lmac_id = pdev->lmac_id;
}

View File

@@ -1764,6 +1764,29 @@ dp_rx_deliver_to_osif_stack(struct dp_soc *soc,
#endif
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \
defined(WLAN_MCAST_MLO)
static bool dp_rx_igmp_handler(struct dp_soc *soc,
struct dp_vdev *vdev,
struct dp_peer *peer,
qdf_nbuf_t nbuf)
{
if (soc->arch_ops.dp_rx_mcast_handler) {
if (soc->arch_ops.dp_rx_mcast_handler(soc, vdev, peer, nbuf))
return true;
}
return false;
}
#else
static bool dp_rx_igmp_handler(struct dp_soc *soc,
struct dp_vdev *vdev,
struct dp_peer *peer,
qdf_nbuf_t nbuf)
{
return false;
}
#endif
/**
* dp_rx_err_route_hdl() - Function to send EAPOL frames to stack
* Free any other packet which comes in
@@ -1836,6 +1859,9 @@ dp_rx_err_route_hdl(struct dp_soc *soc, qdf_nbuf_t nbuf,
qdf_nbuf_pull_head(nbuf, (msdu_metadata.l3_hdr_pad +
soc->rx_pkt_tlv_size));
if (dp_rx_igmp_handler(soc, vdev, peer, nbuf))
return;
dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, NULL, 0, 1);
/*

View File

@@ -65,6 +65,42 @@
#define DP_RETRY_COUNT 7
#ifdef WLAN_MCAST_MLO
#define DP_TX_TCL_METADATA_PDEV_ID_SET(_var, _val)\
HTT_TX_TCL_METADATA_V2_PDEV_ID_SET(_var, _val)
#define DP_TX_TCL_METADATA_VALID_HTT_SET(_var, _val) \
HTT_TX_TCL_METADATA_V2_VALID_HTT_SET(_var, _val)
#define DP_TX_TCL_METADATA_TYPE_SET(_var, _val) \
HTT_TX_TCL_METADATA_TYPE_V2_SET(_var, _val)
#define DP_TX_TCL_METADATA_HOST_INSPECTED_SET(_var, _val) \
HTT_TX_TCL_METADATA_V2_HOST_INSPECTED_SET(_var, _val)
#define DP_TX_TCL_METADATA_PEER_ID_SET(_var, _val) \
HTT_TX_TCL_METADATA_V2_PEER_ID_SET(_var, _val)
#define DP_TX_TCL_METADATA_VDEV_ID_SET(_var, _val) \
HTT_TX_TCL_METADATA_V2_VDEV_ID_SET(_var, _val)
#define DP_TCL_METADATA_TYPE_PEER_BASED \
HTT_TCL_METADATA_V2_TYPE_PEER_BASED
#define DP_TCL_METADATA_TYPE_VDEV_BASED \
HTT_TCL_METADATA_V2_TYPE_VDEV_BASED
#else
#define DP_TX_TCL_METADATA_PDEV_ID_SET(_var, _val)\
HTT_TX_TCL_METADATA_PDEV_ID_SET(_var, _val)
#define DP_TX_TCL_METADATA_VALID_HTT_SET(_var, _val) \
HTT_TX_TCL_METADATA_VALID_HTT_SET(_var, _val)
#define DP_TX_TCL_METADATA_TYPE_SET(_var, _val) \
HTT_TX_TCL_METADATA_TYPE_SET(_var, _val)
#define DP_TX_TCL_METADATA_HOST_INSPECTED_SET(_var, _val) \
HTT_TX_TCL_METADATA_HOST_INSPECTED_SET(_var, _val)
#define DP_TX_TCL_METADATA_PEER_ID_SET(_var, _val) \
HTT_TX_TCL_METADATA_PEER_ID_SET(_var, _val)
#define DP_TX_TCL_METADATA_VDEV_ID_SET(_var, _val) \
HTT_TX_TCL_METADATA_VDEV_ID_SET(_var, _val)
#define DP_TCL_METADATA_TYPE_PEER_BASED \
HTT_TCL_METADATA_TYPE_PEER_BASED
#define DP_TCL_METADATA_TYPE_VDEV_BASED \
HTT_TCL_METADATA_TYPE_VDEV_BASED
#endif
/*mapping between hal encrypt type and cdp_sec_type*/
uint8_t sec_type_map[MAX_CDP_SEC_TYPE] = {HAL_TX_ENCRYPT_TYPE_NO_CIPHER,
HAL_TX_ENCRYPT_TYPE_WEP_128,
@@ -1908,6 +1944,41 @@ int dp_tx_frame_is_drop(struct dp_vdev *vdev, uint8_t *srcmac, uint8_t *dstmac)
return 0;
}
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \
defined(WLAN_MCAST_MLO)
/* MLO peer id for reinject*/
#define DP_MLO_MCAST_REINJECT_PEER_ID 0XFFFD
/* MLO vdev id inc offset */
#define DP_MLO_VDEV_ID_OFFSET 0x80
static inline void
dp_tx_update_mcast_param(uint16_t peer_id,
uint16_t *htt_tcl_metadata,
struct dp_vdev *vdev,
struct dp_tx_msdu_info_s *msdu_info)
{
if (peer_id == DP_MLO_MCAST_REINJECT_PEER_ID) {
*htt_tcl_metadata = 0;
DP_TX_TCL_METADATA_TYPE_SET(
*htt_tcl_metadata,
HTT_TCL_METADATA_V2_TYPE_GLOBAL_SEQ_BASED);
HTT_TX_TCL_METADATA_GLBL_SEQ_NO_SET(*htt_tcl_metadata,
msdu_info->gsn);
msdu_info->vdev_id = vdev->vdev_id + DP_MLO_VDEV_ID_OFFSET;
} else {
msdu_info->vdev_id = vdev->vdev_id;
}
}
#else
static inline void
dp_tx_update_mcast_param(uint16_t peer_id,
uint16_t *htt_tcl_metadata,
struct dp_vdev *vdev,
struct dp_tx_msdu_info_s *msdu_info)
{
}
#endif
/**
* dp_tx_send_msdu_single() - Setup descriptor and enqueue single MSDU to TCL
* @vdev: DP vdev handle
@@ -1950,17 +2021,17 @@ dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
if (qdf_unlikely(peer_id == DP_INVALID_PEER)) {
htt_tcl_metadata = vdev->htt_tcl_metadata;
HTT_TX_TCL_METADATA_HOST_INSPECTED_SET(htt_tcl_metadata, 1);
DP_TX_TCL_METADATA_HOST_INSPECTED_SET(htt_tcl_metadata, 1);
} else if (qdf_unlikely(peer_id != HTT_INVALID_PEER)) {
HTT_TX_TCL_METADATA_TYPE_SET(htt_tcl_metadata,
HTT_TCL_METADATA_TYPE_PEER_BASED);
HTT_TX_TCL_METADATA_PEER_ID_SET(htt_tcl_metadata,
DP_TX_TCL_METADATA_TYPE_SET(htt_tcl_metadata,
DP_TCL_METADATA_TYPE_PEER_BASED);
DP_TX_TCL_METADATA_PEER_ID_SET(htt_tcl_metadata,
peer_id);
} else
htt_tcl_metadata = vdev->htt_tcl_metadata;
if (msdu_info->exception_fw)
HTT_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 1);
DP_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 1);
dp_tx_desc_update_fast_comp_flag(soc, tx_desc,
!pdev->enhanced_stats_en);
@@ -1979,6 +2050,7 @@ dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
tx_desc->dma_addr = qdf_nbuf_mapped_paddr_get(tx_desc->nbuf);
dp_tx_desc_history_add(soc, tx_desc->dma_addr, nbuf,
tx_desc->id, DP_TX_DESC_MAP);
dp_tx_update_mcast_param(peer_id, &htt_tcl_metadata, vdev, msdu_info);
/* Enqueue the Tx MSDU descriptor to HW for transmit */
status = soc->arch_ops.tx_hw_enqueue(soc, vdev, tx_desc,
htt_tcl_metadata,
@@ -2177,7 +2249,7 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
htt_tcl_metadata = vdev->htt_tcl_metadata;
if (msdu_info->exception_fw) {
HTT_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 1);
DP_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 1);
}
/*
@@ -2204,6 +2276,10 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
}
}
dp_tx_update_mcast_param(DP_INVALID_PEER,
&htt_tcl_metadata,
vdev,
msdu_info);
/*
* Enqueue the Tx MSDU descriptor to HW for transmit
*/
@@ -3226,6 +3302,7 @@ int dp_tx_proxy_arp(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
* @vdev: datapath vdev handle
* @tx_desc: software descriptor head pointer
* @status : Tx completion status from HTT descriptor
* @reinject_reason : reinject reason from HTT descriptor
*
* This function reinjects frames back to Target.
* Todo - Host queue needs to be added
@@ -3236,7 +3313,8 @@ static
void dp_tx_reinject_handler(struct dp_soc *soc,
struct dp_vdev *vdev,
struct dp_tx_desc_s *tx_desc,
uint8_t *status)
uint8_t *status,
uint8_t reinject_reason)
{
struct dp_peer *peer = NULL;
uint32_t peer_id = HTT_INVALID_PEER;
@@ -3252,15 +3330,23 @@ void dp_tx_reinject_handler(struct dp_soc *soc,
qdf_assert(vdev);
qdf_mem_zero(&msdu_info, sizeof(msdu_info));
dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue);
dp_tx_debug("Tx reinject path");
DP_STATS_INC_PKT(vdev, tx_i.reinject_pkts, 1,
qdf_nbuf_len(tx_desc->nbuf));
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
#ifdef WLAN_MCAST_MLO
if (reinject_reason == HTT_TX_FW2WBM_REINJECT_REASON_MLO_MCAST) {
if (soc->arch_ops.dp_tx_mcast_handler)
soc->arch_ops.dp_tx_mcast_handler(soc, vdev, nbuf);
dp_tx_desc_release(tx_desc, tx_desc->pool_id);
return;
}
#endif
#endif
#ifdef WDS_VENDOR_EXTENSION
if (qdf_unlikely(vdev->tx_encap_type != htt_cmn_pkt_type_raw)) {
is_mcast = (IS_MULTICAST(wh->i_addr1)) ? 1 : 0;
@@ -3318,6 +3404,9 @@ void dp_tx_reinject_handler(struct dp_soc *soc,
dp_tx_debug("nbuf copy failed");
break;
}
qdf_mem_zero(&msdu_info, sizeof(msdu_info));
dp_tx_get_queue(vdev, nbuf,
&msdu_info.tx_queue);
nbuf_copy = dp_tx_send_msdu_single(vdev,
nbuf_copy,
@@ -4498,7 +4587,13 @@ void dp_tx_process_htt_completion(struct dp_soc *soc,
}
case HTT_TX_FW2WBM_TX_STATUS_REINJECT:
{
dp_tx_reinject_handler(soc, vdev, tx_desc, status);
uint8_t reinject_reason;
reinject_reason =
HTT_TX_WBM_COMPLETION_V2_REINJECT_REASON_GET(
htt_desc[0]);
dp_tx_reinject_handler(soc, vdev, tx_desc,
status, reinject_reason);
break;
}
case HTT_TX_FW2WBM_TX_STATUS_INSPECT:
@@ -4843,21 +4938,21 @@ QDF_STATUS dp_tx_vdev_attach(struct dp_vdev *vdev)
/*
* Fill HTT TCL Metadata with Vdev ID and MAC ID
*/
HTT_TX_TCL_METADATA_TYPE_SET(vdev->htt_tcl_metadata,
HTT_TCL_METADATA_TYPE_VDEV_BASED);
DP_TX_TCL_METADATA_TYPE_SET(vdev->htt_tcl_metadata,
DP_TCL_METADATA_TYPE_VDEV_BASED);
HTT_TX_TCL_METADATA_VDEV_ID_SET(vdev->htt_tcl_metadata,
DP_TX_TCL_METADATA_VDEV_ID_SET(vdev->htt_tcl_metadata,
vdev->vdev_id);
pdev_id =
dp_get_target_pdev_id_for_host_pdev_id(vdev->pdev->soc,
vdev->pdev->pdev_id);
HTT_TX_TCL_METADATA_PDEV_ID_SET(vdev->htt_tcl_metadata, pdev_id);
DP_TX_TCL_METADATA_PDEV_ID_SET(vdev->htt_tcl_metadata, pdev_id);
/*
* Set HTT Extension Valid bit to 0 by default
*/
HTT_TX_TCL_METADATA_VALID_HTT_SET(vdev->htt_tcl_metadata, 0);
DP_TX_TCL_METADATA_VALID_HTT_SET(vdev->htt_tcl_metadata, 0);
dp_tx_vdev_update_search_flags(vdev);

View File

@@ -179,6 +179,8 @@ struct dp_tx_queue {
* @exception_fw: Duplicate frame to be sent to firmware
* @ppdu_cookie: 16-bit ppdu_cookie that has to be replayed back in completions
* @ix_tx_sniffer: Indicates if the packet has to be sniffed
* @gsn: global sequence for reinjected mcast packets
* @vdev_id : vdev_id for reinjected mcast packets
*
* This structure holds the complete MSDU information needed to program the
* Hardware TCL and MSDU extension descriptors for different frame types
@@ -197,6 +199,12 @@ struct dp_tx_msdu_info_s {
} u;
uint32_t meta_data[DP_TX_MSDU_INFO_META_DATA_DWORDS];
uint16_t ppdu_cookie;
#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
#ifdef WLAN_MCAST_MLO
uint16_t gsn;
uint8_t vdev_id;
#endif
#endif
};
#ifndef QCA_HOST_MODE_WIFI_DISABLED

View File

@@ -1713,6 +1713,12 @@ struct dp_arch_ops {
/* MLO ops */
#ifdef WLAN_FEATURE_11BE_MLO
#ifdef WLAN_MCAST_MLO
void (*dp_tx_mcast_handler)(struct dp_soc *soc, struct dp_vdev *vdev,
qdf_nbuf_t nbuf);
bool (*dp_rx_mcast_handler)(struct dp_soc *soc, struct dp_vdev *vdev,
struct dp_peer *peer, qdf_nbuf_t nbuf);
#endif
void (*mlo_peer_find_hash_detach)(struct dp_soc *soc);
QDF_STATUS (*mlo_peer_find_hash_attach)(struct dp_soc *soc);
void (*mlo_peer_find_hash_add)(struct dp_soc *soc,

View File

@@ -75,6 +75,7 @@
#define QDF_NBUF_TRAC_IPV6_OFFSET 14
#define QDF_NBUF_TRAC_IPV6_HEADER_SIZE 40
#define QDF_NBUF_TRAC_ICMP_TYPE 1
#define QDF_NBUF_TRAC_IGMP_TYPE 2
#define QDF_NBUF_TRAC_TCP_TYPE 6
#define QDF_NBUF_TRAC_TCP_FLAGS_OFFSET (47 - 34)
#define QDF_NBUF_TRAC_TCP_ACK_OFFSET (42 - 34)
@@ -84,6 +85,7 @@
#define QDF_NBUF_TRAC_TCP_DPORT_OFFSET (36 - 34)
#define QDF_NBUF_TRAC_UDP_TYPE 17
#define QDF_NBUF_TRAC_ICMPV6_TYPE 0x3a
#define QDF_NBUF_TRAC_HOPOPTS_TYPE 0
#define QDF_NBUF_TRAC_DHCP6_SRV_PORT 547
#define QDF_NBUF_TRAC_DHCP6_CLI_PORT 546
#define QDF_NBUF_TRAC_MDNS_SRC_N_DST_PORT 5353
@@ -2886,6 +2888,34 @@ bool qdf_nbuf_is_ipv4_wapi_pkt(qdf_nbuf_t buf)
return __qdf_nbuf_is_ipv4_wapi_pkt(buf);
}
/**
* qdf_nbuf_is_ipv4_igmp_pkt() - check if packet is a igmp packet or not
* @buf: buffer
*
* This api is for ipv4 packet.
*
* Return: true if packet is igmp packet
*/
static inline
bool qdf_nbuf_is_ipv4_igmp_pkt(qdf_nbuf_t buf)
{
return __qdf_nbuf_data_is_ipv4_igmp_pkt(qdf_nbuf_data(buf));
}
/**
* qdf_nbuf_is_ipv6_igmp_pkt() - check if packet is a igmp packet or not
* @buf: buffer
*
* This api is for ipv6 packet.
*
* Return: true if packet is igmp packet
*/
static inline
bool qdf_nbuf_is_ipv6_igmp_pkt(qdf_nbuf_t buf)
{
return __qdf_nbuf_data_is_ipv6_igmp_pkt(qdf_nbuf_data(buf));
}
/**
* qdf_nbuf_is_ipv4_tdls_pkt() - check if packet is a tdls packet or not
* @buf: buffer

View File

@@ -861,6 +861,8 @@ bool __qdf_nbuf_data_is_ipv4_dhcp_pkt(uint8_t *data);
bool __qdf_nbuf_data_is_ipv6_dhcp_pkt(uint8_t *data);
bool __qdf_nbuf_data_is_ipv6_mdns_pkt(uint8_t *data);
bool __qdf_nbuf_data_is_ipv4_eapol_pkt(uint8_t *data);
bool __qdf_nbuf_data_is_ipv4_igmp_pkt(uint8_t *data);
bool __qdf_nbuf_data_is_ipv6_igmp_pkt(uint8_t *data);
bool __qdf_nbuf_data_is_ipv4_arp_pkt(uint8_t *data);
bool __qdf_nbuf_is_bcast_pkt(__qdf_nbuf_t nbuf);
bool __qdf_nbuf_data_is_arp_req(uint8_t *data);

View File

@@ -1614,6 +1614,62 @@ bool __qdf_nbuf_is_ipv4_wapi_pkt(struct sk_buff *skb)
}
qdf_export_symbol(__qdf_nbuf_is_ipv4_wapi_pkt);
/**
* __qdf_nbuf_data_is_ipv4_igmp_pkt() - check if skb data is a igmp packet
* @data: Pointer to network data buffer
*
* This api is for ipv4 packet.
*
* Return: true if packet is igmp packet
* false otherwise.
*/
bool __qdf_nbuf_data_is_ipv4_igmp_pkt(uint8_t *data)
{
if (__qdf_nbuf_data_is_ipv4_pkt(data)) {
uint8_t pkt_type;
pkt_type = (uint8_t)(*(uint8_t *)(data +
QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET));
if (pkt_type == QDF_NBUF_TRAC_IGMP_TYPE)
return true;
}
return false;
}
qdf_export_symbol(__qdf_nbuf_data_is_ipv4_igmp_pkt);
/**
* __qdf_nbuf_data_is_ipv6_igmp_pkt() - check if skb data is a igmp packet
* @data: Pointer to network data buffer
*
* This api is for ipv6 packet.
*
* Return: true if packet is igmp packet
* false otherwise.
*/
bool __qdf_nbuf_data_is_ipv6_igmp_pkt(uint8_t *data)
{
if (__qdf_nbuf_data_is_ipv6_pkt(data)) {
uint8_t pkt_type;
uint8_t next_hdr;
pkt_type = (uint8_t)(*(uint8_t *)(data +
QDF_NBUF_TRAC_IPV6_PROTO_TYPE_OFFSET));
next_hdr = (uint8_t)(*(uint8_t *)(data +
QDF_NBUF_TRAC_IPV6_HEADER_SIZE));
if (pkt_type == QDF_NBUF_TRAC_ICMPV6_TYPE)
return true;
if ((pkt_type == QDF_NBUF_TRAC_HOPOPTS_TYPE) &&
(next_hdr == QDF_NBUF_TRAC_HOPOPTS_TYPE))
return true;
}
return false;
}
qdf_export_symbol(__qdf_nbuf_data_is_ipv6_igmp_pkt);
/**
* __qdf_nbuf_is_ipv4_tdls_pkt() - check if skb data is a tdls packet
* @skb: Pointer to network buffer