Commit 8bc205ef authored by Leon Romanovsky's avatar Leon Romanovsky Committed by Jason Gunthorpe

RDMA/counter: Combine allocation and bind logic

RDMA counters are allocated and bounded to QP immediately after that.
Only after this two step process they are really usable. By combining
the logic, we are ensuring that once counter is returned to the caller,
it will have everything set.

Link: https://lore.kernel.org/r/20201104144008.3808124-3-leon@kernel.orgSigned-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 7af80c02
...@@ -64,7 +64,39 @@ int rdma_counter_set_auto_mode(struct ib_device *dev, u8 port, ...@@ -64,7 +64,39 @@ int rdma_counter_set_auto_mode(struct ib_device *dev, u8 port,
return ret; return ret;
} }
static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port, static void auto_mode_init_counter(struct rdma_counter *counter,
const struct ib_qp *qp,
enum rdma_nl_counter_mask new_mask)
{
struct auto_mode_param *param = &counter->mode.param;
counter->mode.mode = RDMA_COUNTER_MODE_AUTO;
counter->mode.mask = new_mask;
if (new_mask & RDMA_COUNTER_MASK_QP_TYPE)
param->qp_type = qp->qp_type;
}
static int __rdma_counter_bind_qp(struct rdma_counter *counter,
struct ib_qp *qp)
{
int ret;
if (qp->counter)
return -EINVAL;
if (!qp->device->ops.counter_bind_qp)
return -EOPNOTSUPP;
mutex_lock(&counter->lock);
ret = qp->device->ops.counter_bind_qp(counter, qp);
mutex_unlock(&counter->lock);
return ret;
}
static struct rdma_counter *alloc_and_bind(struct ib_device *dev, u8 port,
struct ib_qp *qp,
enum rdma_nl_counter_mode mode) enum rdma_nl_counter_mode mode)
{ {
struct rdma_port_counter *port_counter; struct rdma_port_counter *port_counter;
...@@ -88,10 +120,21 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port, ...@@ -88,10 +120,21 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port,
port_counter = &dev->port_data[port].port_counter; port_counter = &dev->port_data[port].port_counter;
mutex_lock(&port_counter->lock); mutex_lock(&port_counter->lock);
if (mode == RDMA_COUNTER_MODE_MANUAL) { switch (mode) {
case RDMA_COUNTER_MODE_MANUAL:
ret = __counter_set_mode(&port_counter->mode, ret = __counter_set_mode(&port_counter->mode,
RDMA_COUNTER_MODE_MANUAL, 0); RDMA_COUNTER_MODE_MANUAL, 0);
if (ret) if (ret) {
mutex_unlock(&port_counter->lock);
goto err_mode;
}
break;
case RDMA_COUNTER_MODE_AUTO:
auto_mode_init_counter(counter, qp, port_counter->mode.mask);
break;
default:
ret = -EOPNOTSUPP;
mutex_unlock(&port_counter->lock);
goto err_mode; goto err_mode;
} }
...@@ -102,10 +145,15 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port, ...@@ -102,10 +145,15 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port,
kref_init(&counter->kref); kref_init(&counter->kref);
mutex_init(&counter->lock); mutex_init(&counter->lock);
ret = __rdma_counter_bind_qp(counter, qp);
if (ret)
goto err_mode;
rdma_restrack_parent_name(&counter->res, &qp->res);
rdma_restrack_add(&counter->res);
return counter; return counter;
err_mode: err_mode:
mutex_unlock(&port_counter->lock);
kfree(counter->stats); kfree(counter->stats);
err_stats: err_stats:
rdma_restrack_put(&counter->res); rdma_restrack_put(&counter->res);
...@@ -132,19 +180,6 @@ static void rdma_counter_free(struct rdma_counter *counter) ...@@ -132,19 +180,6 @@ static void rdma_counter_free(struct rdma_counter *counter)
kfree(counter); kfree(counter);
} }
static void auto_mode_init_counter(struct rdma_counter *counter,
const struct ib_qp *qp,
enum rdma_nl_counter_mask new_mask)
{
struct auto_mode_param *param = &counter->mode.param;
counter->mode.mode = RDMA_COUNTER_MODE_AUTO;
counter->mode.mask = new_mask;
if (new_mask & RDMA_COUNTER_MASK_QP_TYPE)
param->qp_type = qp->qp_type;
}
static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter, static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,
enum rdma_nl_counter_mask auto_mask) enum rdma_nl_counter_mask auto_mask)
{ {
...@@ -161,24 +196,6 @@ static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter, ...@@ -161,24 +196,6 @@ static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,
return match; return match;
} }
static int __rdma_counter_bind_qp(struct rdma_counter *counter,
struct ib_qp *qp)
{
int ret;
if (qp->counter)
return -EINVAL;
if (!qp->device->ops.counter_bind_qp)
return -EOPNOTSUPP;
mutex_lock(&counter->lock);
ret = qp->device->ops.counter_bind_qp(counter, qp);
mutex_unlock(&counter->lock);
return ret;
}
static int __rdma_counter_unbind_qp(struct ib_qp *qp) static int __rdma_counter_unbind_qp(struct ib_qp *qp)
{ {
struct rdma_counter *counter = qp->counter; struct rdma_counter *counter = qp->counter;
...@@ -247,13 +264,6 @@ static struct rdma_counter *rdma_get_counter_auto_mode(struct ib_qp *qp, ...@@ -247,13 +264,6 @@ static struct rdma_counter *rdma_get_counter_auto_mode(struct ib_qp *qp,
return counter; return counter;
} }
static void rdma_counter_res_add(struct rdma_counter *counter,
struct ib_qp *qp)
{
rdma_restrack_parent_name(&counter->res, &qp->res);
rdma_restrack_add(&counter->res);
}
static void counter_release(struct kref *kref) static void counter_release(struct kref *kref)
{ {
struct rdma_counter *counter; struct rdma_counter *counter;
...@@ -293,19 +303,9 @@ int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port) ...@@ -293,19 +303,9 @@ int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port)
return ret; return ret;
} }
} else { } else {
counter = rdma_counter_alloc(dev, port, RDMA_COUNTER_MODE_AUTO); counter = alloc_and_bind(dev, port, qp, RDMA_COUNTER_MODE_AUTO);
if (!counter) if (!counter)
return -ENOMEM; return -ENOMEM;
auto_mode_init_counter(counter, qp, port_counter->mode.mask);
ret = __rdma_counter_bind_qp(counter, qp);
if (ret) {
rdma_counter_free(counter);
return ret;
}
rdma_counter_res_add(counter, qp);
} }
return 0; return 0;
...@@ -419,15 +419,6 @@ static struct ib_qp *rdma_counter_get_qp(struct ib_device *dev, u32 qp_num) ...@@ -419,15 +419,6 @@ static struct ib_qp *rdma_counter_get_qp(struct ib_device *dev, u32 qp_num)
return NULL; return NULL;
} }
static int rdma_counter_bind_qp_manual(struct rdma_counter *counter,
struct ib_qp *qp)
{
if ((counter->device != qp->device) || (counter->port != qp->port))
return -EINVAL;
return __rdma_counter_bind_qp(counter, qp);
}
static struct rdma_counter *rdma_get_counter_by_id(struct ib_device *dev, static struct rdma_counter *rdma_get_counter_by_id(struct ib_device *dev,
u32 counter_id) u32 counter_id)
{ {
...@@ -475,7 +466,12 @@ int rdma_counter_bind_qpn(struct ib_device *dev, u8 port, ...@@ -475,7 +466,12 @@ int rdma_counter_bind_qpn(struct ib_device *dev, u8 port,
goto err_task; goto err_task;
} }
ret = rdma_counter_bind_qp_manual(counter, qp); if ((counter->device != qp->device) || (counter->port != qp->port)) {
ret = -EINVAL;
goto err_task;
}
ret = __rdma_counter_bind_qp(counter, qp);
if (ret) if (ret)
goto err_task; goto err_task;
...@@ -520,26 +516,18 @@ int rdma_counter_bind_qpn_alloc(struct ib_device *dev, u8 port, ...@@ -520,26 +516,18 @@ int rdma_counter_bind_qpn_alloc(struct ib_device *dev, u8 port,
goto err; goto err;
} }
counter = rdma_counter_alloc(dev, port, RDMA_COUNTER_MODE_MANUAL); counter = alloc_and_bind(dev, port, qp, RDMA_COUNTER_MODE_MANUAL);
if (!counter) { if (!counter) {
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
} }
ret = rdma_counter_bind_qp_manual(counter, qp);
if (ret)
goto err_bind;
if (counter_id) if (counter_id)
*counter_id = counter->id; *counter_id = counter->id;
rdma_counter_res_add(counter, qp);
rdma_restrack_put(&qp->res); rdma_restrack_put(&qp->res);
return ret; return 0;
err_bind:
rdma_counter_free(counter);
err: err:
rdma_restrack_put(&qp->res); rdma_restrack_put(&qp->res);
return ret; return ret;
......
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