IB/rdmavt/hfi1/qib: Use the MGID and MLID for multicast addressing
The Infiniband spec defines "A multicast address is defined by a MGID and a MLID" (section 10.5). The current code only uses the MGID for identifying multicast groups. Update the driver to be compliant with this definition. Reviewed-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com> Signed-off-by: Michael J. Ruhl <michael.j.ruhl@intel.com> Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
Родитель
8561eae60f
Коммит
aad9ff97dd
|
@ -604,7 +604,7 @@ void hfi1_ib_rcv(struct hfi1_packet *packet)
|
||||||
|
|
||||||
if (lnh != HFI1_LRH_GRH)
|
if (lnh != HFI1_LRH_GRH)
|
||||||
goto drop;
|
goto drop;
|
||||||
mcast = rvt_mcast_find(&ibp->rvp, &hdr->u.l.grh.dgid);
|
mcast = rvt_mcast_find(&ibp->rvp, &hdr->u.l.grh.dgid, lid);
|
||||||
if (!mcast)
|
if (!mcast)
|
||||||
goto drop;
|
goto drop;
|
||||||
list_for_each_entry_rcu(p, &mcast->qp_list, list) {
|
list_for_each_entry_rcu(p, &mcast->qp_list, list) {
|
||||||
|
|
|
@ -356,7 +356,7 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen)
|
||||||
|
|
||||||
if (lnh != QIB_LRH_GRH)
|
if (lnh != QIB_LRH_GRH)
|
||||||
goto drop;
|
goto drop;
|
||||||
mcast = rvt_mcast_find(&ibp->rvp, &hdr->u.l.grh.dgid);
|
mcast = rvt_mcast_find(&ibp->rvp, &hdr->u.l.grh.dgid, lid);
|
||||||
if (mcast == NULL)
|
if (mcast == NULL)
|
||||||
goto drop;
|
goto drop;
|
||||||
this_cpu_inc(ibp->pmastats->n_multicast_rcv);
|
this_cpu_inc(ibp->pmastats->n_multicast_rcv);
|
||||||
|
|
|
@ -100,10 +100,11 @@ static void rvt_mcast_qp_free(struct rvt_mcast_qp *mqp)
|
||||||
/**
|
/**
|
||||||
* mcast_alloc - allocate the multicast GID structure
|
* mcast_alloc - allocate the multicast GID structure
|
||||||
* @mgid: the multicast GID
|
* @mgid: the multicast GID
|
||||||
|
* @lid: the muilticast LID (host order)
|
||||||
*
|
*
|
||||||
* A list of QPs will be attached to this structure.
|
* A list of QPs will be attached to this structure.
|
||||||
*/
|
*/
|
||||||
static struct rvt_mcast *rvt_mcast_alloc(union ib_gid *mgid)
|
static struct rvt_mcast *rvt_mcast_alloc(union ib_gid *mgid, u16 lid)
|
||||||
{
|
{
|
||||||
struct rvt_mcast *mcast;
|
struct rvt_mcast *mcast;
|
||||||
|
|
||||||
|
@ -111,7 +112,9 @@ static struct rvt_mcast *rvt_mcast_alloc(union ib_gid *mgid)
|
||||||
if (!mcast)
|
if (!mcast)
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
||||||
mcast->mgid = *mgid;
|
mcast->mcast_addr.mgid = *mgid;
|
||||||
|
mcast->mcast_addr.lid = lid;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&mcast->qp_list);
|
INIT_LIST_HEAD(&mcast->qp_list);
|
||||||
init_waitqueue_head(&mcast->wait);
|
init_waitqueue_head(&mcast->wait);
|
||||||
atomic_set(&mcast->refcount, 0);
|
atomic_set(&mcast->refcount, 0);
|
||||||
|
@ -131,15 +134,19 @@ static void rvt_mcast_free(struct rvt_mcast *mcast)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rvt_mcast_find - search the global table for the given multicast GID
|
* rvt_mcast_find - search the global table for the given multicast GID/LID
|
||||||
|
* NOTE: It is valid to have 1 MLID with multiple MGIDs. It is not valid
|
||||||
|
* to have 1 MGID with multiple MLIDs.
|
||||||
* @ibp: the IB port structure
|
* @ibp: the IB port structure
|
||||||
* @mgid: the multicast GID to search for
|
* @mgid: the multicast GID to search for
|
||||||
|
* @lid: the multicast LID portion of the multicast address (host order)
|
||||||
*
|
*
|
||||||
* The caller is responsible for decrementing the reference count if found.
|
* The caller is responsible for decrementing the reference count if found.
|
||||||
*
|
*
|
||||||
* Return: NULL if not found.
|
* Return: NULL if not found.
|
||||||
*/
|
*/
|
||||||
struct rvt_mcast *rvt_mcast_find(struct rvt_ibport *ibp, union ib_gid *mgid)
|
struct rvt_mcast *rvt_mcast_find(struct rvt_ibport *ibp, union ib_gid *mgid,
|
||||||
|
u16 lid)
|
||||||
{
|
{
|
||||||
struct rb_node *n;
|
struct rb_node *n;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -153,15 +160,18 @@ struct rvt_mcast *rvt_mcast_find(struct rvt_ibport *ibp, union ib_gid *mgid)
|
||||||
|
|
||||||
mcast = rb_entry(n, struct rvt_mcast, rb_node);
|
mcast = rb_entry(n, struct rvt_mcast, rb_node);
|
||||||
|
|
||||||
ret = memcmp(mgid->raw, mcast->mgid.raw,
|
ret = memcmp(mgid->raw, mcast->mcast_addr.mgid.raw,
|
||||||
sizeof(union ib_gid));
|
sizeof(*mgid));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
n = n->rb_left;
|
n = n->rb_left;
|
||||||
} else if (ret > 0) {
|
} else if (ret > 0) {
|
||||||
n = n->rb_right;
|
n = n->rb_right;
|
||||||
} else {
|
} else {
|
||||||
|
/* MGID/MLID must match */
|
||||||
|
if (mcast->mcast_addr.lid == lid) {
|
||||||
atomic_inc(&mcast->refcount);
|
atomic_inc(&mcast->refcount);
|
||||||
found = mcast;
|
found = mcast;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,7 +187,8 @@ EXPORT_SYMBOL(rvt_mcast_find);
|
||||||
*
|
*
|
||||||
* Return: zero if both were added. Return EEXIST if the GID was already in
|
* Return: zero if both were added. Return EEXIST if the GID was already in
|
||||||
* the table but the QP was added. Return ESRCH if the QP was already
|
* the table but the QP was added. Return ESRCH if the QP was already
|
||||||
* attached and neither structure was added.
|
* attached and neither structure was added. Return EINVAL if the MGID was
|
||||||
|
* found, but the MLID did NOT match.
|
||||||
*/
|
*/
|
||||||
static int rvt_mcast_add(struct rvt_dev_info *rdi, struct rvt_ibport *ibp,
|
static int rvt_mcast_add(struct rvt_dev_info *rdi, struct rvt_ibport *ibp,
|
||||||
struct rvt_mcast *mcast, struct rvt_mcast_qp *mqp)
|
struct rvt_mcast *mcast, struct rvt_mcast_qp *mqp)
|
||||||
|
@ -195,8 +206,9 @@ static int rvt_mcast_add(struct rvt_dev_info *rdi, struct rvt_ibport *ibp,
|
||||||
pn = *n;
|
pn = *n;
|
||||||
tmcast = rb_entry(pn, struct rvt_mcast, rb_node);
|
tmcast = rb_entry(pn, struct rvt_mcast, rb_node);
|
||||||
|
|
||||||
ret = memcmp(mcast->mgid.raw, tmcast->mgid.raw,
|
ret = memcmp(mcast->mcast_addr.mgid.raw,
|
||||||
sizeof(union ib_gid));
|
tmcast->mcast_addr.mgid.raw,
|
||||||
|
sizeof(mcast->mcast_addr.mgid));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
n = &pn->rb_left;
|
n = &pn->rb_left;
|
||||||
continue;
|
continue;
|
||||||
|
@ -206,6 +218,11 @@ static int rvt_mcast_add(struct rvt_dev_info *rdi, struct rvt_ibport *ibp,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tmcast->mcast_addr.lid != mcast->mcast_addr.lid) {
|
||||||
|
ret = EINVAL;
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
/* Search the QP list to see if this is already there. */
|
/* Search the QP list to see if this is already there. */
|
||||||
list_for_each_entry_rcu(p, &tmcast->qp_list, list) {
|
list_for_each_entry_rcu(p, &tmcast->qp_list, list) {
|
||||||
if (p->qp == mqp->qp) {
|
if (p->qp == mqp->qp) {
|
||||||
|
@ -276,7 +293,7 @@ int rvt_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||||
* Allocate data structures since its better to do this outside of
|
* Allocate data structures since its better to do this outside of
|
||||||
* spin locks and it will most likely be needed.
|
* spin locks and it will most likely be needed.
|
||||||
*/
|
*/
|
||||||
mcast = rvt_mcast_alloc(gid);
|
mcast = rvt_mcast_alloc(gid, lid);
|
||||||
if (!mcast)
|
if (!mcast)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -296,6 +313,10 @@ int rvt_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||||
/* Exceeded the maximum number of mcast groups. */
|
/* Exceeded the maximum number of mcast groups. */
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto bail_mqp;
|
goto bail_mqp;
|
||||||
|
case EINVAL:
|
||||||
|
/* Invalid MGID/MLID pair */
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto bail_mqp;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -344,15 +365,21 @@ int rvt_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||||
}
|
}
|
||||||
|
|
||||||
mcast = rb_entry(n, struct rvt_mcast, rb_node);
|
mcast = rb_entry(n, struct rvt_mcast, rb_node);
|
||||||
ret = memcmp(gid->raw, mcast->mgid.raw,
|
ret = memcmp(gid->raw, mcast->mcast_addr.mgid.raw,
|
||||||
sizeof(union ib_gid));
|
sizeof(*gid));
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
n = n->rb_left;
|
n = n->rb_left;
|
||||||
else if (ret > 0)
|
} else if (ret > 0) {
|
||||||
n = n->rb_right;
|
n = n->rb_right;
|
||||||
else
|
} else {
|
||||||
|
/* MGID/MLID must match */
|
||||||
|
if (mcast->mcast_addr.lid != lid) {
|
||||||
|
spin_unlock_irq(&ibp->lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Search the QP list. */
|
/* Search the QP list. */
|
||||||
list_for_each_entry_safe(p, tmp, &mcast->qp_list, list) {
|
list_for_each_entry_safe(p, tmp, &mcast->qp_list, list) {
|
||||||
|
|
|
@ -516,6 +516,7 @@ int rvt_rkey_ok(struct rvt_qp *qp, struct rvt_sge *sge,
|
||||||
u32 len, u64 vaddr, u32 rkey, int acc);
|
u32 len, u64 vaddr, u32 rkey, int acc);
|
||||||
int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd,
|
int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd,
|
||||||
struct rvt_sge *isge, struct ib_sge *sge, int acc);
|
struct rvt_sge *isge, struct ib_sge *sge, int acc);
|
||||||
struct rvt_mcast *rvt_mcast_find(struct rvt_ibport *ibp, union ib_gid *mgid);
|
struct rvt_mcast *rvt_mcast_find(struct rvt_ibport *ibp, union ib_gid *mgid,
|
||||||
|
u16 lid);
|
||||||
|
|
||||||
#endif /* DEF_RDMA_VT_H */
|
#endif /* DEF_RDMA_VT_H */
|
||||||
|
|
|
@ -435,9 +435,14 @@ struct rvt_mcast_qp {
|
||||||
struct rvt_qp *qp;
|
struct rvt_qp *qp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rvt_mcast_addr {
|
||||||
|
union ib_gid mgid;
|
||||||
|
u16 lid;
|
||||||
|
};
|
||||||
|
|
||||||
struct rvt_mcast {
|
struct rvt_mcast {
|
||||||
struct rb_node rb_node;
|
struct rb_node rb_node;
|
||||||
union ib_gid mgid;
|
struct rvt_mcast_addr mcast_addr;
|
||||||
struct list_head qp_list;
|
struct list_head qp_list;
|
||||||
wait_queue_head_t wait;
|
wait_queue_head_t wait;
|
||||||
atomic_t refcount;
|
atomic_t refcount;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче