// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* * Copyright (c) 2022 Hewlett Packard Enterprise, Inc. All rights reserved. * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved. * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved. */ /* * rxe_mcast.c implements driver support for multicast transport. * It is based on two data structures struct rxe_mcg ('mcg') and * struct rxe_mca ('mca'). An mcg is allocated each time a qp is * attached to a new mgid for the first time. These are indexed by * a red-black tree using the mgid. This data structure is searched * for the mcg when a multicast packet is received and when another * qp is attached to the same mgid. It is cleaned up when the last qp * is detached from the mcg. Each time a qp is attached to an mcg an * mca is created. It holds a pointer to the qp and is added to a list * of qp's that are attached to the mcg. The qp_list is used to replicate * mcast packets in the rxe receive path. */ #include "rxe.h" /** * rxe_mcast_add - add multicast address to rxe device * @rxe: rxe device object * @mgid: multicast address as a gid * * Returns 0 on success else an error */ static int rxe_mcast_add(struct rxe_dev *rxe, union ib_gid *mgid) { … } /** * rxe_mcast_del - delete multicast address from rxe device * @rxe: rxe device object * @mgid: multicast address as a gid * * Returns 0 on success else an error */ static int rxe_mcast_del(struct rxe_dev *rxe, union ib_gid *mgid) { … } /** * __rxe_insert_mcg - insert an mcg into red-black tree (rxe->mcg_tree) * @mcg: mcg object with an embedded red-black tree node * * Context: caller must hold a reference to mcg and rxe->mcg_lock and * is responsible to avoid adding the same mcg twice to the tree. */ static void __rxe_insert_mcg(struct rxe_mcg *mcg) { … } /** * __rxe_remove_mcg - remove an mcg from red-black tree holding lock * @mcg: mcast group object with an embedded red-black tree node * * Context: caller must hold a reference to mcg and rxe->mcg_lock */ static void __rxe_remove_mcg(struct rxe_mcg *mcg) { … } /** * __rxe_lookup_mcg - lookup mcg in rxe->mcg_tree while holding lock * @rxe: rxe device object * @mgid: multicast IP address * * Context: caller must hold rxe->mcg_lock * Returns: mcg on success and takes a ref to mcg else NULL */ static struct rxe_mcg *__rxe_lookup_mcg(struct rxe_dev *rxe, union ib_gid *mgid) { … } /** * rxe_lookup_mcg - lookup up mcg in red-back tree * @rxe: rxe device object * @mgid: multicast IP address * * Returns: mcg if found else NULL */ struct rxe_mcg *rxe_lookup_mcg(struct rxe_dev *rxe, union ib_gid *mgid) { … } /** * __rxe_init_mcg - initialize a new mcg * @rxe: rxe device * @mgid: multicast address as a gid * @mcg: new mcg object * * Context: caller should hold rxe->mcg lock */ static void __rxe_init_mcg(struct rxe_dev *rxe, union ib_gid *mgid, struct rxe_mcg *mcg) { … } /** * rxe_get_mcg - lookup or allocate a mcg * @rxe: rxe device object * @mgid: multicast IP address as a gid * * Returns: mcg on success else ERR_PTR(error) */ static struct rxe_mcg *rxe_get_mcg(struct rxe_dev *rxe, union ib_gid *mgid) { … } /** * rxe_cleanup_mcg - cleanup mcg for kref_put * @kref: struct kref embnedded in mcg */ void rxe_cleanup_mcg(struct kref *kref) { … } /** * __rxe_destroy_mcg - destroy mcg object holding rxe->mcg_lock * @mcg: the mcg object * * Context: caller is holding rxe->mcg_lock * no qp's are attached to mcg */ static void __rxe_destroy_mcg(struct rxe_mcg *mcg) { … } /** * rxe_destroy_mcg - destroy mcg object * @mcg: the mcg object * * Context: no qp's are attached to mcg */ static void rxe_destroy_mcg(struct rxe_mcg *mcg) { … } /** * __rxe_init_mca - initialize a new mca holding lock * @qp: qp object * @mcg: mcg object * @mca: empty space for new mca * * Context: caller must hold references on qp and mcg, rxe->mcg_lock * and pass memory for new mca * * Returns: 0 on success else an error */ static int __rxe_init_mca(struct rxe_qp *qp, struct rxe_mcg *mcg, struct rxe_mca *mca) { … } /** * rxe_attach_mcg - attach qp to mcg if not already attached * @qp: qp object * @mcg: mcg object * * Context: caller must hold reference on qp and mcg. * Returns: 0 on success else an error */ static int rxe_attach_mcg(struct rxe_mcg *mcg, struct rxe_qp *qp) { … } /** * __rxe_cleanup_mca - cleanup mca object holding lock * @mca: mca object * @mcg: mcg object * * Context: caller must hold a reference to mcg and rxe->mcg_lock */ static void __rxe_cleanup_mca(struct rxe_mca *mca, struct rxe_mcg *mcg) { … } /** * rxe_detach_mcg - detach qp from mcg * @mcg: mcg object * @qp: qp object * * Returns: 0 on success else an error if qp is not attached. */ static int rxe_detach_mcg(struct rxe_mcg *mcg, struct rxe_qp *qp) { … } /** * rxe_attach_mcast - attach qp to multicast group (see IBA-11.3.1) * @ibqp: (IB) qp object * @mgid: multicast IP address * @mlid: multicast LID, ignored for RoCEv2 (see IBA-A17.5.6) * * Returns: 0 on success else an errno */ int rxe_attach_mcast(struct ib_qp *ibqp, union ib_gid *mgid, u16 mlid) { … } /** * rxe_detach_mcast - detach qp from multicast group (see IBA-11.3.2) * @ibqp: address of (IB) qp object * @mgid: multicast IP address * @mlid: multicast LID, ignored for RoCEv2 (see IBA-A17.5.6) * * Returns: 0 on success else an errno */ int rxe_detach_mcast(struct ib_qp *ibqp, union ib_gid *mgid, u16 mlid) { … }