[ewg] [PATCH ofed-1.3.1 1/2] Upstream patches (mostly bug fixes) to be included in ofed-1.3.1
Hoang-Nam Nguyen
hnguyen at linux.vnet.ibm.com
Fri May 2 15:58:26 PDT 2008
IB/ehca: Upstream patches (mostly bug fixes) to be included in ofed-1.3.1
0031 IB/ehca: Make symbols used only in a single source file static
0032 IB/ehca: Remove tgid checking
0033 IB/ehca: Support all ibv_devinfo values in query_device() and query_port()
0034 IB/ehca: Prevent posting of SQ WQEs if QP not in RTS
0035 IB/ehca: Move high-volume debug output to higher debug levels
0036 IB/ehca: Remove mr_largepage parameter
0037 IB/ehca: Make some module parameters bool, update descriptions
0038 IB/ehca: Bump version number to 0026
0039 IB/ehca: handle negative return value from ibmebus_request_irq() properly
0040 IB/ehca: Allocate event queue size depending on max number of CQs and QPs
Signed-off-by: Hoang-Nam Nguyen <hnguyen at de.ibm.com>
---
...ke-symbols-used-only-in-a-single-source-f.patch | 137 ++++++
.../fixes/ehca_0032_Remove-tgid-checking.patch | 462 ++++++++++++++++++++
...pport-all-ibv_devinfo-values-in-query_dev.patch | 190 ++++++++
...event-posting-of-SQ-WQEs-if-QP-not-in-RTS.patch | 67 +++
...ve-high-volume-debug-output-to-higher-deb.patch | 402 +++++++++++++++++
.../ehca_0036_Remove-mr_largepage-parameter.patch | 84 ++++
...ake-some-module-parameters-bool-update-de.patch | 78 ++++
.../ehca_0038_Bump-version-number-to-0026.patch | 27 ++
...ndle-negative-return-value-from-ibmebus_r.patch | 91 ++++
...llocate-event-queue-size-depending-on-max.patch | 302 +++++++++++++
10 files changed, 1840 insertions(+), 0 deletions(-)
create mode 100644 kernel_patches/fixes/ehca_0031_Make-symbols-used-only-in-a-single-source-f.patch
create mode 100644 kernel_patches/fixes/ehca_0032_Remove-tgid-checking.patch
create mode 100644 kernel_patches/fixes/ehca_0033_Support-all-ibv_devinfo-values-in-query_dev.patch
create mode 100644 kernel_patches/fixes/ehca_0034_Prevent-posting-of-SQ-WQEs-if-QP-not-in-RTS.patch
create mode 100644 kernel_patches/fixes/ehca_0035_Move-high-volume-debug-output-to-higher-deb.patch
create mode 100644 kernel_patches/fixes/ehca_0036_Remove-mr_largepage-parameter.patch
create mode 100644 kernel_patches/fixes/ehca_0037_Make-some-module-parameters-bool-update-de.patch
create mode 100644 kernel_patches/fixes/ehca_0038_Bump-version-number-to-0026.patch
create mode 100644 kernel_patches/fixes/ehca_0039_handle-negative-return-value-from-ibmebus_r.patch
create mode 100644 kernel_patches/fixes/ehca_0040_Allocate-event-queue-size-depending-on-max.patch
diff --git a/kernel_patches/fixes/ehca_0031_Make-symbols-used-only-in-a-single-source-f.patch b/kernel_patches/fixes/ehca_0031_Make-symbols-used-only-in-a-single-source-f.patch
new file mode 100644
index 0000000..0795360
--- /dev/null
+++ b/kernel_patches/fixes/ehca_0031_Make-symbols-used-only-in-a-single-source-f.patch
@@ -0,0 +1,137 @@
+From e8e91f6b4dc1179a70b0d21241b769c0ebfaa129 Mon Sep 17 00:00:00 2001
+From: Roland Dreier <rolandd at cisco.com>
+Date: Wed, 16 Apr 2008 21:01:10 -0700
+Subject: [PATCH] IB/ehca: Make symbols used only in a single source file static
+
+Allow the compiler to optimize better and generate smaller code:
+
+add/remove: 0/6 grow/shrink: 2/0 up/down: 1528/-1864 (-336)
+function old new delta
+.ehca_set_pagebuf 1344 2172 +828
+.ehca_probe 2312 3012 +700
+ehca_set_pagebuf_phys 24 - -24
+ehca_set_pagebuf_fmr 24 - -24
+ehca_init_device 24 - -24
+.ehca_set_pagebuf_fmr 480 - -480
+.ehca_set_pagebuf_phys 512 - -512
+.ehca_init_device 800 - -800
+
+Also this fixes warnings like:
+
+ drivers/infiniband/hw/ehca/ehca_mrmw.c:2015:5: warning: symbol 'ehca_set_pagebuf_fmr' was not declared. Should it be static?
+
+Signed-off-by: Roland Dreier <rolandd at cisco.com>
+---
+ drivers/infiniband/hw/ehca/ehca_hca.c | 2 +-
+ drivers/infiniband/hw/ehca/ehca_main.c | 19 ++++++++++---------
+ drivers/infiniband/hw/ehca/ehca_mrmw.c | 10 ++++------
+ 3 files changed, 15 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
+index 5bd7b59..8832123 100644
+--- a/drivers/infiniband/hw/ehca/ehca_hca.c
++++ b/drivers/infiniband/hw/ehca/ehca_hca.c
+@@ -314,7 +314,7 @@ query_gid1:
+ return ret;
+ }
+
+-const u32 allowed_port_caps = (
++static const u32 allowed_port_caps = (
+ IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP |
+ IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP |
+ IB_PORT_VENDOR_CLASS_SUP);
+diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
+index a86ebcc..65b3362 100644
+--- a/drivers/infiniband/hw/ehca/ehca_main.c
++++ b/drivers/infiniband/hw/ehca/ehca_main.c
+@@ -57,16 +57,17 @@ MODULE_AUTHOR("Christoph Raisch <raisch at de.ibm.com>");
+ MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
+ MODULE_VERSION(HCAD_VERSION);
+
+-int ehca_open_aqp1 = 0;
++static int ehca_open_aqp1 = 0;
++static int ehca_hw_level = 0;
++static int ehca_poll_all_eqs = 1;
++static int ehca_mr_largepage = 1;
++
+ int ehca_debug_level = 0;
+-int ehca_hw_level = 0;
+ int ehca_nr_ports = 2;
+ int ehca_use_hp_mr = 0;
+ int ehca_port_act_time = 30;
+-int ehca_poll_all_eqs = 1;
+ int ehca_static_rate = -1;
+ int ehca_scaling_code = 0;
+-int ehca_mr_largepage = 1;
+ int ehca_lock_hcalls = -1;
+
+ module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO);
+@@ -396,7 +397,7 @@ init_node_guid1:
+ return ret;
+ }
+
+-int ehca_init_device(struct ehca_shca *shca)
++static int ehca_init_device(struct ehca_shca *shca)
+ {
+ int ret;
+
+@@ -579,8 +580,8 @@ static ssize_t ehca_store_debug_level(struct device_driver *ddp,
+ return 1;
+ }
+
+-DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
+- ehca_show_debug_level, ehca_store_debug_level);
++static DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
++ ehca_show_debug_level, ehca_store_debug_level);
+
+ static struct attribute *ehca_drv_attrs[] = {
+ &driver_attr_debug_level.attr,
+@@ -941,7 +942,7 @@ void ehca_poll_eqs(unsigned long data)
+ spin_unlock(&shca_list_lock);
+ }
+
+-int __init ehca_module_init(void)
++static int __init ehca_module_init(void)
+ {
+ int ret;
+
+@@ -988,7 +989,7 @@ module_init1:
+ return ret;
+ };
+
+-void __exit ehca_module_exit(void)
++static void __exit ehca_module_exit(void)
+ {
+ if (ehca_poll_all_eqs == 1)
+ del_timer_sync(&poll_eqs_timer);
+diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
+index e239bbf..5e99c45 100644
+--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
++++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
+@@ -1952,9 +1952,8 @@ next_kpage:
+ return ret;
+ }
+
+-int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
+- u32 number,
+- u64 *kpage)
++static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
++ u32 number, u64 *kpage)
+ {
+ int ret = 0;
+ struct ib_phys_buf *pbuf;
+@@ -2012,9 +2011,8 @@ int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
+ return ret;
+ }
+
+-int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
+- u32 number,
+- u64 *kpage)
++static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
++ u32 number, u64 *kpage)
+ {
+ int ret = 0;
+ u64 *fmrlist;
+--
+1.5.5
+
diff --git a/kernel_patches/fixes/ehca_0032_Remove-tgid-checking.patch b/kernel_patches/fixes/ehca_0032_Remove-tgid-checking.patch
new file mode 100644
index 0000000..38c0b3c
--- /dev/null
+++ b/kernel_patches/fixes/ehca_0032_Remove-tgid-checking.patch
@@ -0,0 +1,462 @@
+From f4f82994d1ea0cd01058a245985f1eb5e569e6d3 Mon Sep 17 00:00:00 2001
+From: Hoang-Nam Nguyen <hnguyen at de.ibm.com>
+Date: Wed, 16 Apr 2008 21:01:13 -0700
+Subject: [PATCH] IB/ehca: Remove tgid checking
+
+Pavel Emelyanov <xemul at openvz.org> mentioned in <http://lkml.org/lkml/2008/3/17/131>
+that the task_struct->tgid field is about to become deprecated, so the
+uses in the ehca driver need to be fixed up.
+
+However, all the uses in ehca are for some object ownership checking
+that is not really needed, and anyway is implementing a policy that
+should be in common code rather than a low-level driver. So just
+remove all the checks.
+
+Signed-off-by: Hoang-Nam Nguyen <hnguyen at de.ibm.com>
+Signed-off-by: Roland Dreier <rolandd at cisco.com>
+---
+ drivers/infiniband/hw/ehca/ehca_av.c | 31 ------------------
+ drivers/infiniband/hw/ehca/ehca_classes.h | 2 -
+ drivers/infiniband/hw/ehca/ehca_cq.c | 19 -----------
+ drivers/infiniband/hw/ehca/ehca_mrmw.c | 32 -------------------
+ drivers/infiniband/hw/ehca/ehca_pd.c | 11 ------
+ drivers/infiniband/hw/ehca/ehca_qp.c | 48 -----------------------------
+ drivers/infiniband/hw/ehca/ehca_uverbs.c | 19 -----------
+ 7 files changed, 0 insertions(+), 162 deletions(-)
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
+index 194c1c3..56735ea 100644
+--- a/drivers/infiniband/hw/ehca/ehca_av.c
++++ b/drivers/infiniband/hw/ehca/ehca_av.c
+@@ -41,9 +41,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-
+-#include <asm/current.h>
+-
+ #include "ehca_tools.h"
+ #include "ehca_iverbs.h"
+ #include "hcp_if.h"
+@@ -170,17 +167,8 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+ {
+ struct ehca_av *av;
+ struct ehca_ud_av new_ehca_av;
+- struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+ struct ehca_shca *shca = container_of(ah->pd->device, struct ehca_shca,
+ ib_device);
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+
+ memset(&new_ehca_av, 0, sizeof(new_ehca_av));
+ new_ehca_av.sl = ah_attr->sl;
+@@ -242,15 +230,6 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+ int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+ {
+ struct ehca_av *av = container_of(ah, struct ehca_av, ib_ah);
+- struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+
+ memcpy(&ah_attr->grh.dgid, &av->av.grh.word_3,
+ sizeof(ah_attr->grh.dgid));
+@@ -273,16 +252,6 @@ int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+
+ int ehca_destroy_ah(struct ib_ah *ah)
+ {
+- struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+-
+ kmem_cache_free(av_cache, container_of(ah, struct ehca_av, ib_ah));
+
+ return 0;
+diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
+index 92cce8a..0d13fe0 100644
+--- a/drivers/infiniband/hw/ehca/ehca_classes.h
++++ b/drivers/infiniband/hw/ehca/ehca_classes.h
+@@ -132,7 +132,6 @@ struct ehca_shca {
+ struct ehca_pd {
+ struct ib_pd ib_pd;
+ struct ipz_pd fw_pd;
+- u32 ownpid;
+ /* small queue mgmt */
+ struct mutex lock;
+ struct list_head free[2];
+@@ -215,7 +214,6 @@ struct ehca_cq {
+ atomic_t nr_events; /* #events seen */
+ wait_queue_head_t wait_completion;
+ spinlock_t task_lock;
+- u32 ownpid;
+ /* mmap counter for resources mapped into user space */
+ u32 mm_count_queue;
+ u32 mm_count_galpa;
+diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
+index 0467c15..ec0cfcf 100644
+--- a/drivers/infiniband/hw/ehca/ehca_cq.c
++++ b/drivers/infiniband/hw/ehca/ehca_cq.c
+@@ -43,8 +43,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-#include <asm/current.h>
+-
+ #include "ehca_iverbs.h"
+ #include "ehca_classes.h"
+ #include "ehca_irq.h"
+@@ -148,7 +146,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
+ spin_lock_init(&my_cq->task_lock);
+ atomic_set(&my_cq->nr_events, 0);
+ init_waitqueue_head(&my_cq->wait_completion);
+- my_cq->ownpid = current->tgid;
+
+ cq = &my_cq->ib_cq;
+
+@@ -320,7 +317,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
+ struct ehca_shca *shca = container_of(device, struct ehca_shca,
+ ib_device);
+ struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+- u32 cur_pid = current->tgid;
+ unsigned long flags;
+
+ if (cq->uobject) {
+@@ -329,12 +325,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
+ "user space cq_num=%x", my_cq->cq_number);
+ return -EINVAL;
+ }
+- if (my_cq->ownpid != cur_pid) {
+- ehca_err(device, "Invalid caller pid=%x ownpid=%x "
+- "cq_num=%x",
+- cur_pid, my_cq->ownpid, my_cq->cq_number);
+- return -EINVAL;
+- }
+ }
+
+ /*
+@@ -374,15 +364,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
+
+ int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
+ {
+- struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
+- u32 cur_pid = current->tgid;
+-
+- if (cq->uobject && my_cq->ownpid != cur_pid) {
+- ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_cq->ownpid);
+- return -EINVAL;
+- }
+-
+ /* TODO: proper resize needs to be done */
+ ehca_err(cq->device, "not implemented yet");
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
+index 5e99c45..f26997f 100644
+--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
++++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
+@@ -40,8 +40,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-#include <asm/current.h>
+-
+ #include <rdma/ib_umem.h>
+
+ #include "ehca_iverbs.h"
+@@ -419,7 +417,6 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
+ struct ehca_shca *shca =
+ container_of(mr->device, struct ehca_shca, ib_device);
+ struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+- struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
+ u64 new_size;
+ u64 *new_start;
+ u32 new_acl;
+@@ -429,15 +426,6 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
+ u32 num_kpages = 0;
+ u32 num_hwpages = 0;
+ struct ehca_mr_pginfo pginfo;
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- (my_pd->ownpid != cur_pid)) {
+- ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- ret = -EINVAL;
+- goto rereg_phys_mr_exit0;
+- }
+
+ if (!(mr_rereg_mask & IB_MR_REREG_TRANS)) {
+ /* TODO not supported, because PHYP rereg hCall needs pages */
+@@ -577,19 +565,9 @@ int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
+ struct ehca_shca *shca =
+ container_of(mr->device, struct ehca_shca, ib_device);
+ struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+- struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
+- u32 cur_pid = current->tgid;
+ unsigned long sl_flags;
+ struct ehca_mr_hipzout_parms hipzout;
+
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- (my_pd->ownpid != cur_pid)) {
+- ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- ret = -EINVAL;
+- goto query_mr_exit0;
+- }
+-
+ if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
+ ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
+ "e_mr->flags=%x", mr, e_mr, e_mr->flags);
+@@ -634,16 +612,6 @@ int ehca_dereg_mr(struct ib_mr *mr)
+ struct ehca_shca *shca =
+ container_of(mr->device, struct ehca_shca, ib_device);
+ struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+- struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- (my_pd->ownpid != cur_pid)) {
+- ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- ret = -EINVAL;
+- goto dereg_mr_exit0;
+- }
+
+ if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
+ ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
+diff --git a/drivers/infiniband/hw/ehca/ehca_pd.c b/drivers/infiniband/hw/ehca/ehca_pd.c
+index 43bcf08..2fe5548 100644
+--- a/drivers/infiniband/hw/ehca/ehca_pd.c
++++ b/drivers/infiniband/hw/ehca/ehca_pd.c
+@@ -38,8 +38,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-#include <asm/current.h>
+-
+ #include "ehca_tools.h"
+ #include "ehca_iverbs.h"
+
+@@ -58,7 +56,6 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
+ return ERR_PTR(-ENOMEM);
+ }
+
+- pd->ownpid = current->tgid;
+ for (i = 0; i < 2; i++) {
+ INIT_LIST_HEAD(&pd->free[i]);
+ INIT_LIST_HEAD(&pd->full[i]);
+@@ -85,18 +82,10 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
+
+ int ehca_dealloc_pd(struct ib_pd *pd)
+ {
+- u32 cur_pid = current->tgid;
+ struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
+ int i, leftovers = 0;
+ struct ipz_small_queue_page *page, *tmp;
+
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(pd->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+-
+ for (i = 0; i < 2; i++) {
+ list_splice(&my_pd->full[i], &my_pd->free[i]);
+ list_for_each_entry_safe(page, tmp, &my_pd->free[i], list) {
+diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
+index 1012f15..a9fd419 100644
+--- a/drivers/infiniband/hw/ehca/ehca_qp.c
++++ b/drivers/infiniband/hw/ehca/ehca_qp.c
+@@ -43,9 +43,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-
+-#include <asm/current.h>
+-
+ #include "ehca_classes.h"
+ #include "ehca_tools.h"
+ #include "ehca_qes.h"
+@@ -1526,16 +1523,6 @@ int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
+ ib_device);
+ struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
+- struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+- ib_pd);
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(ibqp->pd->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+
+ /* The if-block below caches qp_attr to be modified for GSI and SMI
+ * qps during the initialization by ib_mad. When the respective port
+@@ -1636,23 +1623,13 @@ int ehca_query_qp(struct ib_qp *qp,
+ int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
+ {
+ struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
+- struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+- ib_pd);
+ struct ehca_shca *shca = container_of(qp->device, struct ehca_shca,
+ ib_device);
+ struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+ struct hcp_modify_qp_control_block *qpcb;
+- u32 cur_pid = current->tgid;
+ int cnt, ret = 0;
+ u64 h_ret;
+
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(qp->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+-
+ if (qp_attr_mask & QP_ATTR_QUERY_NOT_SUPPORTED) {
+ ehca_err(qp->device, "Invalid attribute mask "
+ "ehca_qp=%p qp_num=%x qp_attr_mask=%x ",
+@@ -1797,8 +1774,6 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ {
+ struct ehca_qp *my_qp =
+ container_of(ibsrq, struct ehca_qp, ib_srq);
+- struct ehca_pd *my_pd =
+- container_of(ibsrq->pd, struct ehca_pd, ib_pd);
+ struct ehca_shca *shca =
+ container_of(ibsrq->pd->device, struct ehca_shca, ib_device);
+ struct hcp_modify_qp_control_block *mqpcb;
+@@ -1806,14 +1781,6 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ u64 h_ret;
+ int ret = 0;
+
+- u32 cur_pid = current->tgid;
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(ibsrq->pd->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+-
+ mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!mqpcb) {
+ ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb "
+@@ -1864,22 +1831,13 @@ modify_srq_exit0:
+ int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
+ {
+ struct ehca_qp *my_qp = container_of(srq, struct ehca_qp, ib_srq);
+- struct ehca_pd *my_pd = container_of(srq->pd, struct ehca_pd, ib_pd);
+ struct ehca_shca *shca = container_of(srq->device, struct ehca_shca,
+ ib_device);
+ struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+ struct hcp_modify_qp_control_block *qpcb;
+- u32 cur_pid = current->tgid;
+ int ret = 0;
+ u64 h_ret;
+
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(srq->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+-
+ qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!qpcb) {
+ ehca_err(srq->device, "Out of memory for qpcb "
+@@ -1919,7 +1877,6 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+ ib_pd);
+ struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1];
+- u32 cur_pid = current->tgid;
+ u32 qp_num = my_qp->real_qp_num;
+ int ret;
+ u64 h_ret;
+@@ -1934,11 +1891,6 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ "user space qp_num=%x", qp_num);
+ return -EINVAL;
+ }
+- if (my_pd->ownpid != cur_pid) {
+- ehca_err(dev, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+ }
+
+ if (my_qp->send_cq) {
+diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
+index 5234d6c..1b07f2b 100644
+--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
++++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
+@@ -40,8 +40,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-#include <asm/current.h>
+-
+ #include "ehca_classes.h"
+ #include "ehca_iverbs.h"
+ #include "ehca_mrmw.h"
+@@ -253,11 +251,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ u32 idr_handle = fileoffset & 0x1FFFFFF;
+ u32 q_type = (fileoffset >> 27) & 0x1; /* CQ, QP,... */
+ u32 rsrc_type = (fileoffset >> 25) & 0x3; /* sq,rq,cmnd_window */
+- u32 cur_pid = current->tgid;
+ u32 ret;
+ struct ehca_cq *cq;
+ struct ehca_qp *qp;
+- struct ehca_pd *pd;
+ struct ib_uobject *uobject;
+
+ switch (q_type) {
+@@ -270,13 +266,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ if (!cq)
+ return -EINVAL;
+
+- if (cq->ownpid != cur_pid) {
+- ehca_err(cq->ib_cq.device,
+- "Invalid caller pid=%x ownpid=%x",
+- cur_pid, cq->ownpid);
+- return -ENOMEM;
+- }
+-
+ if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context)
+ return -EINVAL;
+
+@@ -298,14 +287,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ if (!qp)
+ return -EINVAL;
+
+- pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd);
+- if (pd->ownpid != cur_pid) {
+- ehca_err(qp->ib_qp.device,
+- "Invalid caller pid=%x ownpid=%x",
+- cur_pid, pd->ownpid);
+- return -ENOMEM;
+- }
+-
+ uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject;
+ if (!uobject || uobject->context != context)
+ return -EINVAL;
+--
+1.5.5
+
diff --git a/kernel_patches/fixes/ehca_0033_Support-all-ibv_devinfo-values-in-query_dev.patch b/kernel_patches/fixes/ehca_0033_Support-all-ibv_devinfo-values-in-query_dev.patch
new file mode 100644
index 0000000..6e8e326
--- /dev/null
+++ b/kernel_patches/fixes/ehca_0033_Support-all-ibv_devinfo-values-in-query_dev.patch
@@ -0,0 +1,190 @@
+From c83b5b1cb2b050c7a9054f330598df99c31abb98 Mon Sep 17 00:00:00 2001
+From: Stefan Roscher <ossrosch at linux.vnet.ibm.com>
+Date: Wed, 16 Apr 2008 21:09:35 -0700
+Subject: [PATCH] IB/ehca: Support all ibv_devinfo values in query_device() and query_port()
+
+Also, introduce a few inline helper functions to make the code more readable.
+
+Signed-off-by: Stefan Roscher <stefan.roscher at de.ibm.com>
+Signed-off-by: Roland Dreier <rolandd at cisco.com>
+---
+ drivers/infiniband/hw/ehca/ehca_hca.c | 127 ++++++++++++++++++++------------
+ 1 files changed, 79 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
+index 8832123..2515cbd 100644
+--- a/drivers/infiniband/hw/ehca/ehca_hca.c
++++ b/drivers/infiniband/hw/ehca/ehca_hca.c
+@@ -43,6 +43,11 @@
+ #include "ehca_iverbs.h"
+ #include "hcp_if.h"
+
++static unsigned int limit_uint(unsigned int value)
++{
++ return min_t(unsigned int, value, INT_MAX);
++}
++
+ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
+ {
+ int i, ret = 0;
+@@ -83,37 +88,40 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
+ props->vendor_id = rblock->vendor_id >> 8;
+ props->vendor_part_id = rblock->vendor_part_id >> 16;
+ props->hw_ver = rblock->hw_ver;
+- props->max_qp = min_t(unsigned, rblock->max_qp, INT_MAX);
+- props->max_qp_wr = min_t(unsigned, rblock->max_wqes_wq, INT_MAX);
+- props->max_sge = min_t(unsigned, rblock->max_sge, INT_MAX);
+- props->max_sge_rd = min_t(unsigned, rblock->max_sge_rd, INT_MAX);
+- props->max_cq = min_t(unsigned, rblock->max_cq, INT_MAX);
+- props->max_cqe = min_t(unsigned, rblock->max_cqe, INT_MAX);
+- props->max_mr = min_t(unsigned, rblock->max_mr, INT_MAX);
+- props->max_mw = min_t(unsigned, rblock->max_mw, INT_MAX);
+- props->max_pd = min_t(unsigned, rblock->max_pd, INT_MAX);
+- props->max_ah = min_t(unsigned, rblock->max_ah, INT_MAX);
+- props->max_fmr = min_t(unsigned, rblock->max_mr, INT_MAX);
++ props->max_qp = limit_uint(rblock->max_qp);
++ props->max_qp_wr = limit_uint(rblock->max_wqes_wq);
++ props->max_sge = limit_uint(rblock->max_sge);
++ props->max_sge_rd = limit_uint(rblock->max_sge_rd);
++ props->max_cq = limit_uint(rblock->max_cq);
++ props->max_cqe = limit_uint(rblock->max_cqe);
++ props->max_mr = limit_uint(rblock->max_mr);
++ props->max_mw = limit_uint(rblock->max_mw);
++ props->max_pd = limit_uint(rblock->max_pd);
++ props->max_ah = limit_uint(rblock->max_ah);
++ props->max_ee = limit_uint(rblock->max_rd_ee_context);
++ props->max_rdd = limit_uint(rblock->max_rd_domain);
++ props->max_fmr = limit_uint(rblock->max_mr);
++ props->local_ca_ack_delay = limit_uint(rblock->local_ca_ack_delay);
++ props->max_qp_rd_atom = limit_uint(rblock->max_rr_qp);
++ props->max_ee_rd_atom = limit_uint(rblock->max_rr_ee_context);
++ props->max_res_rd_atom = limit_uint(rblock->max_rr_hca);
++ props->max_qp_init_rd_atom = limit_uint(rblock->max_act_wqs_qp);
++ props->max_ee_init_rd_atom = limit_uint(rblock->max_act_wqs_ee_context);
+
+ if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
+- props->max_srq = props->max_qp;
+- props->max_srq_wr = props->max_qp_wr;
++ props->max_srq = limit_uint(props->max_qp);
++ props->max_srq_wr = limit_uint(props->max_qp_wr);
+ props->max_srq_sge = 3;
+ }
+
+- props->max_pkeys = 16;
+- props->local_ca_ack_delay
+- = rblock->local_ca_ack_delay;
+- props->max_raw_ipv6_qp
+- = min_t(unsigned, rblock->max_raw_ipv6_qp, INT_MAX);
+- props->max_raw_ethy_qp
+- = min_t(unsigned, rblock->max_raw_ethy_qp, INT_MAX);
+- props->max_mcast_grp
+- = min_t(unsigned, rblock->max_mcast_grp, INT_MAX);
+- props->max_mcast_qp_attach
+- = min_t(unsigned, rblock->max_mcast_qp_attach, INT_MAX);
++ props->max_pkeys = 16;
++ props->local_ca_ack_delay = limit_uint(rblock->local_ca_ack_delay);
++ props->max_raw_ipv6_qp = limit_uint(rblock->max_raw_ipv6_qp);
++ props->max_raw_ethy_qp = limit_uint(rblock->max_raw_ethy_qp);
++ props->max_mcast_grp = limit_uint(rblock->max_mcast_grp);
++ props->max_mcast_qp_attach = limit_uint(rblock->max_mcast_qp_attach);
+ props->max_total_mcast_qp_attach
+- = min_t(unsigned, rblock->max_total_mcast_qp_attach, INT_MAX);
++ = limit_uint(rblock->max_total_mcast_qp_attach);
+
+ /* translate device capabilities */
+ props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID |
+@@ -128,6 +136,46 @@ query_device1:
+ return ret;
+ }
+
++static int map_mtu(struct ehca_shca *shca, u32 fw_mtu)
++{
++ switch (fw_mtu) {
++ case 0x1:
++ return IB_MTU_256;
++ case 0x2:
++ return IB_MTU_512;
++ case 0x3:
++ return IB_MTU_1024;
++ case 0x4:
++ return IB_MTU_2048;
++ case 0x5:
++ return IB_MTU_4096;
++ default:
++ ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
++ fw_mtu);
++ return 0;
++ }
++}
++
++static int map_number_of_vls(struct ehca_shca *shca, u32 vl_cap)
++{
++ switch (vl_cap) {
++ case 0x1:
++ return 1;
++ case 0x2:
++ return 2;
++ case 0x3:
++ return 4;
++ case 0x4:
++ return 8;
++ case 0x5:
++ return 15;
++ default:
++ ehca_err(&shca->ib_device, "invalid Vl Capability: %x.",
++ vl_cap);
++ return 0;
++ }
++}
++
+ int ehca_query_port(struct ib_device *ibdev,
+ u8 port, struct ib_port_attr *props)
+ {
+@@ -152,31 +200,13 @@ int ehca_query_port(struct ib_device *ibdev,
+
+ memset(props, 0, sizeof(struct ib_port_attr));
+
+- switch (rblock->max_mtu) {
+- case 0x1:
+- props->active_mtu = props->max_mtu = IB_MTU_256;
+- break;
+- case 0x2:
+- props->active_mtu = props->max_mtu = IB_MTU_512;
+- break;
+- case 0x3:
+- props->active_mtu = props->max_mtu = IB_MTU_1024;
+- break;
+- case 0x4:
+- props->active_mtu = props->max_mtu = IB_MTU_2048;
+- break;
+- case 0x5:
+- props->active_mtu = props->max_mtu = IB_MTU_4096;
+- break;
+- default:
+- ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
+- rblock->max_mtu);
+- break;
+- }
+-
++ props->active_mtu = props->max_mtu = map_mtu(shca, rblock->max_mtu);
+ props->port_cap_flags = rblock->capability_mask;
+ props->gid_tbl_len = rblock->gid_tbl_len;
+- props->max_msg_sz = rblock->max_msg_sz;
++ if (rblock->max_msg_sz)
++ props->max_msg_sz = rblock->max_msg_sz;
++ else
++ props->max_msg_sz = 0x1 << 31;
+ props->bad_pkey_cntr = rblock->bad_pkey_cntr;
+ props->qkey_viol_cntr = rblock->qkey_viol_cntr;
+ props->pkey_tbl_len = rblock->pkey_tbl_len;
+@@ -186,6 +216,7 @@ int ehca_query_port(struct ib_device *ibdev,
+ props->sm_sl = rblock->sm_sl;
+ props->subnet_timeout = rblock->subnet_timeout;
+ props->init_type_reply = rblock->init_type_reply;
++ props->max_vl_num = map_number_of_vls(shca, rblock->vl_cap);
+
+ if (rblock->state && rblock->phys_width) {
+ props->phys_state = rblock->phys_pstate;
+--
+1.5.5
+
diff --git a/kernel_patches/fixes/ehca_0034_Prevent-posting-of-SQ-WQEs-if-QP-not-in-RTS.patch b/kernel_patches/fixes/ehca_0034_Prevent-posting-of-SQ-WQEs-if-QP-not-in-RTS.patch
new file mode 100644
index 0000000..d1afa57
--- /dev/null
+++ b/kernel_patches/fixes/ehca_0034_Prevent-posting-of-SQ-WQEs-if-QP-not-in-RTS.patch
@@ -0,0 +1,67 @@
+From 863fb09fbf1eb74f56ea02184a62165056aa29cb Mon Sep 17 00:00:00 2001
+From: Joachim Fenkes <fenkes at de.ibm.com>
+Date: Wed, 23 Apr 2008 11:55:45 -0700
+Subject: [PATCH] IB/ehca: Prevent posting of SQ WQEs if QP not in RTS
+
+...as required by IB Spec, C10-29.
+
+Signed-off-by: Joachim Fenkes <fenkes at de.ibm.com>
+Signed-off-by: Roland Dreier <rolandd at cisco.com>
+---
+ drivers/infiniband/hw/ehca/ehca_classes.h | 1 +
+ drivers/infiniband/hw/ehca/ehca_qp.c | 3 +++
+ drivers/infiniband/hw/ehca/ehca_reqs.c | 5 +++++
+ 3 files changed, 9 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
+index 0d13fe0..3d6d946 100644
+--- a/drivers/infiniband/hw/ehca/ehca_classes.h
++++ b/drivers/infiniband/hw/ehca/ehca_classes.h
+@@ -160,6 +160,7 @@ struct ehca_qp {
+ };
+ u32 qp_type;
+ enum ehca_ext_qp_type ext_type;
++ enum ib_qp_state state;
+ struct ipz_queue ipz_squeue;
+ struct ipz_queue ipz_rqueue;
+ struct h_galpas galpas;
+diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
+index 3eb14a5..5a653d7 100644
+--- a/drivers/infiniband/hw/ehca/ehca_qp.c
++++ b/drivers/infiniband/hw/ehca/ehca_qp.c
+@@ -550,6 +550,7 @@ static struct ehca_qp *internal_create_qp(
+ spin_lock_init(&my_qp->spinlock_r);
+ my_qp->qp_type = qp_type;
+ my_qp->ext_type = parms.ext_type;
++ my_qp->state = IB_QPS_RESET;
+
+ if (init_attr->recv_cq)
+ my_qp->recv_cq =
+@@ -1508,6 +1509,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
+ if (attr_mask & IB_QP_QKEY)
+ my_qp->qkey = attr->qkey;
+
++ my_qp->state = qp_new_state;
++
+ modify_qp_exit2:
+ if (squeue_locked) { /* this means: sqe -> rts */
+ spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
+diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
+index a20bbf4..0b2359e 100644
+--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
++++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
+@@ -421,6 +421,11 @@ int ehca_post_send(struct ib_qp *qp,
+ int ret = 0;
+ unsigned long flags;
+
++ if (unlikely(my_qp->state != IB_QPS_RTS)) {
++ ehca_err(qp->device, "QP not in RTS state qpn=%x", qp->qp_num);
++ return -EINVAL;
++ }
++
+ /* LOCK the QUEUE */
+ spin_lock_irqsave(&my_qp->spinlock_s, flags);
+
+--
+1.5.5
+
diff --git a/kernel_patches/fixes/ehca_0035_Move-high-volume-debug-output-to-higher-deb.patch b/kernel_patches/fixes/ehca_0035_Move-high-volume-debug-output-to-higher-deb.patch
new file mode 100644
index 0000000..1587839
--- /dev/null
+++ b/kernel_patches/fixes/ehca_0035_Move-high-volume-debug-output-to-higher-deb.patch
@@ -0,0 +1,402 @@
+From 4da27d6d5b92c8fe4b3a3e5bcf42606d9e4a6fc8 Mon Sep 17 00:00:00 2001
+From: Joachim Fenkes <fenkes at de.ibm.com>
+Date: Wed, 23 Apr 2008 11:55:45 -0700
+Subject: [PATCH] IB/ehca: Move high-volume debug output to higher debug levels
+
+Signed-off-by: Joachim Fenkes <fenkes at de.ibm.com>
+Signed-off-by: Roland Dreier <rolandd at cisco.com>
+---
+ drivers/infiniband/hw/ehca/ehca_irq.c | 2 +-
+ drivers/infiniband/hw/ehca/ehca_main.c | 14 ++++++--
+ drivers/infiniband/hw/ehca/ehca_mrmw.c | 16 ++++++----
+ drivers/infiniband/hw/ehca/ehca_qp.c | 12 ++++----
+ drivers/infiniband/hw/ehca/ehca_reqs.c | 46 ++++++++++++++---------------
+ drivers/infiniband/hw/ehca/ehca_uverbs.c | 6 +--
+ drivers/infiniband/hw/ehca/hcp_if.c | 23 ++++++++-------
+ 7 files changed, 63 insertions(+), 56 deletions(-)
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
+index b5ca94c..ca5eb0c 100644
+--- a/drivers/infiniband/hw/ehca/ehca_irq.c
++++ b/drivers/infiniband/hw/ehca/ehca_irq.c
+@@ -633,7 +633,7 @@ static inline int find_next_online_cpu(struct ehca_comp_pool *pool)
+ unsigned long flags;
+
+ WARN_ON_ONCE(!in_interrupt());
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 3)
+ ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
+
+ spin_lock_irqsave(&pool->last_cpu_lock, flags);
+diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
+index 65b3362..4379bef 100644
+--- a/drivers/infiniband/hw/ehca/ehca_main.c
++++ b/drivers/infiniband/hw/ehca/ehca_main.c
+@@ -85,8 +85,8 @@ module_param_named(lock_hcalls, ehca_lock_hcalls, bool, S_IRUGO);
+ MODULE_PARM_DESC(open_aqp1,
+ "AQP1 on startup (0: no (default), 1: yes)");
+ MODULE_PARM_DESC(debug_level,
+- "debug level"
+- " (0: no debug traces (default), 1: with debug traces)");
++ "Amount of debug output (0: none (default), 1: traces, "
++ "2: some dumps, 3: lots)");
+ MODULE_PARM_DESC(hw_level,
+ "hardware level"
+ " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)");
+@@ -275,6 +275,7 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
+ u64 h_ret;
+ struct hipz_query_hca *rblock;
+ struct hipz_query_port *port;
++ const char *loc_code;
+
+ static const u32 pgsize_map[] = {
+ HCA_CAP_MR_PGSIZE_4K, 0x1000,
+@@ -283,6 +284,12 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
+ HCA_CAP_MR_PGSIZE_16M, 0x1000000,
+ };
+
++ ehca_gen_dbg("Probing adapter %s...",
++ shca->ofdev->node->full_name);
++ loc_code = of_get_property(shca->ofdev->node, "ibm,loc-code", NULL);
++ if (loc_code)
++ ehca_gen_dbg(" ... location lode=%s", loc_code);
++
+ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!rblock) {
+ ehca_gen_err("Cannot allocate rblock memory.");
+@@ -567,8 +574,7 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
+
+ static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf)
+ {
+- return snprintf(buf, PAGE_SIZE, "%d\n",
+- ehca_debug_level);
++ return snprintf(buf, PAGE_SIZE, "%d\n", ehca_debug_level);
+ }
+
+ static ssize_t ehca_store_debug_level(struct device_driver *ddp,
+diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
+index f26997f..46ae4eb 100644
+--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
++++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
+@@ -1794,8 +1794,9 @@ static int ehca_check_kpages_per_ate(struct scatterlist *page_list,
+ int t;
+ for (t = start_idx; t <= end_idx; t++) {
+ u64 pgaddr = page_to_pfn(sg_page(&page_list[t])) << PAGE_SHIFT;
+- ehca_gen_dbg("chunk_page=%lx value=%016lx", pgaddr,
+- *(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
++ if (ehca_debug_level >= 3)
++ ehca_gen_dbg("chunk_page=%lx value=%016lx", pgaddr,
++ *(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
+ if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
+ ehca_gen_err("uncontiguous page found pgaddr=%lx "
+ "prev_pgaddr=%lx page_list_i=%x",
+@@ -1862,10 +1863,13 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
+ pgaddr &
+ ~(pginfo->hwpage_size - 1));
+ }
+- ehca_gen_dbg("kpage=%lx chunk_page=%lx "
+- "value=%016lx", *kpage, pgaddr,
+- *(u64 *)abs_to_virt(
+- phys_to_abs(pgaddr)));
++ if (ehca_debug_level >= 3) {
++ u64 val = *(u64 *)abs_to_virt(
++ phys_to_abs(pgaddr));
++ ehca_gen_dbg("kpage=%lx chunk_page=%lx "
++ "value=%016lx",
++ *kpage, pgaddr, val);
++ }
+ prev_pgaddr = pgaddr;
+ i++;
+ pginfo->kpage_cnt++;
+diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
+index 5a653d7..57bef11 100644
+--- a/drivers/infiniband/hw/ehca/ehca_qp.c
++++ b/drivers/infiniband/hw/ehca/ehca_qp.c
+@@ -966,7 +966,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
+ qp_num, bad_send_wqe_p);
+ /* convert wqe pointer to vadr */
+ bad_send_wqe_v = abs_to_virt((u64)bad_send_wqe_p);
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num);
+ squeue = &my_qp->ipz_squeue;
+ if (ipz_queue_abs_to_offset(squeue, (u64)bad_send_wqe_p, &q_ofs)) {
+@@ -979,7 +979,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
+ wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs);
+ *bad_wqe_cnt = 0;
+ while (wqe->optype != 0xff && wqe->wqef != 0xff) {
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num);
+ wqe->nr_of_data_seg = 0; /* suppress data access */
+ wqe->wqef = WQEF_PURGE; /* WQE to be purged */
+@@ -1451,7 +1451,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
+ /* no support for max_send/recv_sge yet */
+ }
+
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(mqpcb, 4*70, "qp_num=%x", ibqp->qp_num);
+
+ h_ret = hipz_h_modify_qp(shca->ipz_hca_handle,
+@@ -1766,7 +1766,7 @@ int ehca_query_qp(struct ib_qp *qp,
+ if (qp_init_attr)
+ *qp_init_attr = my_qp->init_attr;
+
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(qpcb, 4*70, "qp_num=%x", qp->qp_num);
+
+ query_qp_exit1:
+@@ -1814,7 +1814,7 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ goto modify_srq_exit0;
+ }
+
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(mqpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
+
+ h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, my_qp->ipz_qp_handle,
+@@ -1867,7 +1867,7 @@ int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
+ srq_attr->srq_limit = EHCA_BMASK_GET(
+ MQPCB_CURR_SRQ_LIMIT, qpcb->curr_srq_limit);
+
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(qpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
+
+ query_srq_exit1:
+diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
+index 0b2359e..bbe0436 100644
+--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
++++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
+@@ -81,7 +81,7 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
+ recv_wr->sg_list[cnt_ds].length;
+ }
+
+- if (ehca_debug_level) {
++ if (ehca_debug_level >= 3) {
+ ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p",
+ ipz_rqueue);
+ ehca_dmp(wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
+@@ -281,7 +281,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
+ return -EINVAL;
+ }
+
+- if (ehca_debug_level) {
++ if (ehca_debug_level >= 3) {
+ ehca_gen_dbg("SEND WQE written into queue qp=%p ", qp);
+ ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "send wqe");
+ }
+@@ -459,13 +459,14 @@ int ehca_post_send(struct ib_qp *qp,
+ goto post_send_exit0;
+ }
+ wqe_cnt++;
+- ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d",
+- my_qp, qp->qp_num, wqe_cnt);
+ } /* eof for cur_send_wr */
+
+ post_send_exit0:
+ iosync(); /* serialize GAL register access */
+ hipz_update_sqa(my_qp, wqe_cnt);
++ if (unlikely(ret || ehca_debug_level >= 2))
++ ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
++ my_qp, qp->qp_num, wqe_cnt, ret);
+ my_qp->message_count += wqe_cnt;
+ spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
+ return ret;
+@@ -525,13 +526,14 @@ static int internal_post_recv(struct ehca_qp *my_qp,
+ goto post_recv_exit0;
+ }
+ wqe_cnt++;
+- ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d",
+- my_qp, my_qp->real_qp_num, wqe_cnt);
+ } /* eof for cur_recv_wr */
+
+ post_recv_exit0:
+ iosync(); /* serialize GAL register access */
+ hipz_update_rqa(my_qp, wqe_cnt);
++ if (unlikely(ret || ehca_debug_level >= 2))
++ ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
++ my_qp, my_qp->real_qp_num, wqe_cnt, ret);
+ spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
+ return ret;
+ }
+@@ -575,16 +577,17 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
+ struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
+ struct ehca_cqe *cqe;
+ struct ehca_qp *my_qp;
+- int cqe_count = 0;
++ int cqe_count = 0, is_error;
+
+ poll_cq_one_read_cqe:
+ cqe = (struct ehca_cqe *)
+ ipz_qeit_get_inc_valid(&my_cq->ipz_queue);
+ if (!cqe) {
+ ret = -EAGAIN;
+- ehca_dbg(cq->device, "Completion queue is empty ehca_cq=%p "
+- "cq_num=%x ret=%i", my_cq, my_cq->cq_number, ret);
+- goto poll_cq_one_exit0;
++ if (ehca_debug_level >= 3)
++ ehca_dbg(cq->device, "Completion queue is empty "
++ "my_cq=%p cq_num=%x", my_cq, my_cq->cq_number);
++ goto poll_cq_one_exit0;
+ }
+
+ /* prevents loads being reordered across this point */
+@@ -614,7 +617,7 @@ poll_cq_one_read_cqe:
+ ehca_dbg(cq->device,
+ "Got CQE with purged bit qp_num=%x src_qp=%x",
+ cqe->local_qp_number, cqe->remote_qp_number);
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(cqe, 64, "qp_num=%x src_qp=%x",
+ cqe->local_qp_number,
+ cqe->remote_qp_number);
+@@ -627,11 +630,13 @@ poll_cq_one_read_cqe:
+ }
+ }
+
+- /* tracing cqe */
+- if (unlikely(ehca_debug_level)) {
++ is_error = cqe->status & WC_STATUS_ERROR_BIT;
++
++ /* trace error CQEs if debug_level >= 1, trace all CQEs if >= 3 */
++ if (unlikely(ehca_debug_level >= 3 || (ehca_debug_level && is_error))) {
+ ehca_dbg(cq->device,
+- "Received COMPLETION ehca_cq=%p cq_num=%x -----",
+- my_cq, my_cq->cq_number);
++ "Received %sCOMPLETION ehca_cq=%p cq_num=%x -----",
++ is_error ? "ERROR " : "", my_cq, my_cq->cq_number);
+ ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x",
+ my_cq, my_cq->cq_number);
+ ehca_dbg(cq->device,
+@@ -654,8 +659,9 @@ poll_cq_one_read_cqe:
+ /* update also queue adder to throw away this entry!!! */
+ goto poll_cq_one_exit0;
+ }
++
+ /* eval ib_wc_status */
+- if (unlikely(cqe->status & WC_STATUS_ERROR_BIT)) {
++ if (unlikely(is_error)) {
+ /* complete with errors */
+ map_ib_wc_status(cqe->status, &wc->status);
+ wc->vendor_err = wc->status;
+@@ -676,14 +682,6 @@ poll_cq_one_read_cqe:
+ wc->imm_data = cpu_to_be32(cqe->immediate_data);
+ wc->sl = cqe->service_level;
+
+- if (unlikely(wc->status != IB_WC_SUCCESS))
+- ehca_dbg(cq->device,
+- "ehca_cq=%p cq_num=%x WARNING unsuccessful cqe "
+- "OPType=%x status=%x qp_num=%x src_qp=%x wr_id=%lx "
+- "cqe=%p", my_cq, my_cq->cq_number, cqe->optype,
+- cqe->status, cqe->local_qp_number,
+- cqe->remote_qp_number, cqe->work_request_id, cqe);
+-
+ poll_cq_one_exit0:
+ if (cqe_count > 0)
+ hipz_update_feca(my_cq, cqe_count);
+diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
+index 1b07f2b..e43ed8f 100644
+--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
++++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
+@@ -211,8 +211,7 @@ static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
+ break;
+
+ case 1: /* qp rqueue_addr */
+- ehca_dbg(qp->ib_qp.device, "qp_num=%x rqueue",
+- qp->ib_qp.qp_num);
++ ehca_dbg(qp->ib_qp.device, "qp_num=%x rq", qp->ib_qp.qp_num);
+ ret = ehca_mmap_queue(vma, &qp->ipz_rqueue,
+ &qp->mm_count_rqueue);
+ if (unlikely(ret)) {
+@@ -224,8 +223,7 @@ static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
+ break;
+
+ case 2: /* qp squeue_addr */
+- ehca_dbg(qp->ib_qp.device, "qp_num=%x squeue",
+- qp->ib_qp.qp_num);
++ ehca_dbg(qp->ib_qp.device, "qp_num=%x sq", qp->ib_qp.qp_num);
+ ret = ehca_mmap_queue(vma, &qp->ipz_squeue,
+ &qp->mm_count_squeue);
+ if (unlikely(ret)) {
+diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
+index 7029aa6..5245e13 100644
+--- a/drivers/infiniband/hw/ehca/hcp_if.c
++++ b/drivers/infiniband/hw/ehca/hcp_if.c
+@@ -123,8 +123,9 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
+ int i, sleep_msecs;
+ unsigned long flags = 0;
+
+- ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
+- opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
++ if (unlikely(ehca_debug_level >= 2))
++ ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
++ opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+
+ for (i = 0; i < 5; i++) {
+ /* serialize hCalls to work around firmware issue */
+@@ -148,7 +149,8 @@ static long ehca_plpar_hcall_norets(unsigned long opcode,
+ opcode, ret, arg1, arg2, arg3,
+ arg4, arg5, arg6, arg7);
+ else
+- ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
++ if (unlikely(ehca_debug_level >= 2))
++ ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
+
+ return ret;
+ }
+@@ -172,8 +174,10 @@ static long ehca_plpar_hcall9(unsigned long opcode,
+ int i, sleep_msecs;
+ unsigned long flags = 0;
+
+- ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
+- arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
++ if (unlikely(ehca_debug_level >= 2))
++ ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
++ arg1, arg2, arg3, arg4, arg5,
++ arg6, arg7, arg8, arg9);
+
+ for (i = 0; i < 5; i++) {
+ /* serialize hCalls to work around firmware issue */
+@@ -201,7 +205,7 @@ static long ehca_plpar_hcall9(unsigned long opcode,
+ ret, outs[0], outs[1], outs[2], outs[3],
+ outs[4], outs[5], outs[6], outs[7],
+ outs[8]);
+- } else
++ } else if (unlikely(ehca_debug_level >= 2))
+ ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
+ ret, outs[0], outs[1], outs[2], outs[3],
+ outs[4], outs[5], outs[6], outs[7],
+@@ -381,7 +385,7 @@ u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
+ r_cb, /* r6 */
+ 0, 0, 0, 0);
+
+- if (ehca_debug_level)
++ if (ehca_debug_level >= 2)
+ ehca_dmp(query_port_response_block, 64, "response_block");
+
+ return ret;
+@@ -731,9 +735,6 @@ u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
+ u64 ret;
+ u64 outs[PLPAR_HCALL9_BUFSIZE];
+
+- ehca_gen_dbg("kernel PAGE_SIZE=%x access_ctrl=%016x "
+- "vaddr=%lx length=%lx",
+- (u32)PAGE_SIZE, access_ctrl, vaddr, length);
+ ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
+ adapter_handle.handle, /* r4 */
+ 5, /* r5 */
+@@ -758,7 +759,7 @@ u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
+ {
+ u64 ret;
+
+- if (unlikely(ehca_debug_level >= 2)) {
++ if (unlikely(ehca_debug_level >= 3)) {
+ if (count > 1) {
+ u64 *kpage;
+ int i;
+--
+1.5.5
+
diff --git a/kernel_patches/fixes/ehca_0036_Remove-mr_largepage-parameter.patch b/kernel_patches/fixes/ehca_0036_Remove-mr_largepage-parameter.patch
new file mode 100644
index 0000000..74da75f
--- /dev/null
+++ b/kernel_patches/fixes/ehca_0036_Remove-mr_largepage-parameter.patch
@@ -0,0 +1,84 @@
+From a7607c9b1112b498c3044c9e5bc68fdb4985f93e Mon Sep 17 00:00:00 2001
+From: Joachim Fenkes <fenkes at de.ibm.com>
+Date: Wed, 23 Apr 2008 11:55:45 -0700
+Subject: [PATCH] IB/ehca: Remove mr_largepage parameter
+
+Always enable large page support; didn't seem to cause problems for anyone.
+
+Signed-off-by: Joachim Fenkes <fenkes at de.ibm.com>
+Signed-off-by: Roland Dreier <rolandd at cisco.com>
+---
+ drivers/infiniband/hw/ehca/ehca_main.c | 22 +++-------------------
+ 1 files changed, 3 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
+index 4379bef..ab02ac8 100644
+--- a/drivers/infiniband/hw/ehca/ehca_main.c
++++ b/drivers/infiniband/hw/ehca/ehca_main.c
+@@ -60,7 +60,6 @@ MODULE_VERSION(HCAD_VERSION);
+ static int ehca_open_aqp1 = 0;
+ static int ehca_hw_level = 0;
+ static int ehca_poll_all_eqs = 1;
+-static int ehca_mr_largepage = 1;
+
+ int ehca_debug_level = 0;
+ int ehca_nr_ports = 2;
+@@ -79,7 +78,6 @@ module_param_named(port_act_time, ehca_port_act_time, int, S_IRUGO);
+ module_param_named(poll_all_eqs, ehca_poll_all_eqs, int, S_IRUGO);
+ module_param_named(static_rate, ehca_static_rate, int, S_IRUGO);
+ module_param_named(scaling_code, ehca_scaling_code, int, S_IRUGO);
+-module_param_named(mr_largepage, ehca_mr_largepage, int, S_IRUGO);
+ module_param_named(lock_hcalls, ehca_lock_hcalls, bool, S_IRUGO);
+
+ MODULE_PARM_DESC(open_aqp1,
+@@ -104,9 +102,6 @@ MODULE_PARM_DESC(static_rate,
+ "set permanent static rate (default: disabled)");
+ MODULE_PARM_DESC(scaling_code,
+ "set scaling code (0: disabled/default, 1: enabled)");
+-MODULE_PARM_DESC(mr_largepage,
+- "use large page for MR (0: use PAGE_SIZE (default), "
+- "1: use large page depending on MR size");
+ MODULE_PARM_DESC(lock_hcalls,
+ "serialize all hCalls made by the driver "
+ "(default: autodetect)");
+@@ -357,11 +352,9 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
+
+ /* translate supported MR page sizes; always support 4K */
+ shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;
+- if (ehca_mr_largepage) { /* support extra sizes only if enabled */
+- for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
+- if (rblock->memory_page_size_supported & pgsize_map[i])
+- shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
+- }
++ for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
++ if (rblock->memory_page_size_supported & pgsize_map[i])
++ shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
+
+ /* query max MTU from first port -- it's the same for all ports */
+ port = (struct hipz_query_port *)rblock;
+@@ -663,14 +656,6 @@ static ssize_t ehca_show_adapter_handle(struct device *dev,
+ }
+ static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL);
+
+-static ssize_t ehca_show_mr_largepage(struct device *dev,
+- struct device_attribute *attr,
+- char *buf)
+-{
+- return sprintf(buf, "%d\n", ehca_mr_largepage);
+-}
+-static DEVICE_ATTR(mr_largepage, S_IRUGO, ehca_show_mr_largepage, NULL);
+-
+ static struct attribute *ehca_dev_attrs[] = {
+ &dev_attr_adapter_handle.attr,
+ &dev_attr_num_ports.attr,
+@@ -687,7 +672,6 @@ static struct attribute *ehca_dev_attrs[] = {
+ &dev_attr_cur_mw.attr,
+ &dev_attr_max_pd.attr,
+ &dev_attr_max_ah.attr,
+- &dev_attr_mr_largepage.attr,
+ NULL
+ };
+
+--
+1.5.5
+
diff --git a/kernel_patches/fixes/ehca_0037_Make-some-module-parameters-bool-update-de.patch b/kernel_patches/fixes/ehca_0037_Make-some-module-parameters-bool-update-de.patch
new file mode 100644
index 0000000..1050918
--- /dev/null
+++ b/kernel_patches/fixes/ehca_0037_Make-some-module-parameters-bool-update-de.patch
@@ -0,0 +1,78 @@
+From 0455e36d81db76f5f4acb68a820da43adfa7ccec Mon Sep 17 00:00:00 2001
+From: Joachim Fenkes <fenkes at de.ibm.com>
+Date: Wed, 23 Apr 2008 11:55:45 -0700
+Subject: [PATCH] IB/ehca: Make some module parameters bool, update descriptions
+
+Signed-off-by: Joachim Fenkes <fenkes at de.ibm.com>
+Signed-off-by: Roland Dreier <rolandd at cisco.com>
+---
+ drivers/infiniband/hw/ehca/ehca_main.c | 37 +++++++++++++++----------------
+ 1 files changed, 18 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
+index ab02ac8..45fe35a 100644
+--- a/drivers/infiniband/hw/ehca/ehca_main.c
++++ b/drivers/infiniband/hw/ehca/ehca_main.c
+@@ -69,41 +69,40 @@ int ehca_static_rate = -1;
+ int ehca_scaling_code = 0;
+ int ehca_lock_hcalls = -1;
+
+-module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO);
+-module_param_named(debug_level, ehca_debug_level, int, S_IRUGO);
+-module_param_named(hw_level, ehca_hw_level, int, S_IRUGO);
+-module_param_named(nr_ports, ehca_nr_ports, int, S_IRUGO);
+-module_param_named(use_hp_mr, ehca_use_hp_mr, int, S_IRUGO);
+-module_param_named(port_act_time, ehca_port_act_time, int, S_IRUGO);
+-module_param_named(poll_all_eqs, ehca_poll_all_eqs, int, S_IRUGO);
+-module_param_named(static_rate, ehca_static_rate, int, S_IRUGO);
+-module_param_named(scaling_code, ehca_scaling_code, int, S_IRUGO);
++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(hw_level, ehca_hw_level, int, S_IRUGO);
++module_param_named(nr_ports, ehca_nr_ports, int, S_IRUGO);
++module_param_named(use_hp_mr, ehca_use_hp_mr, bool, S_IRUGO);
++module_param_named(port_act_time, ehca_port_act_time, int, S_IRUGO);
++module_param_named(poll_all_eqs, ehca_poll_all_eqs, bool, 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_PARM_DESC(open_aqp1,
+- "AQP1 on startup (0: no (default), 1: yes)");
++ "Open AQP1 on startup (default: no)");
+ MODULE_PARM_DESC(debug_level,
+ "Amount of debug output (0: none (default), 1: traces, "
+ "2: some dumps, 3: lots)");
+ MODULE_PARM_DESC(hw_level,
+- "hardware level"
+- " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)");
++ "Hardware level (0: autosensing (default), "
++ "0x10..0x14: eHCA, 0x20..0x23: eHCA2)");
+ MODULE_PARM_DESC(nr_ports,
+ "number of connected ports (-1: autodetect, 1: port one only, "
+ "2: two ports (default)");
+ MODULE_PARM_DESC(use_hp_mr,
+- "high performance MRs (0: no (default), 1: yes)");
++ "Use high performance MRs (default: no)");
+ MODULE_PARM_DESC(port_act_time,
+- "time to wait for port activation (default: 30 sec)");
++ "Time to wait for port activation (default: 30 sec)");
+ MODULE_PARM_DESC(poll_all_eqs,
+- "polls all event queues periodically"
+- " (0: no, 1: yes (default))");
++ "Poll all event queues periodically (default: yes)");
+ MODULE_PARM_DESC(static_rate,
+- "set permanent static rate (default: disabled)");
++ "Set permanent static rate (default: no static rate)");
+ MODULE_PARM_DESC(scaling_code,
+- "set scaling code (0: disabled/default, 1: enabled)");
++ "Enable scaling code (default: no)");
+ MODULE_PARM_DESC(lock_hcalls,
+- "serialize all hCalls made by the driver "
++ "Serialize all hCalls made by the driver "
+ "(default: autodetect)");
+
+ DEFINE_RWLOCK(ehca_qp_idr_lock);
+--
+1.5.5
+
diff --git a/kernel_patches/fixes/ehca_0038_Bump-version-number-to-0026.patch b/kernel_patches/fixes/ehca_0038_Bump-version-number-to-0026.patch
new file mode 100644
index 0000000..926bbef
--- /dev/null
+++ b/kernel_patches/fixes/ehca_0038_Bump-version-number-to-0026.patch
@@ -0,0 +1,27 @@
+From 14fb05b3497351fbeb514381bcd227d84e115bd9 Mon Sep 17 00:00:00 2001
+From: Joachim Fenkes <fenkes at de.ibm.com>
+Date: Wed, 23 Apr 2008 11:55:45 -0700
+Subject: [PATCH] IB/ehca: Bump version number to 0026
+
+Signed-off-by: Joachim Fenkes <fenkes at de.ibm.com>
+Signed-off-by: Roland Dreier <rolandd at cisco.com>
+---
+ drivers/infiniband/hw/ehca/ehca_main.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
+index 45fe35a..6504897 100644
+--- a/drivers/infiniband/hw/ehca/ehca_main.c
++++ b/drivers/infiniband/hw/ehca/ehca_main.c
+@@ -50,7 +50,7 @@
+ #include "ehca_tools.h"
+ #include "hcp_if.h"
+
+-#define HCAD_VERSION "SVNEHCA_0025"
++#define HCAD_VERSION "SVNEHCA_0026"
+
+ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_AUTHOR("Christoph Raisch <raisch at de.ibm.com>");
+--
+1.5.5
+
diff --git a/kernel_patches/fixes/ehca_0039_handle-negative-return-value-from-ibmebus_r.patch b/kernel_patches/fixes/ehca_0039_handle-negative-return-value-from-ibmebus_r.patch
new file mode 100644
index 0000000..6585824
--- /dev/null
+++ b/kernel_patches/fixes/ehca_0039_handle-negative-return-value-from-ibmebus_r.patch
@@ -0,0 +1,91 @@
+From 7df109d917e85d3da2e25bd495c4997e87ed2a4e Mon Sep 17 00:00:00 2001
+From: Hoang-Nam Nguyen <hnguyen at linux.vnet.ibm.com>
+Date: Tue, 29 Apr 2008 13:46:52 -0700
+Subject: [PATCH] IB/ehca: handle negative return value from ibmebus_request_irq() properly
+
+ehca_create_eq() was assigning a signed return value to an unsiged
+local variable and then checking if the variable was < 0, which meant
+that errors were always ignored. Fix this by using one variable for
+signed integer return values and another for u64 hcall return values.
+
+Bug originally found by Roel Kluin <12o3l at tiscali.nl>.
+
+Signed-off-by: Hoang-Nam Nguyen <hnguyen at de.ibm.com>
+Signed-off-by: Roland Dreier <rolandd at cisco.com>
+---
+ drivers/infiniband/hw/ehca/ehca_eq.c | 35 ++++++++++++++++-----------------
+ 1 files changed, 17 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
+index b4ac617..49660df 100644
+--- a/drivers/infiniband/hw/ehca/ehca_eq.c
++++ b/drivers/infiniband/hw/ehca/ehca_eq.c
+@@ -54,7 +54,8 @@ int ehca_create_eq(struct ehca_shca *shca,
+ struct ehca_eq *eq,
+ const enum ehca_eq_type type, const u32 length)
+ {
+- u64 ret;
++ int ret;
++ u64 h_ret;
+ u32 nr_pages;
+ u32 i;
+ void *vpage;
+@@ -73,15 +74,15 @@ int ehca_create_eq(struct ehca_shca *shca,
+ return -EINVAL;
+ }
+
+- ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
+- &eq->pf,
+- type,
+- length,
+- &eq->ipz_eq_handle,
+- &eq->length,
+- &nr_pages, &eq->ist);
++ h_ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
++ &eq->pf,
++ type,
++ length,
++ &eq->ipz_eq_handle,
++ &eq->length,
++ &nr_pages, &eq->ist);
+
+- if (ret != H_SUCCESS) {
++ if (h_ret != H_SUCCESS) {
+ ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq);
+ return -EINVAL;
+ }
+@@ -97,24 +98,22 @@ int ehca_create_eq(struct ehca_shca *shca,
+ u64 rpage;
+
+ vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
+- if (!vpage) {
+- ret = H_RESOURCE;
++ if (!vpage)
+ goto create_eq_exit2;
+- }
+
+ rpage = virt_to_abs(vpage);
+- ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
+- eq->ipz_eq_handle,
+- &eq->pf,
+- 0, 0, rpage, 1);
++ h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
++ eq->ipz_eq_handle,
++ &eq->pf,
++ 0, 0, rpage, 1);
+
+ if (i == (nr_pages - 1)) {
+ /* last page */
+ vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
+- if (ret != H_SUCCESS || vpage)
++ if (h_ret != H_SUCCESS || vpage)
+ goto create_eq_exit2;
+ } else {
+- if (ret != H_PAGE_REGISTERED || !vpage)
++ if (h_ret != H_PAGE_REGISTERED || !vpage)
+ goto create_eq_exit2;
+ }
+ }
+--
+1.5.5
+
diff --git a/kernel_patches/fixes/ehca_0040_Allocate-event-queue-size-depending-on-max.patch b/kernel_patches/fixes/ehca_0040_Allocate-event-queue-size-depending-on-max.patch
new file mode 100644
index 0000000..6967a23
--- /dev/null
+++ b/kernel_patches/fixes/ehca_0040_Allocate-event-queue-size-depending-on-max.patch
@@ -0,0 +1,302 @@
+From d227fa7288adebe5ba37fa8e4a589c977d4e4a34 Mon Sep 17 00:00:00 2001
+From: Stefan Roscher <ossrosch at linux.vnet.ibm.com>
+Date: Tue, 29 Apr 2008 13:46:53 -0700
+Subject: [PATCH] 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 at de.ibm.com>
+Signed-off-by: Roland Dreier <rolandd at cisco.com>
+---
+ drivers/infiniband/hw/ehca/ehca_classes.h | 5 ++++
+ drivers/infiniband/hw/ehca/ehca_cq.c | 11 +++++++++
+ drivers/infiniband/hw/ehca/ehca_main.c | 36 +++++++++++++++++++++++++++-
+ drivers/infiniband/hw/ehca/ehca_qp.c | 26 +++++++++++++++++++-
+ 4 files changed, 74 insertions(+), 4 deletions(-)
+
+diff -Nurp linux-2.6_1/drivers/infiniband/hw/ehca/ehca_classes.h linux-2.6_2/drivers/infiniband/hw/ehca/ehca_classes.h
+--- linux-2.6_1/drivers/infiniband/hw/ehca/ehca_classes.h 2008-05-02 19:28:26.000000000 +0200
++++ linux-2.6_2/drivers/infiniband/hw/ehca/ehca_classes.h 2008-05-02 19:28:47.000000000 +0200
+@@ -66,6 +66,7 @@ struct ehca_av;
+ #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;
+@@ -127,6 +128,8 @@ struct ehca_shca {
+ /* 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 {
+@@ -344,6 +347,8 @@ extern int ehca_use_hp_mr;
+ 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 */
+diff -Nurp linux-2.6_1/drivers/infiniband/hw/ehca/ehca_cq.c linux-2.6_2/drivers/infiniband/hw/ehca/ehca_cq.c
+--- linux-2.6_1/drivers/infiniband/hw/ehca/ehca_cq.c 2008-05-02 19:28:26.000000000 +0200
++++ linux-2.6_2/drivers/infiniband/hw/ehca/ehca_cq.c 2008-05-02 19:28:47.000000000 +0200
+@@ -132,10 +132,19 @@ struct ib_cq *ehca_create_cq(struct ib_d
+ 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;
+ }
+
+diff -Nurp linux-2.6_1/drivers/infiniband/hw/ehca/ehca_main.c linux-2.6_2/drivers/infiniband/hw/ehca/ehca_main.c
+--- linux-2.6_1/drivers/infiniband/hw/ehca/ehca_main.c 2008-05-02 19:28:26.000000000 +0200
++++ linux-2.6_2/drivers/infiniband/hw/ehca/ehca_main.c 2008-05-02 19:28:47.000000000 +0200
+@@ -68,6 +68,8 @@ int ehca_port_act_time = 30;
+ 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);
+@@ -79,6 +81,8 @@ module_param_named(poll_all_eqs, ehca_p
+ 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)");
+@@ -104,6 +108,12 @@ MODULE_PARM_DESC(scaling_code,
+ 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);
+@@ -355,6 +365,25 @@ static int ehca_sense_attributes(struct
+ 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);
+@@ -679,7 +708,7 @@ static int __devinit ehca_probe(struct o
+ 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) {
+@@ -700,6 +729,8 @@ static int __devinit ehca_probe(struct o
+ 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);
+
+@@ -719,8 +750,9 @@ static int __devinit ehca_probe(struct o
+ 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;
+diff -Nurp linux-2.6_1/drivers/infiniband/hw/ehca/ehca_qp.c linux-2.6_2/drivers/infiniband/hw/ehca/ehca_qp.c
+--- linux-2.6_1/drivers/infiniband/hw/ehca/ehca_qp.c 2008-05-02 19:28:26.000000000 +0200
++++ linux-2.6_2/drivers/infiniband/hw/ehca/ehca_qp.c 2008-05-02 19:32:25.000000000 +0200
+@@ -421,6 +421,14 @@ static struct ehca_qp *internal_create_q
+ u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
+ unsigned long 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);
++ }
++
+ memset(&parms, 0, sizeof(parms));
+ qp_type = init_attr->qp_type;
+
+@@ -428,6 +436,7 @@ static struct ehca_qp *internal_create_q
+ 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);
+ }
+
+@@ -452,6 +461,7 @@ static struct ehca_qp *internal_create_q
+
+ if (is_llqp && has_srq) {
+ ehca_err(pd->device, "LLQPs can't have an SRQ");
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(-EINVAL);
+ }
+
+@@ -463,6 +473,7 @@ static struct ehca_qp *internal_create_q
+ 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);
+ }
+ }
+@@ -474,6 +485,7 @@ static struct ehca_qp *internal_create_q
+ 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);
+ }
+
+@@ -487,6 +499,7 @@ static struct ehca_qp *internal_create_q
+ "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;
+@@ -494,6 +507,7 @@ static struct ehca_qp *internal_create_q
+ 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
+@@ -505,20 +519,22 @@ static struct ehca_qp *internal_create_q
+ "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
+@@ -530,6 +546,7 @@ static struct ehca_qp *internal_create_q
+ "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);
+ }
+ }
+@@ -540,6 +557,7 @@ static struct ehca_qp *internal_create_q
+ 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);
+ }
+
+@@ -820,6 +838,7 @@ create_qp_exit1:
+
+ create_qp_exit0:
+ kmem_cache_free(qp_cache, my_qp);
++ atomic_dec(&shca->num_qps);
+ return ERR_PTR(ret);
+ }
+
+@@ -1945,6 +1964,7 @@ static int internal_destroy_qp(struct ib
+ 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;
+ }
+
--
1.5.5
More information about the ewg
mailing list