aboutsummaryrefslogtreecommitdiff
path: root/drivers/infiniband/hw/ehca/ehca_cq.c
diff options
context:
space:
mode:
authorStefan Roscher <ossrosch@linux.vnet.ibm.com>2008-04-29 13:46:53 -0700
committerRoland Dreier <rolandd@cisco.com>2008-04-29 13:46:53 -0700
commitd227fa7288adebe5ba37fa8e4a589c977d4e4a34 (patch)
tree8e0f080fc78f0342b5fd2531615ea525333d8d25 /drivers/infiniband/hw/ehca/ehca_cq.c
parentf56bcd8013566d4ad4759ae5fc85a6660e4655c7 (diff)
IB/ehca: Allocate event queue size depending on max number of CQs and QPs
If a lot of QPs fall into Error state at once and the EQ of the respective HCA is too small, it might overrun, causing the eHCA driver to stop processing completion events and calling the application's completion handlers, effectively causing traffic to stop. Fix this by limiting available QPs and CQs to a customizable max count, and determining EQ size based on these counts and a worst-case assumption. Signed-off-by: Stefan Roscher <stefan.roscher@de.ibm.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ehca/ehca_cq.c')
-rw-r--r--drivers/infiniband/hw/ehca/ehca_cq.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index ec0cfcf3073..5540b276a33 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -132,10 +132,19 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
return ERR_PTR(-EINVAL);
+ if (!atomic_add_unless(&shca->num_cqs, 1, ehca_max_cq)) {
+ ehca_err(device, "Unable to create CQ, max number of %i "
+ "CQs reached.", ehca_max_cq);
+ ehca_err(device, "To increase the maximum number of CQs "
+ "use the number_of_cqs module parameter.\n");
+ return ERR_PTR(-ENOSPC);
+ }
+
my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL);
if (!my_cq) {
ehca_err(device, "Out of memory for ehca_cq struct device=%p",
device);
+ atomic_dec(&shca->num_cqs);
return ERR_PTR(-ENOMEM);
}
@@ -305,6 +314,7 @@ create_cq_exit2:
create_cq_exit1:
kmem_cache_free(cq_cache, my_cq);
+ atomic_dec(&shca->num_cqs);
return cq;
}
@@ -359,6 +369,7 @@ int ehca_destroy_cq(struct ib_cq *cq)
ipz_queue_dtor(NULL, &my_cq->ipz_queue);
kmem_cache_free(cq_cache, my_cq);
+ atomic_dec(&shca->num_cqs);
return 0;
}