Commit c88bd03f authored by Naresh Gottumukkala's avatar Naresh Gottumukkala Committed by Roland Dreier

RDMA/ocrdma: Fix to work with even a single MSI-X vector

There are cases like SRIOV where can get only one MSI-X vector
allocated for RoCE.  In that case we need to use the vector for both
data plane and control plane.  We need to use EQ create version V2.
Signed-off-by: default avatarNaresh Gottumukkala <bgottumukkala@emulex.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent d3cb6c0b
...@@ -132,8 +132,7 @@ struct ocrdma_dev { ...@@ -132,8 +132,7 @@ struct ocrdma_dev {
struct ocrdma_cq **cq_tbl; struct ocrdma_cq **cq_tbl;
struct ocrdma_qp **qp_tbl; struct ocrdma_qp **qp_tbl;
struct ocrdma_eq meq; struct ocrdma_eq *eq_tbl;
struct ocrdma_eq *qp_eq_tbl;
int eq_cnt; int eq_cnt;
u16 base_eqid; u16 base_eqid;
u16 max_eq; u16 max_eq;
......
...@@ -364,22 +364,6 @@ static void ocrdma_build_q_pages(struct ocrdma_pa *q_pa, int cnt, ...@@ -364,22 +364,6 @@ static void ocrdma_build_q_pages(struct ocrdma_pa *q_pa, int cnt,
} }
} }
static void ocrdma_assign_eq_vect_gen2(struct ocrdma_dev *dev,
struct ocrdma_eq *eq)
{
/* assign vector and update vector id for next EQ */
eq->vector = dev->nic_info.msix.start_vector;
dev->nic_info.msix.start_vector += 1;
}
static void ocrdma_free_eq_vect_gen2(struct ocrdma_dev *dev)
{
/* this assumes that EQs are freed in exactly reverse order
* as its allocation.
*/
dev->nic_info.msix.start_vector -= 1;
}
static int ocrdma_mbx_delete_q(struct ocrdma_dev *dev, struct ocrdma_queue_info *q, static int ocrdma_mbx_delete_q(struct ocrdma_dev *dev, struct ocrdma_queue_info *q,
int queue_type) int queue_type)
{ {
...@@ -420,11 +404,8 @@ static int ocrdma_mbx_create_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq) ...@@ -420,11 +404,8 @@ static int ocrdma_mbx_create_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
memset(cmd, 0, sizeof(*cmd)); memset(cmd, 0, sizeof(*cmd));
ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_EQ, OCRDMA_SUBSYS_COMMON, ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_EQ, OCRDMA_SUBSYS_COMMON,
sizeof(*cmd)); sizeof(*cmd));
if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY)
cmd->req.rsvd_version = 0;
else
cmd->req.rsvd_version = 2;
cmd->req.rsvd_version = 2;
cmd->num_pages = 4; cmd->num_pages = 4;
cmd->valid = OCRDMA_CREATE_EQ_VALID; cmd->valid = OCRDMA_CREATE_EQ_VALID;
cmd->cnt = 4 << OCRDMA_CREATE_EQ_CNT_SHIFT; cmd->cnt = 4 << OCRDMA_CREATE_EQ_CNT_SHIFT;
...@@ -435,12 +416,7 @@ static int ocrdma_mbx_create_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq) ...@@ -435,12 +416,7 @@ static int ocrdma_mbx_create_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
NULL); NULL);
if (!status) { if (!status) {
eq->q.id = rsp->vector_eqid & 0xffff; eq->q.id = rsp->vector_eqid & 0xffff;
if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) {
ocrdma_assign_eq_vect_gen2(dev, eq);
} else {
eq->vector = (rsp->vector_eqid >> 16) & 0xffff; eq->vector = (rsp->vector_eqid >> 16) & 0xffff;
dev->nic_info.msix.start_vector += 1;
}
eq->q.created = true; eq->q.created = true;
} }
return status; return status;
...@@ -483,8 +459,6 @@ static void _ocrdma_destroy_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq) ...@@ -483,8 +459,6 @@ static void _ocrdma_destroy_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
{ {
if (eq->q.created) { if (eq->q.created) {
ocrdma_mbx_delete_q(dev, &eq->q, QTYPE_EQ); ocrdma_mbx_delete_q(dev, &eq->q, QTYPE_EQ);
if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY)
ocrdma_free_eq_vect_gen2(dev);
ocrdma_free_q(dev, &eq->q); ocrdma_free_q(dev, &eq->q);
} }
} }
...@@ -503,13 +477,12 @@ static void ocrdma_destroy_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq) ...@@ -503,13 +477,12 @@ static void ocrdma_destroy_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
_ocrdma_destroy_eq(dev, eq); _ocrdma_destroy_eq(dev, eq);
} }
static void ocrdma_destroy_qp_eqs(struct ocrdma_dev *dev) static void ocrdma_destroy_eqs(struct ocrdma_dev *dev)
{ {
int i; int i;
/* deallocate the data path eqs */
for (i = 0; i < dev->eq_cnt; i++) for (i = 0; i < dev->eq_cnt; i++)
ocrdma_destroy_eq(dev, &dev->qp_eq_tbl[i]); ocrdma_destroy_eq(dev, &dev->eq_tbl[i]);
} }
static int ocrdma_mbx_mq_cq_create(struct ocrdma_dev *dev, static int ocrdma_mbx_mq_cq_create(struct ocrdma_dev *dev,
...@@ -598,7 +571,7 @@ static int ocrdma_create_mq(struct ocrdma_dev *dev) ...@@ -598,7 +571,7 @@ static int ocrdma_create_mq(struct ocrdma_dev *dev)
if (status) if (status)
goto alloc_err; goto alloc_err;
status = ocrdma_mbx_mq_cq_create(dev, &dev->mq.cq, &dev->meq.q); status = ocrdma_mbx_mq_cq_create(dev, &dev->mq.cq, &dev->eq_tbl[0].q);
if (status) if (status)
goto mbx_cq_free; goto mbx_cq_free;
...@@ -1304,19 +1277,19 @@ static u16 ocrdma_bind_eq(struct ocrdma_dev *dev) ...@@ -1304,19 +1277,19 @@ static u16 ocrdma_bind_eq(struct ocrdma_dev *dev)
u16 eq_id; u16 eq_id;
mutex_lock(&dev->dev_lock); mutex_lock(&dev->dev_lock);
cq_cnt = dev->qp_eq_tbl[0].cq_cnt; cq_cnt = dev->eq_tbl[0].cq_cnt;
eq_id = dev->qp_eq_tbl[0].q.id; eq_id = dev->eq_tbl[0].q.id;
/* find the EQ which is has the least number of /* find the EQ which is has the least number of
* CQs associated with it. * CQs associated with it.
*/ */
for (i = 0; i < dev->eq_cnt; i++) { for (i = 0; i < dev->eq_cnt; i++) {
if (dev->qp_eq_tbl[i].cq_cnt < cq_cnt) { if (dev->eq_tbl[i].cq_cnt < cq_cnt) {
cq_cnt = dev->qp_eq_tbl[i].cq_cnt; cq_cnt = dev->eq_tbl[i].cq_cnt;
eq_id = dev->qp_eq_tbl[i].q.id; eq_id = dev->eq_tbl[i].q.id;
selected_eq = i; selected_eq = i;
} }
} }
dev->qp_eq_tbl[selected_eq].cq_cnt += 1; dev->eq_tbl[selected_eq].cq_cnt += 1;
mutex_unlock(&dev->dev_lock); mutex_unlock(&dev->dev_lock);
return eq_id; return eq_id;
} }
...@@ -1327,9 +1300,9 @@ static void ocrdma_unbind_eq(struct ocrdma_dev *dev, u16 eq_id) ...@@ -1327,9 +1300,9 @@ static void ocrdma_unbind_eq(struct ocrdma_dev *dev, u16 eq_id)
mutex_lock(&dev->dev_lock); mutex_lock(&dev->dev_lock);
for (i = 0; i < dev->eq_cnt; i++) { for (i = 0; i < dev->eq_cnt; i++) {
if (dev->qp_eq_tbl[i].q.id != eq_id) if (dev->eq_tbl[i].q.id != eq_id)
continue; continue;
dev->qp_eq_tbl[i].cq_cnt -= 1; dev->eq_tbl[i].cq_cnt -= 1;
break; break;
} }
mutex_unlock(&dev->dev_lock); mutex_unlock(&dev->dev_lock);
...@@ -2434,38 +2407,7 @@ int ocrdma_free_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah) ...@@ -2434,38 +2407,7 @@ int ocrdma_free_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
return 0; return 0;
} }
static int ocrdma_create_mq_eq(struct ocrdma_dev *dev) static int ocrdma_create_eqs(struct ocrdma_dev *dev)
{
int status;
int irq;
unsigned long flags = 0;
int num_eq = 0;
if (dev->nic_info.intr_mode == BE_INTERRUPT_MODE_INTX) {
flags = IRQF_SHARED;
} else {
num_eq = dev->nic_info.msix.num_vectors -
dev->nic_info.msix.start_vector;
/* minimum two vectors/eq are required for rdma to work.
* one for control path and one for data path.
*/
if (num_eq < 2)
return -EBUSY;
}
status = ocrdma_create_eq(dev, &dev->meq, OCRDMA_EQ_LEN);
if (status)
return status;
sprintf(dev->meq.irq_name, "ocrdma_mq%d", dev->id);
irq = ocrdma_get_irq(dev, &dev->meq);
status = request_irq(irq, ocrdma_irq_handler, flags, dev->meq.irq_name,
&dev->meq);
if (status)
_ocrdma_destroy_eq(dev, &dev->meq);
return status;
}
static int ocrdma_create_qp_eqs(struct ocrdma_dev *dev)
{ {
int num_eq, i, status = 0; int num_eq, i, status = 0;
int irq; int irq;
...@@ -2480,46 +2422,43 @@ static int ocrdma_create_qp_eqs(struct ocrdma_dev *dev) ...@@ -2480,46 +2422,43 @@ static int ocrdma_create_qp_eqs(struct ocrdma_dev *dev)
num_eq = min_t(u32, num_eq, num_online_cpus()); num_eq = min_t(u32, num_eq, num_online_cpus());
} }
dev->qp_eq_tbl = kzalloc(sizeof(struct ocrdma_eq) * num_eq, GFP_KERNEL); if (!num_eq)
if (!dev->qp_eq_tbl) return -EINVAL;
dev->eq_tbl = kzalloc(sizeof(struct ocrdma_eq) * num_eq, GFP_KERNEL);
if (!dev->eq_tbl)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < num_eq; i++) { for (i = 0; i < num_eq; i++) {
status = ocrdma_create_eq(dev, &dev->qp_eq_tbl[i], status = ocrdma_create_eq(dev, &dev->eq_tbl[i],
OCRDMA_EQ_LEN); OCRDMA_EQ_LEN);
if (status) { if (status) {
status = -EINVAL; status = -EINVAL;
break; break;
} }
sprintf(dev->qp_eq_tbl[i].irq_name, "ocrdma_qp%d-%d", sprintf(dev->eq_tbl[i].irq_name, "ocrdma%d-%d",
dev->id, i); dev->id, i);
irq = ocrdma_get_irq(dev, &dev->qp_eq_tbl[i]); irq = ocrdma_get_irq(dev, &dev->eq_tbl[i]);
status = request_irq(irq, ocrdma_irq_handler, flags, status = request_irq(irq, ocrdma_irq_handler, flags,
dev->qp_eq_tbl[i].irq_name, dev->eq_tbl[i].irq_name,
&dev->qp_eq_tbl[i]); &dev->eq_tbl[i]);
if (status) { if (status)
_ocrdma_destroy_eq(dev, &dev->qp_eq_tbl[i]); goto done;
status = -EINVAL;
break;
}
dev->eq_cnt += 1; dev->eq_cnt += 1;
} }
/* one eq is sufficient for data path to work */ /* one eq is sufficient for data path to work */
if (dev->eq_cnt >= 1)
return 0; return 0;
ocrdma_destroy_qp_eqs(dev); done:
ocrdma_destroy_eqs(dev);
return status; return status;
} }
int ocrdma_init_hw(struct ocrdma_dev *dev) int ocrdma_init_hw(struct ocrdma_dev *dev)
{ {
int status; int status;
/* set up control path eq */
status = ocrdma_create_mq_eq(dev); /* create the eqs */
if (status) status = ocrdma_create_eqs(dev);
return status;
/* set up data path eq */
status = ocrdma_create_qp_eqs(dev);
if (status) if (status)
goto qpeq_err; goto qpeq_err;
status = ocrdma_create_mq(dev); status = ocrdma_create_mq(dev);
...@@ -2542,9 +2481,8 @@ int ocrdma_init_hw(struct ocrdma_dev *dev) ...@@ -2542,9 +2481,8 @@ int ocrdma_init_hw(struct ocrdma_dev *dev)
conf_err: conf_err:
ocrdma_destroy_mq(dev); ocrdma_destroy_mq(dev);
mq_err: mq_err:
ocrdma_destroy_qp_eqs(dev); ocrdma_destroy_eqs(dev);
qpeq_err: qpeq_err:
ocrdma_destroy_eq(dev, &dev->meq);
pr_err("%s() status=%d\n", __func__, status); pr_err("%s() status=%d\n", __func__, status);
return status; return status;
} }
...@@ -2553,10 +2491,9 @@ void ocrdma_cleanup_hw(struct ocrdma_dev *dev) ...@@ -2553,10 +2491,9 @@ void ocrdma_cleanup_hw(struct ocrdma_dev *dev)
{ {
ocrdma_mbx_delete_ah_tbl(dev); ocrdma_mbx_delete_ah_tbl(dev);
/* cleanup the data path eqs */ /* cleanup the eqs */
ocrdma_destroy_qp_eqs(dev); ocrdma_destroy_eqs(dev);
/* cleanup the control path */ /* cleanup the control path */
ocrdma_destroy_mq(dev); ocrdma_destroy_mq(dev);
ocrdma_destroy_eq(dev, &dev->meq);
} }
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