|
@@ -62,6 +62,11 @@ struct ast_del_ctxt {
|
|
|
typedef void dp_peer_iter_func(struct dp_soc *soc, struct dp_peer *peer,
|
|
|
void *arg);
|
|
|
void dp_peer_unref_delete(struct dp_peer *peer, enum dp_mod_id id);
|
|
|
+struct dp_peer *dp_peer_find_hash_find(struct dp_soc *soc,
|
|
|
+ uint8_t *peer_mac_addr,
|
|
|
+ int mac_addr_is_aligned,
|
|
|
+ uint8_t vdev_id,
|
|
|
+ enum dp_mod_id id);
|
|
|
|
|
|
/**
|
|
|
* dp_peer_get_ref() - Returns peer object given the peer id
|
|
@@ -968,4 +973,462 @@ static inline void dp_get_rx_reo_queue_info(
|
|
|
{
|
|
|
}
|
|
|
#endif /* DUMP_REO_QUEUE_INFO_IN_DDR */
|
|
|
+
|
|
|
+static inline int dp_peer_find_mac_addr_cmp(
|
|
|
+ union dp_align_mac_addr *mac_addr1,
|
|
|
+ union dp_align_mac_addr *mac_addr2)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * Intentionally use & rather than &&.
|
|
|
+ * because the operands are binary rather than generic boolean,
|
|
|
+ * the functionality is equivalent.
|
|
|
+ * Using && has the advantage of short-circuited evaluation,
|
|
|
+ * but using & has the advantage of no conditional branching,
|
|
|
+ * which is a more significant benefit.
|
|
|
+ */
|
|
|
+ return !((mac_addr1->align4.bytes_abcd == mac_addr2->align4.bytes_abcd)
|
|
|
+ & (mac_addr1->align4.bytes_ef == mac_addr2->align4.bytes_ef));
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_peer_delete() - delete DP peer
|
|
|
+ *
|
|
|
+ * @soc: Datatpath soc
|
|
|
+ * @peer: Datapath peer
|
|
|
+ * @arg: argument to iter function
|
|
|
+ *
|
|
|
+ * Return: void
|
|
|
+ */
|
|
|
+void dp_peer_delete(struct dp_soc *soc,
|
|
|
+ struct dp_peer *peer,
|
|
|
+ void *arg);
|
|
|
+
|
|
|
+#ifdef WLAN_FEATURE_11BE_MLO
|
|
|
+/* set peer type */
|
|
|
+#define DP_PEER_SET_TYPE(_peer, _type_val) \
|
|
|
+ ((_peer)->peer_type = (_type_val))
|
|
|
+/* is MLO connection link peer */
|
|
|
+#define IS_MLO_DP_LINK_PEER(_peer) \
|
|
|
+ ((_peer)->peer_type == CDP_LINK_PEER_TYPE && (_peer)->mld_peer)
|
|
|
+/* is MLO connection mld peer */
|
|
|
+#define IS_MLO_DP_MLD_PEER(_peer) \
|
|
|
+ ((_peer)->peer_type == CDP_MLD_PEER_TYPE)
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_link_peer_add_mld_peer() - add mld peer pointer to link peer,
|
|
|
+ increase mld peer ref_cnt
|
|
|
+ * @link_peer: link peer pointer
|
|
|
+ * @mld_peer: mld peer pointer
|
|
|
+ *
|
|
|
+ * Return: none
|
|
|
+ */
|
|
|
+static inline
|
|
|
+void dp_link_peer_add_mld_peer(struct dp_peer *link_peer,
|
|
|
+ struct dp_peer *mld_peer)
|
|
|
+{
|
|
|
+ /* increase mld_peer ref_cnt */
|
|
|
+ dp_peer_get_ref(NULL, mld_peer, DP_MOD_ID_CDP);
|
|
|
+ link_peer->mld_peer = mld_peer;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_link_peer_del_mld_peer() - delete mld peer pointer from link peer,
|
|
|
+ decrease mld peer ref_cnt
|
|
|
+ * @link_peer: link peer pointer
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static inline
|
|
|
+void dp_link_peer_del_mld_peer(struct dp_peer *link_peer)
|
|
|
+{
|
|
|
+ dp_peer_unref_delete(link_peer->mld_peer, DP_MOD_ID_CDP);
|
|
|
+ link_peer->mld_peer = NULL;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_mld_peer_init_link_peers_info() - init link peers info in mld peer
|
|
|
+ * @mld_peer: mld peer pointer
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static inline
|
|
|
+void dp_mld_peer_init_link_peers_info(struct dp_peer *mld_peer)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ qdf_spinlock_create(&mld_peer->link_peers_info_lock);
|
|
|
+ mld_peer->num_links = 0;
|
|
|
+ for (i = 0; i < DP_MAX_MLO_LINKS; i++)
|
|
|
+ mld_peer->link_peers[i].is_valid = false;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_mld_peer_deinit_link_peers_info() - Deinit link peers info in mld peer
|
|
|
+ * @mld_peer: mld peer pointer
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static inline
|
|
|
+void dp_mld_peer_deinit_link_peers_info(struct dp_peer *mld_peer)
|
|
|
+{
|
|
|
+ qdf_spinlock_destroy(&mld_peer->link_peers_info_lock);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_mld_peer_add_link_peer() - add link peer info to mld peer
|
|
|
+ * @mld_peer: mld dp peer pointer
|
|
|
+ * @link_peer: link dp peer pointer
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static inline
|
|
|
+void dp_mld_peer_add_link_peer(struct dp_peer *mld_peer,
|
|
|
+ struct dp_peer *link_peer)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ struct dp_peer_link_info *link_peer_info;
|
|
|
+
|
|
|
+ qdf_spin_lock_bh(&mld_peer->link_peers_info_lock);
|
|
|
+ for (i = 0; i < DP_MAX_MLO_LINKS; i++) {
|
|
|
+ link_peer_info = &mld_peer->link_peers[i];
|
|
|
+ if (!link_peer_info->is_valid) {
|
|
|
+ qdf_mem_copy(link_peer_info->mac_addr.raw,
|
|
|
+ link_peer->mac_addr.raw,
|
|
|
+ QDF_MAC_ADDR_SIZE);
|
|
|
+ link_peer_info->is_valid = true;
|
|
|
+ link_peer_info->vdev_id = link_peer->vdev->vdev_id;
|
|
|
+ mld_peer->num_links++;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ qdf_spin_unlock_bh(&mld_peer->link_peers_info_lock);
|
|
|
+
|
|
|
+ if (i == DP_MAX_MLO_LINKS)
|
|
|
+ dp_err("fail to add link peer" QDF_MAC_ADDR_FMT "to mld peer",
|
|
|
+ QDF_MAC_ADDR_REF(link_peer->mac_addr.raw));
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_mld_peer_del_link_peer() - Delete link peer info from MLD peer
|
|
|
+ * @mld_peer: MLD dp peer pointer
|
|
|
+ * @link_peer: link dp peer pointer
|
|
|
+ *
|
|
|
+ * Return: number of links left after deletion
|
|
|
+ */
|
|
|
+static inline
|
|
|
+uint8_t dp_mld_peer_del_link_peer(struct dp_peer *mld_peer,
|
|
|
+ struct dp_peer *link_peer)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ struct dp_peer_link_info *link_peer_info;
|
|
|
+ uint8_t num_links;
|
|
|
+
|
|
|
+ qdf_spin_lock_bh(&mld_peer->link_peers_info_lock);
|
|
|
+ for (i = 0; i < DP_MAX_MLO_LINKS; i++) {
|
|
|
+ link_peer_info = &mld_peer->link_peers[i];
|
|
|
+ if (link_peer_info->is_valid &&
|
|
|
+ !dp_peer_find_mac_addr_cmp(&link_peer->mac_addr,
|
|
|
+ &link_peer_info->mac_addr)) {
|
|
|
+ link_peer_info->is_valid = false;
|
|
|
+ mld_peer->num_links--;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ num_links = mld_peer->num_links;
|
|
|
+ qdf_spin_unlock_bh(&mld_peer->link_peers_info_lock);
|
|
|
+
|
|
|
+ if (i == DP_MAX_MLO_LINKS)
|
|
|
+ dp_err("fail to del link peer" QDF_MAC_ADDR_FMT "to mld peer",
|
|
|
+ QDF_MAC_ADDR_REF(link_peer->mac_addr.raw));
|
|
|
+
|
|
|
+ return num_links;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_get_link_peers_ref_from_mld_peer() - get link peers pointer and
|
|
|
+ increase link peers ref_cnt
|
|
|
+ * @soc: dp_soc handle
|
|
|
+ * @mld_peer: dp mld peer pointer
|
|
|
+ * @mld_link_peers: structure that hold links peers ponter array and number
|
|
|
+ * @mod_id: id of module requesting reference
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static inline
|
|
|
+void dp_get_link_peers_ref_from_mld_peer(
|
|
|
+ struct dp_soc *soc,
|
|
|
+ struct dp_peer *mld_peer,
|
|
|
+ struct dp_mld_link_peers *mld_link_peers,
|
|
|
+ enum dp_mod_id mod_id)
|
|
|
+{
|
|
|
+ struct dp_peer *peer;
|
|
|
+ uint8_t i = 0, j = 0;
|
|
|
+ struct dp_peer_link_info *link_peer_info;
|
|
|
+
|
|
|
+ qdf_mem_zero(mld_link_peers, sizeof(*mld_link_peers));
|
|
|
+ qdf_spin_lock_bh(&mld_peer->link_peers_info_lock);
|
|
|
+ for (i = 0; i < DP_MAX_MLO_LINKS; i++) {
|
|
|
+ link_peer_info = &mld_peer->link_peers[i];
|
|
|
+ if (link_peer_info->is_valid) {
|
|
|
+ peer = dp_peer_find_hash_find(
|
|
|
+ soc,
|
|
|
+ link_peer_info->mac_addr.raw,
|
|
|
+ true,
|
|
|
+ link_peer_info->vdev_id,
|
|
|
+ mod_id);
|
|
|
+ if (peer)
|
|
|
+ mld_link_peers->link_peers[j++] = peer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ qdf_spin_unlock_bh(&mld_peer->link_peers_info_lock);
|
|
|
+
|
|
|
+ mld_link_peers->num_links = j;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_release_link_peers_ref() - release all link peers reference
|
|
|
+ * @mld_link_peers: structure that hold links peers ponter array and number
|
|
|
+ * @mod_id: id of module requesting reference
|
|
|
+ *
|
|
|
+ * Return: None.
|
|
|
+ */
|
|
|
+static inline
|
|
|
+void dp_release_link_peers_ref(
|
|
|
+ struct dp_mld_link_peers *mld_link_peers,
|
|
|
+ enum dp_mod_id mod_id)
|
|
|
+{
|
|
|
+ struct dp_peer *peer;
|
|
|
+ uint8_t i;
|
|
|
+
|
|
|
+ for (i = 0; i < mld_link_peers->num_links; i++) {
|
|
|
+ peer = mld_link_peers->link_peers[i];
|
|
|
+ if (peer)
|
|
|
+ dp_peer_unref_delete(peer, mod_id);
|
|
|
+ mld_link_peers->link_peers[i] = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ mld_link_peers->num_links = 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_peer_get_tgt_peer_hash_find() - get MLD dp_peer handle
|
|
|
+ for processing
|
|
|
+ * @soc: soc handle
|
|
|
+ * @peer_mac_addr: peer mac address
|
|
|
+ * @mac_addr_is_aligned: is mac addr alligned
|
|
|
+ * @vdev_id: vdev_id
|
|
|
+ * @mod_id: id of module requesting reference
|
|
|
+ *
|
|
|
+ * for MLO connection, get corresponding MLD peer,
|
|
|
+ * otherwise get link peer for non-MLO case.
|
|
|
+ *
|
|
|
+ * return: peer in success
|
|
|
+ * NULL in failure
|
|
|
+ */
|
|
|
+static inline
|
|
|
+struct dp_peer *dp_peer_get_tgt_peer_hash_find(struct dp_soc *soc,
|
|
|
+ uint8_t *peer_mac,
|
|
|
+ int mac_addr_is_aligned,
|
|
|
+ uint8_t vdev_id,
|
|
|
+ enum dp_mod_id mod_id)
|
|
|
+{
|
|
|
+ struct dp_peer *ta_peer = NULL;
|
|
|
+ struct dp_peer *peer = dp_peer_find_hash_find(soc,
|
|
|
+ peer_mac, 0, vdev_id,
|
|
|
+ mod_id);
|
|
|
+
|
|
|
+ if (peer) {
|
|
|
+ /* mlo connection link peer, get mld peer with reference */
|
|
|
+ if (IS_MLO_DP_LINK_PEER(peer)) {
|
|
|
+ /* increase mld peer ref_cnt */
|
|
|
+ if (QDF_STATUS_SUCCESS ==
|
|
|
+ dp_peer_get_ref(soc, peer->mld_peer, mod_id))
|
|
|
+ ta_peer = peer->mld_peer;
|
|
|
+ else
|
|
|
+ ta_peer = NULL;
|
|
|
+
|
|
|
+ /* relese peer reference that added by hash find */
|
|
|
+ dp_peer_unref_delete(peer, mod_id);
|
|
|
+ } else {
|
|
|
+ /* mlo MLD peer or non-mlo link peer */
|
|
|
+ ta_peer = peer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return ta_peer;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_peer_get_tgt_peer_by_id() - Returns target peer object given the peer id
|
|
|
+ * @soc : core DP soc context
|
|
|
+ * @peer_id : peer id from peer object can be retrieved
|
|
|
+ * @mod_id : ID ot module requesting reference
|
|
|
+ *
|
|
|
+ * for MLO connection, get corresponding MLD peer,
|
|
|
+ * otherwise get link peer for non-MLO case.
|
|
|
+ *
|
|
|
+ * return: peer in success
|
|
|
+ * NULL in failure
|
|
|
+ */
|
|
|
+static inline
|
|
|
+struct dp_peer *dp_peer_get_tgt_peer_by_id(struct dp_soc *soc,
|
|
|
+ uint16_t peer_id,
|
|
|
+ enum dp_mod_id mod_id)
|
|
|
+{
|
|
|
+ struct dp_peer *ta_peer = NULL;
|
|
|
+ struct dp_peer *peer = dp_peer_get_ref_by_id(soc, peer_id, mod_id);
|
|
|
+
|
|
|
+ if (peer) {
|
|
|
+ /* mlo connection link peer, get mld peer with reference */
|
|
|
+ if (IS_MLO_DP_LINK_PEER(peer)) {
|
|
|
+ /* increase mld peer ref_cnt */
|
|
|
+ if (QDF_STATUS_SUCCESS ==
|
|
|
+ dp_peer_get_ref(soc, peer->mld_peer, mod_id))
|
|
|
+ ta_peer = peer->mld_peer;
|
|
|
+ else
|
|
|
+ ta_peer = NULL;
|
|
|
+
|
|
|
+ /* relese peer reference that added by hash find */
|
|
|
+ dp_peer_unref_delete(peer, mod_id);
|
|
|
+ } else {
|
|
|
+ /* mlo MLD peer or non-mlo link peer */
|
|
|
+ ta_peer = peer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return ta_peer;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_peer_mlo_delete() - peer MLO related delete operation
|
|
|
+ * @soc: Soc handle
|
|
|
+ * @peer: DP peer handle
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static inline
|
|
|
+void dp_peer_mlo_delete(struct dp_soc *soc,
|
|
|
+ struct dp_peer *peer)
|
|
|
+{
|
|
|
+ /* MLO connection link peer */
|
|
|
+ if (IS_MLO_DP_LINK_PEER(peer)) {
|
|
|
+ /* if last link peer deletion, delete MLD peer */
|
|
|
+ if (dp_mld_peer_del_link_peer(peer->mld_peer, peer) == 0)
|
|
|
+ dp_peer_delete(soc, peer->mld_peer, NULL);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_peer_mlo_setup() - create MLD peer and MLO related initialization
|
|
|
+ * @soc: Soc handle
|
|
|
+ * @vdev_id: Vdev ID
|
|
|
+ * @peer_setup_info: peer setup information for MLO
|
|
|
+ */
|
|
|
+QDF_STATUS dp_peer_mlo_setup(
|
|
|
+ struct dp_soc *soc,
|
|
|
+ struct dp_peer *peer,
|
|
|
+ uint8_t vdev_id,
|
|
|
+ struct cdp_peer_setup_info *setup_info);
|
|
|
+#else
|
|
|
+#define DP_PEER_SET_TYPE(_peer, _type_val) /* no op */
|
|
|
+#define IS_MLO_DP_LINK_PEER(_peer) false
|
|
|
+#define IS_MLO_DP_MLD_PEER(_peer) false
|
|
|
+
|
|
|
+static inline
|
|
|
+struct dp_peer *dp_peer_get_tgt_peer_hash_find(struct dp_soc *soc,
|
|
|
+ uint8_t *peer_mac,
|
|
|
+ int mac_addr_is_aligned,
|
|
|
+ uint8_t vdev_id,
|
|
|
+ enum dp_mod_id mod_id)
|
|
|
+{
|
|
|
+ return dp_peer_find_hash_find(soc, peer_mac,
|
|
|
+ mac_addr_is_aligned, vdev_id,
|
|
|
+ mod_id);
|
|
|
+}
|
|
|
+
|
|
|
+static inline
|
|
|
+struct dp_peer *dp_peer_get_tgt_peer_by_id(struct dp_soc *soc,
|
|
|
+ uint16_t peer_id,
|
|
|
+ enum dp_mod_id mod_id)
|
|
|
+{
|
|
|
+ return dp_peer_get_ref_by_id(soc, peer_id, mod_id);
|
|
|
+}
|
|
|
+
|
|
|
+static inline
|
|
|
+QDF_STATUS dp_peer_mlo_setup(
|
|
|
+ struct dp_soc *soc,
|
|
|
+ struct dp_peer *peer,
|
|
|
+ uint8_t vdev_id,
|
|
|
+ struct cdp_peer_setup_info *setup_info)
|
|
|
+{
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+static inline
|
|
|
+void dp_mld_peer_init_link_peers_info(struct dp_peer *mld_peer)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static inline
|
|
|
+void dp_mld_peer_deinit_link_peers_info(struct dp_peer *mld_peer)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static inline
|
|
|
+void dp_link_peer_del_mld_peer(struct dp_peer *link_peer)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static inline
|
|
|
+void dp_peer_mlo_delete(struct dp_soc *soc,
|
|
|
+ struct dp_peer *peer)
|
|
|
+{
|
|
|
+}
|
|
|
+#endif /* WLAN_FEATURE_11BE_MLO */
|
|
|
+
|
|
|
+static inline
|
|
|
+QDF_STATUS dp_peer_rx_tids_create(struct dp_peer *peer)
|
|
|
+{
|
|
|
+ uint8_t i;
|
|
|
+
|
|
|
+ if (IS_MLO_DP_MLD_PEER(peer)) {
|
|
|
+ dp_peer_info("skip for mld peer");
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (peer->rx_tid) {
|
|
|
+ QDF_BUG(0);
|
|
|
+ dp_peer_err("peer rx_tid mem already exist");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ peer->rx_tid = qdf_mem_malloc(DP_MAX_TIDS *
|
|
|
+ sizeof(struct dp_rx_tid));
|
|
|
+
|
|
|
+ if (!peer->rx_tid) {
|
|
|
+ dp_err("fail to alloc tid for peer" QDF_MAC_ADDR_FMT,
|
|
|
+ QDF_MAC_ADDR_REF(peer->mac_addr.raw));
|
|
|
+ return QDF_STATUS_E_NOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ qdf_mem_zero(peer->rx_tid, DP_MAX_TIDS * sizeof(struct dp_rx_tid));
|
|
|
+ for (i = 0; i < DP_MAX_TIDS; i++)
|
|
|
+ qdf_spinlock_create(&peer->rx_tid[i].tid_lock);
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+static inline
|
|
|
+void dp_peer_rx_tids_destroy(struct dp_peer *peer)
|
|
|
+{
|
|
|
+ uint8_t i;
|
|
|
+
|
|
|
+ if (!IS_MLO_DP_LINK_PEER(peer)) {
|
|
|
+ for (i = 0; i < DP_MAX_TIDS; i++)
|
|
|
+ qdf_spinlock_destroy(&peer->rx_tid[i].tid_lock);
|
|
|
+
|
|
|
+ qdf_mem_free(peer->rx_tid);
|
|
|
+ }
|
|
|
+
|
|
|
+ peer->rx_tid = NULL;
|
|
|
+}
|
|
|
#endif /* _DP_PEER_H_ */
|