#include "ehca_irq.h"
 
 #define EHCA_EQE_CACHE_SIZE 20
+#define EHCA_MAX_NUM_QUEUES 0xffff
 
 struct ehca_eqe_cache_entry {
        struct ehca_eqe *eqe;
        /* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */
        u32 hca_cap_mr_pgsize;
        int max_mtu;
+       atomic_t num_cqs;
+       atomic_t num_qps;
 };
 
 struct ehca_pd {
 extern int ehca_scaling_code;
 extern int ehca_lock_hcalls;
 extern int ehca_nr_ports;
+extern int ehca_max_cq;
+extern int ehca_max_qp;
 
 struct ipzu_queue_resp {
        u32 qe_size;      /* queue entry size */
 
        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);
        }
 
 create_cq_exit1:
        kmem_cache_free(cq_cache, my_cq);
 
+       atomic_dec(&shca->num_cqs);
        return cq;
 }
 
        ipz_queue_dtor(NULL, &my_cq->ipz_queue);
        kmem_cache_free(cq_cache, my_cq);
 
+       atomic_dec(&shca->num_cqs);
        return 0;
 }
 
 
 int ehca_static_rate   = -1;
 int ehca_scaling_code  = 0;
 int ehca_lock_hcalls   = -1;
+int ehca_max_cq        = -1;
+int ehca_max_qp        = -1;
 
 module_param_named(open_aqp1,     ehca_open_aqp1,     bool, S_IRUGO);
 module_param_named(debug_level,   ehca_debug_level,   int,  S_IRUGO);
 module_param_named(static_rate,   ehca_static_rate,   int,  S_IRUGO);
 module_param_named(scaling_code,  ehca_scaling_code,  bool, S_IRUGO);
 module_param_named(lock_hcalls,   ehca_lock_hcalls,   bool, S_IRUGO);
+module_param_named(number_of_cqs, ehca_max_cq,        int,  S_IRUGO);
+module_param_named(number_of_qps, ehca_max_qp,        int,  S_IRUGO);
 
 MODULE_PARM_DESC(open_aqp1,
                 "Open AQP1 on startup (default: no)");
 MODULE_PARM_DESC(lock_hcalls,
                 "Serialize all hCalls made by the driver "
                 "(default: autodetect)");
+MODULE_PARM_DESC(number_of_cqs,
+               "Max number of CQs which can be allocated "
+               "(default: autodetect)");
+MODULE_PARM_DESC(number_of_qps,
+               "Max number of QPs which can be allocated "
+               "(default: autodetect)");
 
 DEFINE_RWLOCK(ehca_qp_idr_lock);
 DEFINE_RWLOCK(ehca_cq_idr_lock);
                if (rblock->memory_page_size_supported & pgsize_map[i])
                        shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
 
+       /* Set maximum number of CQs and QPs to calculate EQ size */
+       if (ehca_max_qp == -1)
+               ehca_max_qp = min_t(int, rblock->max_qp, EHCA_MAX_NUM_QUEUES);
+       else if (ehca_max_qp < 1 || ehca_max_qp > rblock->max_qp) {
+               ehca_gen_err("Requested number of QPs is out of range (1 - %i) "
+                       "specified by HW", rblock->max_qp);
+               ret = -EINVAL;
+               goto sense_attributes1;
+       }
+
+       if (ehca_max_cq == -1)
+               ehca_max_cq = min_t(int, rblock->max_cq, EHCA_MAX_NUM_QUEUES);
+       else if (ehca_max_cq < 1 || ehca_max_cq > rblock->max_cq) {
+               ehca_gen_err("Requested number of CQs is out of range (1 - %i) "
+                       "specified by HW", rblock->max_cq);
+               ret = -EINVAL;
+               goto sense_attributes1;
+       }
+
        /* query max MTU from first port -- it's the same for all ports */
        port = (struct hipz_query_port *)rblock;
        h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
        struct ehca_shca *shca;
        const u64 *handle;
        struct ib_pd *ibpd;
-       int ret, i;
+       int ret, i, eq_size;
 
        handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
        if (!handle) {
                return -ENOMEM;
        }
        mutex_init(&shca->modify_mutex);
+       atomic_set(&shca->num_cqs, 0);
+       atomic_set(&shca->num_qps, 0);
        for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
                spin_lock_init(&shca->sport[i].mod_sqp_lock);
 
                goto probe1;
        }
 
+       eq_size = 2 * ehca_max_cq + 4 * ehca_max_qp;
        /* create event queues */
-       ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048);
+       ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, eq_size);
        if (ret) {
                ehca_err(&shca->ib_device, "Cannot create EQ.");
                goto probe1;
 
        u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
        unsigned long flags;
 
-       if (init_attr->create_flags)
+       if (!atomic_add_unless(&shca->num_qps, 1, ehca_max_qp)) {
+               ehca_err(pd->device, "Unable to create QP, max number of %i "
+                        "QPs reached.", ehca_max_qp);
+               ehca_err(pd->device, "To increase the maximum number of QPs "
+                        "use the number_of_qps module parameter.\n");
+               return ERR_PTR(-ENOSPC);
+       }
+
+       if (init_attr->create_flags) {
+               atomic_dec(&shca->num_qps);
                return ERR_PTR(-EINVAL);
+       }
 
        memset(&parms, 0, sizeof(parms));
        qp_type = init_attr->qp_type;
                init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) {
                ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed",
                         init_attr->sq_sig_type);
+               atomic_dec(&shca->num_qps);
                return ERR_PTR(-EINVAL);
        }
 
 
        if (is_llqp && has_srq) {
                ehca_err(pd->device, "LLQPs can't have an SRQ");
+               atomic_dec(&shca->num_qps);
                return ERR_PTR(-EINVAL);
        }
 
                        ehca_err(pd->device, "no more than three SGEs "
                                 "supported for SRQ  pd=%p  max_sge=%x",
                                 pd, init_attr->cap.max_recv_sge);
+                       atomic_dec(&shca->num_qps);
                        return ERR_PTR(-EINVAL);
                }
        }
            qp_type != IB_QPT_SMI &&
            qp_type != IB_QPT_GSI) {
                ehca_err(pd->device, "wrong QP Type=%x", qp_type);
+               atomic_dec(&shca->num_qps);
                return ERR_PTR(-EINVAL);
        }
 
                                         "or max_rq_wr=%x for RC LLQP",
                                         init_attr->cap.max_send_wr,
                                         init_attr->cap.max_recv_wr);
+                               atomic_dec(&shca->num_qps);
                                return ERR_PTR(-EINVAL);
                        }
                        break;
                        if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) {
                                ehca_err(pd->device, "UD LLQP not supported "
                                         "by this adapter");
+                               atomic_dec(&shca->num_qps);
                                return ERR_PTR(-ENOSYS);
                        }
                        if (!(init_attr->cap.max_send_sge <= 5
                                         "or max_recv_sge=%x for UD LLQP",
                                         init_attr->cap.max_send_sge,
                                         init_attr->cap.max_recv_sge);
+                               atomic_dec(&shca->num_qps);
                                return ERR_PTR(-EINVAL);
                        } else if (init_attr->cap.max_send_wr > 255) {
                                ehca_err(pd->device,
                                         "Invalid Number of "
                                         "max_send_wr=%x for UD QP_TYPE=%x",
                                         init_attr->cap.max_send_wr, qp_type);
+                               atomic_dec(&shca->num_qps);
                                return ERR_PTR(-EINVAL);
                        }
                        break;
                default:
                        ehca_err(pd->device, "unsupported LL QP Type=%x",
                                 qp_type);
+                       atomic_dec(&shca->num_qps);
                        return ERR_PTR(-EINVAL);
-                       break;
                }
        } else {
                int max_sge = (qp_type == IB_QPT_UD || qp_type == IB_QPT_SMI
                                 "send_sge=%x recv_sge=%x max_sge=%x",
                                 init_attr->cap.max_send_sge,
                                 init_attr->cap.max_recv_sge, max_sge);
+                       atomic_dec(&shca->num_qps);
                        return ERR_PTR(-EINVAL);
                }
        }
        my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);
        if (!my_qp) {
                ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
+               atomic_dec(&shca->num_qps);
                return ERR_PTR(-ENOMEM);
        }
 
 
 create_qp_exit0:
        kmem_cache_free(qp_cache, my_qp);
+       atomic_dec(&shca->num_qps);
        return ERR_PTR(ret);
 }
 
        if (HAS_SQ(my_qp))
                ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
        kmem_cache_free(qp_cache, my_qp);
+       atomic_dec(&shca->num_qps);
        return 0;
 }