Commit d97099fe authored by Jason Gunthorpe's avatar Jason Gunthorpe

IB{cm, core}: Introduce and use ah_attr copy, move, replace APIs

Introduce AH attribute copy, move and replace APIs to be used by core and
provider drivers.

In CM code flow when ah attribute might be re-initialized twice while
processing incoming request, or initialized once while from path record
while sending out CM requests. Therefore use rdma_move_ah_attr API to
handle such scenarios instead of memcpy().

Provider drivers keeps a copy ah_attr during the lifetime of the ah.
Therefore, use rdma_replace_ah_attr() which conditionally release
reference to old ah_attr and holds reference to new attribute whose
referrence is released when the AH is freed.
Signed-off-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent 947c99ec
......@@ -474,7 +474,7 @@ static int cm_init_av_for_lap(struct cm_port *port, struct ib_wc *wc,
if (ret)
return ret;
memcpy(&av->ah_attr, &new_ah_attr, sizeof(new_ah_attr));
rdma_move_ah_attr(&av->ah_attr, &new_ah_attr);
return 0;
}
......@@ -569,7 +569,7 @@ static int cm_init_av_by_path(struct sa_path_rec *path, struct cm_av *av,
ret = add_cm_id_to_port_list(cm_id_priv, av, port);
if (ret)
return ret;
memcpy(&av->ah_attr, &new_ah_attr, sizeof(new_ah_attr));
rdma_move_ah_attr(&av->ah_attr, &new_ah_attr);
return 0;
}
......
......@@ -326,6 +326,60 @@ EXPORT_SYMBOL(ib_dealloc_pd);
/* Address handles */
/**
* rdma_copy_ah_attr - Copy rdma ah attribute from source to destination.
* @dest: Pointer to destination ah_attr. Contents of the destination
* pointer is assumed to be invalid and attribute are overwritten.
* @src: Pointer to source ah_attr.
*/
void rdma_copy_ah_attr(struct rdma_ah_attr *dest,
const struct rdma_ah_attr *src)
{
*dest = *src;
if (dest->grh.sgid_attr)
rdma_hold_gid_attr(dest->grh.sgid_attr);
}
EXPORT_SYMBOL(rdma_copy_ah_attr);
/**
* rdma_replace_ah_attr - Replace valid ah_attr with new new one.
* @old: Pointer to existing ah_attr which needs to be replaced.
* old is assumed to be valid or zero'd
* @new: Pointer to the new ah_attr.
*
* rdma_replace_ah_attr() first releases any reference in the old ah_attr if
* old the ah_attr is valid; after that it copies the new attribute and holds
* the reference to the replaced ah_attr.
*/
void rdma_replace_ah_attr(struct rdma_ah_attr *old,
const struct rdma_ah_attr *new)
{
rdma_destroy_ah_attr(old);
*old = *new;
if (old->grh.sgid_attr)
rdma_hold_gid_attr(old->grh.sgid_attr);
}
EXPORT_SYMBOL(rdma_replace_ah_attr);
/**
* rdma_move_ah_attr - Move ah_attr pointed by source to destination.
* @dest: Pointer to destination ah_attr to copy to.
* dest is assumed to be valid or zero'd
* @src: Pointer to the new ah_attr.
*
* rdma_move_ah_attr() first releases any reference in the destination ah_attr
* if it is valid. This also transfers ownership of internal references from
* src to dest, making src invalid in the process. No new reference of the src
* ah_attr is taken.
*/
void rdma_move_ah_attr(struct rdma_ah_attr *dest, struct rdma_ah_attr *src)
{
rdma_destroy_ah_attr(dest);
*dest = *src;
src->grh.sgid_attr = NULL;
}
EXPORT_SYMBOL(rdma_move_ah_attr);
/*
* Validate that the rdma_ah_attr is valid for the device before passing it
* off to the driver.
......
......@@ -2302,7 +2302,7 @@ struct ib_ah *qedr_create_ah(struct ib_pd *ibpd, struct rdma_ah_attr *attr,
if (!ah)
return ERR_PTR(-ENOMEM);
ah->attr = *attr;
rdma_copy_ah_attr(&ah->attr, attr);
return &ah->ibah;
}
......@@ -2311,6 +2311,7 @@ int qedr_destroy_ah(struct ib_ah *ibah)
{
struct qedr_ah *ah = get_qedr_ah(ibah);
rdma_destroy_ah_attr(&ah->attr);
kfree(ah);
return 0;
}
......
......@@ -120,7 +120,8 @@ struct ib_ah *rvt_create_ah(struct ib_pd *pd,
dev->n_ahs_allocated++;
spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
ah->attr = *ah_attr;
rdma_copy_ah_attr(&ah->attr, ah_attr);
atomic_set(&ah->refcount, 0);
if (dev->driver_f.notify_new_ah)
......@@ -148,6 +149,7 @@ int rvt_destroy_ah(struct ib_ah *ibah)
dev->n_ahs_allocated--;
spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
rdma_destroy_ah_attr(&ah->attr);
kfree(ah);
return 0;
......
......@@ -1336,13 +1336,13 @@ int rvt_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
qp->qp_access_flags = attr->qp_access_flags;
if (attr_mask & IB_QP_AV) {
qp->remote_ah_attr = attr->ah_attr;
rdma_replace_ah_attr(&qp->remote_ah_attr, &attr->ah_attr);
qp->s_srate = rdma_ah_get_static_rate(&attr->ah_attr);
qp->srate_mbps = ib_rate_to_mbps(qp->s_srate);
}
if (attr_mask & IB_QP_ALT_PATH) {
qp->alt_ah_attr = attr->alt_ah_attr;
rdma_replace_ah_attr(&qp->alt_ah_attr, &attr->alt_ah_attr);
qp->s_alt_pkey_index = attr->alt_pkey_index;
}
......@@ -1459,6 +1459,8 @@ int rvt_destroy_qp(struct ib_qp *ibqp)
vfree(qp->s_wq);
rdi->driver_f.qp_priv_free(rdi, qp);
kfree(qp->s_ack_queue);
rdma_destroy_ah_attr(&qp->remote_ah_attr);
rdma_destroy_ah_attr(&qp->alt_ah_attr);
kfree(qp);
return 0;
}
......
......@@ -4034,6 +4034,11 @@ void rdma_destroy_ah_attr(struct rdma_ah_attr *ah_attr);
void rdma_move_grh_sgid_attr(struct rdma_ah_attr *attr, union ib_gid *dgid,
u32 flow_label, u8 hop_limit, u8 traffic_class,
const struct ib_gid_attr *sgid_attr);
void rdma_copy_ah_attr(struct rdma_ah_attr *dest,
const struct rdma_ah_attr *src);
void rdma_replace_ah_attr(struct rdma_ah_attr *old,
const struct rdma_ah_attr *new);
void rdma_move_ah_attr(struct rdma_ah_attr *dest, struct rdma_ah_attr *src);
/**
* rdma_ah_find_type - Return address handle type.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment